From 71afff9c76d8eeeb185226cb1ca2b7ae31a21587 Mon Sep 17 00:00:00 2001 From: Tom King Date: Tue, 5 Sep 2023 09:46:43 +1000 Subject: [PATCH] - added panel component/stories/docs/tests --- apps/docs/content/components/panel.yaml | 1 + apps/docs/content/components/panel/code.mdoc | 31 ++++ .../components/code/code.inject-components.ts | 1 + apps/docs/src/components/layout/nav-items.tsx | 1 + packages/ui/src/components/index.ts | 1 + .../panel/components/body/body.component.tsx | 13 ++ .../panel/components/body/body.styles.ts | 9 + .../panel/components/body/body.types.ts | 3 + .../components/panel/components/body/index.ts | 2 + .../components/footer/footer.component.tsx | 13 ++ .../panel/components/footer/footer.styles.ts | 11 ++ .../panel/components/footer/footer.types.ts | 3 + .../panel/components/footer/index.ts | 2 + .../src/components/panel/components/index.ts | 2 + packages/ui/src/components/panel/index.ts | 2 + .../src/components/panel/panel.component.tsx | 17 ++ .../ui/src/components/panel/panel.spec.tsx | 37 +++++ .../ui/src/components/panel/panel.stories.tsx | 156 ++++++++++++++++++ .../ui/src/components/panel/panel.styles.ts | 22 +++ .../ui/src/components/panel/panel.types.ts | 16 ++ .../components/caption/caption.styles.ts | 2 +- 21 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 apps/docs/content/components/panel.yaml create mode 100644 apps/docs/content/components/panel/code.mdoc create mode 100644 packages/ui/src/components/panel/components/body/body.component.tsx create mode 100644 packages/ui/src/components/panel/components/body/body.styles.ts create mode 100644 packages/ui/src/components/panel/components/body/body.types.ts create mode 100644 packages/ui/src/components/panel/components/body/index.ts create mode 100644 packages/ui/src/components/panel/components/footer/footer.component.tsx create mode 100644 packages/ui/src/components/panel/components/footer/footer.styles.ts create mode 100644 packages/ui/src/components/panel/components/footer/footer.types.ts create mode 100644 packages/ui/src/components/panel/components/footer/index.ts create mode 100644 packages/ui/src/components/panel/components/index.ts create mode 100644 packages/ui/src/components/panel/index.ts create mode 100644 packages/ui/src/components/panel/panel.component.tsx create mode 100644 packages/ui/src/components/panel/panel.spec.tsx create mode 100644 packages/ui/src/components/panel/panel.stories.tsx create mode 100644 packages/ui/src/components/panel/panel.styles.ts create mode 100644 packages/ui/src/components/panel/panel.types.ts diff --git a/apps/docs/content/components/panel.yaml b/apps/docs/content/components/panel.yaml new file mode 100644 index 000000000..7fdbf0ac4 --- /dev/null +++ b/apps/docs/content/components/panel.yaml @@ -0,0 +1 @@ +name: Panel \ No newline at end of file diff --git a/apps/docs/content/components/panel/code.mdoc b/apps/docs/content/components/panel/code.mdoc new file mode 100644 index 000000000..e50cd179b --- /dev/null +++ b/apps/docs/content/components/panel/code.mdoc @@ -0,0 +1,31 @@ +## Panel Looks +```jsx +
+ + + They found themselves standing on the very edge of the Wild Wood. Rocks and brambles and tree-roots behind them, + confusedly heaped and tangled; in front, a great space of quiet fields, hemmed by lines of hedges black on the + snow, and, far ahead, a glint of the familiar old river, while the wintry sun hung red and low on the horizon. The + Otter, as knowing all the paths, took charge of the party, and they trailed out on a bee-line for a distant stile. + Pausing there a moment and looking back, they saw the whole mass of the Wild Wood, dense, menacing, compact, + grimly set in vast white surroundings; simultaneously they turned and made swiftly for home, for firelight and the + familiar things it played on, for the voice, sounding cheerily outside their window, of the river that they knew + and trusted in all its moods, that never made them afraid with any amazement. + + Panel footer + + + + They found themselves standing on the very edge of the Wild Wood. Rocks and brambles and tree-roots behind them, + confusedly heaped and tangled; in front, a great space of quiet fields, hemmed by lines of hedges black on the + snow, and, far ahead, a glint of the familiar old river, while the wintry sun hung red and low on the horizon. The + Otter, as knowing all the paths, took charge of the party, and they trailed out on a bee-line for a distant stile. + Pausing there a moment and looking back, they saw the whole mass of the Wild Wood, dense, menacing, compact, + grimly set in vast white surroundings; simultaneously they turned and made swiftly for home, for firelight and the + familiar things it played on, for the voice, sounding cheerily outside their window, of the river that they knew + and trusted in all its moods, that never made them afraid with any amazement. + + Panel footer + +
+``` diff --git a/apps/docs/src/components/code/code.inject-components.ts b/apps/docs/src/components/code/code.inject-components.ts index adb087dde..43808ac00 100644 --- a/apps/docs/src/components/code/code.inject-components.ts +++ b/apps/docs/src/components/code/code.inject-components.ts @@ -18,6 +18,7 @@ export { Link, Table, DatePicker, + Panel, } from '@westpac/ui'; export { diff --git a/apps/docs/src/components/layout/nav-items.tsx b/apps/docs/src/components/layout/nav-items.tsx index 27d25253e..a90b2500a 100644 --- a/apps/docs/src/components/layout/nav-items.tsx +++ b/apps/docs/src/components/layout/nav-items.tsx @@ -24,6 +24,7 @@ export const DEFAULT_NAV_ITEMS: NavItem[] = [ { href: '/components/link', label: 'Link' }, { href: '/components/table', label: 'Table' }, { href: '/components/date-picker', label: 'Date Picker' }, + { href: '/components/panel', label: 'Panel' }, ], }, ]; diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index 52ead6986..f8e1d8aa0 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -19,3 +19,4 @@ export * from './link/index.js'; export * from './date-picker/index.js'; export * from './grid/index.js'; export * from './table/index.js'; +export * from './panel/index.js'; diff --git a/packages/ui/src/components/panel/components/body/body.component.tsx b/packages/ui/src/components/panel/components/body/body.component.tsx new file mode 100644 index 000000000..f4e3e5a0d --- /dev/null +++ b/packages/ui/src/components/panel/components/body/body.component.tsx @@ -0,0 +1,13 @@ +import React from 'react'; + +import { styles as bodyStyles } from './body.styles.js'; +import { type BodyProps } from './body.types.js'; + +export function Body({ className, children, ...props }: BodyProps) { + const styles = bodyStyles({}); + return ( +
+ {children} +
+ ); +} diff --git a/packages/ui/src/components/panel/components/body/body.styles.ts b/packages/ui/src/components/panel/components/body/body.styles.ts new file mode 100644 index 000000000..1d3532f5d --- /dev/null +++ b/packages/ui/src/components/panel/components/body/body.styles.ts @@ -0,0 +1,9 @@ +import { tv } from 'tailwind-variants'; + +export const styles = tv( + { + slots: { base: 'max-xsl:px-2 typography-body-10 p-4' }, + variants: {}, + }, + { responsiveVariants: ['xsl', 'sm', 'md', 'lg', 'xl'] }, +); diff --git a/packages/ui/src/components/panel/components/body/body.types.ts b/packages/ui/src/components/panel/components/body/body.types.ts new file mode 100644 index 000000000..c870eb108 --- /dev/null +++ b/packages/ui/src/components/panel/components/body/body.types.ts @@ -0,0 +1,3 @@ +import { HTMLAttributes } from 'react'; + +export type BodyProps = HTMLAttributes; diff --git a/packages/ui/src/components/panel/components/body/index.ts b/packages/ui/src/components/panel/components/body/index.ts new file mode 100644 index 000000000..45f1caffd --- /dev/null +++ b/packages/ui/src/components/panel/components/body/index.ts @@ -0,0 +1,2 @@ +export { Body } from './body.component.js'; +export { type BodyProps } from './body.types.js'; diff --git a/packages/ui/src/components/panel/components/footer/footer.component.tsx b/packages/ui/src/components/panel/components/footer/footer.component.tsx new file mode 100644 index 000000000..1b7fc9bbc --- /dev/null +++ b/packages/ui/src/components/panel/components/footer/footer.component.tsx @@ -0,0 +1,13 @@ +import React from 'react'; + +import { styles as footerStyles } from './footer.styles.js'; +import { type FooterProps } from './footer.types.js'; + +export function Footer({ className, children, ...props }: FooterProps) { + const styles = footerStyles(); + return ( +
+ {children} +
+ ); +} diff --git a/packages/ui/src/components/panel/components/footer/footer.styles.ts b/packages/ui/src/components/panel/components/footer/footer.styles.ts new file mode 100644 index 000000000..9487b8483 --- /dev/null +++ b/packages/ui/src/components/panel/components/footer/footer.styles.ts @@ -0,0 +1,11 @@ +import { tv } from 'tailwind-variants'; + +export const styles = tv( + { + slots: { + base: 'border-t-1 border-border bg-light max-xsl:px-2 border-0 border-t px-4 py-[0.625rem]', + }, + variants: {}, + }, + { responsiveVariants: ['xsl', 'sm', 'md', 'lg', 'xl'] }, +); diff --git a/packages/ui/src/components/panel/components/footer/footer.types.ts b/packages/ui/src/components/panel/components/footer/footer.types.ts new file mode 100644 index 000000000..20b759076 --- /dev/null +++ b/packages/ui/src/components/panel/components/footer/footer.types.ts @@ -0,0 +1,3 @@ +import { HTMLAttributes } from 'react'; + +export type FooterProps = HTMLAttributes; diff --git a/packages/ui/src/components/panel/components/footer/index.ts b/packages/ui/src/components/panel/components/footer/index.ts new file mode 100644 index 000000000..32773b56a --- /dev/null +++ b/packages/ui/src/components/panel/components/footer/index.ts @@ -0,0 +1,2 @@ +export { Footer } from './footer.component.js'; +export { type FooterProps } from './footer.types.js'; diff --git a/packages/ui/src/components/panel/components/index.ts b/packages/ui/src/components/panel/components/index.ts new file mode 100644 index 000000000..909d9e81a --- /dev/null +++ b/packages/ui/src/components/panel/components/index.ts @@ -0,0 +1,2 @@ +export * from './body/index.js'; +export * from './footer/index.js'; diff --git a/packages/ui/src/components/panel/index.ts b/packages/ui/src/components/panel/index.ts new file mode 100644 index 000000000..11eacd6ef --- /dev/null +++ b/packages/ui/src/components/panel/index.ts @@ -0,0 +1,2 @@ +export { Panel } from './panel.component.js'; +export { type PanelProps } from './panel.types.js'; diff --git a/packages/ui/src/components/panel/panel.component.tsx b/packages/ui/src/components/panel/panel.component.tsx new file mode 100644 index 000000000..aa2e32b3c --- /dev/null +++ b/packages/ui/src/components/panel/panel.component.tsx @@ -0,0 +1,17 @@ +import React from 'react'; + +import { Body, Footer } from './components/index.js'; +import { styles as panelStyles } from './panel.styles.js'; +import { type PanelProps } from './panel.types.js'; + +export function Panel({ className, children, heading, headingTag: Tag = 'h1', look = 'hero', ...props }: PanelProps) { + const styles = panelStyles({ look }); + return ( +
+ {heading} + {children} +
+ ); +} +Panel.Body = Body; +Panel.Footer = Footer; diff --git a/packages/ui/src/components/panel/panel.spec.tsx b/packages/ui/src/components/panel/panel.spec.tsx new file mode 100644 index 000000000..580455c4d --- /dev/null +++ b/packages/ui/src/components/panel/panel.spec.tsx @@ -0,0 +1,37 @@ +import { render } from '@testing-library/react'; + +import { Panel } from './panel.component.js'; + +describe('Panel', () => { + it('renders the component', () => { + const { container } = render( + + Test body + Test footer + , + ); + expect(container).toBeInTheDocument(); + }); + + it('should have the correct default styling', () => { + const { getByText, getByTestId } = render( + + Test body + Test footer + , + ); + expect(getByTestId('panel')).toHaveClass('border-hero'); + expect(getByText('test heading')).toHaveClass('bg-hero text-white'); + }); + + it('should have the correct faint styling', () => { + const { getByText, getByTestId } = render( + + Test body + Test footer + , + ); + expect(getByTestId('panel')).toHaveClass('border-border'); + expect(getByText('test heading')).toHaveClass('text-text bg-background border-b-border border-0 border-b'); + }); +}); diff --git a/packages/ui/src/components/panel/panel.stories.tsx b/packages/ui/src/components/panel/panel.stories.tsx new file mode 100644 index 000000000..b4e5d0780 --- /dev/null +++ b/packages/ui/src/components/panel/panel.stories.tsx @@ -0,0 +1,156 @@ +import { type Meta, StoryFn, type StoryObj } from '@storybook/react'; + +import { Table } from '../table/index.js'; + +import { Panel } from './panel.component.js'; + +const meta: Meta = { + title: 'Example/Panel', + component: Panel, + tags: ['autodocs'], + decorators: [ + (Story: StoryFn) => ( +
+ +
+ ), + ], + parameters: { + layout: 'center', + }, + args: { + heading: 'Panel title', + }, +}; + +export default meta; +type Story = StoryObj; + +/** + * > Default usage example + */ +export const DefaultStory: Story = { + args: { + children: [ + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora officiis officia omnis aperiam voluptate + suscipit, laudantium praesentium quas consequatur placeat, perferendis eligendi saepe in unde sequi dolores + excepturi doloremque autem! Lorem ipsum dolor sit amet, consectetur adipisicing elit. + , + Panel footer, + ], + }, +}; + +/** + * > Faint look example + */ +export const FaintLookPanel: Story = { + args: { + look: 'faint', + children: [ + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora officiis officia omnis aperiam voluptate + suscipit, laudantium praesentium quas consequatur placeat, perferendis eligendi saepe in unde sequi dolores + excepturi doloremque autem! Lorem ipsum dolor sit amet, consectetur adipisicing elit. + , + Panel footer, + ], + }, +}; + +/** + * > Example using a table + */ +export const PanelWithTable: Story = { + args: { + children: [ + + + Caption this table width is: (100%) + + + + Name + Type + Date Modified + + + + + Games + File folder + 6/7/2020 + + + Program Files + File folder + 4/7/2021 + + + bootmgr + System file + 11/20/2010 + + + log.txt + Text Document + 1/18/2016 + + + Footer goes here and should colSpan all columns +
, + ], + }, +}; + +/** + * > Example using a table with a body and a panel footer + */ +export const PanelWithTableAndBody: Story = { + args: { + children: [ + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora officiis officia omnis aperiam voluptate + suscipit, laudantium praesentium quas consequatur placeat, perferendis eligendi saepe in unde sequi dolores + excepturi doloremque autem! Lorem ipsum dolor sit amet, consectetur adipisicing elit. + , + + + Caption this table width is: (100%) + + + + Name + Type + Date Modified + + + + + Games + File folder + 6/7/2020 + + + Program Files + File folder + 4/7/2021 + + + bootmgr + System file + 11/20/2010 + + + log.txt + Text Document + 1/18/2016 + + + Footer goes here and should colSpan all columns +
, + Panel footer, + ], + }, +}; diff --git a/packages/ui/src/components/panel/panel.styles.ts b/packages/ui/src/components/panel/panel.styles.ts new file mode 100644 index 000000000..5710a5289 --- /dev/null +++ b/packages/ui/src/components/panel/panel.styles.ts @@ -0,0 +1,22 @@ +import { tv } from 'tailwind-variants'; + +export const styles = tv( + { + slots: { + base: 'border-hero group/panel mb-4 overflow-hidden rounded-[0.1875rem] border', + header: 'max-xsl:px-2 px-4 py-[0.625rem]', + }, + variants: { + look: { + hero: { + header: 'bg-hero text-white', + }, + faint: { + base: 'border-border', + header: 'text-text bg-background border-b-border border-0 border-b', + }, + }, + }, + }, + { responsiveVariants: ['xsl', 'sm', 'md', 'lg', 'xl'] }, +); diff --git a/packages/ui/src/components/panel/panel.types.ts b/packages/ui/src/components/panel/panel.types.ts new file mode 100644 index 000000000..4ea156d38 --- /dev/null +++ b/packages/ui/src/components/panel/panel.types.ts @@ -0,0 +1,16 @@ +import { HTMLAttributes } from 'react'; + +export type PanelProps = { + /** + * The heading of the panel + */ + heading: string; + /** + * Tag for heading defaults to h1 + */ + headingTag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; + /** + * The styling of the panel + */ + look?: 'faint' | 'hero'; +} & HTMLAttributes; diff --git a/packages/ui/src/components/table/components/caption/caption.styles.ts b/packages/ui/src/components/table/components/caption/caption.styles.ts index 05b0ee8b7..40918673c 100644 --- a/packages/ui/src/components/table/components/caption/caption.styles.ts +++ b/packages/ui/src/components/table/components/caption/caption.styles.ts @@ -2,7 +2,7 @@ import { tv } from 'tailwind-variants'; export const styles = tv( { - base: 'typography-body-8 mb-2 text-left font-light', + base: 'typography-body-8 max-xsl:group-first/panel:px-2 max-xsl:group-first/panel:pt-2 mb-2 text-left font-light group-first/panel:px-4 group-first/panel:pt-4', variants: {}, }, { responsiveVariants: ['xsl', 'sm', 'md', 'lg', 'xl'] },