Skip to content

Commit

Permalink
docs(side-panel): more examples
Browse files Browse the repository at this point in the history
  • Loading branch information
nkrantz committed Feb 5, 2025
1 parent 5bf6cf4 commit b4ba31b
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface LivePreviewProps {
disabled?: boolean;
noInline?: boolean;
showOverflow?: boolean;
height?: string;
}

const LivePreview: React.FC<React.PropsWithChildren<LivePreviewProps>> = ({
Expand All @@ -31,6 +32,7 @@ const LivePreview: React.FC<React.PropsWithChildren<LivePreviewProps>> = ({
noInline = false,
showOverflow = false,
scope,
height = "unset",
}) => {
const [viewCode, setViewCode] = React.useState(false);
const id = useUID();
Expand Down Expand Up @@ -72,6 +74,7 @@ const LivePreview: React.FC<React.PropsWithChildren<LivePreviewProps>> = ({
borderTopRightRadius="borderRadius20"
position="relative"
overflow={overflow}
height={height}
>
<ReactLivePreview />
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const getStaticProps = async () => {
pageHeaderData: {
categoryRoute: SidebarCategoryRoutes.COMPONENTS,
githubUrl: '/?path=/story/components-alert--neutral',
storybookUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/alert',
storybookUrl: '/?path=/story/components-paragraph--default',
},
},
};
Expand Down
123 changes: 110 additions & 13 deletions packages/paste-website/src/pages/components/side-panel/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export const meta = {

import {Anchor} from '@twilio-paste/anchor';
import {Callout, CalloutHeading, CalloutText} from '@twilio-paste/callout';
import {SidePanel, SidePanelContainer, SidePanelButton, SidePanelPushContentWrapper, SidePanelHeader, SidePanelBody, useSidePanelState} from '@twilio-paste/side-panel';
import {Heading} from '@twilio-paste/heading';
import {Separator} from '@twilio-paste/separator';

import {SidebarCategoryRoutes} from '../../../constants';
import {
Expand Down Expand Up @@ -54,19 +57,21 @@ export const SidePanelExample = (): React.ReactNode => {
<SidePanelContainer id={sidePanelId} isOpen={isOpen} setIsOpen={setIsOpen}>
<SidePanel>
<SidePanelHeader>
<Heading as="h3" variant="heading30">Heading</Heading>
<ArtificialIntelligenceIcon decorative size="sizeIcon50" color="colorTextIcon" />
<Heading as="h3" variant="heading30" marginBottom="space0">
Assistant
</Heading>
<SidePanelHeaderActions>
<Button variant="reset">
<MoreIcon decorative={false} title="side panel actions menu" />
<Button variant="secondary_icon" size="reset" onClick={() => {}}>
<MoreIcon decorative={false} title="open menu" size="sizeIcon50" />
</Button>
</SidePanelHeaderActions>
</SidePanelHeader>
<Separator orientation="horizontal" verticalSpacing="space0" />
<SidePanelBody>
<Separator orientation="horizontal" verticalSpacing="space0" />
Side Panel content goes here.
</SidePanelBody>
<SidePanelFooter>
<SidePanelFooter variant="chat">
Footer content goes here.
</SidePanelFooter>
</SidePanel>
Expand All @@ -86,6 +91,8 @@ export const SidePanelExample = (): React.ReactNode => {

Side Panel is a container that pushes the main page content when open. It's important for page content to be responsive when using a Side Panel so that the opening and closing of the panel doesn't cause the page to jump or shift. At mobile breakpoints, the Side Panel overlays the page content and takes up the full width of the viewport.

Side Panel is primarily used within [AI experiences](/experiences/artificial-intelligence) and on pages using the [filter pattern](/patterns/filter) when there are too many filter options to display on the page.

<Callout variant="warning" marginY="space70">
<CalloutHeading as="h4">Only use one Side Panel on a page</CalloutHeading>
<CalloutText>
Expand Down Expand Up @@ -127,19 +134,21 @@ export const SidePanelExample = (): React.ReactNode => {
<SidePanelContainer id={sidePanelId} isOpen={isOpen} setIsOpen={setIsOpen}>
<SidePanel>
<SidePanelHeader>
<Heading as="h3" variant="heading30">Heading</Heading>
<ArtificialIntelligenceIcon decorative size="sizeIcon50" color="colorTextIcon" />
<Heading as="h3" variant="heading30" marginBottom="space0">
Assistant
</Heading>
<SidePanelHeaderActions>
<Button variant="reset">
<MoreIcon decorative={false} title="side panel actions menu" />
<Button variant="secondary_icon" size="reset" onClick={() => {}}>
<MoreIcon decorative={false} title="open menu" size="sizeIcon50" />
</Button>
</SidePanelHeaderActions>
</SidePanelHeader>
<Separator orientation="horizontal" verticalSpacing="space0" />
<SidePanelBody>
<Separator orientation="horizontal" verticalSpacing="space0" />
Side Panel content goes here.
</SidePanelBody>
<SidePanelFooter>
<SidePanelFooter variant="chat">
Footer content goes here.
</SidePanelFooter>
</SidePanel>
Expand All @@ -153,6 +162,49 @@ export const SidePanelExample = (): React.ReactNode => {
}`}
/>

### Side Panel with Footer

Use the `default` variant of SidePanelFooter when you need to add actions to the bottom of the Side Panel. Use the `chat` variant of Side Panel Footer for AI use cases.

<StoryPreview
title="Side Panel Footer example"
storyID="components-side-panel--filter"
height="500px"
code={`
export const SidePanelExample = (): React.ReactNode => {
const [isOpen, setIsOpen] = React.useState(true);
const sidePanelId = useUID();
return (
<SidePanelContainer id={sidePanelId} isOpen={isOpen} setIsOpen={setIsOpen}>
<SidePanel>
<SidePanelHeader>
<Heading as="h3" variant="heading30" marginBottom="space0">
More filters
</Heading>
</SidePanelHeader>
<Separator orientation="horizontal" verticalSpacing="space0" />
<SidePanelBody>
Side Panel content goes here.
</SidePanelBody>
<SidePanelFooter>
Footer content goes here.
</SidePanelFooter>
</SidePanel>
<SidePanelPushContentWrapper>
<Box paddingTop="space40" paddingLeft="space40" paddingRight="space40">
<SidePanelButton variant="secondary" size="rounded_small" pressed={isOpen}>
More filters
<Badge as="span" variant="neutral_counter">
2
</Badge>
</SidePanelButton>
</Box>
</SidePanelPushContentWrapper>
</SidePanelContainer>
)
}`}
/>

### Internationalization

To internationalize Side Panel, simply pass different text as children to the Side Panel components. The only exceptions are the close button in the SidePanelHeader and the SidePanelButton/SidePanelBadgeButton. To change the buttons' accessible label text, use the `i18nCloseSidePanelTitle` and `i18nOpenSidePanel` props on the `SidePanelContainer`.
Expand All @@ -167,24 +219,69 @@ export const SidePanelExample = (): React.ReactNode => {
const sidePanelId = useUID();
return (
<SidePanelContainer id={sidePanelId} isOpen={isOpen} setIsOpen={setIsOpen} i18nCloseSidePanelTitle="cerrar panel lateral" i18nOpenSidePanelTitle="abrir panel lateral">
<SidePanel>
<SidePanel label="el panel lateral">
<SidePanelHeader>
<Heading as="h3" variant="heading30">Título</Heading>
<Heading as="h5" variant="heading30" marginBottom="space0">Título</Heading>
</SidePanelHeader>
<SidePanelBody>
Side Panel content goes here.
</SidePanelBody>
</SidePanel>
<SidePanelPushContentWrapper>
<Box paddingTop="space40" paddingLeft="space40" paddingRight="space40">
<SidePanelButton variant="secondary">Probar Panel Lateral</SidePanelButton>
<SidePanelButton variant="primary">Probar Panel Lateral</SidePanelButton>
</Box>
</SidePanelPushContentWrapper>
</SidePanelContainer>
)
}`}
/>

### Using the state hook

Side Panel comes with the option of using a hook to manage the open and close state of the panel. The `useSidePanelState` hook returns an object to spread onto SidePanelContainer and a function to pass to the `onClick` of SidePanelButton.

<LivePreview
scope={{
SidePanel,
SidePanelContainer,
SidePanelButton,
useSidePanelState,
SidePanelPushContentWrapper,
SidePanelHeader,
SidePanelBody,
Heading,
Separator
}}
noInline
height="300px"
>
{`const SidePanelExample = () => {
const { sidePanel, toggleSidePanel } = useSidePanelState({});
return (
<SidePanelContainer {...sidePanel}>
<SidePanelPushContentWrapper>
<SidePanelButton variant="primary" onClick={toggleSidePanel}>
Toggle Side Panel
</SidePanelButton>
</SidePanelPushContentWrapper>
<SidePanel>
<SidePanelHeader>
<Heading as="h3" variant="heading30" marginBottom="space0">
Assistant
</Heading>
</SidePanelHeader>
<Separator orientation="horizontal" verticalSpacing="space0" />
<SidePanelBody>
Side Panel content goes here.
</SidePanelBody>
</SidePanel>
</SidePanelContainer>
)
}
render(<SidePanelExample />)`}
</LivePreview>

## Composition notes

The Side Panel comes with some smaller components that can be used to compose a Side Panel to your application's needs. All of the following components should be used inside of a `SidePanelContainer`, with `SidePanel` and `SidePanelPushContentWrapper` being its direct children. The Side Panel Container controls the positioning of the Side Panel with relation to the page content.
Expand Down

0 comments on commit b4ba31b

Please sign in to comment.