From b82ea4c4a51c197ab4081e7bc404aacbd79fefd1 Mon Sep 17 00:00:00 2001 From: "@casey_baggz_omni" Date: Tue, 27 Aug 2024 13:15:09 -0500 Subject: [PATCH 1/4] feat: add table recipes & components --- docs/app/data/categories.json | 2 +- docs/app/react/side-nav.json | 6 ++ docs/app/react/table/a11y.mdx | 20 +++++ .../react/table/components/table-preview.tsx | 78 ++++++++++++++++ .../table/components/tooltip-preview.tsx | 34 +++++++ docs/app/react/table/dev.mdx | 90 +++++++++++++++++++ docs/app/react/table/guidelines.mdx | 25 ++++++ docs/app/react/table/overview.mdx | 26 ++++++ docs/app/react/table/page.tsx | 54 +++++++++++ docs/mdx-components.tsx | 12 --- packages/panda-preset/src/recipes/index.ts | 10 +++ .../panda-preset/src/recipes/slots/table.ts | 35 ++++++++ packages/panda-preset/src/recipes/tbody.ts | 40 +++++++++ packages/panda-preset/src/recipes/td.ts | 49 ++++++++++ packages/panda-preset/src/recipes/th.ts | 56 ++++++++++++ packages/panda-preset/src/recipes/thead.ts | 29 ++++++ .../react/src/components/FileUploader.tsx | 6 +- .../react/src/components/Notification.tsx | 6 +- .../components/NotificationDescription.tsx | 4 +- .../src/components/NotificationHeading.tsx | 4 +- packages/react/src/components/Table.tsx | 58 ++++++++++++ packages/react/src/components/Tbody.tsx | 31 +++++++ packages/react/src/components/Td.tsx | 22 +++++ packages/react/src/components/Th.tsx | 22 +++++ packages/react/src/components/Thead.tsx | 24 +++++ .../react/src/context/notification-center.tsx | 6 +- packages/react/src/index.ts | 5 ++ .../panda-preset/recipes/slots/table.test.ts | 35 ++++++++ tests/panda-preset/recipes/tbody.test.ts | 37 ++++++++ tests/panda-preset/recipes/td.test.ts | 45 ++++++++++ tests/panda-preset/recipes/th.test.ts | 52 +++++++++++ tests/panda-preset/recipes/thead.test.ts | 18 ++++ tests/react/components/table.test.tsx | 55 ++++++++++++ .../context/notification-center.test.tsx | 10 +++ 34 files changed, 980 insertions(+), 26 deletions(-) create mode 100644 docs/app/react/table/a11y.mdx create mode 100644 docs/app/react/table/components/table-preview.tsx create mode 100644 docs/app/react/table/components/tooltip-preview.tsx create mode 100644 docs/app/react/table/dev.mdx create mode 100644 docs/app/react/table/guidelines.mdx create mode 100644 docs/app/react/table/overview.mdx create mode 100644 docs/app/react/table/page.tsx create mode 100644 packages/panda-preset/src/recipes/slots/table.ts create mode 100644 packages/panda-preset/src/recipes/tbody.ts create mode 100644 packages/panda-preset/src/recipes/td.ts create mode 100644 packages/panda-preset/src/recipes/th.ts create mode 100644 packages/panda-preset/src/recipes/thead.ts create mode 100644 packages/react/src/components/Table.tsx create mode 100644 packages/react/src/components/Tbody.tsx create mode 100644 packages/react/src/components/Td.tsx create mode 100644 packages/react/src/components/Th.tsx create mode 100644 packages/react/src/components/Thead.tsx create mode 100644 tests/panda-preset/recipes/slots/table.test.ts create mode 100644 tests/panda-preset/recipes/tbody.test.ts create mode 100644 tests/panda-preset/recipes/td.test.ts create mode 100644 tests/panda-preset/recipes/th.test.ts create mode 100644 tests/panda-preset/recipes/thead.test.ts create mode 100644 tests/react/components/table.test.tsx diff --git a/docs/app/data/categories.json b/docs/app/data/categories.json index 1ccf130b..5eb55a05 100644 --- a/docs/app/data/categories.json +++ b/docs/app/data/categories.json @@ -12,7 +12,7 @@ "containment": { "name": "Containment", "description": "Components that contain other components.", - "items": ["Confirm Modal", "Prompt Modal", "Modal"] + "items": ["Confirm Modal", "Prompt Modal", "Modal", "Table"] }, "navigation": { "name": "Navigation", diff --git a/docs/app/react/side-nav.json b/docs/app/react/side-nav.json index 82b2e378..43987698 100644 --- a/docs/app/react/side-nav.json +++ b/docs/app/react/side-nav.json @@ -69,6 +69,12 @@ "tag": "", "type": "route" }, + { + "label": "Table", + "route": "/react/table", + "tag": "next", + "type": "route" + }, { "label": "Navigation", "type": "heading" diff --git a/docs/app/react/table/a11y.mdx b/docs/app/react/table/a11y.mdx new file mode 100644 index 00000000..8ca2f8ad --- /dev/null +++ b/docs/app/react/table/a11y.mdx @@ -0,0 +1,20 @@ +--- +--- + +import { + WhenToUseAdmonition +} from '@/app/components/Admonition' +import OverviewList from '@/app/components/OverviewList' + +## Use Cases + + + +## Keyboard Navigation + +| Keys | Actions | +| -------- | --------------------------------------------------------------- | +| Tab | Navigate to actions within the table cells. | diff --git a/docs/app/react/table/components/table-preview.tsx b/docs/app/react/table/components/table-preview.tsx new file mode 100644 index 00000000..40376c65 --- /dev/null +++ b/docs/app/react/table/components/table-preview.tsx @@ -0,0 +1,78 @@ +'use client' + +import { + Table, + Tbody, + Th, + Thead, + Tr, + Td, + Toggle, + Field, + useToggle, +} from '@cerberus-design/react' + +export function BasicTablePreview() { + const first = useToggle() + const second = useToggle() + const third = useToggle() + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + +
AnimalWildAdopt
DogFalse + + + +
CatMaybe + + + +
FishTrue + + + +
+ ) +} diff --git a/docs/app/react/table/components/tooltip-preview.tsx b/docs/app/react/table/components/tooltip-preview.tsx new file mode 100644 index 00000000..fba4baa2 --- /dev/null +++ b/docs/app/react/table/components/tooltip-preview.tsx @@ -0,0 +1,34 @@ +import { Information } from '@cerberus-design/icons' +import { IconButton } from '@cerberus-design/react' +import { hstack } from '@cerberus/styled-system/patterns' + +export function BasicTooltipPreview() { + return ( + + + + ) +} + +export function PositioningTooltipPreview() { + return ( +
+ + + + + + + + + + + + +
+ ) +} diff --git a/docs/app/react/table/dev.mdx b/docs/app/react/table/dev.mdx new file mode 100644 index 00000000..5c484f96 --- /dev/null +++ b/docs/app/react/table/dev.mdx @@ -0,0 +1,90 @@ +--- +npm: '@cerberus-design/react' +source: 'components/Table.tsx' +recipe: 'table.ts' +--- + +import CodePreview from '@/app/components/CodePreview' +import { + NoteAdmonition +} from '@/app/components/Admonition' +import { + BasicTablePreview +} from '@/app/react/table/components/table-preview' + +```tsx +import { Table } from '@cerberus-design/react' +``` + +## Usage + +}> +```tsx title="table.tsx" {6} +import { Table } from '@cerberus-design/react' + +function BasicTablePreview() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Basic Table +
Header 1Header 2Header 3
Row 1, Cell 1Row 1, Cell 2Row 1, Cell 3
Row 2, Cell 1Row 2, Cell 2Row 2, Cell 3
Row 3, Cell 1Row 3, Cell 2Row 3, Cell 3
+ ) +} +``` +
+ +## Sizes + +}> +```tsx title="table.tsx" {10,13,16,19,23} +import { Table } from '@cerberus-design/react' +``` + + +## Customization + +You can customize the table by utilizing the `cx` function. + +}> +```tsx title="table.tsx" {10,13,16,19,23} +import { Table } from '@cerberus-design/react' +``` + + +## API + +All of the following props are required to display a table. + +| Name | Default | Description | +| -------- | ------- | ------------------------------------------------------------- | +| aria-label | `undefined` | The content of the tooltip and accessible label. | +| data-tooltip | `undefined` | The attribute that triggers a tooltip. | diff --git a/docs/app/react/table/guidelines.mdx b/docs/app/react/table/guidelines.mdx new file mode 100644 index 00000000..b935587a --- /dev/null +++ b/docs/app/react/table/guidelines.mdx @@ -0,0 +1,25 @@ +--- +--- + +import CodePreview from '@/app/components/CodePreview' +import OverviewList from '@/app/components/OverviewList' +import { + WhenToUseAdmonition, + WhenNotToUseAdmonition, +} from '@/app/components/Admonition' +import { + BasicTablePreview +} from '@/app/react/table/components/table-preview' + +## Usage + +A table provides a way to organize data in a grid format. Tables are used to display data-centric information and can contain actions, such as buttons or links. + + + + + + +## Standard Table + +} /> diff --git a/docs/app/react/table/overview.mdx b/docs/app/react/table/overview.mdx new file mode 100644 index 00000000..1dab5738 --- /dev/null +++ b/docs/app/react/table/overview.mdx @@ -0,0 +1,26 @@ +--- +heading: 'Table' +description: 'Tables display data-centric information.' +a11y: 'forms' +--- + +import CodePreview from '@/app/components/CodePreview' +import OverviewList from '@/app/components/OverviewList' +import { + BasicTablePreview +} from '@/app/react/table/components/table-preview' + + + +## Example + +} /> + +## Resources + +| Name | Resource | Status | +| -------- | -------- | ---------------------------------------------------- | +| Figma | [Design Kit (Figma)](https://www.figma.com/design/ducwqOCxoxcWc3ReV3FYd8/Digital-University-Component-Library?m=auto&node-id=0-1) | Private | \ No newline at end of file diff --git a/docs/app/react/table/page.tsx b/docs/app/react/table/page.tsx new file mode 100644 index 00000000..d3ca2831 --- /dev/null +++ b/docs/app/react/table/page.tsx @@ -0,0 +1,54 @@ +import ApiLinks from '@/app/components/ApiLinks' +import { + TabPageContent, + TabPageContentLayout, +} from '../../components/PageLayout' +import FeatureHeader from '@/app/components/FeatureHeader' +import type { MatchFeatureKind } from '@/app/components/MatchFeatureImg' +import PageTabs from '@/app/components/PageTabs' + +import Overview, { frontmatter } from './overview.mdx' +import Guidelines from './guidelines.mdx' +import Dev, { frontmatter as devFrontmatter } from './dev.mdx' +import A11y from './a11y.mdx' + +export default function TablePage() { + return ( + <> + + + + + + + } + guidelines={ + + + + } + dev={ + +
+ + +
+
+ } + a11y={ + + + + } + /> +
+ + ) +} diff --git a/docs/mdx-components.tsx b/docs/mdx-components.tsx index efa9b699..ce5152e9 100644 --- a/docs/mdx-components.tsx +++ b/docs/mdx-components.tsx @@ -154,18 +154,6 @@ export function useMDXComponents(components: MDXComponents): MDXComponents { {...props} /> ), - tr: (props) => ( - - ), th: (props) => ( = defineSlotRecipe({ + className: 'table', + description: 'The styles for Table components', + slots: ['container', 'table', 'caption'], + + base: { + container: { + border: '1px solid', + borderColor: 'page.border.200', + rounded: 'md', + overflow: 'hidden', + }, + table: { + borderCollapse: 'collapse', + borderSpacing: '0', + width: 'full', + }, + caption: { + h: '0', + lineHeight: '0', + opacity: '0', + }, + }, +}) diff --git a/packages/panda-preset/src/recipes/tbody.ts b/packages/panda-preset/src/recipes/tbody.ts new file mode 100644 index 00000000..559c5786 --- /dev/null +++ b/packages/panda-preset/src/recipes/tbody.ts @@ -0,0 +1,40 @@ +import { + defineRecipe, + type RecipeConfig, + type RecipeVariantRecord, +} from '@pandacss/dev' + +/** + * This module contains the tbody recipe. + * @module + */ + +/** + * Styles for the tbody component + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + */ +export const tbody: RecipeConfig = defineRecipe({ + className: 'tbody', + description: 'Styles for the Tbody component.', + + base: { + bgColor: 'page.surface.100', + }, + + variants: { + decoration: { + zebra: { + '& tr': { + _even: { + bgColor: 'page.surface.initial', + }, + }, + }, + default: {}, + }, + }, + + defaultVariants: { + decoration: 'default', + }, +}) diff --git a/packages/panda-preset/src/recipes/td.ts b/packages/panda-preset/src/recipes/td.ts new file mode 100644 index 00000000..9657f06e --- /dev/null +++ b/packages/panda-preset/src/recipes/td.ts @@ -0,0 +1,49 @@ +import { + defineRecipe, + type RecipeConfig, + type RecipeVariantRecord, +} from '@pandacss/dev' + +/** + * This module contains the td recipe. + * @module + */ + +/** + * Styles for the td component + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + */ +export const td: RecipeConfig = defineRecipe({ + className: 'td', + description: 'Styles for the Td component.', + + base: { + borderTop: '1px solid', + borderColor: 'page.border.200', + textStyle: 'label-md', + _last: { + borderRight: 'none', + }, + }, + + variants: { + size: { + sm: { + h: '2rem', + pxi: '3', + }, + md: { + h: '3rem', + pxi: '3', + }, + lg: { + h: '3.5rem', + pxi: '4', + }, + }, + }, + + defaultVariants: { + size: 'md', + }, +}) diff --git a/packages/panda-preset/src/recipes/th.ts b/packages/panda-preset/src/recipes/th.ts new file mode 100644 index 00000000..edf06bbb --- /dev/null +++ b/packages/panda-preset/src/recipes/th.ts @@ -0,0 +1,56 @@ +import { + defineRecipe, + type RecipeConfig, + type RecipeVariantRecord, +} from '@pandacss/dev' + +/** + * This module contains the th recipe. + * @module + */ + +/** + * Styles for the th component + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + */ +export const th: RecipeConfig = defineRecipe({ + className: 'th', + description: 'Styles for the Th component.', + + base: { + borderColor: 'page.border.200', + bgColor: 'page.bg.initial', + fontWeight: '600', + textAlign: 'left', + textStyle: 'label-md', + transitionProperty: 'background-color', + transitionDuration: '150ms', + verticalAlign: 'middle', + _last: { + borderRight: 'none', + }, + _hover: { + bgColor: 'page.bg.100', + }, + _active: { + bgColor: 'action.ghost.active', + }, + }, + + variants: { + size: { + md: { + h: '3rem', + pxi: '3', + }, + lg: { + h: '3.5rem', + pxi: '4', + }, + }, + }, + + defaultVariants: { + size: 'md', + }, +}) diff --git a/packages/panda-preset/src/recipes/thead.ts b/packages/panda-preset/src/recipes/thead.ts new file mode 100644 index 00000000..f96cafc7 --- /dev/null +++ b/packages/panda-preset/src/recipes/thead.ts @@ -0,0 +1,29 @@ +import { + defineRecipe, + type RecipeConfig, + type RecipeVariantRecord, +} from '@pandacss/dev' + +/** + * This module contains the thead recipe. + * @module + */ + +/** + * Styles for the Thead component + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + */ +export const thead: RecipeConfig = defineRecipe({ + className: 'thead', + description: 'Styles for the Thead component.', + + base: { + _first: { + borderTop: 'none', + }, + }, + + variants: {}, + + defaultVariants: {}, +}) diff --git a/packages/react/src/components/FileUploader.tsx b/packages/react/src/components/FileUploader.tsx index 01b2e3ac..e8782e7d 100644 --- a/packages/react/src/components/FileUploader.tsx +++ b/packages/react/src/components/FileUploader.tsx @@ -1,10 +1,10 @@ 'use client' -import { cx } from '@cerberus-design/styled-system/css' -import { circle, vstack } from '@cerberus-design/styled-system/patterns' +import { cx } from '@cerberus/styled-system/css' +import { circle, vstack } from '@cerberus/styled-system/patterns' import { type InputHTMLAttributes } from 'react' import { Show } from './Show' -import { fileUploader, modalIcon } from '@cerberus-design/styled-system/recipes' +import { fileUploader, modalIcon } from '@cerberus/styled-system/recipes' import { $cerberusIcons } from '../config/defineIcons' export interface FileUploaderProps diff --git a/packages/react/src/components/Notification.tsx b/packages/react/src/components/Notification.tsx index f871e0f2..a95c9737 100644 --- a/packages/react/src/components/Notification.tsx +++ b/packages/react/src/components/Notification.tsx @@ -1,11 +1,11 @@ 'use client' -import { cx } from '@cerberus-design/styled-system/css' -import { hstack, vstack } from '@cerberus-design/styled-system/patterns' +import { cx } from '@cerberus/styled-system/css' +import { hstack, vstack } from '@cerberus/styled-system/patterns' import { notification, type NotificationVariantProps, -} from '@cerberus-design/styled-system/recipes' +} from '@cerberus/styled-system/recipes' import { useRef, type DialogHTMLAttributes, diff --git a/packages/react/src/components/NotificationDescription.tsx b/packages/react/src/components/NotificationDescription.tsx index 389404c0..09a21d0a 100644 --- a/packages/react/src/components/NotificationDescription.tsx +++ b/packages/react/src/components/NotificationDescription.tsx @@ -3,11 +3,11 @@ * @module */ -import { cx } from '@cerberus-design/styled-system/css' +import { cx } from '@cerberus/styled-system/css' import { notification, type NotificationVariantProps, -} from '@cerberus-design/styled-system/recipes' +} from '@cerberus/styled-system/recipes' import type { HTMLAttributes } from 'react' export interface BaseNotificationDescriptionProps diff --git a/packages/react/src/components/NotificationHeading.tsx b/packages/react/src/components/NotificationHeading.tsx index 38aa22bc..7d479d89 100644 --- a/packages/react/src/components/NotificationHeading.tsx +++ b/packages/react/src/components/NotificationHeading.tsx @@ -3,11 +3,11 @@ * @module */ -import { cx } from '@cerberus-design/styled-system/css' +import { cx } from '@cerberus/styled-system/css' import { notification, type NotificationVariantProps, -} from '@cerberus-design/styled-system/recipes' +} from '@cerberus/styled-system/recipes' import type { HTMLAttributes } from 'react' export interface BaseNotificationHeadingProps diff --git a/packages/react/src/components/Table.tsx b/packages/react/src/components/Table.tsx new file mode 100644 index 00000000..32a7fea6 --- /dev/null +++ b/packages/react/src/components/Table.tsx @@ -0,0 +1,58 @@ +import { cx } from '@cerberus/styled-system/css' +import { table } from '@cerberus/styled-system/recipes' +import type { PropsWithChildren, TableHTMLAttributes } from 'react' + +/** + * This module contains the table component. + * @module + */ + +export interface TableProps extends TableHTMLAttributes { + caption: string +} + +/** + * The Table component is used to render a table. + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + * @prop caption - An easy to understand description of the table. + * @example + * ```tsx + * + * {children} + *
+ * ``` + */ +export function Table(props: PropsWithChildren) { + const { caption, children, ...nativeProps } = props + const styles = table() + + return ( +
+ + + {children} +
{caption}
+
+ ) +} + +// We only provide this for consistency with the rest of the components + +export type TrProps = TableHTMLAttributes + +/** + * The Tr component is used to render a table row. + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + * @example + * ```tsx + * + * {children} + * + * ``` + */ +export function Tr(props: PropsWithChildren) { + return +} diff --git a/packages/react/src/components/Tbody.tsx b/packages/react/src/components/Tbody.tsx new file mode 100644 index 00000000..77d8528d --- /dev/null +++ b/packages/react/src/components/Tbody.tsx @@ -0,0 +1,31 @@ +import { tbody, type TbodyVariantProps } from '@cerberus/styled-system/recipes' +import { cx } from '@cerberus/styled-system/css' +import type { PropsWithChildren, TableHTMLAttributes } from 'react' + +export type TbodyBaseProps = TableHTMLAttributes +export type TbodyProps = TbodyBaseProps & TbodyVariantProps + +/** + * The TBody component is used to render a table body. + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + * @example + * ```tsx + * + * {children} + * + * ``` + */ +export function Tbody(props: PropsWithChildren) { + const { decoration, ...nativeProps } = props + return ( + + ) +} diff --git a/packages/react/src/components/Td.tsx b/packages/react/src/components/Td.tsx new file mode 100644 index 00000000..ae5d8865 --- /dev/null +++ b/packages/react/src/components/Td.tsx @@ -0,0 +1,22 @@ +import { cx } from '@cerberus/styled-system/css' +import { td } from '@cerberus/styled-system/recipes' +import type { TableHTMLAttributes } from 'react' + +/** + * Th component for the Td component + * @module + */ + +export type TdProps = TableHTMLAttributes + +/** + * Styles for the Th component + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + * @example + * ```tsx + * Data cell + * ``` + */ +export function Td(props: TdProps) { + return +} diff --git a/packages/react/src/components/Th.tsx b/packages/react/src/components/Th.tsx new file mode 100644 index 00000000..22122de6 --- /dev/null +++ b/packages/react/src/components/Th.tsx @@ -0,0 +1,22 @@ +import { cx } from '@cerberus/styled-system/css' +import { th } from '@cerberus/styled-system/recipes' +import type { TableHTMLAttributes } from 'react' + +/** + * Th component for the Table component + * @module + */ + +export type ThProps = TableHTMLAttributes + +/** + * Styles for the Th component + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + * @example + * ```tsx + * Header 1 + * ``` + */ +export function Th(props: ThProps) { + return +} diff --git a/packages/react/src/components/Thead.tsx b/packages/react/src/components/Thead.tsx new file mode 100644 index 00000000..1c560920 --- /dev/null +++ b/packages/react/src/components/Thead.tsx @@ -0,0 +1,24 @@ +import { cx } from '@cerberus/styled-system/css' +import { thead } from '@cerberus/styled-system/recipes' +import type { TableHTMLAttributes } from 'react' + +/** + * This module contains the Thead component. + * @module + */ + +export type TheadProps = TableHTMLAttributes + +/** + * The Thead component is used to render a table header. + * @definition [Table docs](https://cerberus.digitalu.design/react/table) + * @example + * ```tsx + * + * {children} + * + * ``` + */ +export function Thead(props: TheadProps) { + return +} diff --git a/packages/react/src/context/notification-center.tsx b/packages/react/src/context/notification-center.tsx index 333a81ad..a2979125 100644 --- a/packages/react/src/context/notification-center.tsx +++ b/packages/react/src/context/notification-center.tsx @@ -14,11 +14,11 @@ import { Show } from '../components/Show' import { NotificationHeading } from '../components/NotificationHeading' import { NotificationDescription } from '../components/NotificationDescription' import { Notification } from '../components/Notification' -import { animateIn, vstack } from '@cerberus-design/styled-system/patterns' +import { animateIn, vstack } from '@cerberus/styled-system/patterns' import { Portal, type PortalProps } from '../components/Portal' -import { notification } from '@cerberus-design/styled-system/recipes' +import { notification } from '@cerberus/styled-system/recipes' import { Button } from '../components/Button' -import { cx } from '@cerberus-design/styled-system/css' +import { cx } from '@cerberus/styled-system/css' /** * This module provides a context and hook for notifications. diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 5dfd98cb..713abc43 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -29,6 +29,11 @@ export * from './components/Radio' export * from './components/Tab' export * from './components/TabList' export * from './components/TabPanel' +export * from './components/Table' +export * from './components/Thead' +export * from './components/Th' +export * from './components/Td' +export * from './components/Tbody' export * from './components/Tag' export * from './components/Textarea' export * from './components/Toggle' diff --git a/tests/panda-preset/recipes/slots/table.test.ts b/tests/panda-preset/recipes/slots/table.test.ts new file mode 100644 index 00000000..fd193ec9 --- /dev/null +++ b/tests/panda-preset/recipes/slots/table.test.ts @@ -0,0 +1,35 @@ +import { describe, test, expect } from 'bun:test' +import { slotRecipes } from '@cerberus-design/panda-preset' + +describe('table recipe', () => { + const { table } = slotRecipes + + test('should be exported', () => { + expect(table).toBeDefined() + }) + + test('should have a base style', () => { + expect(table.base?.container).toMatchObject({ + border: '1px solid', + borderColor: 'page.border.200', + rounded: 'md', + overflow: 'hidden', + }) + }) + + test('should have a table style', () => { + expect(table.base?.table).toMatchObject({ + borderCollapse: 'collapse', + borderSpacing: '0', + width: 'full', + }) + }) + + test('should have a caption style', () => { + expect(table.base?.caption).toMatchObject({ + h: '0', + lineHeight: '0', + opacity: '0', + }) + }) +}) diff --git a/tests/panda-preset/recipes/tbody.test.ts b/tests/panda-preset/recipes/tbody.test.ts new file mode 100644 index 00000000..e9dbe677 --- /dev/null +++ b/tests/panda-preset/recipes/tbody.test.ts @@ -0,0 +1,37 @@ +import { describe, test, expect } from 'bun:test' +import { recipes } from '@cerberus-design/panda-preset' + +describe('tbody recipe', () => { + const { tbody } = recipes + + test('should be exported', () => { + expect(tbody).toBeDefined() + }) + + test('should have a base style', () => { + expect(tbody.base).toMatchObject({ + bgColor: 'page.surface.100', + }) + }) + + test('should have a decoration variant', () => { + expect(tbody.variants).toMatchObject({ + decoration: { + zebra: { + '& tr': { + _even: { + bgColor: 'page.surface.initial', + }, + }, + }, + default: {}, + }, + }) + }) + + test('should have a default decoration variant', () => { + expect(tbody.defaultVariants).toMatchObject({ + decoration: 'default', + }) + }) +}) diff --git a/tests/panda-preset/recipes/td.test.ts b/tests/panda-preset/recipes/td.test.ts new file mode 100644 index 00000000..b2633313 --- /dev/null +++ b/tests/panda-preset/recipes/td.test.ts @@ -0,0 +1,45 @@ +import { describe, test, expect } from 'bun:test' +import { recipes } from '@cerberus-design/panda-preset' + +describe('td recipe', () => { + const { td } = recipes + + test('should be exported', () => { + expect(td).toBeDefined() + }) + + test('should have a base style', () => { + expect(td.base).toMatchObject({ + borderTop: '1px solid', + borderColor: 'page.border.200', + textStyle: 'label-md', + _last: { + borderRight: 'none', + }, + }) + }) + + test('should have size variants', () => { + const { size } = td.variants as { size: Record } + expect(size).toMatchObject({ + sm: { + h: '2rem', + pxi: '3', + }, + md: { + h: '3rem', + pxi: '3', + }, + lg: { + h: '3.5rem', + pxi: '4', + }, + }) + }) + + test('should have a default size variant', () => { + expect(td.defaultVariants).toMatchObject({ + size: 'md', + }) + }) +}) diff --git a/tests/panda-preset/recipes/th.test.ts b/tests/panda-preset/recipes/th.test.ts new file mode 100644 index 00000000..4ce8d6e9 --- /dev/null +++ b/tests/panda-preset/recipes/th.test.ts @@ -0,0 +1,52 @@ +import { describe, test, expect } from 'bun:test' +import { recipes } from '@cerberus-design/panda-preset' + +describe('th recipe', () => { + const { th } = recipes + + test('should be exported', () => { + expect(th).toBeDefined() + }) + + test('should have a base style', () => { + expect(th.base).toMatchObject({ + borderColor: 'page.border.200', + bgColor: 'page.bg.initial', + fontWeight: '600', + textAlign: 'left', + textStyle: 'label-md', + transitionProperty: 'background-color', + transitionDuration: '150ms', + verticalAlign: 'middle', + _last: { + borderRight: 'none', + }, + _hover: { + bgColor: 'page.bg.100', + }, + _active: { + bgColor: 'action.ghost.active', + }, + }) + }) + + test('should have size variants', () => { + const { size } = th.variants as { size: Record } + expect(size).toMatchObject({ + md: { + h: '3rem', + pxi: '3', + }, + lg: { + h: '3.5rem', + pxi: '4', + }, + }) + }) + + test('should have a default size variant', () => { + expect(th.defaultVariants).toMatchObject({ + size: 'md', + }) + }) +}) diff --git a/tests/panda-preset/recipes/thead.test.ts b/tests/panda-preset/recipes/thead.test.ts new file mode 100644 index 00000000..549b773e --- /dev/null +++ b/tests/panda-preset/recipes/thead.test.ts @@ -0,0 +1,18 @@ +import { describe, test, expect } from 'bun:test' +import { recipes } from '@cerberus-design/panda-preset' + +describe('thead recipe', () => { + const { thead } = recipes + + test('should be exported', () => { + expect(thead).toBeDefined() + }) + + test('should have a base style', () => { + expect(thead.base).toMatchObject({ + _first: { + borderTop: 'none', + }, + }) + }) +}) diff --git a/tests/react/components/table.test.tsx b/tests/react/components/table.test.tsx new file mode 100644 index 00000000..4d2db7e8 --- /dev/null +++ b/tests/react/components/table.test.tsx @@ -0,0 +1,55 @@ +import { describe, test, expect, afterEach } from 'bun:test' +import { cleanup, render, screen } from '@testing-library/react' +import { Table, Tbody, Td, Th, Thead, Tr } from '@cerberus-design/react' +import { setupStrictMode } from '@/utils' + +describe('Table', () => { + setupStrictMode() + afterEach(cleanup) + + test('should render a table element', () => { + render( + + + + + + + + + + + + + + + + + + + + + + + + + +
Header 1Header 2Header 3
Row 1, Cell 1Row 1, Cell 2Row 1, Cell 3
Row 2, Cell 1Row 2, Cell 2Row 2, Cell 3
Row 3, Cell 1Row 3, Cell 2Row 3, Cell 3
, + ) + + expect(screen.getByRole('table')).toBeTruthy() + expect(screen.getByRole('caption')).toBeTruthy() + expect(screen.getByText(/Header 1/i)).toBeTruthy() + expect(screen.getByText(/Header 2/i)).toBeTruthy() + expect(screen.getByText(/Header 3/i)).toBeTruthy() + expect(screen.getByText(/Row 1, Cell 1/i)).toBeTruthy() + expect(screen.getByText(/Row 1, Cell 2/i)).toBeTruthy() + expect(screen.getByText(/Row 1, Cell 3/i)).toBeTruthy() + expect(screen.getByText(/Row 2, Cell 1/i)).toBeTruthy() + expect(screen.getByText(/Row 2, Cell 2/i)).toBeTruthy() + expect(screen.getByText(/Row 2, Cell 3/i)).toBeTruthy() + expect(screen.getByText(/Row 3, Cell 1/i)).toBeTruthy() + expect(screen.getByText(/Row 3, Cell 2/i)).toBeTruthy() + expect(screen.getByText(/Row 3, Cell 3/i)).toBeTruthy() + }) +}) diff --git a/tests/react/context/notification-center.test.tsx b/tests/react/context/notification-center.test.tsx index 175bac5b..1f789c36 100644 --- a/tests/react/context/notification-center.test.tsx +++ b/tests/react/context/notification-center.test.tsx @@ -53,6 +53,16 @@ describe('NotificationCenter & useNotificationCenter', () => { expect(screen.queryByText(/new feature!/i)).toBeNull() }) + test('should close all notifications', async () => { + render() + await userEvent.click(screen.getByText(/notify/i)) + await userEvent.click(screen.getByText(/notify/i)) + await userEvent.click(screen.getByText(/notify/i)) + await userEvent.click(screen.getByText(/notify/i)) + await userEvent.click(screen.getByRole('button', { name: /close all/i })) + expect(screen.queryByText(/new feature!/i)).toBeNull() + }) + test('should throw an error if used outside of FeatureFlags', () => { // don't clog up the console with errors spyOn(console, 'error').mockImplementation(() => null) From 324f323c8584427dd2776cd63c4d58b40890df39 Mon Sep 17 00:00:00 2001 From: "@casey_baggz_omni" Date: Tue, 27 Aug 2024 13:17:21 -0500 Subject: [PATCH 2/4] chore: kill unused preview file in table --- .../table/components/tooltip-preview.tsx | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 docs/app/react/table/components/tooltip-preview.tsx diff --git a/docs/app/react/table/components/tooltip-preview.tsx b/docs/app/react/table/components/tooltip-preview.tsx deleted file mode 100644 index fba4baa2..00000000 --- a/docs/app/react/table/components/tooltip-preview.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Information } from '@cerberus-design/icons' -import { IconButton } from '@cerberus-design/react' -import { hstack } from '@cerberus/styled-system/patterns' - -export function BasicTooltipPreview() { - return ( - - - - ) -} - -export function PositioningTooltipPreview() { - return ( -
- - - - - - - - - - - - -
- ) -} From de3a52e7cc5c353236e6cd24a7449ccb86aa18b6 Mon Sep 17 00:00:00 2001 From: "@casey_baggz_omni" Date: Tue, 27 Aug 2024 15:21:06 -0500 Subject: [PATCH 3/4] docs: update table examples --- .../react/table/components/table-preview.tsx | 167 +++++++++ docs/app/react/table/dev.mdx | 333 +++++++++++++++--- docs/app/react/table/overview.mdx | 15 +- packages/react/src/components/Tbody.tsx | 4 +- packages/react/src/components/Td.tsx | 18 +- packages/react/src/components/Th.tsx | 10 +- 6 files changed, 489 insertions(+), 58 deletions(-) diff --git a/docs/app/react/table/components/table-preview.tsx b/docs/app/react/table/components/table-preview.tsx index 40376c65..48e33939 100644 --- a/docs/app/react/table/components/table-preview.tsx +++ b/docs/app/react/table/components/table-preview.tsx @@ -11,6 +11,94 @@ import { Field, useToggle, } from '@cerberus-design/react' +import { css } from '@cerberus/styled-system/css' +import { hstack } from '@cerberus/styled-system/patterns' + +export function SizesPreview() { + return ( +
+ + + + + + + + + + + +
Medium
Small
+ + + + + + + + + + + +
Medium
Medium
+ + + + + + + + + + + +
Large
Large
+
+ ) +} + +export function DecorationPreview() { + return ( +
+ + + + + + + + + + + + + + + + + +
Default
one
two
three
+ + + + + + + + + + + + + + + + + +
Zebra
one
two
three
+
+ ) +} export function BasicTablePreview() { const first = useToggle() @@ -76,3 +164,82 @@ export function BasicTablePreview() { ) } + +export function CustomizedPreview() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Wu-Tang Members + + Alias +
Method ManJohnny Blaze
RaekwonThe Chef
GZAThe Genius
Ghostface KillahTony Starks
Inspectah DeckRebel INS
U-GodGolden Arms
Masta KillaNoodles
Ol' Dirty BastardAson Unique
RZABobby Digital
+ ) +} diff --git a/docs/app/react/table/dev.mdx b/docs/app/react/table/dev.mdx index 5c484f96..10ef7e0b 100644 --- a/docs/app/react/table/dev.mdx +++ b/docs/app/react/table/dev.mdx @@ -9,54 +9,103 @@ import { NoteAdmonition } from '@/app/components/Admonition' import { - BasicTablePreview + BasicTablePreview, + SizesPreview, + DecorationPreview, + CustomizedPreview } from '@/app/react/table/components/table-preview' ```tsx -import { Table } from '@cerberus-design/react' +import { + Table, + Tbody, + Th, + Thead, + Tr, + Td +} from '@cerberus-design/react' ``` ## Usage }> -```tsx title="table.tsx" {6} -import { Table } from '@cerberus-design/react' +```tsx title="table.tsx" +'use client' + +import { + Table, + Tbody, + Th, + Thead, + Tr, + Td, + Toggle, + Field, + useToggle, +} from '@cerberus-design/react' function BasicTablePreview() { + const first = useToggle() + const second = useToggle() + const third = useToggle() + return ( - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Basic Table -
Header 1Header 2Header 3
Row 1, Cell 1Row 1, Cell 2Row 1, Cell 3
Row 2, Cell 1Row 2, Cell 2Row 2, Cell 3
Row 3, Cell 1Row 3, Cell 2Row 3, Cell 3
+ + + + + + + + + + + + + + + + + + + + + + + + + +
AnimalWildAdopt
DogFalse + + + +
CatMaybe + + + +
FishTrue + + + +
) } ``` @@ -64,27 +113,213 @@ function BasicTablePreview() { ## Sizes -}> -```tsx title="table.tsx" {10,13,16,19,23} -import { Table } from '@cerberus-design/react' +}> +```tsx title="table.tsx" {17,22,29,34,41,46} +import { + Table, + Tbody, + Th, + Thead, + Tr, + Td, +} from '@cerberus-design/react' +import { hstack } from '@cerberus/styled-system/patterns' + +function SizesPreview() { + return ( +
+ + + + + + + + + + + +
Medium
Small
+ + + + + + + + + + + +
Medium
Medium
+ + + + + + + + + + + +
Large
Large
+
+ ) +} ```
## Customization -You can customize the table by utilizing the `cx` function. +You can customize the table by utilizing the `css` function. For full control, we recommend extending the recipes provided in your panda config. -}> -```tsx title="table.tsx" {10,13,16,19,23} -import { Table } from '@cerberus-design/react' +}> +```tsx title="table.tsx" +import { css } from '@cerberus/styled-system/css' +import { + Table, + Tbody, + Th, + Thead, + Tr, + Td, +} from '@cerberus-design/react' + +function CustomizedPreview() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Wu-Tang Members + + Alias +
Method ManJohnny Blaze
RaekwonThe Chef
GZAThe Genius
Ghostface KillahTony Starks
Inspectah DeckRebel INS
U-GodGolden Arms
Masta KillaNoodles
Ol' Dirty BastardAson Unique
RZABobby Digital
+ ) +} ```
## API -All of the following props are required to display a table. +All Table components extend the native HTML elements. The following APIs are the only exception. + +### Table + +```ts showLineNumbers=false +interface TableProps extends TableHTMLAttributes { + caption: string +} + +define function Table(props: PropsWithChildren): ReactNode +```` + +| Name | Default | Description | +| -------- | ------- | -------------------------------------------- | +| caption | | A description of the table used for accessibility. | + +### Th + +```ts showLineNumbers=false +export type ThBaseProps = TableHTMLAttributes +export type ThProps = ThBaseProps & ThVariantProps + +define function Th(props: ThProps): ReactNode +```` + +| Name | Default | Description | +| -------- | ------- | -------------------------------------------- | +| size | `md` | The cell size of the th. | + +### Tbody + +```ts showLineNumbers=false +export type TbodyBaseProps = TableHTMLAttributes +export type TbodyProps = TbodyBaseProps & TbodyVariantProps + +define function Tbody(props: TbodyProps): ReactNode +```` + +| Name | Default | Description | +| -------- | ------- | -------------------------------------------- | +| decoration | `default` | Which style decoration to display for rows. | + +### Td + +```ts showLineNumbers=false +export type TdBaseProps = TableHTMLAttributes +export type TdProps = TdBaseProps & TdVariantProps + +define function Td(props: TdProps): ReactNode +```` -| Name | Default | Description | -| -------- | ------- | ------------------------------------------------------------- | -| aria-label | `undefined` | The content of the tooltip and accessible label. | -| data-tooltip | `undefined` | The attribute that triggers a tooltip. | +| Name | Default | Description | +| -------- | ------- | -------------------------------------------- | +| size | `md` | The cell size of the td. | \ No newline at end of file diff --git a/docs/app/react/table/overview.mdx b/docs/app/react/table/overview.mdx index 1dab5738..02683a77 100644 --- a/docs/app/react/table/overview.mdx +++ b/docs/app/react/table/overview.mdx @@ -7,18 +7,31 @@ a11y: 'forms' import CodePreview from '@/app/components/CodePreview' import OverviewList from '@/app/components/OverviewList' import { - BasicTablePreview + BasicTablePreview, + SizesPreview, + DecorationPreview } from '@/app/react/table/components/table-preview' ## Example } /> +## Sizes + +} /> + +## Decoration + +} /> + ## Resources | Name | Resource | Status | diff --git a/packages/react/src/components/Tbody.tsx b/packages/react/src/components/Tbody.tsx index 77d8528d..8385e93c 100644 --- a/packages/react/src/components/Tbody.tsx +++ b/packages/react/src/components/Tbody.tsx @@ -1,6 +1,6 @@ import { tbody, type TbodyVariantProps } from '@cerberus/styled-system/recipes' import { cx } from '@cerberus/styled-system/css' -import type { PropsWithChildren, TableHTMLAttributes } from 'react' +import type { TableHTMLAttributes } from 'react' export type TbodyBaseProps = TableHTMLAttributes export type TbodyProps = TbodyBaseProps & TbodyVariantProps @@ -15,7 +15,7 @@ export type TbodyProps = TbodyBaseProps & TbodyVariantProps * * ``` */ -export function Tbody(props: PropsWithChildren) { +export function Tbody(props: TbodyProps) { const { decoration, ...nativeProps } = props return ( +export type TdBaseProps = TableHTMLAttributes +export type TdProps = TdBaseProps & TdVariantProps /** * Styles for the Th component @@ -18,5 +19,16 @@ export type TdProps = TableHTMLAttributes * ``` */ export function Td(props: TdProps) { - return + const { size, ...nativeProps } = props + return ( + + ) } diff --git a/packages/react/src/components/Th.tsx b/packages/react/src/components/Th.tsx index 22122de6..c077ae2b 100644 --- a/packages/react/src/components/Th.tsx +++ b/packages/react/src/components/Th.tsx @@ -1,5 +1,5 @@ import { cx } from '@cerberus/styled-system/css' -import { th } from '@cerberus/styled-system/recipes' +import { th, type ThVariantProps } from '@cerberus/styled-system/recipes' import type { TableHTMLAttributes } from 'react' /** @@ -7,7 +7,8 @@ import type { TableHTMLAttributes } from 'react' * @module */ -export type ThProps = TableHTMLAttributes +export type ThBaseProps = TableHTMLAttributes +export type ThProps = ThBaseProps & ThVariantProps /** * Styles for the Th component @@ -18,5 +19,8 @@ export type ThProps = TableHTMLAttributes * ``` */ export function Th(props: ThProps) { - return + const { size, ...nativeProps } = props + return ( + + ) } From f63b92d442a05a822eab39e5c78479698e46fe42 Mon Sep 17 00:00:00 2001 From: "@casey_baggz_omni" Date: Tue, 27 Aug 2024 15:24:31 -0500 Subject: [PATCH 4/4] chore(docs): fix next lint error --- docs/app/react/table/components/table-preview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/app/react/table/components/table-preview.tsx b/docs/app/react/table/components/table-preview.tsx index 48e33939..d9b7ab66 100644 --- a/docs/app/react/table/components/table-preview.tsx +++ b/docs/app/react/table/components/table-preview.tsx @@ -232,7 +232,7 @@ export function CustomizedPreview() { Noodles - Ol' Dirty Bastard + Ol' Dirty Bastard Ason Unique