@gt-chile/ui
v0.5.0
Published
React design system for reusable GT visual primitives.
Readme
@gt-chile/ui
React design system built with TypeScript, Tailwind CSS, Storybook, and a dedicated documentation app.
The public GitHub Pages site serves the documentation app at the root path and Storybook under /storybook/.
Development
# bun
bun install
bun run docs
bun run storybook
# pnpm
pnpm install
pnpm docs
pnpm storybook
# npm
npm install
npm run docs
npm run storybookBuild
# bun
bun run build
bun run build:docs
bun run build:pages
# pnpm
pnpm build
pnpm build:docs
pnpm build:pages
# npm
npm run build
npm run build:docs
npm run build:pagesValidation
# bun
bun run check
# pnpm
pnpm check
# npm
npm run checkCI/CD
The repository is configured for GitHub Actions with three workflows:
CI: runs on pull requests and pushes tomain, installs dependencies withbun, and executesbun run check.Release: runs on pushes tomain, uses Changesets to open or update the release pull request, and publishes the package to npm after the release pull request is merged through npm trusted publishing with OIDC.Docs And Storybook Pages: runs on pushes tomainand deploys the documentation app to GitHub Pages root and Storybook under/storybook/.
Release Flow
- Add a changeset in every pull request that changes the published package.
- Merge the pull request into
main. - GitHub Actions updates or creates the release pull request with the next package version.
- Merge the release pull request to publish the package to npm.
Create a changeset locally with:
bunx changesetRequired GitHub Configuration
Configure these repository settings before the first release:
- Configure npm trusted publishing for
@gt-chile/uiwith:- GitHub organization or user:
Grant-Thornton-Chile - Repository:
gt-design-system - Workflow filename:
release.yml
- GitHub organization or user:
- Enable GitHub Pages and set the source to
GitHub Actions.
No NPM_TOKEN secret is required for publishing. GITHUB_TOKEN is provided automatically by GitHub Actions and is still used for release pull requests and tags.
Published Artifacts
- npm package:
@gt-chile/ui - documentation site:
https://grant-thornton-chile.github.io/gt-design-system/ - Storybook site:
https://grant-thornton-chile.github.io/gt-design-system/storybook/
Storybook remains available locally as a component development and QA surface, and is also published under the /storybook/ path in GitHub Pages.
Installation
# pnpm
pnpm add @gt-chile/ui
# npm
npm install @gt-chile/ui
# bun
bun add @gt-chile/uiCLI
The package now ships with a source installer CLI so teams can keep using the published library or copy components into their own codebase.
For beta testing from npm:
npx @gt-chile/ui@beta init
npx @gt-chile/ui@beta add badge
npx @gt-chile/ui@beta list# initialize the local UI workspace and import the editable source stylesheet once
npx @gt-chile/ui init
# copy one or more components as source files into src/components/ui
npx @gt-chile/ui add badge button input
# inspect the available component names
npx @gt-chile/ui listCLI behavior
initcreatessrc/styles.cssfrom the package stylesheet and tries to add the import to your app entry file.- By default,
initcopies the readable source stylesheet so teams can edit it locally. Pass--compiled-stylesif you want the compiled package CSS instead. addcopies the selected component source intosrc/components/ui, while shared helpers stay insrc/lib.addalso updatessrc/components/ui/index.tsso the copied components can be re-exported from a single local entrypoint.- Existing files are preserved by default. Use
--overwriteif you want to replace them. - Dependency packages used by the copied components are installed automatically unless you pass
--no-install.
Example local imports after using the CLI:
import { Badge, Button } from "./components/ui";Required CSS import
Important: The components will not render correctly without the stylesheet. You must import it once in your app entrypoint (e.g.
main.tsx,App.tsx, orlayout.tsx).
import "@gt-chile/ui/styles.css";Then consume components from the package root:
import {
Badge,
Breadcrumb,
Button,
Card,
Dialog,
Dot,
EmptyState,
FileDropzone,
FormField,
Heading,
Input,
NotificationListItem,
PageHeader,
RiskBadge,
Select,
StatusDot,
StatusGridCell,
StatusPill,
Table,
TableRowActions,
Text,
ToastProvider,
useToast,
} from "@gt-chile/ui";No additional Tailwind configuration is needed in the consuming app when importing the published compiled stylesheet. If you use the CLI source installation flow, the generated src/styles.css already includes the Tailwind v4 setup for this design system.
Theme Tokens
The stylesheet exposes CSS variables for the light and dark themes. Storybook switches themes through data-theme, and consumers can do the same.
<div data-theme="dark">
<App />
</div>Available theme exports:
tokenslightThemedarkTheme
Component Groups
Core primitives:
ButtonBadgeIconButtonCardInputSelectToggleChipSkeletonFormFieldHeadingTextDot
Feedback and overlays:
TooltipDialogDropdownToastProvideruseToastEmptyStateFileDropzone
Composed layout components:
ActionCardAlertCardSectionHeaderPageHeaderBreadcrumbStatCardStepperYearTabsRiskBadgeStatusDotStatusPillStatusGridCellNotificationListItem
Table system:
TableTableRootTableToolbarTableHeaderTableBodyTableRowTableCellTableSelectionCellTableEmptyTablePaginationTableRowActionsTableTextStackuseTableState
Usage Examples
Forms
import { FormField, Input, Select } from "@gt-chile/ui";
const regionOptions = [
{ value: "rm", label: "Metropolitan Region" },
{ value: "valpo", label: "Valparaiso" },
{ value: "bio", label: "Biobio" },
];
export function ClientForm() {
return (
<div className="grid gap-4 md:grid-cols-2">
<FormField label="Client name" hint="Visible in dashboards and exports">
<Input placeholder=" " />
</FormField>
<Select
label="Region"
options={regionOptions}
value="rm"
onChange={(value) => console.log(value)}
/>
</div>
);
}Toasts
Wrap your app once with ToastProvider and call showToast from useToast where needed.
import { Button, ToastProvider, useToast } from "@gt-chile/ui";
function SaveButton() {
const { showToast } = useToast();
return (
<Button
onClick={() => {
showToast({
tone: "success",
title: "Settings saved",
description: "Changes were applied successfully.",
});
}}
>
Save
</Button>
);
}
export function App() {
return (
<ToastProvider>
<SaveButton />
</ToastProvider>
);
}File Upload
Use FileDropzone when the product needs a reusable drag-and-drop surface without coupling UI to upload or validation business rules.
import { FileDropzone } from "@gt-chile/ui";
export function UploadPanel() {
return (
<FileDropzone
title="Drag and drop PDF files here or browse your device"
description="The app can validate company, period, and document structure before confirming the upload."
buttonLabel="Choose files"
accept=".pdf,application/pdf"
multiple
onFilesSelect={(files) => {
console.log(files);
}}
/>
);
}Status Components
These components cover the semantic status patterns used across BusinessTools tables, dashboards, and notifications.
import {
Dot,
RiskBadge,
StatusDot,
StatusGridCell,
StatusPill,
} from "@gt-chile/ui";
export function StatusPreview() {
return (
<div className="flex flex-wrap items-center gap-3">
<StatusPill tone="ok" label="Declared" />
<RiskBadge level="MEDIA" />
<StatusDot status="Open" />
<Dot status="yellow" />
<StatusGridCell
status="obs"
context="VAT return"
note="Observation pending review"
/>
</div>
);
}Row Actions
Use TableRowActions when a row needs one visible primary action plus an overflow menu for secondary actions.
import { TableRowActions } from "@gt-chile/ui";
export function ActionsCell() {
return (
<TableRowActions
primaryAction={{
label: "Review",
onClick: () => console.log("review"),
}}
items={[
{
label: "View details",
onClick: () => console.log("details"),
},
{
label: "Delete",
tone: "err",
confirm: {
title: "Delete record",
description: "This action cannot be undone.",
confirmLabel: "Delete",
tone: "err",
},
onClick: () => console.log("delete"),
},
]}
/>
);
}Notifications
Use NotificationListItem for notification center panels and compact bell dropdown lists.
import { NotificationListItem } from "@gt-chile/ui";
export function NotificationPreview() {
return (
<NotificationListItem
item={{
id: "SII-12903",
description: "The tax authority issued a new observation.",
date: "2026-04-15",
type: "Notification",
risk: "MEDIA",
status: "Open",
isNew: true,
organization: "SII",
}}
variant="panel"
/>
);
}Table
The table API is designed for reusable data presentation. It supports client-side sorting, column filters, selection, and pagination. Export behavior is intentionally left to the consuming app.
import { Badge, Table, TableTextStack, type TableColumn } from "@gt-chile/ui";
type ClientRow = {
id: number;
company: string;
taxId: string;
owner: string;
status: "ready" | "pending" | "risk";
};
const columns: TableColumn<ClientRow>[] = [
{
key: "company",
header: "Company",
accessor: (row) => (
<TableTextStack primary={row.company} secondary={row.taxId} />
),
textValue: (row) => `${row.company} ${row.taxId}`,
truncate: true,
minWidth: 220,
},
{
key: "owner",
header: "Owner",
},
{
key: "status",
header: "Status",
render: (row) => {
const tone =
row.status === "ready"
? "ok"
: row.status === "pending"
? "warn"
: "err";
return <Badge tone={tone}>{row.status}</Badge>;
},
textValue: (row) => row.status,
align: "center",
},
];
export function ClientTable({ rows }: { rows: ClientRow[] }) {
return (
<Table
columns={columns}
data={rows}
sortable
selectable
showColumnFilters
pagination={{
currentPage: 1,
pageSize: 10,
onPageChange: (page) => console.log(page),
}}
/>
);
}Breadcrumb and Page Header
Breadcrumb is router-agnostic. Use href for links or onClick for app-controlled navigation.
import { Breadcrumb, PageHeader, Button } from "@gt-chile/ui";
export function ReportsHeader() {
return (
<PageHeader
breadcrumbItems={[
{ label: "Dashboard", href: "/dashboard" },
{ label: "Reports" },
]}
title="Tax reports"
subtitle="Manage exports, filters, and scheduled deliveries."
actions={<Button>New report</Button>}
/>
);
}API Notes
TooltipuseswidthClassNamefor content width customization.StatusDotusesstatusas its public prop name.StatusGridCelluseshrefwith a native anchor to remain router-agnostic.NotificationListItemexpects a typeditemobject and supportspanelandcompactvariants.TableRowActionssupports grouped menu items and optional destructive confirmations.TableColumn.textValueprovides plain text for filtering when a column renders custom JSX.Table.showColumnFiltersenables the per-column filter row.TablePaginationState.totalItemsmarks server-side pagination when provided.Breadcrumbstays navigation-library agnostic by design.ActionCardandAlertCardare navigation-library agnostic and supporthreforonClick.
