minutework 0.1.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.
Files changed (203) hide show
  1. package/EXTERNAL_ALPHA.md +74 -0
  2. package/README.md +57 -0
  3. package/assets/claude-local/CLAUDE.md.template +45 -0
  4. package/assets/claude-local/bundle.json +22 -0
  5. package/assets/claude-local/skills/README.md +6 -0
  6. package/assets/claude-local/skills/app-pack-authoring.md +8 -0
  7. package/assets/claude-local/skills/event-bus.md +8 -0
  8. package/assets/claude-local/skills/ontology-mapping.md +8 -0
  9. package/assets/claude-local/skills/openclaw-skill-importer.md +7 -0
  10. package/assets/claude-local/skills/schema-engine.md +8 -0
  11. package/assets/claude-local/skills/secrets-runtime-bridge.md +9 -0
  12. package/assets/claude-local/skills/sidecar-generation.md +9 -0
  13. package/assets/templates/fastapi-sidecar/.env.example +8 -0
  14. package/assets/templates/fastapi-sidecar/README.md +77 -0
  15. package/assets/templates/fastapi-sidecar/poetry.lock +757 -0
  16. package/assets/templates/fastapi-sidecar/pyproject.toml +42 -0
  17. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/__init__.py +3 -0
  18. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/auth.py +70 -0
  19. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/bridge/__init__.py +3 -0
  20. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/bridge/client.py +71 -0
  21. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/logging_utils.py +25 -0
  22. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/main.py +85 -0
  23. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/receipts.py +24 -0
  24. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/settings.py +41 -0
  25. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/template_validation.py +26 -0
  26. package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/worker.py +33 -0
  27. package/assets/templates/fastapi-sidecar/template.json +43 -0
  28. package/assets/templates/fastapi-sidecar/template.schema.json +160 -0
  29. package/assets/templates/fastapi-sidecar/tests/conftest.py +36 -0
  30. package/assets/templates/fastapi-sidecar/tests/test_app.py +39 -0
  31. package/assets/templates/fastapi-sidecar/tests/test_auth.py +32 -0
  32. package/assets/templates/fastapi-sidecar/tests/test_bridge_client.py +31 -0
  33. package/assets/templates/fastapi-sidecar/tests/test_materialization.py +55 -0
  34. package/assets/templates/fastapi-sidecar/tests/test_template_contract.py +49 -0
  35. package/assets/templates/fastapi-sidecar/tests/test_worker.py +7 -0
  36. package/assets/templates/fastapi-sidecar/tools/template/validate_template.py +20 -0
  37. package/assets/templates/next-tenant-app/.env.example +8 -0
  38. package/assets/templates/next-tenant-app/.storybook/main.ts +19 -0
  39. package/assets/templates/next-tenant-app/.storybook/preview.tsx +38 -0
  40. package/assets/templates/next-tenant-app/README.md +115 -0
  41. package/assets/templates/next-tenant-app/components.json +21 -0
  42. package/assets/templates/next-tenant-app/eslint.config.mjs +41 -0
  43. package/assets/templates/next-tenant-app/next-env.d.ts +6 -0
  44. package/assets/templates/next-tenant-app/next.config.ts +8 -0
  45. package/assets/templates/next-tenant-app/package-lock.json +9682 -0
  46. package/assets/templates/next-tenant-app/package.json +59 -0
  47. package/assets/templates/next-tenant-app/pnpm-lock.yaml +6062 -0
  48. package/assets/templates/next-tenant-app/postcss.config.mjs +8 -0
  49. package/assets/templates/next-tenant-app/src/app/api/auth/context/route.test.ts +90 -0
  50. package/assets/templates/next-tenant-app/src/app/api/auth/context/route.ts +78 -0
  51. package/assets/templates/next-tenant-app/src/app/api/auth/login/route.ts +31 -0
  52. package/assets/templates/next-tenant-app/src/app/api/auth/logout/route.ts +16 -0
  53. package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.test.ts +79 -0
  54. package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.ts +40 -0
  55. package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.test.ts +42 -0
  56. package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.ts +29 -0
  57. package/assets/templates/next-tenant-app/src/app/api/auth/session/route.ts +26 -0
  58. package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.test.ts +40 -0
  59. package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.ts +47 -0
  60. package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.test.ts +43 -0
  61. package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.ts +45 -0
  62. package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.test.ts +83 -0
  63. package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.tsx +30 -0
  64. package/assets/templates/next-tenant-app/src/app/app/layout.tsx +20 -0
  65. package/assets/templates/next-tenant-app/src/app/app/page.test.ts +62 -0
  66. package/assets/templates/next-tenant-app/src/app/app/page.tsx +24 -0
  67. package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.test.ts +70 -0
  68. package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.tsx +57 -0
  69. package/assets/templates/next-tenant-app/src/app/blog/page.test.ts +42 -0
  70. package/assets/templates/next-tenant-app/src/app/blog/page.tsx +37 -0
  71. package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.test.ts +70 -0
  72. package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.tsx +55 -0
  73. package/assets/templates/next-tenant-app/src/app/docs/page.test.ts +42 -0
  74. package/assets/templates/next-tenant-app/src/app/docs/page.tsx +37 -0
  75. package/assets/templates/next-tenant-app/src/app/globals.css +70 -0
  76. package/assets/templates/next-tenant-app/src/app/layout.tsx +69 -0
  77. package/assets/templates/next-tenant-app/src/app/login/page.test.ts +55 -0
  78. package/assets/templates/next-tenant-app/src/app/login/page.tsx +33 -0
  79. package/assets/templates/next-tenant-app/src/app/page.test.ts +56 -0
  80. package/assets/templates/next-tenant-app/src/app/page.tsx +35 -0
  81. package/assets/templates/next-tenant-app/src/app/pricing/page.test.ts +55 -0
  82. package/assets/templates/next-tenant-app/src/app/pricing/page.tsx +35 -0
  83. package/assets/templates/next-tenant-app/src/app/providers.tsx +25 -0
  84. package/assets/templates/next-tenant-app/src/app/robots.test.ts +20 -0
  85. package/assets/templates/next-tenant-app/src/app/robots.ts +18 -0
  86. package/assets/templates/next-tenant-app/src/app/sitemap.test.ts +49 -0
  87. package/assets/templates/next-tenant-app/src/app/sitemap.ts +54 -0
  88. package/assets/templates/next-tenant-app/src/components/ui/button.tsx +59 -0
  89. package/assets/templates/next-tenant-app/src/components/ui/input.tsx +21 -0
  90. package/assets/templates/next-tenant-app/src/design-system/docs/governance.mdx +26 -0
  91. package/assets/templates/next-tenant-app/src/design-system/patterns/panel-frame.stories.tsx +48 -0
  92. package/assets/templates/next-tenant-app/src/design-system/patterns/panel-frame.tsx +26 -0
  93. package/assets/templates/next-tenant-app/src/design-system/patterns/status-badge.stories.tsx +26 -0
  94. package/assets/templates/next-tenant-app/src/design-system/patterns/status-badge.tsx +35 -0
  95. package/assets/templates/next-tenant-app/src/design-system/patterns/theme-mode-toggle.stories.tsx +21 -0
  96. package/assets/templates/next-tenant-app/src/design-system/patterns/theme-mode-toggle.tsx +75 -0
  97. package/assets/templates/next-tenant-app/src/design-system/primitives/button.stories.tsx +37 -0
  98. package/assets/templates/next-tenant-app/src/design-system/primitives/button.ts +1 -0
  99. package/assets/templates/next-tenant-app/src/design-system/primitives/input.stories.tsx +26 -0
  100. package/assets/templates/next-tenant-app/src/design-system/primitives/input.ts +1 -0
  101. package/assets/templates/next-tenant-app/src/design-system/recipes/chrome.ts +28 -0
  102. package/assets/templates/next-tenant-app/src/design-system/tokens/foundation.css +31 -0
  103. package/assets/templates/next-tenant-app/src/design-system/tokens/index.css +3 -0
  104. package/assets/templates/next-tenant-app/src/design-system/tokens/manifest.json +85 -0
  105. package/assets/templates/next-tenant-app/src/design-system/tokens/manifest.ts +87 -0
  106. package/assets/templates/next-tenant-app/src/design-system/tokens/semantic.css +105 -0
  107. package/assets/templates/next-tenant-app/src/design-system/tokens/theme.css +59 -0
  108. package/assets/templates/next-tenant-app/src/design-system/tokens/tokens.stories.tsx +71 -0
  109. package/assets/templates/next-tenant-app/src/features/auth/components/login-screen.tsx +198 -0
  110. package/assets/templates/next-tenant-app/src/features/dashboard/components/tenant-dashboard.tsx +153 -0
  111. package/assets/templates/next-tenant-app/src/features/examples/runtime-command-demo/components/runtime-command-demo.tsx +342 -0
  112. package/assets/templates/next-tenant-app/src/features/public-shell/components/content-article.tsx +66 -0
  113. package/assets/templates/next-tenant-app/src/features/public-shell/components/content-collection.tsx +108 -0
  114. package/assets/templates/next-tenant-app/src/features/public-shell/components/marketing-page-canvas.tsx +111 -0
  115. package/assets/templates/next-tenant-app/src/features/public-shell/components/public-site-shell.tsx +111 -0
  116. package/assets/templates/next-tenant-app/src/features/shell/components/private-app-shell.tsx +624 -0
  117. package/assets/templates/next-tenant-app/src/lib/app-routes.test.ts +20 -0
  118. package/assets/templates/next-tenant-app/src/lib/app-routes.ts +59 -0
  119. package/assets/templates/next-tenant-app/src/lib/content/__fixtures__/public-site-snapshot.ts +189 -0
  120. package/assets/templates/next-tenant-app/src/lib/content/adapter.server.test.ts +318 -0
  121. package/assets/templates/next-tenant-app/src/lib/content/adapter.server.ts +232 -0
  122. package/assets/templates/next-tenant-app/src/lib/content/contracts.ts +339 -0
  123. package/assets/templates/next-tenant-app/src/lib/content/custom-adapter.ts +5 -0
  124. package/assets/templates/next-tenant-app/src/lib/content/empty-state.ts +96 -0
  125. package/assets/templates/next-tenant-app/src/lib/platform/auth.server.test.ts +75 -0
  126. package/assets/templates/next-tenant-app/src/lib/platform/auth.server.ts +25 -0
  127. package/assets/templates/next-tenant-app/src/lib/platform/client.server.test.ts +170 -0
  128. package/assets/templates/next-tenant-app/src/lib/platform/client.server.ts +661 -0
  129. package/assets/templates/next-tenant-app/src/lib/platform/contracts.ts +131 -0
  130. package/assets/templates/next-tenant-app/src/lib/platform/endpoints.server.ts +34 -0
  131. package/assets/templates/next-tenant-app/src/lib/platform/env.server.test.ts +102 -0
  132. package/assets/templates/next-tenant-app/src/lib/platform/env.server.ts +87 -0
  133. package/assets/templates/next-tenant-app/src/lib/platform/route-response.ts +33 -0
  134. package/assets/templates/next-tenant-app/src/lib/platform/session.server.ts +108 -0
  135. package/assets/templates/next-tenant-app/src/lib/public-site.test.ts +20 -0
  136. package/assets/templates/next-tenant-app/src/lib/public-site.ts +49 -0
  137. package/assets/templates/next-tenant-app/src/lib/theme-config.ts +10 -0
  138. package/assets/templates/next-tenant-app/src/lib/theme.tsx +159 -0
  139. package/assets/templates/next-tenant-app/src/lib/utils.ts +6 -0
  140. package/assets/templates/next-tenant-app/template.json +27 -0
  141. package/assets/templates/next-tenant-app/template.schema.json +160 -0
  142. package/assets/templates/next-tenant-app/test/server-only-stub.ts +1 -0
  143. package/assets/templates/next-tenant-app/tools/design-system/build-token-manifest.mjs +3 -0
  144. package/assets/templates/next-tenant-app/tools/design-system/check-imports.mjs +9 -0
  145. package/assets/templates/next-tenant-app/tools/design-system/check-stories.mjs +9 -0
  146. package/assets/templates/next-tenant-app/tools/design-system/check-values.mjs +9 -0
  147. package/assets/templates/next-tenant-app/tools/design-system/checks.mjs +238 -0
  148. package/assets/templates/next-tenant-app/tools/design-system/eslint-plugin-design-system.mjs +184 -0
  149. package/assets/templates/next-tenant-app/tools/design-system/playwright.config.mjs +34 -0
  150. package/assets/templates/next-tenant-app/tools/design-system/run-checks.mjs +22 -0
  151. package/assets/templates/next-tenant-app/tools/design-system/shared.mjs +166 -0
  152. package/assets/templates/next-tenant-app/tools/design-system/visual.spec.ts +41 -0
  153. package/assets/templates/next-tenant-app/tools/template/validate-route-contract.mjs +39 -0
  154. package/assets/templates/next-tenant-app/tools/template/validate-template.mjs +45 -0
  155. package/assets/templates/next-tenant-app/tsconfig.json +42 -0
  156. package/assets/templates/next-tenant-app/vitest.config.ts +25 -0
  157. package/bin/minutework.js +40 -0
  158. package/dist/auth.d.ts +59 -0
  159. package/dist/auth.js +338 -0
  160. package/dist/auth.js.map +1 -0
  161. package/dist/browser.d.ts +1 -0
  162. package/dist/browser.js +26 -0
  163. package/dist/browser.js.map +1 -0
  164. package/dist/cli.d.ts +2 -0
  165. package/dist/cli.js +5 -0
  166. package/dist/cli.js.map +1 -0
  167. package/dist/compile.d.ts +20 -0
  168. package/dist/compile.js +121 -0
  169. package/dist/compile.js.map +1 -0
  170. package/dist/config.d.ts +25 -0
  171. package/dist/config.js +102 -0
  172. package/dist/config.js.map +1 -0
  173. package/dist/deploy-state.d.ts +35 -0
  174. package/dist/deploy-state.js +30 -0
  175. package/dist/deploy-state.js.map +1 -0
  176. package/dist/deploy.d.ts +22 -0
  177. package/dist/deploy.js +308 -0
  178. package/dist/deploy.js.map +1 -0
  179. package/dist/developer-client.d.ts +88 -0
  180. package/dist/developer-client.js +78 -0
  181. package/dist/developer-client.js.map +1 -0
  182. package/dist/index.d.ts +27 -0
  183. package/dist/index.js +290 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/init.d.ts +22 -0
  186. package/dist/init.js +421 -0
  187. package/dist/init.js.map +1 -0
  188. package/dist/launcher.d.ts +1 -0
  189. package/dist/launcher.js +50 -0
  190. package/dist/launcher.js.map +1 -0
  191. package/dist/paths.d.ts +12 -0
  192. package/dist/paths.js +33 -0
  193. package/dist/paths.js.map +1 -0
  194. package/dist/sandbox.d.ts +30 -0
  195. package/dist/sandbox.js +852 -0
  196. package/dist/sandbox.js.map +1 -0
  197. package/dist/state.d.ts +46 -0
  198. package/dist/state.js +82 -0
  199. package/dist/state.js.map +1 -0
  200. package/dist/tokens.d.ts +14 -0
  201. package/dist/tokens.js +293 -0
  202. package/dist/tokens.js.map +1 -0
  203. package/package.json +43 -0
