@xenide-io/the-old-ui-theme 0.7.0 → 0.9.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 +9 -10
- package/dist/{Chip-Cq3AiAji.d.mts → Chip-BzuNgJIa.d.mts} +81 -23
- package/dist/{Chip-Cq3AiAji.d.ts → Chip-BzuNgJIa.d.ts} +81 -23
- package/dist/{ai-message-blocknote-WABTHFY7.mjs → ai-message-blocknote-D4Z6DUCJ.mjs} +9 -3
- package/dist/chunk-2EO5VCXP.mjs +3912 -0
- package/dist/chunk-APKRZQRO.mjs +251 -0
- package/dist/chunk-BS7BZI5W.mjs +19 -0
- package/dist/chunk-IULORI3A.mjs +8 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +997 -576
- package/dist/index.mjs +49 -45
- package/dist/suite.d.mts +157 -55
- package/dist/suite.d.ts +157 -55
- package/dist/suite.js +4249 -801
- package/dist/suite.mjs +2578 -594
- package/dist/theme-boot-P-oqKVZF.d.mts +74 -0
- package/dist/theme-boot-P-oqKVZF.d.ts +74 -0
- package/dist/theme-boot.d.mts +2 -0
- package/dist/theme-boot.d.ts +2 -0
- package/dist/theme-boot.js +44 -0
- package/dist/theme-boot.mjs +8 -0
- package/dist/ui.d.mts +5 -29
- package/dist/ui.d.ts +5 -29
- package/dist/ui.js +647 -352
- package/dist/ui.mjs +10 -12
- package/docs/README.md +34 -0
- package/docs/ai-quick-reference.md +56 -0
- package/docs/component-library-improvement-plan.md +751 -0
- package/docs/component-reference.md +81 -0
- package/docs/components.md +48 -0
- package/docs/demos.md +19 -0
- package/docs/installation.md +117 -0
- package/docs/suite-audit.md +34 -0
- package/docs/theme-token-reference.md +67 -0
- package/docs/themes.md +164 -0
- package/package.json +22 -21
- package/public/fonts/OpenRunde-Bold.woff2 +0 -0
- package/public/fonts/OpenRunde-Medium.woff2 +0 -0
- package/public/fonts/OpenRunde-Regular.woff2 +0 -0
- package/public/fonts/OpenRunde-Semibold.woff2 +0 -0
- package/scripts/package-smoke.mjs +43 -0
- package/src/app/globals.css +2 -1
- package/src/components/ui/Accordion.tsx +20 -6
- package/src/components/ui/Avatar.tsx +5 -3
- package/src/components/ui/Calendar.tsx +187 -63
- package/src/components/ui/Card.test.tsx +38 -0
- package/src/components/ui/Card.tsx +77 -14
- package/src/components/ui/CollapsibleSection.tsx +12 -4
- package/src/components/ui/CommandPalette.test.tsx +91 -4
- package/src/components/ui/CommandPalette.tsx +138 -128
- package/src/components/ui/EmptyState.tsx +2 -2
- package/src/components/ui/FormField.tsx +1 -1
- package/src/components/ui/Input.tsx +42 -18
- package/src/components/ui/Kbd.tsx +18 -3
- package/src/components/ui/Modal.tsx +3 -1
- package/src/components/ui/Progress.tsx +14 -5
- package/src/components/ui/SegmentedControl.tsx +2 -2
- package/src/components/ui/SettingsLayout.tsx +1 -1
- package/src/components/ui/Stat.tsx +3 -2
- package/src/components/ui/Table.tsx +8 -3
- package/src/components/ui/Tooltip.test.tsx +70 -1
- package/src/components/ui/Tooltip.tsx +53 -29
- package/src/components/ui/Typography.tsx +103 -49
- package/src/components/ui/avatar-stat.test.tsx +23 -0
- package/src/components/ui/calendar.test.tsx +88 -0
- package/src/components/ui/disclosure.test.tsx +39 -0
- package/src/components/ui/index.ts +44 -6
- package/src/components/ui/progress.test.tsx +15 -0
- package/src/components/ui/typography.test.tsx +26 -1
- package/src/styles/suite-skin.css +8 -2
- package/src/styles/themes.css +184 -68
- package/src/suite/components/ai-message-blocknote.tsx +13 -2
- package/src/suite/components/ai-panel.tsx +41 -10
- package/src/suite/components/app-switcher.test.tsx +21 -6
- package/src/suite/components/app-switcher.tsx +7 -11
- package/src/suite/components/suite-app-layout.tsx +12 -3
- package/src/suite/components/suite-bottom-nav.tsx +0 -1
- package/src/suite/components/suite-clients-projects-directory.test.tsx +71 -0
- package/src/suite/components/suite-clients-projects-directory.tsx +943 -0
- package/src/suite/components/suite-integration-picker.test.tsx +224 -0
- package/src/suite/components/suite-integration-picker.tsx +939 -0
- package/src/suite/components/suite-integration-rules.test.tsx +157 -0
- package/src/suite/components/suite-integration-rules.tsx +471 -0
- package/src/suite/components/suite-mobile-drawer.test.tsx +18 -2
- package/src/suite/components/suite-mobile-drawer.tsx +65 -98
- package/src/suite/components/suite-notification-bell.tsx +29 -4
- package/src/suite/components/suite-sidebar.tsx +25 -25
- package/src/suite/components/suite-skeleton.tsx +2 -2
- package/src/suite/components/suite-user-menu.tsx +9 -8
- package/src/suite/components/theme-provider.test.tsx +87 -3
- package/src/suite/components/theme-provider.tsx +144 -23
- package/src/suite/components/today-ui.tsx +79 -68
- package/src/suite/components/workspace-switcher.test.tsx +56 -0
- package/src/suite/components/workspace-switcher.tsx +3 -3
- package/src/suite/icons/app-accents.ts +12 -12
- package/src/suite/icons/glyphs.ts +6 -12
- package/src/suite/index.ts +27 -0
- package/src/suite/lib/apps.test.ts +9 -1
- package/src/suite/lib/apps.ts +14 -8
- package/src/suite/lib/cookies.ts +53 -0
- package/src/suite/lib/theme-boot.ts +32 -0
- package/src/suite/lib/theme-cookie.ts +7 -0
- package/src/suite/lib/use-sidebar-width.ts +5 -51
- package/dist/chunk-KDR6HI6F.mjs +0 -1075
- package/dist/chunk-NOI42JNZ.mjs +0 -151
- package/dist/chunk-VXISSXTB.mjs +0 -2564
- package/src/suite/lib/use-lock-mobile-page-zoom.test.tsx +0 -65
- package/src/suite/lib/use-lock-mobile-page-zoom.ts +0 -51
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Component Reference
|
|
2
|
+
|
|
3
|
+
The published package is `@xenide-io/the-old-ui-theme`. Import the supported
|
|
4
|
+
product surface from the package root:
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
import { Button, Card, H1, P } from "@xenide-io/the-old-ui-theme";
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The `/ui` entry additionally exposes `Range`, `Kbd`, `SearchGroup`,
|
|
11
|
+
`FilterControls`, `ThemeDomSync`, `ThemeSwitcher`, and catalogue helpers.
|
|
12
|
+
The `/suite` entry exposes ShellStack-specific application chrome and workflow
|
|
13
|
+
components; it is not a generic primitive library.
|
|
14
|
+
|
|
15
|
+
## Actions And Feedback
|
|
16
|
+
|
|
17
|
+
| Component | Primary API |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `Button` | `variant`, `size`, `shape`, `loading`, `icon`, `sideIcon`, `split`, `outline` |
|
|
20
|
+
| `ButtonChrome` | Shared visual button chrome for product-specific actions. |
|
|
21
|
+
| `Alert` | `status`, `title`, `description`, `icon`, `onDismiss`, `live` |
|
|
22
|
+
| `Badge` | `variant`, `size` |
|
|
23
|
+
| `Loader` | `variant`, `size`, `label` |
|
|
24
|
+
| `LoadingState` | `label`, `title`, `description`, `variant`, `size` |
|
|
25
|
+
| `Skeleton` | `shape` |
|
|
26
|
+
| `Progress` | `value`, `max`, `label`, `showPercentage`, `size` |
|
|
27
|
+
| `EmptyState` | `icon`, `title`, `description`, `action` |
|
|
28
|
+
|
|
29
|
+
## Forms
|
|
30
|
+
|
|
31
|
+
| Component | Primary API |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `FormField` | `controlId`, `label`, `hideLabel`, `helperText`, `error`, `required` |
|
|
34
|
+
| `Input` | Native input props plus `label`, `hideLabel`, `error`, `helperText`, `size`, `variant` |
|
|
35
|
+
| `Select` | Native select props plus `label`, `hideLabel`, `error`, `helperText`, `size` |
|
|
36
|
+
| `Textarea` | Native textarea props plus `label`, `hideLabel`, `error`, `helperText`, `size` |
|
|
37
|
+
| `Checkbox`, `Radio`, `Toggle` | Native control props plus label and field feedback props. |
|
|
38
|
+
| `FileUpload` | File-input wrapper with label and prompt. |
|
|
39
|
+
| `SearchInput` | Search field with optional shortcut and density. |
|
|
40
|
+
| `Range` (`/ui`) | Native range wrapper with labels and value display. |
|
|
41
|
+
|
|
42
|
+
## Overlays And Selection
|
|
43
|
+
|
|
44
|
+
| Component | Primary API |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `Modal` | `open`, `onClose`, `title`, `description`, `footer`, `size`, dismissal controls |
|
|
47
|
+
| `DropdownMenu` | Radix-backed `trigger`, `align`, `side`, menu content. |
|
|
48
|
+
| `DropdownItem`, `DropdownRadioGroup`, `DropdownRadioItem` | Canonical menu item composition. |
|
|
49
|
+
| `Tooltip` | `content`, `side`, `align`, `open`, `defaultOpen`, `onOpenChange` |
|
|
50
|
+
| `Accordion` | `items`, `allowMultiple`, `defaultOpen` |
|
|
51
|
+
| `SegmentedControl` | `options`, `value`, `onChange` |
|
|
52
|
+
| `Calendar` | `value`, `onChange` |
|
|
53
|
+
| `CommandPalette` | `items`, `isOpen`, `onClose` |
|
|
54
|
+
| `FilterBar`, `FilterMenu`, `SortMenu`, `FilterChips` | Stateless filtering composition. |
|
|
55
|
+
|
|
56
|
+
## Content And Layout
|
|
57
|
+
|
|
58
|
+
| Component | Primary API |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `Card` | `title`, `description`, `media`, `actions`, `footer`, `variant` |
|
|
61
|
+
| `Panel` | `title`, `description`, native div props. |
|
|
62
|
+
| `Table` | `data`, `columns`, `getRowKey`, `caption`, density and ribbon props. |
|
|
63
|
+
| `Stat` | `label`, `value`, `tone`, `icon`, `footer` |
|
|
64
|
+
| `Avatar`, `AvatarGroup` | `size`, `status`, label/icon and grouping props. |
|
|
65
|
+
| `AuthLayout`, `AuthCard`, `AuthDivider` | Authentication page composition. |
|
|
66
|
+
| `SettingsLayout`, `SettingsNav` | Settings page composition and navigation. |
|
|
67
|
+
|
|
68
|
+
## Typography And Utilities
|
|
69
|
+
|
|
70
|
+
`Display`, `SectionTitle`, `H1` through `H5`, `P`, `Small`, `Caption`,
|
|
71
|
+
`Overline`, `Lead`, `Mono`, `Label`, `Link`, `Chip`, `Dot`, `Spinner`,
|
|
72
|
+
`Icon`, and `IconByName` are exported from the root package.
|
|
73
|
+
|
|
74
|
+
Themes are provided through `THEMES`, `THEME_GROUPS`, `getTheme`,
|
|
75
|
+
`persistTheme`, `readStoredTheme`, `THEME_INIT_SCRIPT`, `ThemeDomSync`, and
|
|
76
|
+
`ThemeSwitcher`.
|
|
77
|
+
|
|
78
|
+
Use the generated TypeScript declarations as the authoritative detailed prop
|
|
79
|
+
reference until per-component API pages are added. Named props interfaces are
|
|
80
|
+
available for the major primitives and are being standardised across the
|
|
81
|
+
remaining public components.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Component Usage
|
|
2
|
+
|
|
3
|
+
Import supported components from `@xenide-io/the-old-ui-theme`. The complete
|
|
4
|
+
supported surface is listed in the [component reference](./component-reference.md).
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
import {
|
|
8
|
+
Alert,
|
|
9
|
+
Button,
|
|
10
|
+
Card,
|
|
11
|
+
Input,
|
|
12
|
+
Modal,
|
|
13
|
+
Table,
|
|
14
|
+
type TableColumn,
|
|
15
|
+
} from "@xenide-io/the-old-ui-theme";
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Use `className` for layout and small local adjustments. Prefer a component's
|
|
19
|
+
typed props and semantic token classes over literal colours or bespoke control
|
|
20
|
+
implementations.
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<Card title="Workspace settings" description="Manage member access.">
|
|
24
|
+
<Input label="Workspace name" defaultValue="Research" />
|
|
25
|
+
<Button variant="primary">Save changes</Button>
|
|
26
|
+
</Card>
|
|
27
|
+
|
|
28
|
+
<Alert status="warning" title="Approaching quota" />
|
|
29
|
+
|
|
30
|
+
<Modal open={open} onClose={() => setOpen(false)} title="Create project">
|
|
31
|
+
<Input label="Project name" autoFocus />
|
|
32
|
+
</Modal>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Tables need stable row identity whenever rows can change order or contain
|
|
36
|
+
stateful content:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
const columns: TableColumn<User>[] = [
|
|
40
|
+
{ key: "name", header: "Name", cell: (user) => user.name },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
<Table data={users} columns={columns} getRowKey={(user) => user.id} />;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For the additional `/ui` surface, import from
|
|
47
|
+
`@xenide-io/the-old-ui-theme/ui`. Use `/suite` only for ShellStack product
|
|
48
|
+
chrome and suite workflow components.
|
package/docs/demos.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Demo Routes
|
|
2
|
+
|
|
3
|
+
The catalogue is intentionally split into focused routes. The root `/` route
|
|
4
|
+
redirects to `/demo` instead of mounting every showcase at once.
|
|
5
|
+
|
|
6
|
+
| Route | Focus |
|
|
7
|
+
| ------------------- | ---------------------------------------------------------- |
|
|
8
|
+
| `/demo` | Demo index and route picker |
|
|
9
|
+
| `/demo/foundations` | Type scale, tokens, themes, icons, setup, and shortcuts |
|
|
10
|
+
| `/demo/components` | Primitive components and everyday controls |
|
|
11
|
+
| `/demo/patterns` | Auth, settings, overlays, filters, and loading flows |
|
|
12
|
+
| `/demo/suite` | Suite shell, sidebar, mobile chrome, and settings patterns |
|
|
13
|
+
|
|
14
|
+
Every showcase maps to a component the ShellStack apps ship. If a component is
|
|
15
|
+
not used by an app, it does not belong in the package or the demo.
|
|
16
|
+
|
|
17
|
+
Every demo route uses the shared `SuiteAppLayout`. The sidebar selection is
|
|
18
|
+
route-aware, the desktop rail is resizable, and the width is persisted per
|
|
19
|
+
browser.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Installation
|
|
2
|
+
|
|
3
|
+
## Build The Library
|
|
4
|
+
|
|
5
|
+
Run this in the UI library repo:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun install
|
|
9
|
+
bun run build:lib
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The library build outputs:
|
|
13
|
+
|
|
14
|
+
```txt
|
|
15
|
+
dist/index.mjs
|
|
16
|
+
dist/index.js
|
|
17
|
+
dist/index.d.ts
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Local Install In Another App
|
|
21
|
+
|
|
22
|
+
Use this while developing locally:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@xenide-io/the-old-ui-theme": "file:../path-to/the-old-ui"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then install in the consuming app:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bun install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Published Install
|
|
39
|
+
|
|
40
|
+
After publishing:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bun add @xenide-io/the-old-ui-theme
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
or:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install @xenide-io/the-old-ui-theme
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Import Styles Once
|
|
53
|
+
|
|
54
|
+
In a Next.js app:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
// app/layout.tsx
|
|
58
|
+
import "@xenide-io/the-old-ui-theme/styles.css";
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Tailwind Setup
|
|
62
|
+
|
|
63
|
+
Add the package preset and include the built package files in `content`.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// tailwind.config.ts
|
|
67
|
+
import theOldUiPreset from "@xenide-io/the-old-ui-theme/tailwind-preset";
|
|
68
|
+
|
|
69
|
+
export default {
|
|
70
|
+
presets: [theOldUiPreset],
|
|
71
|
+
content: [
|
|
72
|
+
"./src/**/*.{ts,tsx}",
|
|
73
|
+
"./app/**/*.{ts,tsx}",
|
|
74
|
+
"./node_modules/@xenide-io/the-old-ui-theme/dist/**/*.{js,mjs}",
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Next.js Theme Setup
|
|
80
|
+
|
|
81
|
+
Use `THEME_INIT_SCRIPT` to avoid a theme flash and `ThemeDomSync` to sync the stored theme after hydration.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// app/layout.tsx
|
|
85
|
+
import "@xenide-io/the-old-ui-theme/styles.css";
|
|
86
|
+
import { THEME_INIT_SCRIPT, ThemeDomSync } from "@xenide-io/the-old-ui-theme";
|
|
87
|
+
|
|
88
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
89
|
+
return (
|
|
90
|
+
<html lang="en" data-theme="hedgehog-light" suppressHydrationWarning>
|
|
91
|
+
<head>
|
|
92
|
+
<script dangerouslySetInnerHTML={{ __html: THEME_INIT_SCRIPT }} />
|
|
93
|
+
</head>
|
|
94
|
+
<body>
|
|
95
|
+
<ThemeDomSync />
|
|
96
|
+
{children}
|
|
97
|
+
</body>
|
|
98
|
+
</html>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Basic Usage
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { Button, Card, H1, P } from "@xenide-io/the-old-ui-theme";
|
|
107
|
+
|
|
108
|
+
export function Example() {
|
|
109
|
+
return (
|
|
110
|
+
<Card
|
|
111
|
+
title={<H1>Dashboard</H1>}
|
|
112
|
+
description={<P tone="subtle">Your workspace overview.</P>}
|
|
113
|
+
actions={<Button variant="primary">Create insight</Button>}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Suite UI Audit
|
|
2
|
+
|
|
3
|
+
The suite apps are separate consumers of this package. The shared package now
|
|
4
|
+
owns the visual language; app code should keep product-specific workflows and
|
|
5
|
+
illustrations.
|
|
6
|
+
|
|
7
|
+
## Move Into The Shared Package
|
|
8
|
+
|
|
9
|
+
| Pattern | Current consumers | Shared home |
|
|
10
|
+
| ------------------------------------------------------------ | ------------------------------------- | ----------------------------------------------------------------------- |
|
|
11
|
+
| Desktop rail, mobile header, bottom navigation | Tides, TurtleTime, ShellStack, Kraken | `SuiteAppLayout`, `SuiteSidebar`, `SuiteMobileHeader`, `SuiteBottomNav` |
|
|
12
|
+
| App switching, notifications, command handoff | All suite apps | `/suite` exports |
|
|
13
|
+
| Cards, alerts, empty/loading states, dialogs, inputs, tables | All suite apps | `/ui` exports and `--ph-*` tokens |
|
|
14
|
+
| Auth and settings chrome | Tides, TurtleTime, ShellStack, Kraken | `AuthLayout`, `AuthCard`, `SettingsLayout` |
|
|
15
|
+
| Theme pairing, semantic status colours, focus rings | All suite apps | `themes.css` and `themes/registry.ts` |
|
|
16
|
+
|
|
17
|
+
## Keep In The Apps
|
|
18
|
+
|
|
19
|
+
- Tides kanban, task detail, BlockNote editor, project and crew controls.
|
|
20
|
+
- TurtleTime tracker, timer state, report charts, and time-entry workflows.
|
|
21
|
+
- ShellStack terminal scene, workspace/billing domain, and API documentation.
|
|
22
|
+
- Kraken document editor, React Flow diagrams, deep research, and citations.
|
|
23
|
+
- Product marks and illustrations that carry product meaning.
|
|
24
|
+
|
|
25
|
+
## Adoption Contract
|
|
26
|
+
|
|
27
|
+
Keep app canvases token-driven and quiet by default:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<SuiteAppLayout {...props} />
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Decorative hero treatments should remain app-owned and opt-in. Do not add
|
|
34
|
+
continuous animated backgrounds to dense product workspaces.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Theme Token Reference
|
|
2
|
+
|
|
3
|
+
The built-in palettes are defined in `src/styles/themes.css`; the registry in
|
|
4
|
+
`src/themes/registry.ts` is the source of truth for IDs, names, and modes.
|
|
5
|
+
|
|
6
|
+
## Theme IDs
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
"hedgehog-light";
|
|
10
|
+
"hedgehog-dark";
|
|
11
|
+
"note";
|
|
12
|
+
"note-dark";
|
|
13
|
+
"turtletime";
|
|
14
|
+
"turtletime-dark";
|
|
15
|
+
"rosepine-light";
|
|
16
|
+
"rosepine-dark";
|
|
17
|
+
"kraken-light";
|
|
18
|
+
"kraken-dark";
|
|
19
|
+
"deepsea-light";
|
|
20
|
+
"deepsea-dark";
|
|
21
|
+
"malibu-light";
|
|
22
|
+
"malibu-dark";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Theme Pairs
|
|
26
|
+
|
|
27
|
+
| Pair | Light | Dark |
|
|
28
|
+
| ----------- | ---------------- | ----------------- |
|
|
29
|
+
| HedgeHog | `hedgehog-light` | `hedgehog-dark` |
|
|
30
|
+
| Note | `note` | `note-dark` |
|
|
31
|
+
| TurtleTime | `turtletime` | `turtletime-dark` |
|
|
32
|
+
| Rosé Pine | `rosepine-light` | `rosepine-dark` |
|
|
33
|
+
| Kraken | `kraken-light` | `kraken-dark` |
|
|
34
|
+
| Tokyo Night | `deepsea-light` | `deepsea-dark` |
|
|
35
|
+
| Malibu | `malibu-light` | `malibu-dark` |
|
|
36
|
+
|
|
37
|
+
## Core Tokens
|
|
38
|
+
|
|
39
|
+
Every built-in theme defines these semantic values:
|
|
40
|
+
|
|
41
|
+
```css
|
|
42
|
+
--ph-canvas
|
|
43
|
+
--ph-surface
|
|
44
|
+
--ph-muted
|
|
45
|
+
--ph-toolbar
|
|
46
|
+
--ph-border
|
|
47
|
+
--ph-border-strong
|
|
48
|
+
--ph-text-primary
|
|
49
|
+
--ph-text-secondary
|
|
50
|
+
--ph-text-tertiary
|
|
51
|
+
--ph-accent
|
|
52
|
+
--ph-accent-hover
|
|
53
|
+
--ph-blue
|
|
54
|
+
--ph-violet
|
|
55
|
+
--ph-purple
|
|
56
|
+
--ph-success
|
|
57
|
+
--ph-warning
|
|
58
|
+
--ph-danger
|
|
59
|
+
--ph-info
|
|
60
|
+
--ph-data-1 through --ph-data-7
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Malibu uses a sun-bleached GTA San Andreas palette in light mode and Shelly's
|
|
64
|
+
deep plum command deck in dark mode, with hot pink, lime, cyan, amber, and
|
|
65
|
+
emerald signals.
|
|
66
|
+
|
|
67
|
+
For the complete token values, read `src/styles/themes.css` directly.
|
package/docs/themes.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Themes
|
|
2
|
+
|
|
3
|
+
Themes are CSS-variable based. Components read semantic `--ph-*` tokens, so changing `html[data-theme]` changes the whole UI without editing components.
|
|
4
|
+
|
|
5
|
+
## Default Theme
|
|
6
|
+
|
|
7
|
+
```txt
|
|
8
|
+
hedgehog-light
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Dark pair:
|
|
12
|
+
|
|
13
|
+
```txt
|
|
14
|
+
hedgehog-dark
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Built-In Theme Pairs
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
export const themePairs = [
|
|
21
|
+
{ name: "HedgeHog", light: "hedgehog-light", dark: "hedgehog-dark" },
|
|
22
|
+
{ name: "Note", light: "note", dark: "note-dark" },
|
|
23
|
+
{ name: "TurtleTime", light: "turtletime", dark: "turtletime-dark" },
|
|
24
|
+
{ name: "Rose Pine", light: "rosepine-light", dark: "rosepine-dark" },
|
|
25
|
+
{ name: "Kraken", light: "kraken-light", dark: "kraken-dark" },
|
|
26
|
+
{ name: "Tokyo Night", light: "deepsea-light", dark: "deepsea-dark" },
|
|
27
|
+
{ name: "Malibu", light: "malibu-light", dark: "malibu-dark" },
|
|
28
|
+
] as const;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Theme Switching
|
|
32
|
+
|
|
33
|
+
Use the built-in switcher:
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { ThemeSwitcher } from "@xenide-io/the-old-ui-theme";
|
|
37
|
+
|
|
38
|
+
<ThemeSwitcher />;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Switch manually and persist to `localStorage`:
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { persistTheme } from "@xenide-io/the-old-ui-theme";
|
|
45
|
+
|
|
46
|
+
persistTheme("malibu-dark");
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Set directly without persistence:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
document.documentElement.setAttribute("data-theme", "malibu-dark");
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Master Color List
|
|
56
|
+
|
|
57
|
+
The source of truth for all theme colors is:
|
|
58
|
+
|
|
59
|
+
```txt
|
|
60
|
+
src/styles/themes.css
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The source of truth for theme IDs, names, groups, and light/dark mode metadata is:
|
|
64
|
+
|
|
65
|
+
```txt
|
|
66
|
+
src/themes/registry.ts
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The rendered demo has a visual swatch guide under **Setup & Theme**.
|
|
70
|
+
|
|
71
|
+
For the complete AI-readable list of every built-in theme and token value, see [Theme Token Reference](./theme-token-reference.md).
|
|
72
|
+
|
|
73
|
+
## Core Theme Tokens
|
|
74
|
+
|
|
75
|
+
Every theme should define these semantic tokens:
|
|
76
|
+
|
|
77
|
+
```css
|
|
78
|
+
--ph-canvas
|
|
79
|
+
--ph-surface
|
|
80
|
+
--ph-muted
|
|
81
|
+
--ph-toolbar
|
|
82
|
+
--ph-border
|
|
83
|
+
--ph-border-strong
|
|
84
|
+
|
|
85
|
+
--ph-text-primary
|
|
86
|
+
--ph-text-secondary
|
|
87
|
+
--ph-text-tertiary
|
|
88
|
+
|
|
89
|
+
--ph-accent
|
|
90
|
+
--ph-accent-hover
|
|
91
|
+
--ph-blue
|
|
92
|
+
--ph-purple
|
|
93
|
+
|
|
94
|
+
--ph-success
|
|
95
|
+
--ph-warning
|
|
96
|
+
--ph-danger
|
|
97
|
+
--ph-info
|
|
98
|
+
|
|
99
|
+
--ph-data-1
|
|
100
|
+
--ph-data-2
|
|
101
|
+
--ph-data-3
|
|
102
|
+
--ph-data-4
|
|
103
|
+
--ph-data-5
|
|
104
|
+
--ph-data-6
|
|
105
|
+
--ph-data-7
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Custom Light And Dark Theme
|
|
109
|
+
|
|
110
|
+
Custom themes work like DaisyUI themes: define a light block and a dark block.
|
|
111
|
+
|
|
112
|
+
```css
|
|
113
|
+
@import "@xenide-io/the-old-ui-theme/styles.css";
|
|
114
|
+
|
|
115
|
+
[data-theme="my-theme-light"] {
|
|
116
|
+
color-scheme: light;
|
|
117
|
+
|
|
118
|
+
--ph-canvas: #f8f5ef;
|
|
119
|
+
--ph-surface: #ffffff;
|
|
120
|
+
--ph-muted: #eee8dd;
|
|
121
|
+
--ph-toolbar: #e5dccd;
|
|
122
|
+
--ph-border: #d7cbb8;
|
|
123
|
+
--ph-border-strong: #a99b87;
|
|
124
|
+
|
|
125
|
+
--ph-text-primary: #15110c;
|
|
126
|
+
--ph-text-secondary: #4d4337;
|
|
127
|
+
--ph-text-tertiary: #796f63;
|
|
128
|
+
|
|
129
|
+
--ph-accent: #f97316;
|
|
130
|
+
--ph-accent-hover: #ea580c;
|
|
131
|
+
--ph-blue: #2563eb;
|
|
132
|
+
--ph-purple: #7c3aed;
|
|
133
|
+
--ph-success: #15803d;
|
|
134
|
+
--ph-warning: #b45309;
|
|
135
|
+
--ph-danger: #dc2626;
|
|
136
|
+
--ph-info: #2563eb;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
[data-theme="my-theme-dark"] {
|
|
140
|
+
color-scheme: dark;
|
|
141
|
+
|
|
142
|
+
--ph-canvas: #11100e;
|
|
143
|
+
--ph-surface: #191713;
|
|
144
|
+
--ph-muted: #242018;
|
|
145
|
+
--ph-toolbar: #2e281f;
|
|
146
|
+
--ph-border: #443a2b;
|
|
147
|
+
--ph-border-strong: #7a6a54;
|
|
148
|
+
|
|
149
|
+
--ph-text-primary: #fff7ed;
|
|
150
|
+
--ph-text-secondary: #d8c8b6;
|
|
151
|
+
--ph-text-tertiary: #a89985;
|
|
152
|
+
|
|
153
|
+
--ph-accent: #fb923c;
|
|
154
|
+
--ph-accent-hover: #fdba74;
|
|
155
|
+
--ph-blue: #60a5fa;
|
|
156
|
+
--ph-purple: #a78bfa;
|
|
157
|
+
--ph-success: #4ade80;
|
|
158
|
+
--ph-warning: #facc15;
|
|
159
|
+
--ph-danger: #f87171;
|
|
160
|
+
--ph-info: #60a5fa;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
If the custom theme should appear in the built-in `ThemeSwitcher`, add both IDs to `src/themes/registry.ts` before building the package.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xenide-io/the-old-ui-theme",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Props-driven React components and theme tokens inspired by classic interface design
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Props-driven React components and theme tokens inspired by classic interface design — optimized for Next.js apps and internal tools.",
|
|
5
5
|
"author": "Xenide",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/xenide-io/the-old-ui-theme",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"packageManager": "bun@1.3.5",
|
|
21
21
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
22
|
+
"node": ">=20.9.0"
|
|
23
23
|
},
|
|
24
24
|
"sideEffects": [
|
|
25
25
|
"*.css"
|
|
@@ -48,6 +48,12 @@
|
|
|
48
48
|
"require": "./dist/suite.js",
|
|
49
49
|
"default": "./dist/suite.mjs"
|
|
50
50
|
},
|
|
51
|
+
"./theme-boot": {
|
|
52
|
+
"types": "./dist/theme-boot.d.ts",
|
|
53
|
+
"import": "./dist/theme-boot.mjs",
|
|
54
|
+
"require": "./dist/theme-boot.js",
|
|
55
|
+
"default": "./dist/theme-boot.mjs"
|
|
56
|
+
},
|
|
51
57
|
"./tailwind-preset": {
|
|
52
58
|
"types": "./dist/tailwind-preset.d.ts",
|
|
53
59
|
"import": "./dist/tailwind-preset.mjs",
|
|
@@ -56,7 +62,9 @@
|
|
|
56
62
|
}
|
|
57
63
|
},
|
|
58
64
|
"files": [
|
|
65
|
+
"docs",
|
|
59
66
|
"dist",
|
|
67
|
+
"public/fonts",
|
|
60
68
|
"scripts",
|
|
61
69
|
"src/app/globals.css",
|
|
62
70
|
"src/components/ui",
|
|
@@ -70,17 +78,18 @@
|
|
|
70
78
|
"scripts": {
|
|
71
79
|
"dev": "next dev",
|
|
72
80
|
"build": "next build",
|
|
73
|
-
"build:lib": "tsup --entry.index src/index.ts --entry.ui src/components/ui/index.ts --entry.suite src/suite/index.ts --entry.tailwind-preset tailwind-preset.ts --format cjs,esm --dts --external react,react-dom,next,iconoir-react,motion --clean --tsconfig ./tsconfig.lib.json",
|
|
81
|
+
"build:lib": "tsup --entry.index src/index.ts --entry.ui src/components/ui/index.ts --entry.suite src/suite/index.ts --entry.theme-boot src/suite/lib/theme-boot.ts --entry.tailwind-preset tailwind-preset.ts --format cjs,esm --dts --external react,react-dom,next,iconoir-react,motion --clean --tsconfig ./tsconfig.lib.json",
|
|
74
82
|
"start": "next start",
|
|
75
|
-
"lint": "
|
|
83
|
+
"lint": "eslint .",
|
|
76
84
|
"typecheck": "tsc --noEmit",
|
|
77
85
|
"test": "vitest run",
|
|
78
86
|
"test:visual": "playwright test --project=desktop-chromium --workers=1 && playwright test --project=mobile-chromium --workers=1",
|
|
79
|
-
"check": "bun run typecheck && bun run test",
|
|
87
|
+
"check": "bun run typecheck && bun run lint && bun run test",
|
|
80
88
|
"clean": "rm -rf .next out *.tsbuildinfo dist",
|
|
81
89
|
"icons:check": "node scripts/sync-posthog-icons.mjs",
|
|
82
|
-
"
|
|
83
|
-
"
|
|
90
|
+
"package:smoke": "node scripts/package-smoke.mjs",
|
|
91
|
+
"prepublishOnly": "bun run build:lib && bun run package:smoke",
|
|
92
|
+
"release": "bun run check && bun run build && bun run build:lib && bun run package:smoke && npm publish"
|
|
84
93
|
},
|
|
85
94
|
"peerDependencies": {
|
|
86
95
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -90,29 +99,21 @@
|
|
|
90
99
|
"iconoir-react": ">=7.11.1",
|
|
91
100
|
"motion": ">=12"
|
|
92
101
|
},
|
|
93
|
-
"peerDependenciesMeta": {
|
|
94
|
-
"iconoir-react": {
|
|
95
|
-
"optional": true
|
|
96
|
-
},
|
|
97
|
-
"motion": {
|
|
98
|
-
"optional": true
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
102
|
"devDependencies": {
|
|
102
103
|
"@playwright/test": "1.54.1",
|
|
103
104
|
"@testing-library/dom": "^10.4.1",
|
|
104
105
|
"@testing-library/jest-dom": "^6.10.0",
|
|
105
106
|
"@testing-library/react": "^16.3.2",
|
|
106
107
|
"@testing-library/user-event": "^14.6.3",
|
|
107
|
-
"@types/d3-scale": "^4.0.9",
|
|
108
108
|
"@types/node": "^20.19.43",
|
|
109
109
|
"@types/react": "^19.2.18",
|
|
110
110
|
"@types/react-dom": "^19.2.4",
|
|
111
111
|
"autoprefixer": "^10.5.4",
|
|
112
|
+
"eslint": "^9.0.0",
|
|
113
|
+
"eslint-config-next": "^16.3.4",
|
|
112
114
|
"iconoir-react": "^7.11.1",
|
|
113
|
-
"motion": "^12.43.0",
|
|
114
|
-
"d3-scale": "^4.0.2",
|
|
115
115
|
"jsdom": "^26.1.0",
|
|
116
|
+
"motion": "^12.43.0",
|
|
116
117
|
"next": "^16.3.0",
|
|
117
118
|
"postcss": "^8.5.25",
|
|
118
119
|
"react": "^18.3.1",
|
|
@@ -120,8 +121,8 @@
|
|
|
120
121
|
"tailwindcss": "^3.4.19",
|
|
121
122
|
"tsup": "^8.5.1",
|
|
122
123
|
"typescript": "^6.0.3",
|
|
123
|
-
"
|
|
124
|
-
"
|
|
124
|
+
"typescript7": "npm:typescript@^7.0.2",
|
|
125
|
+
"vitest": "^3.2.7"
|
|
125
126
|
},
|
|
126
127
|
"publishConfig": {
|
|
127
128
|
"access": "public"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|