Skip to content

Commit

Permalink
Merge pull request #60 from WestpacGEL/feature/panel
Browse files Browse the repository at this point in the history
Feature/panel
  • Loading branch information
samithaf authored Sep 5, 2023
2 parents 83a837d + 3e86b11 commit 8c6ac65
Show file tree
Hide file tree
Showing 21 changed files with 344 additions and 1 deletion.
1 change: 1 addition & 0 deletions apps/docs/content/components/panel.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name: Panel
31 changes: 31 additions & 0 deletions apps/docs/content/components/panel/code.mdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Panel Looks
```jsx
<div>
<Panel heading="Default panel">
<Panel.Body>
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.Body>
<Panel.Footer>Panel footer</Panel.Footer>
</Panel>
<Panel heading="Faint panel" look="faint">
<Panel.Body>
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.Body>
<Panel.Footer>Panel footer</Panel.Footer>
</Panel>
</div>
```
1 change: 1 addition & 0 deletions apps/docs/src/components/code/code.inject-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export {
Table,
Collapsible,
DatePicker,
Panel,
} from '@westpac/ui';

export {
Expand Down
1 change: 1 addition & 0 deletions apps/docs/src/components/layout/nav-items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const DEFAULT_NAV_ITEMS: NavItem[] = [
{ href: '/components/table', label: 'Table' },
{ href: '/components/collapsible', label: 'Collapsible' },
{ href: '/components/date-picker', label: 'Date Picker' },
{ href: '/components/panel', label: 'Panel' },
],
},
];
1 change: 1 addition & 0 deletions packages/ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ 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';
export * from './collapsible/index.js';
Original file line number Diff line number Diff line change
@@ -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 (
<div className={styles.base({ className })} {...props}>
{children}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -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'] },
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { HTMLAttributes } from 'react';

export type BodyProps = HTMLAttributes<Element>;
2 changes: 2 additions & 0 deletions packages/ui/src/components/panel/components/body/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Body } from './body.component.js';
export { type BodyProps } from './body.types.js';
Original file line number Diff line number Diff line change
@@ -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 (
<div className={styles.base({ className })} {...props}>
{children}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -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'] },
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { HTMLAttributes } from 'react';

export type FooterProps = HTMLAttributes<Element>;
2 changes: 2 additions & 0 deletions packages/ui/src/components/panel/components/footer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Footer } from './footer.component.js';
export { type FooterProps } from './footer.types.js';
2 changes: 2 additions & 0 deletions packages/ui/src/components/panel/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './body/index.js';
export * from './footer/index.js';
2 changes: 2 additions & 0 deletions packages/ui/src/components/panel/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Panel } from './panel.component.js';
export { type PanelProps } from './panel.types.js';
17 changes: 17 additions & 0 deletions packages/ui/src/components/panel/panel.component.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className={styles.base({ className })} {...props}>
<Tag className={styles.header()}>{heading}</Tag>
{children}
</div>
);
}
Panel.Body = Body;
Panel.Footer = Footer;
37 changes: 37 additions & 0 deletions packages/ui/src/components/panel/panel.spec.tsx
Original file line number Diff line number Diff line change
@@ -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(
<Panel heading="test heading">
<Panel.Body>Test body</Panel.Body>
<Panel.Footer>Test footer</Panel.Footer>
</Panel>,
);
expect(container).toBeInTheDocument();
});

it('should have the correct default styling', () => {
const { getByText, getByTestId } = render(
<Panel heading="test heading" data-testid="panel">
<Panel.Body>Test body</Panel.Body>
<Panel.Footer>Test footer</Panel.Footer>
</Panel>,
);
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(
<Panel heading="test heading" data-testid="panel" look="faint">
<Panel.Body>Test body</Panel.Body>
<Panel.Footer>Test footer</Panel.Footer>
</Panel>,
);
expect(getByTestId('panel')).toHaveClass('border-border');
expect(getByText('test heading')).toHaveClass('text-text bg-background border-b-border border-0 border-b');
});
});
156 changes: 156 additions & 0 deletions packages/ui/src/components/panel/panel.stories.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof Panel> = {
title: 'Example/Panel',
component: Panel,
tags: ['autodocs'],
decorators: [
(Story: StoryFn) => (
<div className="p-3">
<Story />
</div>
),
],
parameters: {
layout: 'center',
},
args: {
heading: 'Panel title',
},
};

export default meta;
type Story = StoryObj<typeof meta>;

/**
* > Default usage example
*/
export const DefaultStory: Story = {
args: {
children: [
<Panel.Body>
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.Body>,
<Panel.Footer>Panel footer</Panel.Footer>,
],
},
};

/**
* > Faint look example
*/
export const FaintLookPanel: Story = {
args: {
look: 'faint',
children: [
<Panel.Body>
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.Body>,
<Panel.Footer>Panel footer</Panel.Footer>,
],
},
};

/**
* > Example using a table
*/
export const PanelWithTable: Story = {
args: {
children: [
<Table>
<Table.Caption>
Caption this table width is: <em>(100%)</em>
</Table.Caption>
<Table.Header>
<Table.HeaderRow>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>Type</Table.HeaderCell>
<Table.HeaderCell>Date Modified</Table.HeaderCell>
</Table.HeaderRow>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>Games</Table.Cell>
<Table.Cell>File folder</Table.Cell>
<Table.Cell>6/7/2020</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>Program Files</Table.Cell>
<Table.Cell>File folder</Table.Cell>
<Table.Cell>4/7/2021</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>bootmgr</Table.Cell>
<Table.Cell>System file</Table.Cell>
<Table.Cell>11/20/2010</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>log.txt</Table.Cell>
<Table.Cell>Text Document</Table.Cell>
<Table.Cell>1/18/2016</Table.Cell>
</Table.Row>
</Table.Body>
<Table.Footer colspan={3}>Footer goes here and should colSpan all columns</Table.Footer>
</Table>,
],
},
};

/**
* > Example using a table with a body and a panel footer
*/
export const PanelWithTableAndBody: Story = {
args: {
children: [
<Panel.Body>
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.Body>,
<Table>
<Table.Caption>
Caption this table width is: <em>(100%)</em>
</Table.Caption>
<Table.Header>
<Table.HeaderRow>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>Type</Table.HeaderCell>
<Table.HeaderCell>Date Modified</Table.HeaderCell>
</Table.HeaderRow>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>Games</Table.Cell>
<Table.Cell>File folder</Table.Cell>
<Table.Cell>6/7/2020</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>Program Files</Table.Cell>
<Table.Cell>File folder</Table.Cell>
<Table.Cell>4/7/2021</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>bootmgr</Table.Cell>
<Table.Cell>System file</Table.Cell>
<Table.Cell>11/20/2010</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>log.txt</Table.Cell>
<Table.Cell>Text Document</Table.Cell>
<Table.Cell>1/18/2016</Table.Cell>
</Table.Row>
</Table.Body>
<Table.Footer colspan={3}>Footer goes here and should colSpan all columns</Table.Footer>
</Table>,
<Panel.Footer>Panel footer</Panel.Footer>,
],
},
};
22 changes: 22 additions & 0 deletions packages/ui/src/components/panel/panel.styles.ts
Original file line number Diff line number Diff line change
@@ -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'] },
);
16 changes: 16 additions & 0 deletions packages/ui/src/components/panel/panel.types.ts
Original file line number Diff line number Diff line change
@@ -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<Element>;
Original file line number Diff line number Diff line change
Expand Up @@ -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'] },
Expand Down

0 comments on commit 8c6ac65

Please sign in to comment.