Skip to content

Commit

Permalink
feat: Implements action and dismissible options to tabs v2 (#2435)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrei Zhaleznichenka <[email protected]>
Co-authored-by: Timo <[email protected]>
  • Loading branch information
3 people authored Jul 2, 2024
1 parent e197f9f commit dba9901
Show file tree
Hide file tree
Showing 27 changed files with 1,224 additions and 121 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ src/test-utils/selectors
src/icon/generated
src/internal/generated/custom-css-properties/index.*
vendor/generated-*.txt
# IDEs
.vscode
# System
.DS_Store
173 changes: 173 additions & 0 deletions pages/tabs/actions.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useState } from 'react';
import { Button, Container, Header } from '~components';
import ButtonDropdown from '~components/button-dropdown';
import SpaceBetween from '~components/space-between';
import Tabs, { TabsProps } from '~components/tabs';

export default function TabsDemoPage() {
const [tabsDismissibles, setTabDismissibles] = useState([
{
label: 'First tab',
id: 'first',
dismissible: true,
dismissLabel: 'Dismiss first tab (dismissibles variant)',
onDismiss: () => setTabDismissibles(prevTabs => prevTabs.slice(1)),
content: (
<>
Diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et
accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
dolor sit amet.,
</>
),
},
{
label: 'Second tab',
id: 'second',
dismissible: true,
dismissLabel: 'Dismiss second tab (dismissibles variant)',
onDismiss: () => setTabDismissibles(prevTabs => prevTabs.filter(tab => tab.id !== 'second')),
content: (
<>
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Diam nonumy eirmod tempor
invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.,
</>
),
},
]);

const tabsNoActions: Array<TabsProps.Tab> = [
{
label: 'First tab',
id: 'first',
content:
'Diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
},
{
label: 'Second tab',
id: 'second',
content:
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
},
];
const [tabsXORActions, setTabsXORActions] = useState([
{
label: 'First tab',
id: 'first',
dismissible: true,
dismissLabel: 'Dismiss first tab (xor actions variant)',
onDismiss: () => setTabsXORActions(prevTabs => prevTabs.slice(1)),
content: (
<>
Diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et
accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
dolor sit ameta.,
</>
),
},
{
label: 'Second tab',
id: 'second',
action: <Button iconName="copy" variant="icon" ariaLabel="Action button for the Second tab" />,
content:
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
},
]);

const [tabsBoth, setTabsBoth] = useState([
{
id: 'first',
label: 'Tab w/ action',
action: (
<ButtonDropdown
variant="icon"
ariaLabel="Query actions for first tab (Hybrid component)"
items={[
{ id: 'save', text: 'Save', disabled: true },
{ id: 'saveAs', text: 'Save as' },
{ id: 'rename', text: 'Rename', disabled: true },
{ id: 'delete', text: 'Delete', disabled: true },
]}
expandToViewport={true}
/>
),
content: <p>First tab content</p>,
},
{
id: 'second',
label: 'Second tab label',
content: <p>Second tab content</p>,
},
{
id: 'third',
label: 'Athena-like tab',
dismissible: true,
dismissLabel: 'Dismiss third button (combined tabs variant)',
onDismiss: () => setTabsBoth(prevTabs => prevTabs.slice(0, 2)),
action: (
<ButtonDropdown
variant="icon"
ariaLabel="Query actions for third tab (Hybrid component)"
items={[
{ id: 'save', text: 'Save', disabled: true },
{ id: 'saveAs', text: 'Save as' },
{ id: 'rename', text: 'Rename', disabled: true },
{ id: 'delete', text: 'Delete', disabled: true },
]}
expandToViewport={true}
/>
),
content: (
<Container
header={
<Header variant="h2" description="Container description">
Container title
</Header>
}
>
Container content
</Container>
),
},
]);

return (
<>
<h1>Tabs</h1>

<SpaceBetween size="xs">
<div>
<h2>Tabs with dismissibles</h2>
<Tabs
tabs={tabsDismissibles}
i18nStrings={{ scrollLeftAriaLabel: 'Scroll left', scrollRightAriaLabel: 'Scroll right' }}
/>
</div>
<div>
<h2>Tabs with no actions</h2>
<Tabs
tabs={tabsNoActions}
i18nStrings={{ scrollLeftAriaLabel: 'Scroll left', scrollRightAriaLabel: 'Scroll right' }}
/>
</div>
<div>
<h2>Tabs with action or dismissible</h2>
<Tabs
tabs={tabsXORActions}
i18nStrings={{ scrollLeftAriaLabel: 'Scroll left', scrollRightAriaLabel: 'Scroll right' }}
/>
</div>
<div>
<h2>Tabs with actions and dismissibles</h2>
<Tabs
tabs={tabsBoth}
i18nStrings={{ scrollLeftAriaLabel: 'Scroll left', scrollRightAriaLabel: 'Scroll right' }}
/>
</div>
</SpaceBetween>
</>
);
}
155 changes: 152 additions & 3 deletions pages/tabs/permutations.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ScreenshotArea from '../utils/screenshot-area';
import Tabs, { TabsProps } from '~components/tabs';
import createPermutations from '../utils/permutations';
import PermutationsView from '../utils/permutations-view';
import ButtonDropdown from '~components/button-dropdown';

