Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
283d587
add unwired beta components, based on park-ui patterns
lunelson Apr 28, 2026
9fef108
get all beta stories wired up
lunelson Apr 28, 2026
ee3591c
exclude the beta stories from typechecking temporarily
lunelson Apr 28, 2026
9b3272b
change legacy component stories sidebar path
lunelson Apr 28, 2026
15f85be
fixes for eslint perf
lunelson Apr 28, 2026
99854c0
make sure buildinfo is present for unit tests
lunelson Apr 28, 2026
1f3b787
make all new components appear under "primitives" in ladle
lunelson Apr 28, 2026
6e31b17
add story order config to ladle
lunelson Apr 28, 2026
deda21b
demonstrate cva pattern for typed recipes
lunelson Apr 28, 2026
feb7265
filter tsdown declaration warnings
lunelson Apr 28, 2026
9b46fea
switch ds-components build to tsup
lunelson Apr 28, 2026
b052110
dedupe lockfile after tsup migration
lunelson Apr 28, 2026
aa84dc3
feat: remove ds-components theme entrypoint
lunelson Apr 28, 2026
b8d951a
feat: add ds-components tokens entrypoint
lunelson Apr 28, 2026
ef751ac
feat: move token stories into src tokens
lunelson Apr 28, 2026
cfc8767
refactor: rename preset theme internals
lunelson Apr 28, 2026
4d8056f
refactor: update preset recipes import
lunelson Apr 28, 2026
c4f73d5
delete the MDX story
lunelson Apr 28, 2026
f5dfe95
make the organization in preset/ dir more sensible
lunelson Apr 28, 2026
fa7a818
Fix ds-components PR review issues
lunelson Apr 29, 2026
80ef43e
add a changeset
lunelson Apr 29, 2026
86889ff
fixes for review comments
lunelson Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .changeset/humble-vans-make.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@hashintel/ds-components": minor
"@hashintel/ds-helpers": minor
---

