Table
A component that displays data in a tabular format.
plain
outline
import { Table } from '~/components/ui/table'
export const Demo = (props: Table.RootProps) => {
return (
<Table.Root {...props}>
<Table.Caption>Product Inventory</Table.Caption>
<Table.Head>
<Table.Row>
<Table.Header>ID</Table.Header>
<Table.Header>Name</Table.Header>
<Table.Header>Stock</Table.Header>
<Table.Header textAlign="right">Price</Table.Header>
</Table.Row>
</Table.Head>
<Table.Body>
{productData.map((product, index) => (
<Table.Row key={index}>
<Table.Cell fontWeight="medium">{product.id}</Table.Cell>
<Table.Cell>{product.name}</Table.Cell>
<Table.Cell>{product.stock}</Table.Cell>
<Table.Cell textAlign="right">{product.price}</Table.Cell>
</Table.Row>
))}
</Table.Body>
<Table.Foot>
<Table.Row>
<Table.Cell colSpan={2}>Totals</Table.Cell>
<Table.Cell>87</Table.Cell>
<Table.Cell textAlign="right">$34,163.00</Table.Cell>
</Table.Row>
</Table.Foot>
</Table.Root>
)
}
const productData = [
{ id: 'P001', name: 'MacBook Pro', stock: 12, price: '$1999.00' },
{ id: 'P002', name: 'AirPods Pro', stock: 25, price: '$249.00' },
{ id: 'P003', name: 'Leather Wallet', stock: 50, price: '$79.00' },
]
import { For } from 'solid-js'
import { Table } from '~/components/ui/table'
export const Demo = (props: Table.RootProps) => {
return (
<Table.Root {...props}>
<Table.Caption>Product Inventory</Table.Caption>
<Table.Head>
<Table.Row>
<Table.Header>ID</Table.Header>
<Table.Header>Name</Table.Header>
<Table.Header>Stock</Table.Header>
<Table.Header textAlign="right">Price</Table.Header>
</Table.Row>
</Table.Head>
<Table.Body>
<For each={productData}>
{(product) => (
<Table.Row>
<Table.Cell fontWeight="medium">{product.id}</Table.Cell>
<Table.Cell>{product.name}</Table.Cell>
<Table.Cell>{product.stock}</Table.Cell>
<Table.Cell textAlign="right">{product.price}</Table.Cell>
</Table.Row>
)}
</For>
</Table.Body>
<Table.Foot>
<Table.Row>
<Table.Cell colSpan={2}>Totals</Table.Cell>
<Table.Cell>87</Table.Cell>
<Table.Cell textAlign="right">$34,163.00</Table.Cell>
</Table.Row>
</Table.Foot>
</Table.Root>
)
}
const productData = [
{ id: 'P001', name: 'MacBook Pro', stock: 12, price: '$1999.00' },
{ id: 'P002', name: 'AirPods Pro', stock: 25, price: '$249.00' },
{ id: 'P003', name: 'Leather Wallet', stock: 50, price: '$79.00' },
]
Usage
import { Table } from '~/components/ui/table'
Installation
npx @park-ui/cli components add table
1
Add Styled Primitive
Copy the code snippet below into ~/components/ui/styled/table.tsx
'use client'
import type { Assign, PolymorphicProps } from '@ark-ui/react'
import { ark } from '@ark-ui/react/factory'
import { type TableVariantProps, table } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(table)
export interface RootProps
extends Assign<HTMLStyledProps<'table'>, PolymorphicProps>,
TableVariantProps {}
export const Root = withProvider<HTMLTableElement, RootProps>(ark.table, 'root')
export const Body = withContext<
HTMLTableSectionElement,
Assign<HTMLStyledProps<'tbody'>, PolymorphicProps>
>(ark.tbody, 'body')
export const Caption = withContext<
HTMLTableCaptionElement,
Assign<HTMLStyledProps<'caption'>, PolymorphicProps>
>(ark.caption, 'caption')
export const Cell = withContext<
HTMLTableCellElement,
Assign<HTMLStyledProps<'td'>, PolymorphicProps>
>(ark.td, 'cell')
export const Foot = withContext<
HTMLTableSectionElement,
Assign<HTMLStyledProps<'tfoot'>, PolymorphicProps>
>(ark.tfoot, 'footer')
export const Head = withContext<
HTMLTableSectionElement,
Assign<HTMLStyledProps<'head'>, PolymorphicProps>
>(ark.thead, 'head')
export const Header = withContext<
HTMLTableCellElement,
Assign<HTMLStyledProps<'th'>, PolymorphicProps>
>(ark.th, 'header')
export const Row = withContext<
HTMLTableRowElement,
Assign<HTMLStyledProps<'tr'>, PolymorphicProps>
>(ark.tr, 'row')
import { type Assign, type PolymorphicProps, ark } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { table } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(table)
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<Assign<HTMLStyledProps<'table'>, PolymorphicProps<'table'>>>(
ark.table,
'root',
)
export const Body = withContext<Assign<HTMLStyledProps<'tbody'>, PolymorphicProps<'tbody'>>>(
ark.tbody,
'body',
)
export const Caption = withContext<Assign<HTMLStyledProps<'caption'>, PolymorphicProps<'caption'>>>(
ark.caption,
'caption',
)
export const Cell = withContext<Assign<HTMLStyledProps<'td'>, PolymorphicProps<'td'>>>(
ark.td,
'cell',
)
export const Foot = withContext<Assign<HTMLStyledProps<'tfoot'>, PolymorphicProps<'tfoot'>>>(
ark.tfoot,
'footer',
)
export const Head = withContext<Assign<HTMLStyledProps<'head'>, PolymorphicProps<'head'>>>(
ark.thead,
'head',
)
export const Header = withContext<Assign<HTMLStyledProps<'th'>, PolymorphicProps<'th'>>>(
ark.th,
'header',
)
export const Row = withContext<Assign<HTMLStyledProps<'tr'>, PolymorphicProps<'tr'>>>(ark.tr, 'row')
No snippet found
2
Add Re-Export
To improve the developer experience, re-export the styled primitives in~/components/ui/table.tsx
.
export * as Table from './styled/table'
export * as Table from './styled/table'
3
Integrate Recipe
If you're not using @park-ui/preset
, add the following recipe to yourpanda.config.ts
:
import { defineSlotRecipe } from '@pandacss/dev'
export const table = defineSlotRecipe({
className: 'table',
slots: ['root', 'body', 'cell', 'footer', 'head', 'header', 'row', 'caption'],
base: {
root: {
captionSide: 'bottom',
width: 'full',
},
body: {
'& tr:last-child': {
borderBottomWidth: '0',
},
},
caption: {
color: 'fg.subtle',
},
cell: {
verticalAlign: 'middle',
},
footer: {
fontWeight: 'medium',
borderTopWidth: '1px',
'& tr:last-child': {
borderBottomWidth: '0',
},
},
header: {
color: 'fg.muted',
fontWeight: 'medium',
textAlign: 'left',
verticalAlign: 'middle',
},
row: {
borderBottomWidth: '1px',
transitionDuration: 'normal',
transitionProperty: 'background, color',
transitionTimingFunction: 'default',
},
},
defaultVariants: {
size: 'md',
variant: 'plain',
},
variants: {
variant: {
outline: {
root: {
borderWidth: '1px',
},
head: {
bg: 'bg.subtle',
},
},
plain: {
row: {
_hover: {
bg: 'bg.subtle',
},
_selected: {
bg: 'bg.muted',
},
},
},
},
size: {
sm: {
root: {
textStyle: 'sm',
},
caption: {
mt: '4',
},
cell: {
height: '11',
px: '3',
},
header: {
height: '11',
px: '3',
},
},
md: {
root: {
textStyle: 'sm',
},
caption: {
mt: '4',
},
cell: {
height: '14',
px: '4',
},
header: {
height: '11',
px: '4',
},
},
},
},
})