const permutations = createPermutations<TabsProps>([
{
Expand Down Expand Up @@ -73,6 +74,129 @@ const fitHeightPermutations = createPermutations<TabsProps>([
},
]);

const tabActionPermutations = createPermutations<TabsProps>([
{
activeTabId: ['first', 'second'],
variant: ['default', 'container'],
tabs: [
[
{
label: 'First tab',
id: 'first',
content: 'First content',
href: '#first',
dismissible: true,
dismissLabel: 'Dismiss first tab',
},
{ label: 'Second tab', id: 'second', href: '#second' },
],
[
{
label: 'First tab',
id: 'first',
content: (
<p>
Long text, long enough to wrap. Shoulder tail brisket sausage, shank biltong pork fatback chicken
hamburger doner andouille ham hock. Picanha meatball leberkas, turkey andouille boudin tongue frankfurter.
Fatback tenderloin brisket cow leberkas. Ball tip short loin brisket andouille. Flank turkey drumstick
cow, prosciutto hamburger bresaola pork.
</p>
),
action: (
<ButtonDropdown
variant="icon"
ariaLabel="Query actions for first tab"
items={[
{ id: 'save', text: 'Save', disabled: true },
{ id: 'saveAs', text: 'Save as' },
{ id: 'rename', text: 'Rename', disabled: true },
{ id: 'delete', text: 'Delete', disabled: true },
]}
expandToViewport={true}
/>
),
},
{ label: 'Second tab', id: 'second', disabled: true },
{
label: 'Third tab',
id: 'third',
content: "Third tab's content",
action: (
<ButtonDropdown
variant="icon"
ariaLabel="Query actions for third tab"
items={[
{ id: 'save', text: 'Save', disabled: true },
{ id: 'saveAs', text: 'Save as' },
{ id: 'rename', text: 'Rename', disabled: true },
{ id: 'delete', text: 'Delete', disabled: true },
]}
expandToViewport={true}
/>
),
dismissible: true,
dismissLabel: 'Dismiss third tab',
},
{
label: 'fourth tab',
id: 'fourth',
dismissible: true,
dismissLabel: 'Dismiss fourth tab',
},
],
],
},
{
variant: ['default', 'container', 'stacked'],
tabs: [
['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eight'].map(id => ({
label: `${id} tab`,
id,
content: `${id} content`,
href: `#${id}`,
})),
],
disableContentPaddings: [false, true],
},
]);

const tabActionFitHeightPermutations = createPermutations<TabsProps>([
{
activeTabId: ['first', 'second'],
variant: ['default', 'container'],
fitHeight: [true],
tabs: [
[
{
label: 'First tab',
id: 'first',
dismissible: true,
dismissLabel: 'Dismiss first tab',
content: new Array(10).fill('').map((_, index) => <p key={index}>First content</p>),
},
{
label: 'Second tab',
id: 'second',
action: (
<ButtonDropdown
variant="icon"
ariaLabel="Query actions for second tab"
items={[
{ id: 'save', text: 'Save', disabled: true },
{ id: 'saveAs', text: 'Save as' },
{ id: 'rename', text: 'Rename', disabled: true },
{ id: 'delete', text: 'Delete', disabled: true },
]}
expandToViewport={true}
/>
),
content: <div style={{ blockSize: '100%', display: 'flex', alignItems: 'flex-end' }}>Second content</div>,
},
],
],
},
]);

export default function TabsPermutations() {
return (
<>
Expand All @@ -90,11 +214,36 @@ export default function TabsPermutations() {
/>
<PermutationsView
permutations={fitHeightPermutations}
render={permutation => (
render={fitHeightPermutation => (
<div style={{ blockSize: '200px' }}>
<Tabs
{...fitHeightPermutation}
activeTabId={fitHeightPermutation.activeTabId}
i18nStrings={{ scrollLeftAriaLabel: 'Scroll left', scrollRightAriaLabel: 'Scroll right' }}
/>
</div>
)}
/>
</ScreenshotArea>
<h1>Actionable Tabs permutations</h1>
<ScreenshotArea disableAnimations={true}>
<PermutationsView
permutations={tabActionPermutations}
render={tabActionPermutation => (
<Tabs
{...tabActionPermutation}
activeTabId={tabActionPermutation.activeTabId}
i18nStrings={{ scrollLeftAriaLabel: 'Scroll left', scrollRightAriaLabel: 'Scroll right' }}
/>
)}
/>
<PermutationsView
permutations={tabActionFitHeightPermutations}
render={tabActionFitHeightPermutation => (
<div style={{ blockSize: '200px' }}>
<Tabs
{...permutation}
activeTabId={permutation.activeTabId}
{...tabActionFitHeightPermutation}
activeTabId={tabActionFitHeightPermutation.activeTabId}
i18nStrings={{ scrollLeftAriaLabel: 'Scroll left', scrollRightAriaLabel: 'Scroll right' }}
/>
</div>
Expand Down
Loading

0 comments on commit dba9901

Please sign in to comment.