@conscia-labs/design-system 0.4.0 → 1.0.1

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. `1.0.0` is published as the stable v1 release.
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,16 @@ 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
+ - LoadingButton
75
+ - IconButton
55
76
  - Card
56
77
  - Checkbox
57
78
  - Collapsible
@@ -59,13 +80,19 @@ Reusable interface building blocks composed from React, Radix UI, and ShadCN con
59
80
  - Dropdown menu
60
81
  - Field and form controls
61
82
  - Input and textarea
62
- - Select and searchable select
83
+ - Select, FormSelect, and searchable select
63
84
  - Sheet
64
85
  - Skeleton
65
86
  - Switch
66
87
  - Table
67
88
  - Tabs and navigation tabs
68
89
  - Tooltip
90
+ - Popover
91
+ - Shortcut hint
92
+ - Spinner
93
+ - Avatar group
94
+ - Filter chip
95
+ - Toast provider and viewport
69
96
 
70
97
  ### Patterns
71
98
 
@@ -80,21 +107,74 @@ Higher-level compositions for recurring product workflows:
80
107
  - Empty, loading, and error states
81
108
  - Activity lists and metric bands
82
109
  - Code blocks and value meters
110
+ - Command palette
111
+ - Filter bar
112
+
113
+ ### Supporting interaction patterns
114
+
115
+ #### Command palette
116
+
117
+ `CommandPalette` accepts an explicit list of commands, filters labels and
118
+ keywords, and supports keyboard navigation without a global command registry:
119
+
120
+ ```tsx
121
+ import { Button, CommandPalette } from "@conscia-labs/design-system";
122
+
123
+ <CommandPalette
124
+ items={[{ id: "settings", label: "Open settings", keywords: ["preferences"] }]}
125
+ onSelect={(item) => openCommand(item.id)}
126
+ trigger={<Button variant="outline">Open commands</Button>}
127
+ />
128
+ ```
129
+
130
+ #### Toasts
131
+
132
+ Toasts are opt-in. Mount one provider and viewport, then use `useToast` from a
133
+ descendant component:
134
+
135
+ ```tsx
136
+ import {
137
+ Button,
138
+ ToastProvider,
139
+ ToastViewport,
140
+ useToast,
141
+ } from "@conscia-labs/design-system";
142
+
143
+ function SaveButton() {
144
+ const { add } = useToast();
145
+ return (
146
+ <Button onClick={() => add({ title: "Saved", variant: "success" })}>
147
+ Save
148
+ </Button>
149
+ );
150
+ }
151
+
152
+ function App() {
153
+ return (
154
+ <ToastProvider>
155
+ <SaveButton />
156
+ <ToastViewport />
157
+ </ToastProvider>
158
+ );
159
+ }
160
+ ```
83
161
 
84
162
  ## Quick start
85
163
 
86
164
  ### 1. Install the package
87
165
 
166
+ For v1, install the explicit `1.0.0` range:
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
@@ -233,6 +313,40 @@ export function CreateConnectionCard() {
233
313
  }