Expose preset-owned `tokens` and `semanticTokens` from `@hashintel/ds-components/tokens` in place of the old `./theme` export, and add generated `@hashintel/ds-helpers/recipes` exports for recipe consumers.
1 change: 1 addition & 0 deletions libs/@hashintel/ds-components/.ladle/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default {
viteConfig: "./vite.config.ts",
outDir: ".build/ladle",
envDir: ".",
storyOrder: ["primitives--*", "tokens--*", "legacy--*", "*"],
addons: {
rtl: { enabled: false },
a11y: { enabled: false },
Expand Down
10 changes: 6 additions & 4 deletions libs/@hashintel/ds-components/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ It owns:
- the Panda preset source in `src/preset/**`
- token/codegen scripts in `scripts/**`
- the component library in `src/components/**`
- the token/demo surface in `src/stories/**`, `.ladle/`, and `tests/**`
- the token/demo surface in `src/tokens/**`, `src/stories/Intro.mdx`, `.ladle/`, and `tests/**`

It still consumes the generated runtime styling utilities from `@hashintel/ds-helpers`.

Expand All @@ -36,7 +36,8 @@ Boundary rules:

- `ds-components` generates `../ds-helpers/styled-system` via Panda `outdir`.
- `ds-helpers` must not depend on `ds-components`.
- `@hashintel/ds-components/preset` and `@hashintel/ds-components/theme` are the canonical public preset/theme entrypoints.
- `@hashintel/ds-components/preset` is the canonical public styling entrypoint.
- `@hashintel/ds-components/tokens` is the public package-owned token export for `tokens` and `semanticTokens`.

## Panda CSS Configuration

Expand Down Expand Up @@ -242,8 +243,9 @@ libs/@hashintel/ds-components/
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ components/
β”‚ β”œβ”€β”€ preset/ # Panda preset source of truth
β”‚ β”œβ”€β”€ stories/
β”‚ β”œβ”€β”€ theme.ts # Public `./theme` facade
β”‚ β”œβ”€β”€ stories/ # Shared docs such as Intro.mdx
β”‚ β”œβ”€β”€ tokens/ # Token stories and fixtures
β”‚ β”œβ”€β”€ tokens.ts # Public `./tokens` facade
β”œβ”€β”€ scripts/ # Token/codegen scripts
β”œβ”€β”€ tests/ # Snapshot/demo tests
β”œβ”€β”€ panda.config.ts
Expand Down
19 changes: 13 additions & 6 deletions libs/@hashintel/ds-components/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ This guide covers the current post-FE-612 package layout for humans and coding a
- `@hashintel/ds-components` is the source-owning package.
- `src/preset/**` contains the Panda preset source and theme/token inputs used by the preset.
- `scripts/**` owns token and color code generation.
- `src/components/**`, `src/stories/**`, `.ladle/**`, and `tests/**` are owned here as the component, demo, and snapshot surfaces.
- `src/components/**`, `src/tokens/**`, `src/stories/Intro.mdx`, `.ladle/**`, and `tests/**` are owned here as the component, demo, and snapshot surfaces.
- `@hashintel/ds-helpers` is the generated Panda `styled-system` artifact only.
- The old `@hashintel/ds-theme` package has been retired; use `@hashintel/ds-components/preset` and `@hashintel/ds-components/theme` instead.
- The old `@hashintel/ds-theme` package has been retired; use `@hashintel/ds-components/preset` instead.

For new internal work, treat `ds-components` as the only source of truth.

Expand All @@ -19,9 +19,10 @@ For new internal work, treat `ds-components` as the only source of truth.
| --- | --- | --- |
| Components | `src/components/<Component>/<component>.tsx` and `src/components/*/*.stories.tsx` | Public component entrypoints live at the top of `src/components/` and are built by `tsdown`. |
| Panda preset source | `src/preset.ts`, `src/preset/**` | This is the live preset consumed by `@hashintel/ds-components/preset`. |
| Package-owned theme facade | `src/theme.ts` | Re-exports from `src/preset/theme`. |
| Package-owned token facade | `src/tokens.ts`, `src/preset/tokens.ts` | This is the public `@hashintel/ds-components/tokens` surface and its internal source of truth. |
| Token and color generators | `scripts/**` | Reads `scripts/figma-variables.json` and writes generated preset files under `src/preset/theme/**`. |
| Token demo stories | `src/stories/tokens/**` | Token reference and migration/demo stories live here now. |
| Token demo stories | `src/tokens/**` | Token reference and migration/demo stories live here now. |
| Intro docs | `src/stories/Intro.mdx` | Shared intro documentation for the Ladle surface. |
| Local demo config | `panda.local.config.ts` | Shared Panda config for local demo surfaces such as Ladle. |
| Ladle harness | `.ladle/**` | Used for the token/demo surface and Playwright snapshots. |
| Snapshot tests | `tests/**` | Snapshot harness for the Ladle surface. |
Expand All @@ -41,13 +42,19 @@ When you need token lookup helpers or public token types, use the generated runt
import { token, type Token } from "@hashintel/ds-helpers/tokens";
```

When you need the package-owned Panda token objects that feed the preset, use:

```ts
import { semanticTokens, tokens } from "@hashintel/ds-components/tokens";
```

When a consumer needs the Panda preset, use:

```ts
import { preset, scopedThemeConfig } from "@hashintel/ds-components/preset";
```

Do not resurrect `@hashintel/ds-theme`; `ds-components` now owns the public preset and theme entrypoints directly.
Do not resurrect `@hashintel/ds-theme`; `ds-components` now owns the public preset entrypoint directly.

## Component Workflow

Expand Down Expand Up @@ -171,7 +178,7 @@ Color tokens should come from the semantic palette already defined in the preset

- `yarn dev` is the primary Ladle-based loop and the best default when changing token stories or the demo harness. It uses the shared Vite/PostCSS config for Panda style extraction while Ladle is running.
- `yarn dev:lib` is the lightest loop when you only need the publishable package build watcher.
- `src/stories/tokens/**` owns the token reference stories that used to live under `ds-helpers`.
- `src/tokens/**` owns the token reference stories that used to live under `ds-helpers`.
- `tests/snapshots.spec.ts` exercises the Ladle surface and stores the images in `tests/__snapshots__/`.

## Common Pitfalls
Expand Down
37 changes: 20 additions & 17 deletions libs/@hashintel/ds-components/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# @hashintel/ds-components

React components for HASH's refractive design system, built with TypeScript, Ark UI, and PandaCSS.
React components for HASH's design system, built with TypeScript, Ark UI, and PandaCSS.

## Ownership Model

As of the FE-612 ownership restructure:

- `@hashintel/ds-components` owns the Panda preset source, token/codegen scripts, and demo surfaces.
- `@hashintel/ds-helpers` is the generated Panda `styled-system` artifact.
- The old `@hashintel/ds-theme` surface has been folded into `@hashintel/ds-components/preset` and `@hashintel/ds-components/theme`.
- The old `@hashintel/ds-theme` surface has been folded into `@hashintel/ds-components/preset`.

For new internal work, treat `ds-components` as the source of truth.

## Public Entry Points

| Entry point | Purpose |
| --- | --- |
| `@hashintel/ds-components` | Published component entrypoints from `src/components/*.tsx` |
| Entry point | Purpose |
| --------------------------------- | ------------------------------------------------------------------------------ |
| `@hashintel/ds-components` | Published component entrypoints from `src/components/*.tsx` |
| `@hashintel/ds-components/preset` | Panda preset helpers such as `preset`, `createPreset`, and `scopedThemeConfig` |
| `@hashintel/ds-components/theme` | Package-owned theme facade re-exporting from `src/preset/theme` |
| `@hashintel/ds-components/tokens` | Package-owned Panda token objects such as `tokens` and `semanticTokens` |

Component implementation still uses the generated Panda runtime from `@hashintel/ds-helpers`:

Expand All @@ -27,20 +27,23 @@ import { css, cva, cx } from "@hashintel/ds-helpers/css";
import { Box, Flex, Stack } from "@hashintel/ds-helpers/jsx";
```

Token lookup helpers and token types should also come from `@hashintel/ds-helpers/tokens`.
Token lookup helpers and token types should still come from `@hashintel/ds-helpers/tokens`.
Use `@hashintel/ds-components/tokens` when you need the package-owned Panda token objects themselves.

## Package Layout

| Area | Location |
| --- | --- |
| Components | `src/components/**` |
| Panda preset source | `src/preset.ts`, `src/preset/**` |
| Token and color generators | `scripts/**` |
| Stories | `src/components/*/*.stories.tsx` |
| Token demo stories | `src/stories/**` |
| Local demo config | `panda.local.config.ts` |
| Ladle harness | `.ladle/**` |
| Snapshot tests | `tests/**` |
| Area | Location |
| -------------------------- | -------------------------------- |
| Components | `src/components/**` |
| Panda preset source | `src/preset.ts`, `src/preset/**` |
| Package token facade | `src/tokens.ts` |
| Token and color generators | `scripts/**` |
| Stories | `src/components/*/*.stories.tsx` |
| Token demo stories | `src/tokens/**` |
| Intro docs | `src/stories/Intro.mdx` |
| Local demo config | `panda.local.config.ts` |
| Ladle harness | `.ladle/**` |
| Snapshot tests | `tests/**` |

## Common Commands

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This guide was originally written before the FE-612 ownership restructure. Apply

- preset and token source changes belong in `@hashintel/ds-components/src/preset/**`
- token and color generation lives in `@hashintel/ds-components/scripts/**`
- token demo stories live in `@hashintel/ds-components/src/stories/tokens/**`
- token demo stories live in `@hashintel/ds-components/src/tokens/**`
- `@hashintel/ds-helpers` is the generated Panda runtime only

## Reference Repositories
Expand Down Expand Up @@ -119,7 +119,7 @@ Established mapping from Radix neutral β†’ HASH gray:
| 11 | 60 | Low-contrast text |
| 12 | 90 | High-contrast text |

Visual comparison story: `libs/@hashintel/ds-components/src/stories/tokens/tokens.color-migration.story.tsx`
Visual comparison story: `libs/@hashintel/ds-components/src/tokens/tokens.color-migration.story.tsx`

### Alpha β†’ Solid Mapping

Expand Down Expand Up @@ -301,7 +301,7 @@ bg: 'bg.accent.bold.default'

| File | Purpose |
|------|---------|
| `libs/@hashintel/ds-components/src/stories/tokens/tokens.color-migration.story.tsx` | Visual comparison tool for scale mapping |
| `libs/@hashintel/ds-components/src/tokens/tokens.color-migration.story.tsx` | Visual comparison tool for scale mapping |
| `libs/@hashintel/ds-components/_ai/park-ui-porting-guide.md` | This document |

## Next Steps
Expand Down
34 changes: 27 additions & 7 deletions libs/@hashintel/ds-components/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
import storybook from "eslint-plugin-storybook";
import typescriptEslint from "@typescript-eslint/eslint-plugin";

import { createBase, disableRules } from "@local/eslint/deprecated";

const disableTypeCheckedRules =
typescriptEslint.configs["disable-type-checked"]?.rules ?? {};

export default [
{
ignores: [
Expand All @@ -16,7 +18,6 @@ export default [
],
},
...createBase(import.meta.dirname),
...storybook.configs["flat/recommended"],
...disableRules([]),
{
rules: {
Expand Down Expand Up @@ -44,13 +45,32 @@ export default [
},
},
{
files: ["src/**/*.story.ts{x,}", "src/stories/**/*.{ts,tsx,mdx}"],
// Story files are intentionally excluded from `tsconfig.json` (they live
// in `tsconfig.beta.json`). Running type-aware lint rules on them forces
// ESLint's project service into a slow default-project fallback per file
// *and* type-instantiates the very heavy generated `styled-system` types
// for every single story. Disable type-aware linting entirely for the
// story surface β€” they're demo code, not shipped to consumers.
files: [
"src/**/*.story.ts{x,}",
"src/beta/**/*.stories.ts{x,}",
"src/tokens/**/*.{ts,tsx,mdx}",
Comment thread
cursor[bot] marked this conversation as resolved.
],
languageOptions: {
parserOptions: {
// Drop the type-aware project lookup for story files. Without this,
// every story still costs a full project-service resolve even when
// every type-aware rule is off.
projectService: false,
project: false,
},
},
rules: {
"@typescript-eslint/no-unnecessary-condition": "off",
...disableTypeCheckedRules,
"@typescript-eslint/no-shadow": "off",
"id-length": "off",
"import/no-extraneous-dependencies": ["error", { devDependencies: true }],
"storybook/default-exports": "off",
"storybook/no-redundant-story-name": "off",
"react/no-array-index-key": "off",
},
},
{
Expand Down
24 changes: 13 additions & 11 deletions libs/@hashintel/ds-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
"types": "./dist/preset.d.ts",
"import": "./dist/preset.js"
},
"./theme": {
"types": "./dist/theme.d.ts",
"import": "./dist/theme.js"
"./tokens": {
"types": "./dist/tokens.d.ts",
"import": "./dist/tokens.js"
},
"./panda.buildinfo.json": "./dist/panda.buildinfo.json",
"./*": {
Expand All @@ -47,27 +47,28 @@
"build": "npm-run-all build:lib build:buildinfo",
"build:buildinfo": "panda ship --config panda.config.ts --outfile dist/panda.buildinfo.json",
"build:ladle": "ladle build",
"build:lib": "tsdown",
"build:lib": "tsup --config tsup.config.ts",
Comment thread
lunelson marked this conversation as resolved.
"codegen": "yarn run codegen:colors && yarn run codegen:tokens && yarn run codegen:panda",
"codegen:colors": "tsx scripts/generate-colors-radix.ts",
"codegen:panda": "panda codegen --clean",
"codegen:tokens": "tsx scripts/generate-tokens.ts",
"dev": "yarn dev:ladle",
"dev:ladle": "ladle serve",
"dev:lib": "tsdown --watch",
"dev:lib": "tsup --config tsup.config.ts --watch",
"fix": "npm-run-all --continue-on-error \"fix:*\"",
"fix:eslint": "eslint --fix .",
"fix:eslint": "eslint --cache --fix .",
"fix:format": "biome format --write",
"lint": "npm-run-all --continue-on-error \"lint:*\"",
"lint:eslint": "eslint --report-unused-disable-directives .",
"lint:eslint": "eslint --cache --report-unused-disable-directives .",
"lint:tsc": "tsc --noEmit",
"lint:tsc:beta": "tsc --noEmit -p tsconfig.beta.json",
"prepare": "yarn run codegen",
"prepublishOnly": "turbo run build",
"preview:ladle": "yarn build:ladle && ladle preview",
"test:snapshots": "yarn build:ladle && playwright test",
"test:snapshots:update": "yarn build:ladle && playwright test --update-snapshots",
"test:unit": "vitest run --exclude tests/snapshots.spec.ts",
"test:unit:watch": "vitest --exclude tests/snapshots.spec.ts"
"test:unit": "yarn build:buildinfo && vitest run --exclude tests/snapshots.spec.ts",
"test:unit:watch": "yarn build:buildinfo && vitest --exclude tests/snapshots.spec.ts"
},
"dependencies": {
"@ark-ui/react": "5.26.2",
Expand All @@ -90,6 +91,7 @@
"@playwright/test": "1.58.2",
"@radix-ui/colors": "3.0.0",
"@svgr/rollup": "8.1.0",
"@tanstack/react-virtual": "3.13.24",
"@tsconfig/strictest": "^2.0.8",
"@types/node": "22.18.13",
"@types/react": "19.2.7",
Expand All @@ -100,12 +102,12 @@
"case-anything": "3.1.0",
"colorjs.io": "0.6.1",
"eslint": "9.39.4",
"eslint-plugin-storybook": "10.3.1",
"lorem-ipsum": "2.0.8",
"lucide-react": "0.544.0",
"npm-run-all": "4.1.5",
"react": "19.2.3",
"react-dom": "19.2.3",
"tsdown": "^0.21.4",
"tsup": "^8.5.1",
"tsx": "4.20.6",
"typescript": "5.9.3",
"vite": "7.3.2",
Expand Down
2 changes: 1 addition & 1 deletion libs/@hashintel/ds-components/panda.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { preset } from "./src/preset";
export const coreConfig: Config = {
importMap: "@hashintel/ds-helpers",
outdir: "../ds-helpers/styled-system",
include: ["./src/components/**/*.{ts,tsx}"],
include: ["./src/components/**/*.{ts,tsx}", "./src/beta/**/*.{ts,tsx}"],
jsxFramework: "react",
outExtension: "mjs",
preflight: false,
Expand Down
4 changes: 2 additions & 2 deletions libs/@hashintel/ds-components/panda.local.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export default defineConfig({
...coreConfig,
outdir: "../ds-helpers/styled-system",
include: [
"./src/components/**/*.{ts,tsx}",
"./src/stories/**/*.{ts,tsx}",
...(coreConfig.include ?? []),
"./src/tokens/**/*.{ts,tsx}",
"./.ladle/**/*.{ts,tsx}",
],
staticCss: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import fs from "node:fs";
import { join } from "node:path";
import Color from "colorjs.io";
import * as radixColors from "@radix-ui/colors";
import { withSemantics, type PaletteKind } from "../src/preset/theme/utils";
import { withSemantics, type PaletteKind } from "../src/preset/tokens/utils";

const OUTPUT_DIR = "src/preset/theme/colors";
const OUTPUT_DIR = "src/preset/tokens/gen/colors";
const BARREL_FILE_PATH = "src/preset/tokens/gen/colors.gen.ts";

/**
* Colors to include in generation. Add/remove as needed.
Expand Down Expand Up @@ -482,7 +483,7 @@ export const staticColors = { black, white };
* Aliases are composed in main.ts, not generated here.
*/
function writeBarrelFile(colorNames: string[]): void {
const filePath = join(process.cwd(), "src/preset/theme/colors.gen.ts");
const filePath = join(process.cwd(), BARREL_FILE_PATH);

const imports = colorNames
.map((name) => `import { ${name} } from "./colors/${name}.gen";`)
Expand Down
Loading
Loading