-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tabs (future): add carousel functionality when tabs overflow container (
#5355) * Tabs (future): add carousel functionality when tabs overflow container * Replace Button with div onClick :O * Add a couple more tabs to story * Stylelint * Add stickersheets * Limit tab selector to unique container * Add unique ids for stickersheet examples * Support for RTL * Adjust tab hover back to gray * Add SB/Chromatic test for carousel functionality * Add cleanup to disconnect observers * Add root element to observers to avoid arrows showing when cut off vertically * Adjust SB test to assert arrows are in the document * When selected tab changes, scroll it into view * Use new spacing var * Add typeof Tabs to spec stories meta * Add prefix to testids and only render when testid passed in props * Move scrollAmount to a constant * Extract isRTL into a util * Add a show/hide arrow SB test for RTL
- Loading branch information
1 parent
87ae545
commit f6bd88c
Showing
11 changed files
with
457 additions
and
13 deletions.
There are no files selected for viewing
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,5 @@ | ||
--- | ||
'@kaizen/components': patch | ||
--- | ||
|
||
Tabs (future): add carousel functionality when tabs overflow container width |
118 changes: 118 additions & 0 deletions
118
packages/components/src/__future__/Tabs/_docs/Tabs.spec.stories.tsx
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,118 @@ | ||
import React from 'react' | ||
import { Meta, StoryObj } from '@storybook/react' | ||
import { within, userEvent, expect } from '@storybook/test' | ||
import { Text } from '~components/Text' | ||
import { Tab, TabList, TabPanel, Tabs } from '../index' | ||
|
||
const meta = { | ||
title: 'Components/Tabs/Tabs (Future)/Tests', | ||
parameters: { | ||
controls: { disable: true }, | ||
}, | ||
args: { | ||
children: ( | ||
<> | ||
<TabList aria-label="Tabs" data-testid="sb-arrows"> | ||
<Tab id="one">Tab 1</Tab> | ||
<Tab id="two">Tab 2</Tab> | ||
<Tab id="three" badge="3"> | ||
Tab 3 | ||
</Tab> | ||
<Tab id="disabled" isDisabled> | ||
Disabled Tab | ||
</Tab> | ||
<Tab id="four">Tab 4</Tab> | ||
<Tab id="five">Tab 5</Tab> | ||
</TabList> | ||
<TabPanel id="one" className="p-24"> | ||
<Text variant="body">Content 1</Text> | ||
</TabPanel> | ||
<TabPanel id="two" className="p-24"> | ||
<Text variant="body">Content 2</Text> | ||
</TabPanel> | ||
<TabPanel id="three" className="p-24"> | ||
<Text variant="body">Content 3</Text> | ||
</TabPanel> | ||
<TabPanel id="disabled" className="p-24"> | ||
<Text variant="body">Disabled content</Text> | ||
</TabPanel> | ||
<TabPanel id="four" className="p-24"> | ||
<Text variant="body">Content 4</Text> | ||
</TabPanel> | ||
<TabPanel id="five" className="p-24"> | ||
<Text variant="body">Content 5</Text> | ||
</TabPanel> | ||
</> | ||
), | ||
}, | ||
} satisfies Meta<typeof Tabs> | ||
|
||
export default meta | ||
|
||
type Story = StoryObj<typeof meta> | ||
|
||
export const ArrowsShowingAndHiding: Story = { | ||
render: (args) => { | ||
return ( | ||
<div style={{ maxWidth: '500px' }}> | ||
<Tabs {...args} /> | ||
</div> | ||
) | ||
}, | ||
play: async ({ canvasElement }) => { | ||
const canvas = within(canvasElement.parentElement!) | ||
|
||
expect(canvas.queryByTestId('kz-tablist-left-arrow')).not.toBeInTheDocument() | ||
|
||
const rightArrow = await canvas.findByTestId('sb-arrows-kz-tablist-right-arrow') | ||
|
||
await userEvent.click(rightArrow) | ||
await new Promise((r) => setTimeout(r, 500)) | ||
|
||
const leftArrow = await canvas.findByTestId('sb-arrows-kz-tablist-left-arrow') | ||
|
||
expect(leftArrow).toBeInTheDocument() | ||
expect(rightArrow).toBeInTheDocument() | ||
|
||
await userEvent.click(rightArrow) | ||
await new Promise((r) => setTimeout(r, 500)) | ||
|
||
expect(leftArrow).toBeInTheDocument() | ||
expect(rightArrow).not.toBeInTheDocument() | ||
}, | ||
} | ||
|
||
export const ArrowsShowingAndHidingRTL: Story = { | ||
name: 'Arrows Showing and Hiding (RTL)', | ||
parameters: { | ||
textDirection: 'rtl', | ||
}, | ||
render: (args) => { | ||
return ( | ||
<div style={{ maxWidth: '500px' }}> | ||
<Tabs {...args} /> | ||
</div> | ||
) | ||
}, | ||
play: async ({ canvasElement }) => { | ||
const canvas = within(canvasElement.parentElement!) | ||
|
||
expect(canvas.queryByTestId('kz-tablist-right-arrow')).not.toBeInTheDocument() | ||
|
||
const leftArrow = await canvas.findByTestId('sb-arrows-kz-tablist-left-arrow') | ||
|
||
await userEvent.click(leftArrow) | ||
await new Promise((r) => setTimeout(r, 500)) | ||
|
||
const rightArrow = await canvas.findByTestId('sb-arrows-kz-tablist-right-arrow') | ||
|
||
expect(leftArrow).toBeInTheDocument() | ||
expect(rightArrow).toBeInTheDocument() | ||
|
||
await userEvent.click(leftArrow) | ||
await new Promise((r) => setTimeout(r, 500)) | ||
|
||
expect(rightArrow).toBeInTheDocument() | ||
expect(leftArrow).not.toBeInTheDocument() | ||
}, | ||
} |
84 changes: 84 additions & 0 deletions
84
packages/components/src/__future__/Tabs/_docs/Tabs.stickersheet.stories.tsx
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,84 @@ | ||
import React from 'react' | ||
import { Meta } from '@storybook/react' | ||
import { Text } from '~components/Text' | ||
import { StickerSheet, StickerSheetStory } from '~storybook/components/StickerSheet' | ||
import { Tab, TabList, TabPanel, Tabs } from '../index' | ||
|
||
export default { | ||
title: 'Components/Tabs/Tabs (Future)', | ||
parameters: { | ||
chromatic: { disable: false }, | ||
controls: { disable: true }, | ||
}, | ||
} satisfies Meta | ||
|
||
const ExampleTabs = ({ id }: { id: string }): JSX.Element => ( | ||
<Tabs> | ||
<TabList aria-label="Tabs"> | ||
<Tab id={`${id}-1`}>Tab 1</Tab> | ||
<Tab id={`${id}-2`}>Tab 2</Tab> | ||
<Tab id={`${id}-3`} badge="3"> | ||
Tab 3 | ||
</Tab> | ||
<Tab id={`${id}-disabled`} isDisabled> | ||
Disabled Tab | ||
</Tab> | ||
<Tab id={`${id}-4`}>Tab 4</Tab> | ||
<Tab id={`${id}-5`}>Tab 5</Tab> | ||
</TabList> | ||
<TabPanel id={`${id}-1`} className="p-24"> | ||
<Text variant="body">Content 1</Text> | ||
</TabPanel> | ||
<TabPanel id={`${id}-2`} className="p-24"> | ||
<Text variant="body">Content 2</Text> | ||
</TabPanel> | ||
<TabPanel id={`${id}-3`} className="p-24"> | ||
<Text variant="body">Content 3</Text> | ||
</TabPanel> | ||
<TabPanel id={`${id}-disabled`} className="p-24"> | ||
<Text variant="body">Disabled content</Text> | ||
</TabPanel> | ||
<TabPanel id={`${id}-4`} className="p-24"> | ||
<Text variant="body">Content 4</Text> | ||
</TabPanel> | ||
<TabPanel id={`${id}-5`} className="p-24"> | ||
<Text variant="body">Content 5</Text> | ||
</TabPanel> | ||
</Tabs> | ||
) | ||
|
||
const StickerSheetTemplate: StickerSheetStory = { | ||
render: () => { | ||
return ( | ||
<> | ||
<StickerSheet title="Tabs" layout="stretch"> | ||
<StickerSheet.Row> | ||
<ExampleTabs id="fullwidth" /> | ||
</StickerSheet.Row> | ||
</StickerSheet> | ||
|
||
<StickerSheet title="Overflow (container 500px)" layout="stretch"> | ||
<StickerSheet.Row> | ||
<div style={{ maxWidth: '500px' }}> | ||
<ExampleTabs id="overflow" /> | ||
</div> | ||
</StickerSheet.Row> | ||
</StickerSheet> | ||
</> | ||
) | ||
}, | ||
} | ||
|
||
export const StickerSheetDefault: StickerSheetStory = { | ||
...StickerSheetTemplate, | ||
name: 'Sticker Sheet (Default)', | ||
} | ||
|
||
export const StickerSheetRTL: StickerSheetStory = { | ||
...StickerSheetTemplate, | ||
name: 'Sticker Sheet (RTL)', | ||
parameters: { | ||
...StickerSheetTemplate.parameters, | ||
textDirection: 'rtl', | ||
}, | ||
} |
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 |
---|---|---|
@@ -0,0 +1 @@ | ||
export const SCROLL_AMOUNT = 120 |
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
54 changes: 53 additions & 1 deletion
54
packages/components/src/__future__/Tabs/subcomponents/TabList/TabList.module.css
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 |
---|---|---|
@@ -1,8 +1,60 @@ | ||
.container { | ||
position: relative; | ||
} | ||
|
||
.tabList { | ||
border-bottom: 1px solid rgba(var(--color-gray-600-rgb), 0.1); | ||
padding: var(--spacing-xs) var(--spacing-md) 0; | ||
padding: var(--spacing-6) 0 0; | ||
width: 100%; | ||
height: 100%; | ||
overflow-x: scroll; | ||
white-space: nowrap; | ||
scrollbar-width: none; | ||
scroll-behavior: smooth; | ||
} | ||
|
||
.noPadding { | ||
padding: 0; | ||
} | ||
|
||
.leftArrow, | ||
.rightArrow { | ||
--icon-size: 24; | ||
|
||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
position: absolute; | ||
z-index: 10000; | ||
background: var(--color-white); | ||
inset-block: 0 1px; | ||
width: 48px; | ||
cursor: default; | ||
user-select: none; | ||
} | ||
|
||
/* | ||
* Note: we're purposefully using directional properties instead of start/end for positioning and styling related to the carousel arrows | ||
*/ | ||
.leftArrow { | ||
left: 0; | ||
} | ||
|
||
.leftArrow, | ||
.leftArrow:hover { | ||
border-right: 1px solid rgba(var(--color-gray-600-rgb), 0.1); | ||
} | ||
|
||
.rightArrow { | ||
right: 0; | ||
} | ||
|
||
.rightArrow, | ||
.rightArrow:hover { | ||
border-left: 1px solid rgba(var(--color-gray-600-rgb), 0.1); | ||
} | ||
|
||
.leftArrow:hover, | ||
.rightArrow:hover { | ||
background: var(--color-gray-200); | ||
} |
Oops, something went wrong.