234
314
  ```
235
315
 
316
+ ### Text-in-track switches
317
+
318
+ Use `LabeledSwitch` when the switch state should be visible inside the control.
319
+ It keeps Base UI’s switch behavior and accepts any React node for either label:
320
+
321
+ ```tsx
322
+ import { LabeledSwitch } from "@conscia-labs/design-system";
323
+
324
+ <LabeledSwitch
325
+ aria-label="Deployment status"
326
+ defaultChecked
327
+ onLabel="ENABLED"
328
+ offLabel="DISABLED"
329
+ />
330
+ ```
331
+
332
+ `Switch` also accepts `onLabel` and `offLabel` when a single API needs to support
333
+ both the compact unlabeled style and the text-in-track style. If a label is
334
+ provided without its pair, the missing label defaults to `ON` or `OFF`.
335
+
336
+ ### Loading buttons
337
+
338
+ Use `LoadingButton` for async actions that need stable button layout while a
339
+ mutation is pending. It disables the button, sets `aria-busy`, and replaces the
340
+ normal content with a small spinner and `pendingLabel`:
341
+
342
+ ```tsx
343
+ import { LoadingButton } from "@conscia-labs/design-system";
344
+
345
+ <LoadingButton pending={saveMutation.isPending} pendingLabel="Saving…">
346
+ Save changes
347
+ </LoadingButton>
348
+ ```
349
+
236
350
  ## Building an application shell
237
351
 
238
352
  The shared shell owns presentation and responsive behavior. The host application supplies routes, links, user context, and actions.
@@ -413,6 +527,20 @@ lockups, collapsed navigation identity, and other shared brand placements.
413
527
  The icon is decorative by default. Add an `aria-label` when the mark conveys
414
528
  meaning without adjacent text, and use `className` to control its size.
415
529
 
530
+ ### BrandWordmark
531
+
532
+ `BrandWordmark` is the shared no-tagline Conscia lockup. It embeds the supplied
533
+ 496×113 vector geometry and uses `currentColor`, so applications do not need
534
+ separate black and white assets or runtime asset paths. The default treatment
535
+ matches `BrandIcon`: foreground in light mode and white in dark mode.
536
+
537
+ The wordmark is decorative by default. Add an `aria-label` when it is the only
538
+ accessible naming content, and use `className` to control its width.
539
+
540
+ ```tsx
541
+ <BrandWordmark aria-label="Conscia" className="w-36" />
542
+ ```
543
+
416
544
  ### Sidebar variants and semantic surfaces
417
545
 
418
546
  `AppSidebar` keeps the historical dark treatment by default. Consumers that
@@ -432,14 +560,12 @@ an explicitly light sidebar.
432
560
  </AppShell>
433
561
  ```
434
562
 
435
- The default is intentionally backwards compatible. The sidebar scope exposes
436
- reusable semantic aliases for its canvas, header, content, hover, active,
437
- search, footer, text, icon, group label, count, border, and focus-ring roles.
563
+ The sidebar scope exposes reusable semantic roles for its canvas, header,
564
+ content, hover, active, search, footer, text, icon, group label, count,
565
+ border, and focus-ring roles.
438
566
  Use the generated utilities such as `bg-sidebar-canvas`,
439
567
  `bg-sidebar-hover`, `text-sidebar-primary-text`, and
440
568
  `text-sidebar-metadata-text` in shared or application-owned compositions.
441
- Legacy aliases including `bg-sidebar`, `bg-sidebar-accent`, and
442
- `text-sidebar-foreground` remain supported.
443
569
 
444
570
  Form controls and outline buttons use `bg-surface-control`, with
445
571
  `bg-surface-control-hover` for the outline hover state. These semantic surfaces
@@ -458,16 +584,16 @@ Dark mode uses a calm charcoal surface ladder rather than a pure-black canvas:
458
584
 
459
585
  | Role | Token | Dark value |
460
586
  | --- | --- | --- |
461
- | Application canvas | `--background` / `--canvas` | `#17191c` |
462
- | Standard surface | `--card` / `--surface` | `#1d2024` |
587
+ | Application canvas | `--canvas` | `#17191c` |
588
+ | Standard surface | `--surface` | `#1d2024` |
463
589
  | Raised surface and control | `--surface-raised` / `--surface-control` | `#24272c` |
464
590
  | Muted and control-hover surface | `--surface-muted` / `--surface-control-hover` | `#282b31` |
465
- | Floating surface | `--surface-floating` / `--popover` | `#2c2f36` |
591
+ | Floating surface | `--surface-floating` | `#2c2f36` |
466
592
  | Overlay surface | `--surface-overlay` | `#31343a` |
467
593
 
468
594
  The adjacent steps are intentionally close enough for a calm reading
469
595
  environment while remaining distinguishable through luminance, borders, and
470
- elevation. `--foreground` is a soft high-priority text role (`#eff1f4`), while
596
+ elevation. `--text-primary` is a soft high-priority text role (`#eff1f4`), while
471
597
  `--text-secondary`, `--text-supporting`, and `--text-muted` step down to
