chore: add Table component (#16410)

Reference:
https://www.figma.com/design/JYW69pbgOMr21fCMiQsPXg/Provisioners?node-id=10-2056&m=dev

Unfortunately, it’s kinda hard to apply a border only around the table
body using CSS and make it rounded—at least I couldn’t figure out a sane
way to do that. We’d probably need to use a workaround, like not using
the native HTML table element, but that would add significant work. With
that in mind, I'm wrapping the entire table with a border.

<img width="688" alt="Screenshot 2025-02-03 at 14 37 12"
src="https://github.com/user-attachments/assets/55675df0-1aca-4353-b795-0e3cc2938812"
/>
This commit is contained in:
Bruno Quaresma
2025-02-03 20:24:47 -03:00
committed by GitHub
parent 951a8ed98d
commit 947818f2d3
4 changed files with 201 additions and 1 deletions
-1
View File
@@ -3678,7 +3678,6 @@ packages:
eslint@8.52.0:
resolution: {integrity: sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==, tarball: https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
hasBin: true
espree@9.6.1:
@@ -0,0 +1,90 @@
import type { Meta, StoryObj } from "@storybook/react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "./Table";
const invoices = [
{
invoice: "INV001",
paymentStatus: "Paid",
totalAmount: "$250.00",
paymentMethod: "Credit Card",
},
{
invoice: "INV002",
paymentStatus: "Pending",
totalAmount: "$150.00",
paymentMethod: "PayPal",
},
{
invoice: "INV003",
paymentStatus: "Unpaid",
totalAmount: "$350.00",
paymentMethod: "Bank Transfer",
},
{
invoice: "INV004",
paymentStatus: "Paid",
totalAmount: "$450.00",
paymentMethod: "Credit Card",
},
{
invoice: "INV005",
paymentStatus: "Paid",
totalAmount: "$550.00",
paymentMethod: "PayPal",
},
{
invoice: "INV006",
paymentStatus: "Pending",
totalAmount: "$200.00",
paymentMethod: "Bank Transfer",
},
{
invoice: "INV007",
paymentStatus: "Unpaid",
totalAmount: "$300.00",
paymentMethod: "Credit Card",
},
];
const meta: Meta<typeof Table> = {
title: "components/Table",
component: Table,
args: {
children: (
<>
<TableHeader>
<TableRow>
<TableHead className="w-[100px]">Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead>Method</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{invoices.map((invoice) => (
<TableRow key={invoice.invoice}>
<TableCell className="font-medium">{invoice.invoice}</TableCell>
<TableCell>{invoice.paymentStatus}</TableCell>
<TableCell>{invoice.paymentMethod}</TableCell>
<TableCell className="text-right">
{invoice.totalAmount}
</TableCell>
</TableRow>
))}
</TableBody>
</>
),
},
};
export default meta;
type Story = StoryObj<typeof Table>;
export const Default: Story = {};
+110
View File
@@ -0,0 +1,110 @@
/**
* Copied from shadc/ui on 02/03/2025
* @see {@link https://ui.shadcn.com/docs/components/table}
*/
import * as React from "react";
import { cn } from "utils/cn";
export const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto border border-border border-solid rounded-md">
<table
ref={ref}
className={cn(
"w-full caption-bottom text-xs font-medium text-content-secondary border-collapse",
className,
)}
{...props}
/>
</div>
));
export const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
));
export const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
));
export const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className,
)}
{...props}
/>
));
export const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-0 border-b border-solid border-border transition-colors",
"hover:bg-muted/50 data-[state=selected]:bg-muted",
className,
)}
{...props}
/>
));
export const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"py-2 px-4 text-left align-middle font-semibold",
"[&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className,
)}
{...props}
/>
));
export const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn(
"py-2 px-4 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className,
)}
{...props}
/>
));
export const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
));
+1
View File
@@ -15,6 +15,7 @@ module.exports = {
},
fontSize: {
"2xs": ["0.625rem", "0.875rem"],
xs: ["0.75rem", "1.125rem"],
sm: ["0.875rem", "1.5rem"],
"3xl": ["2rem", "2.5rem"],
},