@@ -0,0 +1,26 @@
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
+
3
+ <Meta title="Design System/Governance" />
4
+
5
+ # Governance
6
+
7
+ The design system lives under `src/design-system` and is the only public visual API for application code.
8
+
9
+ ## Import contract
10
+
11
+ - Allowed in route and feature code: `@/design-system/primitives/*`, `@/design-system/patterns/*`, `@/design-system/recipes/*`, and `@/design-system/tokens/manifest`.
12
+ - Forbidden outside `src/design-system`: `@/components/ui/*`, `@radix-ui/*`, and direct raw token CSS imports.
13
+
14
+ ## Authoring rules
15
+
16
+ - Literal color values belong only in `src/design-system/tokens`.
17
+ - Route and feature code compose primitives and patterns instead of creating one-off inline visual systems.
18
+ - Inline styles are allowed only for CSS variable references or truly dynamic layout values.
19
+ - Reused UI should be promoted into `src/design-system/patterns`.
20
+
21
+ ## Enforcement
22
+
23
+ - `pnpm validate` runs template validation, type generation, token regeneration, `pnpm design-system:check`, and the app test/build pipeline.
24
+ - `pnpm design-system:check` validates imports, raw values, and story coverage.
25
+ - `pnpm build-storybook` keeps documentation coverage intact.
26
+ - `pnpm design-system:visual` is optional for local visual baselines, but `tools/design-system/__screenshots__/` is not shipped in the canonical template bundle.
@@ -0,0 +1,48 @@
1
+ import type { Meta, StoryObj } from "@storybook/nextjs-vite";
2
+
3
+ import { Button } from "@/design-system/primitives/button";
4
+ import { PanelFrame } from "@/design-system/patterns/panel-frame";
5
+
6
+ const meta = {
7
+ title: "Design System/Patterns/Panel Frame",
8
+ component: PanelFrame,
9
+ tags: ["autodocs"],
10
+ } satisfies Meta<typeof PanelFrame>;
11
+
12
+ export default meta;
13
+
14
+ type Story = StoryObj<typeof meta>;
15
+
16
+ export const Raised: Story = {
17
+ render: () => (
18
+ <PanelFrame tone="raised" className="w-96 space-y-4">
19
+ <div className="space-y-1">
20
+ <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
21
+ Tenant thread
22
+ </p>
23
+ <h3 className="text-lg font-semibold text-foreground">Missing rent receipt</h3>
24
+ <p className="text-sm text-muted-foreground">
25
+ Keep recurring workspace panels visually consistent across login, command, and status
26
+ surfaces.
27
+ </p>
28
+ </div>
29
+ <div className="flex gap-2">
30
+ <Button size="sm">Follow up</Button>
31
+ <Button size="sm" variant="outline">
32
+ Open details
33
+ </Button>
34
+ </div>
35
+ </PanelFrame>
36
+ ),
37
+ };
38
+
39
+ export const Sidebar: Story = {
40
+ render: () => (
41
+ <PanelFrame tone="sidebar" radius="none" className="w-80 space-y-3 border-l">
42
+ <h3 className="text-sm font-semibold text-foreground">Shell surface</h3>
43
+ <p className="text-sm text-muted-foreground">
44
+ Use the sidebar tone for docked navigation or support surfaces.
45
+ </p>
46
+ </PanelFrame>
47
+ ),
48
+ };
@@ -0,0 +1,26 @@
1
+ import * as React from "react";
2
+
3
+ import { type VariantProps } from "class-variance-authority";
4
+
5
+ import { panelFrameVariants } from "@/design-system/recipes/chrome";
6
+ import { cn } from "@/lib/utils";
7
+
8
+ type PanelFrameProps = React.ComponentProps<"div"> &
9
+ VariantProps<typeof panelFrameVariants>;
10
+
11
+ function PanelFrame({
12
+ className,
13
+ tone,
14
+ radius,
15
+ padding,
16
+ ...props
17
+ }: PanelFrameProps) {
18
+ return (
19
+ <div
20
+ className={cn(panelFrameVariants({ tone, radius, padding }), className)}
21
+ {...props}
22
+ />
23
+ );
24
+ }
25
+
26
+ export { PanelFrame, panelFrameVariants };
@@ -0,0 +1,26 @@
1
+ import type { Meta, StoryObj } from "@storybook/nextjs-vite";
2
+
3
+ import { StatusBadge } from "@/design-system/patterns/status-badge";
4
+
5
+ const meta = {
6
+ title: "Design System/Patterns/Status Badge",
7
+ component: StatusBadge,
8
+ tags: ["autodocs"],
9
+ } satisfies Meta<typeof StatusBadge>;
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof meta>;
14
+
15
+ export const AllTones: Story = {
16
+ render: () => (
17
+ <div className="flex flex-wrap gap-2">
18
+ <StatusBadge tone="default">Draft</StatusBadge>
19
+ <StatusBadge tone="primary">AI suggested</StatusBadge>
20
+ <StatusBadge tone="success">Completed</StatusBadge>
21
+ <StatusBadge tone="warning">Needs review</StatusBadge>
22
+ <StatusBadge tone="danger">Failed</StatusBadge>
23
+ <StatusBadge tone="info">Queued</StatusBadge>
24
+ </div>
25
+ ),
26
+ };
@@ -0,0 +1,35 @@
1
+ import * as React from "react";
2
+
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ const statusBadgeVariants = cva(
8
+ "inline-flex items-center rounded px-2 py-0.5 text-xs font-medium",
9
+ {
10
+ variants: {
11
+ tone: {
12
+ default: "bg-muted text-muted-foreground",
13
+ primary: "bg-primary/15 text-text-link",
14
+ success: "bg-success/20 text-success",
15
+ warning: "bg-warning/20 text-warning",
16
+ danger: "bg-danger/20 text-danger",
17
+ info: "bg-info/20 text-info",
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ tone: "default",
22
+ },
23
+ },
24
+ );
25
+
26
+ type StatusBadgeProps = React.ComponentProps<"span"> &
27
+ VariantProps<typeof statusBadgeVariants>;
28
+
29
+ function StatusBadge({ className, tone, ...props }: StatusBadgeProps) {
30
+ return (
31
+ <span className={cn(statusBadgeVariants({ tone }), className)} {...props} />
32
+ );
33
+ }
34
+
35
+ export { StatusBadge, statusBadgeVariants };
@@ -0,0 +1,21 @@
1
+ import type { Meta, StoryObj } from "@storybook/nextjs-vite";
2
+
3
+ import { ThemeModeToggle } from "@/design-system/patterns/theme-mode-toggle";
4
+
5
+ const meta = {
6
+ title: "Design System/Patterns/Theme Mode Toggle",
7
+ component: ThemeModeToggle,
8
+ tags: ["autodocs"],
9
+ } satisfies Meta<typeof ThemeModeToggle>;
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof meta>;
14
+
15
+ export const Default: Story = {
16
+ render: () => (
17
+ <div className="w-80 rounded-xl border border-border bg-surface p-4">
18
+ <ThemeModeToggle />
19
+ </div>
20
+ ),
21
+ };
@@ -0,0 +1,75 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import { Monitor, Moon, Sun } from "lucide-react";
6
+
7
+ import { Button } from "@/design-system/primitives/button";
8
+ import { useTheme } from "@/lib/theme";
9
+ import { cn } from "@/lib/utils";
10
+
11
+ type ThemeMode = "light" | "dark" | "system";
12
+
13
+ const themeOptions: Array<{
14
+ icon: React.ComponentType<{ className?: string }>;
15
+ label: string;
16
+ value: ThemeMode;
17
+ }> = [
18
+ { icon: Sun, label: "Light", value: "light" },
19
+ { icon: Moon, label: "Dark", value: "dark" },
20
+ { icon: Monitor, label: "System", value: "system" },
21
+ ];
22
+
23
+ export function ThemeModeToggle({
24
+ className,
25
+ }: React.ComponentProps<"section">) {
26
+ const { resolvedTheme, setTheme, theme } = useTheme();
27
+ const [mounted, setMounted] = React.useState(false);
28
+
29
+ React.useEffect(() => {
30
+ setMounted(true);
31
+ }, []);
32
+
33
+ const activeTheme = mounted ? ((theme ?? "system") as ThemeMode) : "system";
34
+ const resolvedLabel = mounted
35
+ ? activeTheme === "system"
36
+ ? `Following your OS: ${resolvedTheme ?? "light"}`
37
+ : `Locked to ${activeTheme}`
38
+ : "Loading preference";
39
+
40
+ return (
41
+ <section className={cn("space-y-2", className)}>
42
+ <div className="space-y-0.5">
43
+ <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
44
+ Theme
45
+ </p>
46
+ <p className="text-xs text-muted-foreground">{resolvedLabel}</p>
47
+ </div>
48
+ <div className="grid grid-cols-3 gap-1 rounded-xl border border-border bg-muted/60 p-1">
49
+ {themeOptions.map(({ icon: Icon, label, value }) => {
50
+ const isActive = activeTheme === value;
51
+
52
+ return (
53
+ <Button
54
+ key={value}
55
+ type="button"
56
+ size="sm"
57
+ variant="ghost"
58
+ aria-pressed={isActive}
59
+ onClick={() => setTheme(value)}
60
+ className={cn(
61
+ "h-8 justify-center gap-1.5 rounded-lg border px-2 text-xs",
62
+ isActive
63
+ ? "border-primary/20 bg-primary/10 text-text-link shadow-sm hover:bg-primary/15 hover:text-text-link dark:border-primary/40 dark:bg-primary dark:text-primary-foreground dark:hover:bg-primary/90 dark:hover:text-primary-foreground"
64
+ : "border-transparent text-muted-foreground hover:bg-background hover:text-foreground dark:hover:bg-surface-raised",
65
+ )}
66
+ >
67
+ <Icon className="size-3.5" />
68
+ <span>{label}</span>
69
+ </Button>
70
+ );
71
+ })}
72
+ </div>
73
+ </section>
74
+ );
75
+ }
@@ -0,0 +1,37 @@
1
+ import type { Meta, StoryObj } from "@storybook/nextjs-vite";
2
+ import { ArrowRight } from "lucide-react";
3
+
4
+ import { Button } from "@/design-system/primitives/button";
5
+
6
+ const meta = {
7
+ title: "Design System/Primitives/Button",
8
+ component: Button,
9
+ tags: ["autodocs"],
10
+ args: {
11
+ children: "Send follow-up",
12
+ },
13
+ } satisfies Meta<typeof Button>;
14
+
15
+ export default meta;
16
+
17
+ type Story = StoryObj<typeof meta>;
18
+
19
+ export const Primary: Story = {};
20
+
21
+ export const Outline: Story = {
22
+ args: {
23
+ variant: "outline",
24
+ children: "Review details",
25
+ },
26
+ };
27
+
28
+ export const WithIcon: Story = {
29
+ args: {
30
+ children: (
31
+ <>
32
+ Assign owner
33
+ <ArrowRight className="size-4" />
34
+ </>
35
+ ),
36
+ },
37
+ };
@@ -0,0 +1 @@
1
+ export { Button, buttonVariants } from "@/components/ui/button";
@@ -0,0 +1,26 @@
1
+ import type { Meta, StoryObj } from "@storybook/nextjs-vite";
2
+
3
+ import { Input } from "@/design-system/primitives/input";
4
+
5
+ const meta = {
6
+ title: "Design System/Primitives/Input",
7
+ component: Input,
8
+ tags: ["autodocs"],
9
+ args: {
10
+ placeholder: "Search tenants or tasks",
11
+ className: "w-72",
12
+ },
13
+ } satisfies Meta<typeof Input>;
14
+
15
+ export default meta;
16
+
17
+ type Story = StoryObj<typeof meta>;
18
+
19
+ export const Default: Story = {};
20
+
21
+ export const Invalid: Story = {
22
+ args: {
23
+ defaultValue: "late invoice",
24
+ "aria-invalid": true,
25
+ },
26
+ };
@@ -0,0 +1 @@
1
+ export { Input } from "@/components/ui/input";
@@ -0,0 +1,28 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ export const panelFrameVariants = cva("border border-border text-foreground", {
4
+ variants: {
5
+ tone: {
6
+ surface: "bg-surface",
7
+ raised: "bg-surface-raised",
8
+ sidebar: "bg-sidebar",
9
+ floating: "bg-surface shadow-xl",
10
+ },
11
+ radius: {
12
+ none: "rounded-none",
13
+ lg: "rounded-lg",
14
+ xl: "rounded-xl",
15
+ },
16
+ padding: {
17
+ none: "",
18
+ sm: "p-3",
19
+ md: "p-4",
20
+ lg: "p-6",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ tone: "surface",
25
+ radius: "lg",
26
+ padding: "md",
27
+ },
28
+ });
@@ -0,0 +1,31 @@
1
+ :root {
2
+ --ds-foundation-white: #ffffff;
3
+ --ds-foundation-neutral-50: #f7f8fb;
4
+ --ds-foundation-neutral-100: #e5e7eb;
5
+ --ds-foundation-neutral-200: #d7dce5;
6
+ --ds-foundation-neutral-500: #6b7280;
7
+ --ds-foundation-neutral-600: #4b5563;
8
+ --ds-foundation-neutral-700: #2a2d35;
9
+ --ds-foundation-neutral-800: #22262f;
10
+ --ds-foundation-neutral-850: #1a1d23;
11
+ --ds-foundation-neutral-900: #111316;
12
+ --ds-foundation-neutral-950: #0b0d0f;
13
+ --ds-foundation-ink-500: #183247;
14
+ --ds-foundation-ink-700: #102233;
15
+ --ds-foundation-cyan-50: #eef9fd;
16
+ --ds-foundation-cyan-100: #d9f1fb;
17
+ --ds-foundation-cyan-200: #b7e4f3;
18
+ --ds-foundation-cyan-300: #89d4f0;
19
+ --ds-foundation-violet-300: #a78bfa;
20
+ --ds-foundation-violet-500: #7c3aed;
21
+ --ds-foundation-violet-700: #2d1f7a;
22
+ --ds-foundation-cyan-500: #0ea5e9;
23
+ --ds-foundation-cyan-600: #0284c7;
24
+ --ds-foundation-cyan-700: #0f6787;
25
+ --ds-foundation-green-500: #22c55e;
26
+ --ds-foundation-blue-500: #3b82f6;
27
+ --ds-foundation-yellow-500: #f59e0b;
28
+ --ds-foundation-red-500: #ef4444;
29
+ --ds-foundation-overlay-50: rgb(0 0 0 / 0.5);
30
+ --ds-foundation-overlay-60: rgb(0 0 0 / 0.6);
31
+ }
@@ -0,0 +1,3 @@
1
+ @import "./foundation.css";
2
+ @import "./semantic.css";
3
+ @import "./theme.css";
@@ -0,0 +1,85 @@
1
+ {
2
+ "foundation": {
3
+ "ds-foundation-white": "#ffffff",
4
+ "ds-foundation-neutral-50": "#f7f8fb",
5
+ "ds-foundation-neutral-100": "#e5e7eb",
6
+ "ds-foundation-neutral-200": "#d7dce5",
7
+ "ds-foundation-neutral-500": "#6b7280",
8
+ "ds-foundation-neutral-600": "#4b5563",
9
+ "ds-foundation-neutral-700": "#2a2d35",
10
+ "ds-foundation-neutral-800": "#22262f",
11
+ "ds-foundation-neutral-850": "#1a1d23",
12
+ "ds-foundation-neutral-900": "#111316",
13
+ "ds-foundation-neutral-950": "#0b0d0f",
14
+ "ds-foundation-ink-500": "#183247",
15
+ "ds-foundation-ink-700": "#102233",
16
+ "ds-foundation-cyan-50": "#eef9fd",
17
+ "ds-foundation-cyan-100": "#d9f1fb",
18
+ "ds-foundation-cyan-200": "#b7e4f3",
19
+ "ds-foundation-cyan-300": "#89d4f0",
20
+ "ds-foundation-violet-300": "#a78bfa",
21
+ "ds-foundation-violet-500": "#7c3aed",
22
+ "ds-foundation-violet-700": "#2d1f7a",
23
+ "ds-foundation-cyan-500": "#0ea5e9",
24
+ "ds-foundation-cyan-600": "#0284c7",
25
+ "ds-foundation-cyan-700": "#0f6787",
26
+ "ds-foundation-green-500": "#22c55e",
27
+ "ds-foundation-blue-500": "#3b82f6",
28
+ "ds-foundation-yellow-500": "#f59e0b",
29
+ "ds-foundation-red-500": "#ef4444",
30
+ "ds-foundation-overlay-50": "rgb(0 0 0 / 0.5)",
31
+ "ds-foundation-overlay-60": "rgb(0 0 0 / 0.6)"
32
+ },
33
+ "semantic": {
34
+ "background": "var(--ds-foundation-neutral-950)",
35
+ "foreground": "var(--ds-foundation-neutral-100)",
36
+ "card": "var(--ds-foundation-neutral-850)",
37
+ "card-foreground": "var(--ds-foundation-neutral-100)",
38
+ "popover": "var(--ds-foundation-neutral-850)",
39
+ "popover-foreground": "var(--ds-foundation-neutral-100)",
40
+ "primary": "var(--ds-foundation-cyan-500)",
41
+ "primary-foreground": "var(--ds-foundation-white)",
42
+ "secondary": "var(--ds-foundation-neutral-800)",
43
+ "secondary-foreground": "var(--ds-foundation-neutral-100)",
44
+ "muted": "var(--ds-foundation-neutral-850)",
45
+ "muted-foreground": "var(--ds-foundation-neutral-500)",
46
+ "accent": "var(--ds-foundation-ink-700)",
47
+ "accent-foreground": "var(--ds-foundation-neutral-100)",
48
+ "destructive": "var(--ds-foundation-red-500)",
49
+ "destructive-foreground": "var(--ds-foundation-white)",
50
+ "border": "var(--ds-foundation-neutral-700)",
51
+ "input": "var(--ds-foundation-neutral-800)",
52
+ "ring": "var(--ds-foundation-cyan-500)",
53
+ "chart-1": "var(--ds-foundation-cyan-500)",
54
+ "chart-2": "var(--ds-foundation-green-500)",
55
+ "chart-3": "var(--ds-foundation-blue-500)",
56
+ "chart-4": "var(--ds-foundation-yellow-500)",
57
+ "chart-5": "var(--ds-foundation-red-500)",
58
+ "radius": "0.5rem",
59
+ "sidebar": "var(--ds-foundation-neutral-900)",
60
+ "sidebar-foreground": "var(--ds-foundation-neutral-100)",
61
+ "sidebar-primary": "var(--ds-foundation-cyan-500)",
62
+ "sidebar-primary-foreground": "var(--ds-foundation-white)",
63
+ "sidebar-accent": "var(--ds-foundation-neutral-800)",
64
+ "sidebar-accent-foreground": "var(--ds-foundation-neutral-100)",
65
+ "sidebar-border": "var(--ds-foundation-neutral-700)",
66
+ "sidebar-ring": "var(--ds-foundation-cyan-500)",
67
+ "surface": "var(--ds-foundation-neutral-850)",
68
+ "surface-raised": "var(--ds-foundation-neutral-800)",
69
+ "text-link": "var(--ds-foundation-cyan-300)",
70
+ "success": "var(--ds-foundation-green-500)",
71
+ "warning": "var(--ds-foundation-yellow-500)",
72
+ "danger": "var(--ds-foundation-red-500)",
73
+ "info": "var(--ds-foundation-blue-500)",
74
+ "ai-bubble": "var(--ds-foundation-neutral-850)",
75
+ "user-bubble": "var(--ds-foundation-cyan-600)",
76
+ "tenant-rail": "var(--ds-foundation-neutral-950)",
77
+ "tenant-rail-foreground": "var(--ds-foundation-white)",
78
+ "tenant-rail-muted": "rgb(255 255 255 / 0.72)",
79
+ "tenant-rail-border": "rgb(255 255 255 / 0.08)",
80
+ "tenant-rail-surface": "rgb(255 255 255 / 0.06)",
81
+ "overlay": "var(--ds-foundation-overlay-50)",
82
+ "overlay-strong": "var(--ds-foundation-overlay-60)",
83
+ "strong-foreground": "var(--ds-foundation-white)"
84
+ }
85
+ }
@@ -0,0 +1,87 @@
1
+ export const tokenManifest = {
2
+ "foundation": {
3
+ "ds-foundation-white": "#ffffff",
4
+ "ds-foundation-neutral-50": "#f7f8fb",
5
+ "ds-foundation-neutral-100": "#e5e7eb",
6
+ "ds-foundation-neutral-200": "#d7dce5",
7
+ "ds-foundation-neutral-500": "#6b7280",
8
+ "ds-foundation-neutral-600": "#4b5563",
9
+ "ds-foundation-neutral-700": "#2a2d35",
10
+ "ds-foundation-neutral-800": "#22262f",
11
+ "ds-foundation-neutral-850": "#1a1d23",
12
+ "ds-foundation-neutral-900": "#111316",
13
+ "ds-foundation-neutral-950": "#0b0d0f",
14
+ "ds-foundation-ink-500": "#183247",
15
+ "ds-foundation-ink-700": "#102233",
16
+ "ds-foundation-cyan-50": "#eef9fd",
17
+ "ds-foundation-cyan-100": "#d9f1fb",
18
+ "ds-foundation-cyan-200": "#b7e4f3",
19
+ "ds-foundation-cyan-300": "#89d4f0",
20
+ "ds-foundation-violet-300": "#a78bfa",
21
+ "ds-foundation-violet-500": "#7c3aed",
22
+ "ds-foundation-violet-700": "#2d1f7a",
23
+ "ds-foundation-cyan-500": "#0ea5e9",
24
+ "ds-foundation-cyan-600": "#0284c7",
25
+ "ds-foundation-cyan-700": "#0f6787",
26
+ "ds-foundation-green-500": "#22c55e",
27
+ "ds-foundation-blue-500": "#3b82f6",
28
+ "ds-foundation-yellow-500": "#f59e0b",
29
+ "ds-foundation-red-500": "#ef4444",
30
+ "ds-foundation-overlay-50": "rgb(0 0 0 / 0.5)",
31
+ "ds-foundation-overlay-60": "rgb(0 0 0 / 0.6)"
32
+ },
33
+ "semantic": {
34
+ "background": "var(--ds-foundation-neutral-950)",
35
+ "foreground": "var(--ds-foundation-neutral-100)",
36
+ "card": "var(--ds-foundation-neutral-850)",
37
+ "card-foreground": "var(--ds-foundation-neutral-100)",
38
+ "popover": "var(--ds-foundation-neutral-850)",
39
+ "popover-foreground": "var(--ds-foundation-neutral-100)",
40
+ "primary": "var(--ds-foundation-cyan-500)",
41
+ "primary-foreground": "var(--ds-foundation-white)",
42
+ "secondary": "var(--ds-foundation-neutral-800)",
43
+ "secondary-foreground": "var(--ds-foundation-neutral-100)",
44
+ "muted": "var(--ds-foundation-neutral-850)",
45
+ "muted-foreground": "var(--ds-foundation-neutral-500)",
46
+ "accent": "var(--ds-foundation-ink-700)",
47
+ "accent-foreground": "var(--ds-foundation-neutral-100)",
48
+ "destructive": "var(--ds-foundation-red-500)",
49
+ "destructive-foreground": "var(--ds-foundation-white)",
50
+ "border": "var(--ds-foundation-neutral-700)",
51
+ "input": "var(--ds-foundation-neutral-800)",
52
+ "ring": "var(--ds-foundation-cyan-500)",
53
+ "chart-1": "var(--ds-foundation-cyan-500)",
54
+ "chart-2": "var(--ds-foundation-green-500)",
55
+ "chart-3": "var(--ds-foundation-blue-500)",
56
+ "chart-4": "var(--ds-foundation-yellow-500)",
57
+ "chart-5": "var(--ds-foundation-red-500)",
58
+ "radius": "0.5rem",
59
+ "sidebar": "var(--ds-foundation-neutral-900)",
60
+ "sidebar-foreground": "var(--ds-foundation-neutral-100)",
61
+ "sidebar-primary": "var(--ds-foundation-cyan-500)",
62
+ "sidebar-primary-foreground": "var(--ds-foundation-white)",
63
+ "sidebar-accent": "var(--ds-foundation-neutral-800)",
64
+ "sidebar-accent-foreground": "var(--ds-foundation-neutral-100)",
65
+ "sidebar-border": "var(--ds-foundation-neutral-700)",
66
+ "sidebar-ring": "var(--ds-foundation-cyan-500)",
67
+ "surface": "var(--ds-foundation-neutral-850)",
68
+ "surface-raised": "var(--ds-foundation-neutral-800)",
69
+ "text-link": "var(--ds-foundation-cyan-300)",
70
+ "success": "var(--ds-foundation-green-500)",
71
+ "warning": "var(--ds-foundation-yellow-500)",
72
+ "danger": "var(--ds-foundation-red-500)",
73
+ "info": "var(--ds-foundation-blue-500)",
74
+ "ai-bubble": "var(--ds-foundation-neutral-850)",
75
+ "user-bubble": "var(--ds-foundation-cyan-600)",
76
+ "tenant-rail": "var(--ds-foundation-neutral-950)",
77
+ "tenant-rail-foreground": "var(--ds-foundation-white)",
78
+ "tenant-rail-muted": "rgb(255 255 255 / 0.72)",
79
+ "tenant-rail-border": "rgb(255 255 255 / 0.08)",
80
+ "tenant-rail-surface": "rgb(255 255 255 / 0.06)",
81
+ "overlay": "var(--ds-foundation-overlay-50)",
82
+ "overlay-strong": "var(--ds-foundation-overlay-60)",
83
+ "strong-foreground": "var(--ds-foundation-white)"
84
+ }
85
+ } as const
86
+
87
+ export default tokenManifest