472
598
  `#d4d8df`, `#b3bac5`, and `#929aa7`. Use the semantic `bg-surface-*` and
473
599
  `text-*` utilities instead of copying these values into an application. The
@@ -576,7 +702,7 @@ Color communicates meaning rather than palette choice:
576
702
  | --- | --- |
577
703
  | `brand` | Conscia identity and signature moments |
578
704
  | `brand-secondary` | Supporting brand expression |
579
- | `primary` | The primary next action |
705
+ | `action-*` | Primary actions and their hover, active, foreground, and tinted-background roles |
580
706
  | `selection-*` | Current selection or active destination |
581
707
  | `information-*` | Informational messages and evidence |
582
708
  | `success-*` | Healthy, verified, approved, or completed states |
@@ -606,7 +732,7 @@ Prefer semantic variables over component-specific descendant selectors. This kee
606
732
 
607
733
  Accessibility is part of the component contract:
608
734
 
609
- - Radix-backed components provide keyboard interaction and focus management.
735
+ - Base UI-backed components provide keyboard interaction and focus management.
610
736
  - Route-backed navigation uses semantic links and `aria-current`.
611
737
  - Dialogs and sheets provide labelled modal structure.
612
738
  - Form controls expose native labelling and validation attributes.
@@ -689,23 +815,46 @@ Reusable foundation, primitive, and pattern code belongs in `src`. Fixtures and
689
815
 
690
816
  ## Releasing
691
817
 
692
- Releases are published from GitHub Actions through npm trusted publishing. The
693
- release tag must exactly match the version in `package.json`.
818
+ The `1.0.0` release is the first public v1 package. Releases are published from
819
+ GitHub Actions through npm trusted publishing, with the release tag required to
820
+ match the version in `package.json` exactly. npm’s trusted-publishing flow
821
+ provides short-lived CI authentication and provenance for the published
822
+ package.
823
+
824
+ Before creating a release tag, complete the release checklist in the
825
+ [migration ledger](./docs/base-ui-migration.md), finalize the
826
+ [app-owner migration guide](./docs/design-system-v1-migration.md), and run the
827
+ full local validation suite:
828
+
829
+ ```bash
830
+ pnpm lint
831
+ pnpm lint:playground
832
+ pnpm typecheck
833
+ pnpm typecheck:playground
834
+ pnpm test
835
+ pnpm test:package
836
+ pnpm test:consumer
837
+ pnpm build:playground
838
+ pnpm test:visual
839
+ ```
694
840
 
695
- For example, to publish the next patch:
841
+ Then prepare and tag a release. Replace `VERSION` with the package version you
842
+ are releasing:
696
843
 
697
844
  ```bash
698
- pnpm version patch --no-git-tag-version
699
- git add package.json
700
- git commit -m "Release v0.2.1"
701
- git tag -a v0.2.1 -m "Release v0.2.1"
845
+ pnpm version VERSION --no-git-tag-version
846
+ git add package.json README.md docs/base-ui-migration.md docs/design-system-v1-migration.md
847
+ git commit -m "Release vVERSION"
848
+ git tag -a vVERSION -m "Release vVERSION"
702
849
  git push origin main
703
- git push origin v0.2.1
850
+ git push origin vVERSION
704
851
  ```
705
852
 
706
- Pushing the tag starts the `npm-production` release workflow. The
707
- workflow verifies the tag, runs the package tests, builds the publishable
708
- artifacts, and publishes without a long-lived npm token.
853
+ Pushing the tag starts the `npm-production` release workflow. The workflow
854
+ verifies that the tag matches `package.json`, runs the release validation, and
855
+ publishes the package to npm without a long-lived npm token. Because this is a
856
+ scoped public package, the release configuration must retain public access;
857
+ see npm’s [scoped-package publishing guidance](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/).
709
858
 
710
859
  ## Design-system boundaries
711
860
 
@@ -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 };
@@ -0,0 +1,13 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
+
9
+ export {
10
+ __export,
11
+ __publicField
12
+ };
13
+ //# sourceMappingURL=chunk-UVKRO5ER.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}