-
Notifications
You must be signed in to change notification settings - Fork 120
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Uxpt 4810 - Initial creation of the Tabs (#1340)
* initial commit with first coouple of stories * small cleanup of some stuff * fixing to compile for build time * editting stories and adding constants folder for tests * removing unused import * adding portion of snapshot * adding hover state and icon stories * additional test cases * removing unused values * adding change file * reworked to include Radio * lowering coverage to apst cicd * fixing compile issue * PR review and fixups * Update packages/core/src/Tab/Tab.styled.tsx Co-authored-by: Steve Dalonzo <[email protected]> * rush prepare * wip, pushing up to Craig * rush update * rerunning rush update after rebase * fix compiler issue * removing extra await * fixing border-radius * pr fixups * lowering jets coverage * removing bum package.json * fixing small bugs and UI tweaks. * getting tab to properly react onHover for chip * jest coverage * add more stories, better controls, and improve readibility of tabs component. Added vertical orientation * style adjustments * refactoring ids, fixing radio to function correctly, cleaning up types * cleaning up more unneeded indexes * cleaning up unused imports * sorting exports * adding test cases for coverage * reverting changes to jest file * fixing jest coverage * cleaning up types, adding types to Chip, and stylistic changes from Wes * fixing type error * type adjustments * add responsive styling to buttonTab * removed unused import * reworking stories and fixing hover behaviro * removing unused prop * removing import * final adjustments * fixing things again * adding ternary for icon logic * removing flex * config * adding dynamic tab width prop * jest * adding width to chip * jest * removing unused prop * Type adjustments, and using getByRole where applicable * PR feedbacks, adding defaultValue, onTabSelect, ariaLabel, props * adding TSDoc * TSDoc * tsdoc blurb * jest adjustments * moved tabContent to another file --------- Co-authored-by: Steve Dalonzo <[email protected]>
- Loading branch information
Showing
18 changed files
with
868 additions
and
130 deletions.
There are no files selected for viewing
10 changes: 10 additions & 0 deletions
10
common/changes/pcln-design-system/UXPT-4810_2023-07-13-20-28.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"changes": [ | ||
{ | ||
"packageName": "pcln-design-system", | ||
"comment": "Added Tab component", | ||
"type": "minor" | ||
} | ||
], | ||
"packageName": "pcln-design-system" | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,10 @@ | |
{ | ||
"name": "Justin Trenary", | ||
"email": "[email protected]" | ||
}, | ||
{ | ||
"name": "Brandon Soong", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"sideEffects": false, | ||
|
@@ -73,6 +77,7 @@ | |
}, | ||
"dependencies": { | ||
"@radix-ui/react-accordion": "~1.1.2", | ||
"@radix-ui/react-tabs": "~1.0.4", | ||
"@radix-ui/react-dialog": "^1.0.5", | ||
"@radix-ui/react-visually-hidden": "^1.0.3", | ||
"@styled-system/theme-get": "^5.1.2", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,10 +59,7 @@ export const DynamicLabel = () => ( | |
<Label autoHide htmlFor='dynamic-label-with-a-value'> | ||
With value | ||
</Label> | ||
<Input | ||
id='dynamic-label-with-a-value' | ||
name='dynamic-label-with-a-value' | ||
value='[email protected]' /> | ||
<Input id='dynamic-label-with-a-value' name='dynamic-label-with-a-value' value='[email protected]' /> | ||
</FormField> | ||
</Box> | ||
<Box px={2} width={1 / 3}> | ||
|
@@ -175,32 +172,34 @@ const validateEmailFormat = (email) => { | |
} | ||
|
||
export const Usage = () => { | ||
const [email, setEmail] = useState(''); | ||
const [email, setEmail] = useState('') | ||
const [isValidEmail, setIsValidEmail] = useState(false) | ||
const [isFocused, SetIsFocused] = useState(true) | ||
|
||
// update email address | ||
// update email address | ||
const updateInput = (e) => { | ||
const value = e.target.value | ||
setEmail(value) | ||
} | ||
|
||
// handle when focus leave the field | ||
// handle when focus leave the field | ||
const handleBlur = (e) => { | ||
const value = e.target.value | ||
setIsValidEmail(validateEmailFormat(value)) | ||
SetIsFocused(false) | ||
} | ||
|
||
// handle when field is on focus | ||
// handle when field is on focus | ||
const handleFocus = (e) => { | ||
SetIsFocused(true) | ||
} | ||
|
||
return ( | ||
<Box> | ||
<FormField> | ||
<Label autoHide htmlFor='dynamic-label-usage'>Email Address</Label> | ||
<Label autoHide htmlFor='dynamic-label-usage'> | ||
Email Address | ||
</Label> | ||
<Input | ||
id='dynamic-label-usage' | ||
name='dynamic-label-usage' | ||
|
@@ -213,12 +212,11 @@ export const Usage = () => { | |
/> | ||
{isFocused ? null : isValidEmail ? <SuccessIcon color='success' /> : <WarningIcon color='error' />} | ||
</FormField> | ||
{!isFocused && !isValidEmail | ||
? <Tooltip id='demo-error' right color='error'> | ||
Email address is required | ||
</Tooltip> | ||
: null | ||
} | ||
{!isFocused && !isValidEmail ? ( | ||
<Tooltip id='demo-error' right color='error'> | ||
Email address is required | ||
</Tooltip> | ||
) : null} | ||
</Box> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import React from 'react' | ||
import { render, screen } from '../__test__/testing-library' | ||
import { userEvent } from '@storybook/testing-library' | ||
import { Tab } from './Tab' | ||
import { Departure } from 'pcln-icons' | ||
|
||
describe('Tab', () => { | ||
const tabsData = [ | ||
{ id: 'tab1', text: 'Tab 1', children: <div>Tab 1 Content</div>, onTabSelect: () => {} }, | ||
{ id: 'tab2', text: 'Tab 2', children: <div>Tab 2 Content</div>, onTabSelect: () => {} }, | ||
] | ||
const tabsDataWithIcon = [ | ||
{ id: 'tab1', text: 'Tab 1', icon: Departure, children: <div>Tab 1 Content</div>, onTabSelect: () => {} }, | ||
{ id: 'tab2', text: 'Tab 2', children: <div>Tab 2 Content</div>, onTabSelect: () => {} }, | ||
] | ||
|
||
it('renders tabs with correct text', () => { | ||
render(<Tab type='button' tabsData={tabsData} />) | ||
|
||
expect(screen.getByRole('tab', { name: 'Tab 1' })).toBeInTheDocument() | ||
expect(screen.getByRole('tab', { name: 'Tab 2' })).toBeInTheDocument() | ||
}) | ||
|
||
it('renders tab content based on active tab', async () => { | ||
render(<Tab type='button' tabsData={tabsData} />) | ||
|
||
expect(screen.getByRole('tab', { name: 'Tab 1' })).toBeInTheDocument() | ||
expect(screen.getByText('Tab 1 Content')).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 2 Content')).not.toBeInTheDocument() | ||
|
||
await userEvent.click(screen.getByText('Tab 2')) | ||
expect(screen.getByRole('tab', { name: 'Tab 2' })).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 1 Content')).not.toBeInTheDocument() | ||
expect(screen.getByText('Tab 2 Content')).toBeInTheDocument() | ||
}) | ||
it('renders tab content based on active tab with icon', async () => { | ||
render(<Tab type='button' tabsData={tabsDataWithIcon} />) | ||
|
||
expect(screen.getByRole('tab', { name: 'Tab 1' })).toBeInTheDocument() | ||
expect(screen.getByText('Tab 1 Content')).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 2 Content')).not.toBeInTheDocument() | ||
|
||
await userEvent.click(screen.getByText('Tab 2')) | ||
expect(screen.getByRole('tab', { name: 'Tab 2' })).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 1 Content')).not.toBeInTheDocument() | ||
expect(screen.getByText('Tab 2 Content')).toBeInTheDocument() | ||
}) | ||
|
||
it('renders tab content based on active tab in Chip Variation', async () => { | ||
render(<Tab type='chip' tabsData={tabsData} />) | ||
|
||
expect(screen.getByRole('radio', { name: 'Tab 1' })).toBeInTheDocument() | ||
expect(screen.getByText('Tab 1 Content')).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 2 Content')).not.toBeInTheDocument() | ||
|
||
await userEvent.click(screen.getByText('Tab 2')) | ||
expect(screen.getByRole('radio', { name: 'Tab 2' })).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 1 Content')).not.toBeInTheDocument() | ||
expect(screen.getByText('Tab 2 Content')).toBeInTheDocument() | ||
}) | ||
|
||
it('renders tab content based on active tab in Radio Variation', async () => { | ||
render(<Tab type='radio' tabsData={tabsData} />) | ||
|
||
expect(screen.getByRole('tab', { name: 'Tab 1' })).toBeInTheDocument() | ||
expect(screen.getByText('Tab 1 Content')).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 2 Content')).not.toBeInTheDocument() | ||
|
||
await userEvent.click(screen.getByText('Tab 2')) | ||
expect(screen.queryByText('Tab 1 Content')).not.toBeInTheDocument() | ||
expect(screen.getByText('Tab 2 Content')).toBeInTheDocument() | ||
}) | ||
|
||
it('renders tab content based on orientation', async () => { | ||
render(<Tab type='button' orientation='vertical' tabsData={tabsData} />) | ||
expect(screen.getByRole('tab', { name: 'Tab 1' })).toBeInTheDocument() | ||
await userEvent.click(screen.getByText('Tab 1')) | ||
expect(screen.getByText('Tab 1 Content')).toBeInTheDocument() | ||
expect(screen.queryByText('Tab 2 Content')).not.toBeInTheDocument() | ||
|
||
await userEvent.click(screen.getByText('Tab 2')) | ||
expect(screen.queryByText('Tab 1 Content')).not.toBeInTheDocument() | ||
expect(screen.getByText('Tab 2 Content')).toBeInTheDocument() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { TabProps } from './Tab' | ||
import { DefaultContent, DefaultContent2, DefaultContent3 } from '../__test__/mocks/tabContent' | ||
|
||
export const defaultArgs: Partial<TabProps> = { | ||
size: 'md', | ||
type: 'button', | ||
tabsData: [ | ||
{ | ||
id: 't1', | ||
text: 'Tab 1', | ||
children: DefaultContent(), | ||
onTabSelect: () => {}, | ||
}, | ||
{ | ||
id: 't2', | ||
text: 'Tab 2', | ||
children: DefaultContent2(), | ||
onTabSelect: () => {}, | ||
}, | ||
{ | ||
id: 't3', | ||
text: 'Tab 3', | ||
children: DefaultContent3(), | ||
onTabSelect: () => { | ||
alert('onTabSelectFired!') | ||
}, | ||
}, | ||
], | ||
} | ||
export const argTypes = { | ||
size: { | ||
control: 'select', | ||
options: ['sm', 'md'], | ||
}, | ||
type: { | ||
control: 'select', | ||
options: ['chip', 'radio', 'button'], | ||
}, | ||
orientation: { | ||
control: 'select', | ||
options: ['horizontal', 'vertical'], | ||
}, | ||
tabGap: { | ||
control: 'number', | ||
}, | ||
isTransparent: { | ||
defaultValue: false, | ||
control: 'boolean', | ||
}, | ||
border: { | ||
defaultValue: false, | ||
control: 'boolean', | ||
}, | ||
dynamicTabWidth: { | ||
defaultValue: false, | ||
control: 'boolean', | ||
}, | ||
defaultValue: { | ||
defaultValue: 't1', | ||
control: 'select', | ||
options: ['t1', 't2', 't3'], | ||
}, | ||
} |
Oops, something went wrong.