Skip to content

Commit

Permalink
Add documentation page for Popover component
Browse files Browse the repository at this point in the history
  • Loading branch information
acelaya committed Nov 26, 2024
1 parent 54d82ea commit 8b15cae
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/components/feedback/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,13 @@ export type PopoverProps = {
classes?: string | string[];
variant?: 'panel' | 'custom';

/** Whether the popover is currently open or not. Defaults to false */
/** Whether the popover is currently open or not */
open: boolean;
/** The element relative to which the popover should be positioned */
anchorElementRef: RefObject<HTMLElement | undefined>;

/**
* Determines to what side of the anchor element should the popover be
* Determines to which side of the anchor element the popover should be
* aligned.
*
* Defaults to `left`
Expand Down
176 changes: 176 additions & 0 deletions src/pattern-library/components/patterns/feedback/PopoverPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import { Link } from '../../../../components/navigation';
import Library from '../../Library';

export default function PopoverPage() {
return (
<Library.Page
title="Popover"
intro={
<>
<p>
<code>Popover</code> is a floating element rendered above other
content and positioned next to an anchor element.
</p>
</>
}
>
<Library.Section
title="Popover"
intro={
<>
<p>
By default, <code>Popover</code> will be displayed below the
anchor element, unless there is not enough space below.
</p>
<p>
It will always be at least as wide as the anchor element, but it
can grow to fit its content if needed. However, it will never grow
beyond the viewport.
</p>
<p>
In browsers that support it, <code>Popover</code> uses the{' '}
<Link
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/popover"
>
<code>popover</code>
</Link>{' '}
attribute and gets toggled via{' '}
<Link
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/API/Popover_API"
>
popover API
</Link>
. Otherwise, it is rendered as an absolute-positioned element, so
it is recommended to wrap it and its anchor element in a
relative-positioned container.
</p>
</>
}
>
<Library.Pattern>
<Library.Usage symbolName="Popover" />
<Library.Example>
<Library.Demo
title="Basic Popover"
exampleFile="popover-basic"
withSource
/>
</Library.Example>
</Library.Pattern>

<Library.Pattern title="Popover component API">
<Library.Example title="align">
<Library.Info>
<Library.InfoItem label="description">
Determines to which side of the anchor element the popover
should be aligned.
</Library.InfoItem>
<Library.InfoItem label="type">
<code>{"'left' | 'right'"}</code>
</Library.InfoItem>
<Library.InfoItem label="default">
<code>{"'left'"}</code>
</Library.InfoItem>
</Library.Info>
<Library.Demo
title="Right-aligned Popover"
exampleFile="popover-right"
withSource
/>
</Library.Example>
<Library.Example title="anchorElementRef">
<Library.Info>
<Library.InfoItem label="description">
A reference to the element to which the popover should anchor,
which will be used to calculate the popover size and
positioning.
</Library.InfoItem>
<Library.InfoItem label="type">
<code>{'RefObject<HTMLElement | undefined>'}</code>
</Library.InfoItem>
</Library.Info>
</Library.Example>
<Library.Example title="asNativePopover">
<Library.Info>
<Library.InfoItem label="description">
Determines if the{' '}
<Link
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/API/Popover_API"
>
popover API
</Link>{' '}
should be used. It{"'"}s mainly used as a test seam, but can be
used to explicitly disable use of the native popover API.
</Library.InfoItem>
<Library.InfoItem label="type">
<code>boolean</code>
</Library.InfoItem>
<Library.InfoItem label="default">
<code>true</code> if the browser supports <code>[popover]</code>
. Otherwise it is <code>false</code>
</Library.InfoItem>
</Library.Info>
</Library.Example>
<Library.Example title="classes">
<Library.Info>
<Library.InfoItem label="description">
Additional CSS classes to pass to the popover.
</Library.InfoItem>
<Library.InfoItem label="type">
<code>string | string[]</code>
</Library.InfoItem>
<Library.InfoItem label="default">
<code>undefined</code>
</Library.InfoItem>
</Library.Info>
</Library.Example>
<Library.Example title="open">
<Library.Info>
<Library.InfoItem label="description">
Whether the <code>Popover</code> is currently open or not.
</Library.InfoItem>
<Library.InfoItem label="type">
<code>boolean</code>
</Library.InfoItem>
</Library.Info>
</Library.Example>
<Library.Example title="restoreFocusOnClose">
<Library.Info>
<Library.InfoItem label="description">
Determines if focus should be restored when the{' '}
<code>Popover</code> is closed.
</Library.InfoItem>
<Library.InfoItem label="type">
<code>boolean</code>
</Library.InfoItem>
<Library.InfoItem label="default">
<code>false</code>
</Library.InfoItem>
</Library.Info>
</Library.Example>
<Library.Example title="variant">
<Library.Info>
<Library.InfoItem label="description">
Set the <code>Popover</code> style variant.
</Library.InfoItem>
<Library.InfoItem label="type">
<code>{"'panel' | 'custom'"}</code>
</Library.InfoItem>
<Library.InfoItem label="default">
<code>{"'panel'"}</code>
</Library.InfoItem>
</Library.Info>
<Library.Demo
title="Custom Popover"
exampleFile="popover-custom"
withSource
/>
</Library.Example>
</Library.Pattern>
</Library.Section>
</Library.Page>
);
}
18 changes: 3 additions & 15 deletions src/pattern-library/components/patterns/input/SelectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,9 @@ export default function SelectPage() {
{"'"} UI can be customized and values can be objects.
</p>
<p>
In browsers that support it, the listbox uses the{' '}
<Link
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/popover"
>
<code>popover</code>
</Link>{' '}
attribute and gets toggled via{' '}
<Link
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/API/Popover_API"
>
popover API
</Link>
. Otherwise, it is rendered as an absolute-positioned element.
A <Library.Link href="/feedback-popover">Popover</Library.Link>{' '}
component is used to wrap the listbox and ensure it is always
correctly positioned.
</p>

<Library.Example title="Composing and styling Selects">
Expand Down
27 changes: 27 additions & 0 deletions src/pattern-library/examples/popover-basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useRef, useState } from 'preact/hooks';

import { Popover } from '../../components/feedback';
import { Button } from '../../components/input';
import { useClickAway } from '../../hooks/use-click-away';

export default function App() {
const [open, setOpen] = useState(false);
const buttonRef = useRef<HTMLButtonElement | null>(null);

useClickAway(buttonRef, () => setOpen(false));

return (
<div className="relative flex justify-center">
<Button
variant="primary"
elementRef={buttonRef}
onClick={() => setOpen(prev => !prev)}
>
{open ? 'Close' : 'Open'} Popover
</Button>
<Popover open={open} anchorElementRef={buttonRef} classes="p-2">
The content of the popover goes here
</Popover>
</div>
);
}
32 changes: 32 additions & 0 deletions src/pattern-library/examples/popover-custom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useRef, useState } from 'preact/hooks';

import { Popover } from '../../components/feedback';
import { Button } from '../../components/input';
import { useClickAway } from '../../hooks/use-click-away';

export default function App() {
const [open, setOpen] = useState(false);
const buttonRef = useRef<HTMLButtonElement | null>(null);

useClickAway(buttonRef, () => setOpen(false));

return (
<div className="relative flex justify-center">
<Button
variant="primary"
elementRef={buttonRef}
onClick={() => setOpen(prev => !prev)}
>
{open ? 'Close' : 'Open'} Popover
</Button>
<Popover
open={open}
anchorElementRef={buttonRef}
variant="custom"
classes="p-3 border-4 border-slate-7 bg-green-success text-white font-bold rounded-tr-lg rounded-bl-lg"
>
This popover has been customized
</Popover>
</div>
);
}
32 changes: 32 additions & 0 deletions src/pattern-library/examples/popover-right.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useRef, useState } from 'preact/hooks';

import { Popover } from '../../components/feedback';
import { Button } from '../../components/input';
import { useClickAway } from '../../hooks/use-click-away';

export default function App() {
const [open, setOpen] = useState(false);
const buttonRef = useRef<HTMLButtonElement | null>(null);

useClickAway(buttonRef, () => setOpen(false));

return (
<div className="relative flex justify-center">
<Button
variant="primary"
elementRef={buttonRef}
onClick={() => setOpen(prev => !prev)}
>
{open ? 'Close' : 'Open'} Popover
</Button>
<Popover
open={open}
align="right"
anchorElementRef={buttonRef}
classes="p-2"
>
The content of the popover goes here
</Popover>
</div>
);
}
7 changes: 7 additions & 0 deletions src/pattern-library/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import TablePage from './components/patterns/data/TablePage';
import ThumbnailPage from './components/patterns/data/ThumbnailPage';
import CalloutPage from './components/patterns/feedback/CalloutPage';
import DialogPage from './components/patterns/feedback/DialogPage';
import PopoverPage from './components/patterns/feedback/PopoverPage';
import SpinnerPage from './components/patterns/feedback/SpinnerPage';
import ToastMessagesPage from './components/patterns/feedback/ToastMessagesPage';
import UseClickAwayPage from './components/patterns/hooks/UseClickAwayPage';
Expand Down Expand Up @@ -146,6 +147,12 @@ const routes: PlaygroundRoute[] = [
component: DialogPage,
route: '/feedback-dialog',
},
{
title: 'Popover',
group: 'feedback',
component: PopoverPage,
route: '/feedback-popover',
},
{
title: 'Spinner',
group: 'feedback',
Expand Down

0 comments on commit 8b15cae

Please sign in to comment.