@conscia-labs/design-system 0.3.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,6 +5,10 @@ The shared React component library for building clear, consistent, and accessibl
5
5
  `@conscia-labs/design-system` brings Conscia’s visual foundation, reusable interface primitives, and common product patterns together in one package. It is designed for operational applications where information density, predictable interaction, and accessibility matter.
6
6
 
7
7
  > **Package:** available publicly as [`@conscia-labs/design-system`](https://www.npmjs.com/package/@conscia-labs/design-system).
8
+ >
9
+ > **v1.0.0:** this README documents the clean-break v1 contract. The repository is now preparing the `1.0.0` release candidate for publication through the Phase 8 workflow.
10
+ >
11
+ > **Migration:** upgrading an application to v1? Follow the [Design System v1 Migration Guide](https://github.com/conscia-labs/design-system/blob/main/docs/design-system-v1-migration.md).
8
12
 
9
13
  ## Why this package exists
10
14
 
@@ -32,6 +36,19 @@ Use the design system to:
32
36
 
33
37
  Product applications remain responsible for routing, authentication, permissions, data fetching, mutations, validation, and business-specific behavior.
34
38
 
39
+ ## Migrating to v1.0.0
40
+
41
+ Version `1.0.0` is a clean API and implementation break. Component concepts and
42
+ public names remain recognizable, but Radix and shadcn implementation details
43
+ are no longer part of the contract. In particular:
44
+
45
+ - Replace `asChild` with the documented `render` prop where custom-host composition is required.
46
+ - Replace legacy token utilities such as `bg-primary`, `bg-muted`, and `border-input` with the canonical Conscia semantic roles documented in the migration guide.
47
+ - Do not add `@base-ui/react`, `@radix-ui/*`, or copied shadcn components to the application; Base UI is bundled and used internally by the design system.
48
+ - Recheck dialogs, sheets, menus, selects, comboboxes, tabs, tooltips, forms, tables, and icon-only actions against the application’s keyboard and accessibility tests.
49
+
50
+ The complete, agent-readable upgrade runbook is [`docs/design-system-v1-migration.md`](./docs/design-system-v1-migration.md) in this repository. You can also open the [migration guide on GitHub](https://github.com/conscia-labs/design-system/blob/main/docs/design-system-v1-migration.md). The guide is intentionally kept in the repository’s `docs/` directory rather than the npm tarball, so the GitHub link is the durable location for app owners and coding agents.
51
+
35
52
  ## What is included
36
53
 
37
54
  ### Foundation
@@ -46,12 +63,15 @@ Semantic CSS variables for:
46
63
 
47
64
  ### Primitives
48
65
 
49
- Reusable interface building blocks composed from React, Radix UI, and ShadCN conventions:
66
+ Reusable Conscia-owned interface building blocks composed from native React
67
+ markup and Base UI behavior where interaction complexity requires it:
50
68
 
51
69
  - Alert
70
+ - AlertDialog
52
71
  - Avatar
53
72
  - Badge
54
73
  - Button
74
+ - IconButton
55
75
  - Card
56
76
  - Checkbox
57
77
  - Collapsible
@@ -59,13 +79,19 @@ Reusable interface building blocks composed from React, Radix UI, and ShadCN con
59
79
  - Dropdown menu
60
80
  - Field and form controls
61
81
  - Input and textarea
62
- - Select and searchable select
82
+ - Select, FormSelect, and searchable select
63
83
  - Sheet
64
84
  - Skeleton
65
85
  - Switch
66
86
  - Table
67
87
  - Tabs and navigation tabs
68
88
  - Tooltip
89
+ - Popover
90
+ - Shortcut hint
91
+ - Spinner
92
+ - Avatar group
93
+ - Filter chip
94
+ - Toast provider and viewport
69
95
 
70
96
  ### Patterns
71
97
 
@@ -80,21 +106,75 @@ Higher-level compositions for recurring product workflows:
80
106
  - Empty, loading, and error states
81
107
  - Activity lists and metric bands
82
108
  - Code blocks and value meters
109
+ - Command palette
110
+ - Filter bar
111
+
112
+ ### Supporting interaction patterns
113
+
114
+ #### Command palette
115
+
116
+ `CommandPalette` accepts an explicit list of commands, filters labels and
117
+ keywords, and supports keyboard navigation without a global command registry:
118
+
119
+ ```tsx
120
+ import { Button, CommandPalette } from "@conscia-labs/design-system";
121
+
122
+ <CommandPalette
123
+ items={[{ id: "settings", label: "Open settings", keywords: ["preferences"] }]}
124
+ onSelect={(item) => openCommand(item.id)}
125
+ trigger={<Button variant="outline">Open commands</Button>}
126
+ />
127
+ ```
128
+
129
+ #### Toasts
130
+
131
+ Toasts are opt-in. Mount one provider and viewport, then use `useToast` from a
132
+ descendant component:
133
+
134
+ ```tsx
135
+ import {
136
+ Button,
137
+ ToastProvider,
138
+ ToastViewport,
139
+ useToast,
140
+ } from "@conscia-labs/design-system";
141
+
142
+ function SaveButton() {
143
+ const { add } = useToast();
144
+ return (
145
+ <Button onClick={() => add({ title: "Saved", variant: "success" })}>
146
+ Save
147
+ </Button>
148
+ );
149
+ }
150
+
151
+ function App() {
152
+ return (
153
+ <ToastProvider>
154
+ <SaveButton />
155
+ <ToastViewport />
156
+ </ToastProvider>
157
+ );
158
+ }
159
+ ```
83
160
 
84
161
  ## Quick start
85
162
 
86
163
  ### 1. Install the package
87
164
 
165
+ For the v1 release, install the explicit `1.0.0` range after Phase 8 publishes
166
+ the package.
167
+
88
168
  Using pnpm:
89
169
 
90
170
  ```bash
91
- pnpm add @conscia-labs/design-system
171
+ pnpm add @conscia-labs/design-system@^1.0.0
92
172
  ```
93
173
 
94
174
  Using npm:
95
175
 
96
176
  ```bash
97
- npm install @conscia-labs/design-system
177
+ npm install @conscia-labs/design-system@^1.0.0
98
178
  ```
99
179
 
100
180
  The package targets React 19 and ships as modern ESM with TypeScript
@@ -160,10 +240,31 @@ Supported values:
160
240
  | Preference | Values |
161
241
  | --- | --- |
162
242
  | `data-appearance` | `light`, `dark`, `system` |
163
- | `data-density` | `comfortable`, `compact` |
243
+ | `data-density` | `comfortable`, `compact`, `operational` |
164
244
 
165
245
  Comfortable density is the default for general product interfaces. Compact density is intended for high-volume operational workflows such as inventories and data-heavy administration.
166
246
 
247
+ Operational density is an explicit opt-in preset for interfaces that prioritize
248
+ information throughput and deliberate hierarchy: admin pages, chat shells,
249
+ connectors, catalogs, and Workspace-like surfaces. It tightens the shared type
250
+ scale to approximately 13px body/UI text, 12px metadata, 15–16px section titles,
251
+ and a 26px page title with a 650 weight, `-0.04em` tracking, and `1.08` line
252
+ height. It also tightens reusable spacing and control rhythm while preserving
253
+ the existing touch-target, focus-ring, color, radius, and shadow contracts.
254
+
255
+ ```tsx
256
+ <html data-appearance="system" data-density="operational">
257
+ {/* admin, chat, catalog, connector, or workspace-like application */}
258
+ </html>
259
+ ```
260
+
261
+ Use comfortable density for general product reading and mixed-purpose pages.
262
+ Use compact density when an existing consumer already depends on its smaller
263
+ layout preset. Use operational density when the interface needs Workspace-like
264
+ hierarchy across shared components. Do not make 13px the global default: that
265
+ would make narrative, setup, and accessibility-critical product surfaces feel
266
+ compressed.
267
+
167
268
  ### 4. Use a component
168
269
 
169
270
  ```tsx
@@ -271,6 +372,64 @@ export function ProductShell({
271
372
  }
272
373
  ```
273
374
 
375
+ ## Building a workbench surface
376
+
377
+ Workbench patterns provide a reusable composition for applications that need
378
+ global navigation, a contextual rail, a primary work area, and an inspector.
379
+ They own the shell geometry, responsive rail behavior, resource-row rhythm,
380
+ and inspector hierarchy; the host application supplies its routes, data, and
381
+ actions.
382
+
383
+ ```tsx
384
+ import {
385
+ ResourceRow,
386
+ ResourceRowContent,
387
+ ResourceRowIcon,
388
+ ResourceRowMeta,
389
+ ResourceRowTitle,
390
+ WorkbenchInspector,
391
+ WorkbenchInspectorSection,
392
+ WorkbenchMain,
393
+ WorkbenchRail,
394
+ WorkbenchSection,
395
+ WorkbenchSectionHeader,
396
+ WorkbenchShell,
397
+ } from "@conscia-labs/design-system";
398
+
399
+ export function WorkspaceSurface({ children }: { children: React.ReactNode }) {
400
+ return (
401
+ <WorkbenchShell data-density="operational">
402
+ <WorkbenchRail variant="global">Global navigation</WorkbenchRail>
403
+ <WorkbenchRail variant="secondary">Contextual navigation</WorkbenchRail>
404
+ <WorkbenchMain>
405
+ <WorkbenchSection>
406
+ <WorkbenchSectionHeader title="Recent conversations" metadata="12" />
407
+ <ResourceRow as="a" href="/conversations/1">
408
+ <ResourceRowIcon aria-hidden="true" />
409
+ <ResourceRowContent>
410
+ <ResourceRowTitle>Project brief</ResourceRowTitle>
411
+ <ResourceRowMeta>Updated just now</ResourceRowMeta>
412
+ </ResourceRowContent>
413
+ </ResourceRow>
414
+ </WorkbenchSection>
415
+ {children}
416
+ </WorkbenchMain>
417
+ <WorkbenchInspector>
418
+ <WorkbenchInspectorSection label="Details">
419
+ {/* Product-owned metadata and actions */}
420
+ </WorkbenchInspectorSection>
421
+ </WorkbenchInspector>
422
+ </WorkbenchShell>
423
+ );
424
+ }
425
+ ```
426
+
427
+ Use `WorkbenchMobileToolbar` and `WorkbenchBackdrop` when a contextual rail
428
+ needs an explicit mobile drawer trigger. Keep product-specific content styles
429
+ local, but use the shared workbench tokens and row primitives instead of
430
+ recreating shell widths, inspector padding, focus states, or resource-list
431
+ typography.
432
+
274
433
  ### Typography and font loading
275
434
 
276
435
  The design system declares the open-source Source Sans 3 variable font as a
@@ -300,6 +459,23 @@ Prefer these tokens over local `clamp()`, pixel, or one-off font-size values.
300
459
  Product-specific layout styles may still control wrapping, maximum width, or
301
460
  composition when the content requires it.
302
461
 
462
+ Operational consumers can use the token-backed `ds-type-*` utilities without
463
+ creating a parallel styling system:
464
+
465
+ | Role | Utility | Comfortable baseline | Operational intent |
466
+ | --- | --- | --- | --- |
467
+ | Page/display title | `ds-type-page-title`, `ds-type-display-title` | 28px / 56px | 26px / responsive display, 650 weight, tight tracking |
468
+ | Section title | `ds-type-section-title` | 17px | 16px, 650 weight, tighter line-height |
469
+ | Body/UI | `ds-type-body`, `ds-type-ui` | 15px / 14px | 13px with a 1.4–1.5 rhythm |
470
+ | Metadata | `ds-type-metadata` | 13px | 12px supporting context |
471
+ | Menu/eyebrow | `ds-type-menu-item`, `ds-type-menu-label`, `ds-type-eyebrow` | existing compact roles | compact labels with deliberate tracking |
472
+ | Controls | `ds-type-control`, `ds-type-button` | 14px | 13px, with stronger button weight |
473
+
474
+ The utilities resolve through CSS custom properties, so light and dark themes
475
+ retain the same semantic colors and focus behavior. Applications should use
476
+ the preset and shared utilities for type/rhythm, while keeping product-specific
477
+ composition, data, and layout ownership local.
478
+
303
479
  Sidebar section labels are intentionally smaller than navigation rows and
304
480
  slightly more weighted: comfortable density uses a `12px / 600 / 16px`
305
481
  contract with restrained tracking, while compact density reduces the size
@@ -317,6 +493,20 @@ lockups, collapsed navigation identity, and other shared brand placements.
317
493
  The icon is decorative by default. Add an `aria-label` when the mark conveys
318
494
  meaning without adjacent text, and use `className` to control its size.
319
495
 
496
+ ### BrandWordmark
497
+
498
+ `BrandWordmark` is the shared no-tagline Conscia lockup. It embeds the supplied
499
+ 496×113 vector geometry and uses `currentColor`, so applications do not need
500
+ separate black and white assets or runtime asset paths. The default treatment
501
+ matches `BrandIcon`: foreground in light mode and white in dark mode.
502
+
503
+ The wordmark is decorative by default. Add an `aria-label` when it is the only
504
+ accessible naming content, and use `className` to control its width.
505
+
506
+ ```tsx
507
+ <BrandWordmark aria-label="Conscia" className="w-36" />
508
+ ```
509
+
320
510
  ### Sidebar variants and semantic surfaces
321
511
 
322
512
  `AppSidebar` keeps the historical dark treatment by default. Consumers that
@@ -336,14 +526,12 @@ an explicitly light sidebar.
336
526
  </AppShell>
337
527
  ```
338
528
 
339
- The default is intentionally backwards compatible. The sidebar scope exposes
340
- reusable semantic aliases for its canvas, header, content, hover, active,
341
- search, footer, text, icon, group label, count, border, and focus-ring roles.
529
+ The sidebar scope exposes reusable semantic roles for its canvas, header,
530
+ content, hover, active, search, footer, text, icon, group label, count,
531
+ border, and focus-ring roles.
342
532
  Use the generated utilities such as `bg-sidebar-canvas`,
343
533
  `bg-sidebar-hover`, `text-sidebar-primary-text`, and
344
534
  `text-sidebar-metadata-text` in shared or application-owned compositions.
345
- Legacy aliases including `bg-sidebar`, `bg-sidebar-accent`, and
346
- `text-sidebar-foreground` remain supported.
347
535
 
348
536
  Form controls and outline buttons use `bg-surface-control`, with
349
537
  `bg-surface-control-hover` for the outline hover state. These semantic surfaces
@@ -362,16 +550,16 @@ Dark mode uses a calm charcoal surface ladder rather than a pure-black canvas:
362
550
 
363
551
  | Role | Token | Dark value |
364
552
  | --- | --- | --- |
365
- | Application canvas | `--background` / `--canvas` | `#17191c` |
366
- | Standard surface | `--card` / `--surface` | `#1d2024` |
553
+ | Application canvas | `--canvas` | `#17191c` |
554
+ | Standard surface | `--surface` | `#1d2024` |
367
555
  | Raised surface and control | `--surface-raised` / `--surface-control` | `#24272c` |
368
556
  | Muted and control-hover surface | `--surface-muted` / `--surface-control-hover` | `#282b31` |
369
- | Floating surface | `--surface-floating` / `--popover` | `#2c2f36` |
557
+ | Floating surface | `--surface-floating` | `#2c2f36` |
370
558
  | Overlay surface | `--surface-overlay` | `#31343a` |
371
559
 
372
560
  The adjacent steps are intentionally close enough for a calm reading
373
561
  environment while remaining distinguishable through luminance, borders, and
374
- elevation. `--foreground` is a soft high-priority text role (`#eff1f4`), while
562
+ elevation. `--text-primary` is a soft high-priority text role (`#eff1f4`), while
375
563
  `--text-secondary`, `--text-supporting`, and `--text-muted` step down to
376
564
  `#d4d8df`, `#b3bac5`, and `#929aa7`. Use the semantic `bg-surface-*` and
377
565
  `text-*` utilities instead of copying these values into an application. The
@@ -480,7 +668,7 @@ Color communicates meaning rather than palette choice:
480
668
  | --- | --- |
481
669
  | `brand` | Conscia identity and signature moments |
482
670
  | `brand-secondary` | Supporting brand expression |
483
- | `primary` | The primary next action |
671
+ | `action-*` | Primary actions and their hover, active, foreground, and tinted-background roles |
484
672
  | `selection-*` | Current selection or active destination |
485
673
  | `information-*` | Informational messages and evidence |
486
674
  | `success-*` | Healthy, verified, approved, or completed states |
@@ -510,7 +698,7 @@ Prefer semantic variables over component-specific descendant selectors. This kee
510
698
 
511
699
  Accessibility is part of the component contract:
512
700
 
513
- - Radix-backed components provide keyboard interaction and focus management.
701
+ - Base UI-backed components provide keyboard interaction and focus management.
514
702
  - Route-backed navigation uses semantic links and `aria-current`.
515
703
  - Dialogs and sheets provide labelled modal structure.
516
704
  - Form controls expose native labelling and validation attributes.
@@ -593,23 +781,45 @@ Reusable foundation, primitive, and pattern code belongs in `src`. Fixtures and
593
781
 
594
782
  ## Releasing
595
783
 
596
- Releases are published from GitHub Actions through npm trusted publishing. The
597
- release tag must exactly match the version in `package.json`.
784
+ The `1.0.0` release is the first public v1 package. Releases are published from
785
+ GitHub Actions through npm trusted publishing, with the release tag required to
786
+ match the version in `package.json` exactly. npm’s trusted-publishing flow
787
+ provides short-lived CI authentication and provenance for the published
788
+ package.
789
+
790
+ Before creating the v1 release tag, complete the release checklist in the
791
+ [migration ledger](./docs/base-ui-migration.md), finalize the
792
+ [app-owner migration guide](./docs/design-system-v1-migration.md), and run the
793
+ full local validation suite:
794
+
795
+ ```bash
796
+ pnpm lint
797
+ pnpm lint:playground
798
+ pnpm typecheck
799
+ pnpm typecheck:playground
800
+ pnpm test
801
+ pnpm test:package
802
+ pnpm test:consumer
803
+ pnpm build:playground
804
+ pnpm test:visual
805
+ ```
598
806
 
599
- For example, to publish the next patch:
807
+ Then prepare and tag the release:
600
808
 
601
809
  ```bash
602
- pnpm version patch --no-git-tag-version
603
- git add package.json
604
- git commit -m "Release v0.2.1"
605
- git tag -a v0.2.1 -m "Release v0.2.1"
810
+ pnpm version 1.0.0 --no-git-tag-version
811
+ git add package.json README.md docs/base-ui-migration.md docs/design-system-v1-migration.md
812
+ git commit -m "Release v1.0.0"
813
+ git tag -a v1.0.0 -m "Release v1.0.0"
606
814
  git push origin main
607
- git push origin v0.2.1
815
+ git push origin v1.0.0
608
816
  ```
609
817
 
610
- Pushing the tag starts the `npm-production` release workflow. The
611
- workflow verifies the tag, runs the package tests, builds the publishable
612
- artifacts, and publishes without a long-lived npm token.
818
+ Pushing the tag starts the `npm-production` release workflow. The workflow
819
+ verifies that `v1.0.0` matches `package.json`, runs the release validation, and
820
+ publishes the package to npm without a long-lived npm token. Because this is a
821
+ scoped public package, the release configuration must retain public access;
822
+ see npm’s [scoped-package publishing guidance](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/).
613
823
 
614
824
  ## Design-system boundaries
615
825
 
@@ -0,0 +1,49 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import * as React from 'react';
3
+ import { useRender } from '@base-ui/react/use-render';
4
+ import { VariantProps } from 'class-variance-authority';
5
+
6
+ declare const buttonVariants: (props?: ({
7
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
8
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
9
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
10
+ type ButtonProps = React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
11
+ render?: useRender.ComponentProps<"button">["render"];
12
+ };
13
+ declare function Button({ className, variant, size, render, type, ...props }: ButtonProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
14
+ type IconButtonNameProps = {
15
+ "aria-label": string;
16
+ "aria-labelledby"?: string;
17
+ } | {
18
+ "aria-label"?: string;
19
+ "aria-labelledby": string;
20
+ };
21
+ type IconButtonProps = Omit<ButtonProps, "children" | "size" | "aria-label" | "aria-labelledby"> & IconButtonNameProps & {
22
+ children: React.ReactNode;
23
+ size?: "sm" | "default" | "lg";
24
+ };
25
+ declare function IconButton({ className, size, ...props }: IconButtonProps): React.JSX.Element;
26
+
27
+ declare function Input({ className, type, ...props }: React.ComponentProps<"input">): React.JSX.Element;
28
+
29
+ type SeparatorProps = React.ComponentProps<"div"> & {
30
+ decorative?: boolean;
31
+ orientation?: "horizontal" | "vertical";
32
+ };
33
+ declare function Separator({ className, orientation, decorative, role, ...props }: SeparatorProps): React.JSX.Element;
34
+
35
+ declare const cardVariants: (props?: ({
36
+ variant?: "default" | "muted" | "elevated" | null | undefined;
37
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
38
+ type CardProps = React.ComponentProps<"div"> & VariantProps<typeof cardVariants>;
39
+ declare function Card({ className, variant, ...props }: CardProps): React.JSX.Element;
40
+ type CardHeaderProps = React.ComponentProps<"div"> & {
41
+ action?: React.ReactNode;
42
+ };
43
+ declare function CardHeader({ action, children, className, ...props }: CardHeaderProps): React.JSX.Element;
44
+ declare function CardTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
45
+ declare function CardDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
46
+ declare function CardContent({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
47
+ declare function CardFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
48
+
49
+ export { Button as B, Card as C, IconButton as I, Separator as S, type ButtonProps as a, CardContent as b, CardDescription as c, CardFooter as d, CardHeader as e, type CardHeaderProps as f, type CardProps as g, CardTitle as h, type IconButtonProps as i, Input as j, type SeparatorProps as k, buttonVariants as l, cardVariants as m };