@owodesign/owoui 0.1.2 → 0.1.3

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.
@@ -6,6 +6,16 @@
6
6
  <title>owoui Storybook</title>
7
7
  <meta name="color-scheme" content="light dark" />
8
8
  <link rel="stylesheet" href="./app.css" />
9
+ <script>
10
+ (function(){
11
+ var d=document.documentElement,t=localStorage.getItem('owoui-storybook-theme'),
12
+ p=localStorage.getItem('owoui-storybook-preset');
13
+ t=t==='dark'?'dark':'light';
14
+ p=['default','flat','elevated','glass'].indexOf(p)>=0?p:'default';
15
+ d.dataset.theme=t;d.dataset.preset=p;
16
+ d.classList.add('owoui-theme-'+t,'owoui-preset-'+p);
17
+ })();
18
+ </script>
9
19
  </head>
10
20
  <body>
11
21
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owodesign/owoui",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Reusable React UI foundation components and theme presets.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.min.js",
@@ -77,6 +77,8 @@
77
77
  "build:storybook:catalog": "node scripts/build-storybook-catalog.mjs",
78
78
  "build:storybook:static:bundle": "tsup --config tsup.storybook.static.config.ts",
79
79
  "build:storybook:static": "npm run build:storybook:static:bundle && node scripts/build-storybook-static.mjs",
80
+ "dev:storybook": "vite --config vite.config.ts",
81
+ "preview:storybook": "vite preview --config vite.config.ts",
80
82
  "typecheck": "tsc --noEmit -p tsconfig.json",
81
83
  "consumer:smoke": "node examples/consumer-smoke.mjs",
82
84
  "pack:inspect": "npm_config_cache=/tmp/owoui-npm-cache npm pack --dry-run --json .",
@@ -86,6 +88,7 @@
86
88
  "access": "public"
87
89
  },
88
90
  "dependencies": {
91
+ "@floating-ui/dom": "^1.7.6",
89
92
  "clsx": "^2.1.1",
90
93
  "lucide-react": "^0.576.0"
91
94
  },
@@ -97,8 +100,12 @@
97
100
  "@tailwindcss/postcss": "^4.2.1",
98
101
  "@types/react": "^19.0.0",
99
102
  "@types/react-dom": "^19.0.0",
103
+ "@vitejs/plugin-react": "^6.0.1",
100
104
  "postcss": "^8.5.6",
105
+ "react": "^19.2.4",
106
+ "react-dom": "^19.2.4",
101
107
  "tailwindcss": "^4.2.1",
102
- "tsup": "^8.5.1"
108
+ "tsup": "^8.5.1",
109
+ "vite": "^8.0.3"
103
110
  }
104
111
  }
package/src/style.css CHANGED
@@ -7,7 +7,6 @@
7
7
  @import "./styles/ui/dialog.css";
8
8
  @import "./styles/ui/dropdown-menu.css";
9
9
  @import "./styles/ui/drawer.css";
10
- @import "./styles/ui/empty-state.css";
11
10
  @import "./styles/ui/field.css";
12
11
  @import "./styles/ui/icon-button.css";
13
12
  @import "./styles/ui/input.css";
@@ -1,4 +1,18 @@
1
+ /* ================================================================== */
2
+ /* tokens.css — Tailwind v4 theme registration + shared mapping */
3
+ /* */
4
+ /* This file has TWO responsibilities: */
5
+ /* 1. @theme: Register CSS variables for Tailwind (initial values */
6
+ /* are light-mode defaults — a Tailwind v4 technical requirement) */
7
+ /* 2. :root: Shared mapping chains that are the SAME across all */
8
+ /* themes (preset → ui, app-specific derived variables) */
9
+ /* */
10
+ /* All color VALUES live in theme-light.css / theme-dark.css. */
11
+ /* Do NOT add theme-specific colors here. */
12
+ /* ================================================================== */
13
+
1
14
  @theme {
15
+ /* Neutral scale — initial values (light); overridden per-theme */
2
16
  --color-n900: #1a1a1a;
3
17
  --color-n800: #2d2d2d;
4
18
  --color-n700: #4a4a4a;
@@ -7,14 +21,13 @@
7
21
  --color-n400: #d4d4d8;
8
22
  --color-n300: #e4e4e7;
9
23
 
10
- /* Elegant Accent: Muted Clay / Terracotta */
11
- --color-brand-primary: #9f1239;
12
- /* Rose 800 - Elegant and deep */
13
- --color-brand-primary-hover: #be123c;
14
- /* Rose 700 */
15
- --color-brand-accent: #fb7185;
24
+ /* Brand initial values (light); overridden per-theme */
25
+ --color-brand-primary: #1a1a1a;
26
+ --color-brand-primary-hover: #000000;
27
+ --color-brand-accent: #4a4a4a;
16
28
 
17
- --color-surface-canvas: #fafafa;
29
+ /* Surface — initial values (light); overridden per-theme */
30
+ --color-surface-canvas: #ffffff;
18
31
  --color-surface-base: #ffffff;
19
32
  --color-surface-subtle: #fafaf9;
20
33
  --color-surface-raised: #ffffff;
@@ -34,6 +47,7 @@
34
47
  --shadow-raised: 0 10px 20px rgba(15, 23, 42, 0.08);
35
48
  --shadow-popover: 0 18px 40px rgba(15, 23, 42, 0.10);
36
49
 
50
+ /* Status — initial values (light); overridden per-theme */
37
51
  --color-admin-success-bg: rgba(16, 185, 129, 0.10);
38
52
  --color-admin-success-border: rgba(16, 185, 129, 0.20);
39
53
  --color-admin-success-text: #047857;
@@ -47,53 +61,25 @@
47
61
  --color-admin-info-border: rgba(14, 165, 233, 0.20);
48
62
  --color-admin-info-text: #0369a1;
49
63
 
50
- /* Typography — stacks reference next/font CSS variables set on <html> */
64
+ /* Typography — shared across all themes */
51
65
  --font-sans: var(--font-inter), var(--font-noto-sans-sc), system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", Roboto, sans-serif;
52
66
  --font-heading: var(--font-source-serif-pro), var(--font-noto-serif-sc), "Source Serif 4", Georgia, "Times New Roman", serif;
53
67
  --font-mono: "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
54
68
 
69
+ /* Motion — shared across all themes */
55
70
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
56
71
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);
57
72
  }
58
73
 
59
- :root {
60
- --theme-surface-canvas: var(--color-surface-canvas);
61
- --theme-surface-base: var(--color-surface-base);
62
- --theme-surface-subtle: var(--color-surface-subtle);
63
- --theme-surface-raised: var(--color-surface-raised);
64
- --theme-surface-inset: var(--color-surface-inset);
65
- --theme-surface-border: var(--color-surface-border);
66
- --theme-surface-border-muted: rgba(0, 0, 0, 0.06);
67
- --theme-surface-border-strong: var(--color-surface-ring);
68
- --theme-canvas-bg-subtle: #f5f5f4;
69
- --theme-surface-container: #f4f4f5;
70
- --theme-surface-container-high: #ececed;
71
- --theme-surface-container-highest: #e4e4e7;
72
- --theme-text-primary: var(--color-n800);
73
- --theme-text-secondary: var(--color-n600);
74
- --theme-text-muted: var(--color-n500);
75
- --theme-text-on-accent: var(--color-text-on-brand);
76
- --theme-accent-bg: var(--color-brand-primary);
77
- --theme-accent-bg-hover: var(--color-brand-primary-hover);
78
- --theme-accent-bg-muted: color-mix(in srgb, var(--color-brand-primary) 10%, var(--color-surface-base));
79
- --theme-accent-border: color-mix(in srgb, var(--color-brand-primary) 40%, transparent);
80
- --theme-success-bg: var(--color-admin-success-bg);
81
- --theme-success-border: var(--color-admin-success-border);
82
- --theme-success-text: var(--color-admin-success-text);
83
- --theme-warning-bg: var(--color-admin-warning-bg);
84
- --theme-warning-border: var(--color-admin-warning-border);
85
- --theme-warning-text: var(--color-admin-warning-text);
86
- --theme-danger-bg: var(--color-admin-danger-bg);
87
- --theme-danger-bg-emphasis: rgba(239, 68, 68, 0.18);
88
- --theme-danger-border: var(--color-admin-danger-border);
89
- --theme-danger-text: var(--color-admin-danger-text);
90
- --theme-info-bg: var(--color-admin-info-bg);
91
- --theme-info-border: var(--color-admin-info-border);
92
- --theme-info-text: var(--color-admin-info-text);
93
- --theme-control-focus-ring: var(--color-surface-ring);
94
- --theme-control-focus-ring-offset: var(--color-surface-base);
74
+ /* ================================================================== */
75
+ /* Shared mapping chains: preset → ui */
76
+ /* These mappings are identical across all themes. */
77
+ /* Theme files set --theme-*, presets set --preset-*, this layer */
78
+ /* wires them to the final --ui-* that components consume. */
79
+ /* ================================================================== */
95
80
 
96
- /* Signature Look: current qblog default preset qualities */
81
+ :root {
82
+ /* Preset defaults — theme → preset (overridden by preset-*.css) */
97
83
  --preset-surface-bg: var(--theme-surface-base);
98
84
  --preset-surface-bg-subtle: var(--theme-surface-subtle);
99
85
  --preset-surface-bg-raised: var(--theme-surface-raised);
@@ -116,6 +102,7 @@
116
102
  --preset-control-radius-2xl: 2rem;
117
103
  --preset-control-border-width: 1px;
118
104
 
105
+ /* Final UI layer — preset → ui (consumed by components) */
119
106
  --ui-surface-bg: var(--preset-surface-bg);
120
107
  --ui-surface-bg-subtle: var(--preset-surface-bg-subtle);
121
108
  --ui-surface-bg-raised: var(--preset-surface-bg-raised);
@@ -170,6 +157,7 @@
170
157
 
171
158
  --ui-font-heading: var(--font-heading);
172
159
 
160
+ /* Motion & density — shared */
173
161
  --ui-motion-duration-fast: 0.15s;
174
162
  --ui-motion-duration-default: 0.2s;
175
163
  --ui-motion-ease-standard: var(--ease-standard);
@@ -177,14 +165,15 @@
177
165
  --ui-density-default: 1;
178
166
  --ui-density-comfortable: 1.125;
179
167
 
168
+ /* Content layout — shared */
180
169
  --content-min-width: 320px;
181
170
  --content-preferred-width: 70vw;
182
- /* wider for more expansive reading */
183
171
  --content-max-width: 960px;
184
172
  --content-width: clamp(600px, 70vw, 960px);
185
173
  --content-padding: 24px;
186
174
  --header-top-margin: 64px;
187
175
 
176
+ /* App-specific derived variables — shared (reference --ui-* only) */
188
177
  --publish-trigger-bg: var(--ui-surface-bg-subtle);
189
178
  --publish-trigger-border: var(--ui-surface-border);
190
179
  --publish-trigger-text: var(--ui-text-primary);
@@ -257,7 +246,7 @@
257
246
  --workspace-transition-veil-bg: var(--color-overlay-soft);
258
247
  --workspace-transition-stale-bg: color-mix(in srgb, var(--color-overlay-soft) 72%, transparent);
259
248
 
260
- --tooltip-shadow: var(--ui-surface-shadow);
249
+ --tooltip-shadow: var(--ui-surface-shadow-strong);
261
250
  --select-dropdown-shadow: var(--ui-surface-shadow-strong);
262
251
  --theme-picker-shadow: var(--ui-surface-shadow-strong);
263
252
  --drawer-panel-shadow: var(--ui-surface-shadow-strong);
@@ -1,6 +1,6 @@
1
1
  .ui-input {
2
- --field-bg: var(--ui-surface-bg-inset);
3
- --field-border: transparent;
2
+ --field-bg: var(--ui-surface-bg);
3
+ --field-border: var(--ui-surface-border);
4
4
  --field-text: var(--ui-text-primary);
5
5
  --field-placeholder: var(--ui-text-muted);
6
6
  --field-ring: var(--ui-control-focus-ring);
@@ -1,17 +1,17 @@
1
1
  .ui-select__trigger {
2
- --select-bg: var(--ui-surface-bg-inset);
3
- --select-border: transparent;
2
+ --select-bg: var(--ui-surface-bg);
3
+ --select-border: var(--ui-surface-border);
4
4
  --select-text: var(--ui-text-primary);
5
5
  --select-ring: var(--ui-control-focus-ring);
6
6
 
7
7
  background: var(--select-bg);
8
- border: 1px solid var(--select-border);
8
+ border: 0.5px solid var(--select-border);
9
9
  color: var(--select-text);
10
10
  --tw-ring-color: var(--select-ring);
11
11
  }
12
12
 
13
13
  .ui-select__trigger:hover:not(:disabled) {
14
- --select-bg: var(--ui-surface-bg-subtle);
14
+ --select-border: var(--ui-surface-border-strong);
15
15
  }
16
16
 
17
17
  .ui-select__trigger[data-open] {
@@ -12,6 +12,14 @@
12
12
  color: var(--status-notice-icon);
13
13
  }
14
14
 
15
+ .ui-status-notice__title {
16
+ color: var(--ui-text-primary);
17
+ }
18
+
19
+ .ui-status-notice[data-layout="vertical"] .ui-status-notice__title {
20
+ color: var(--status-notice-text);
21
+ }
22
+
15
23
  .ui-status-notice[data-tone="info"] {
16
24
  --status-notice-bg: var(--feedback-info-bg);
17
25
  --status-notice-border: var(--feedback-info-border);
@@ -6,12 +6,17 @@
6
6
  background: var(--tooltip-bg);
7
7
  color: var(--tooltip-text);
8
8
  border: 1px solid var(--tooltip-border);
9
- box-shadow: var(--tooltip-shadow);
9
+ box-shadow:
10
+ 0 0 0 1px color-mix(in srgb, var(--tooltip-border) 55%, transparent),
11
+ var(--tooltip-shadow);
12
+ backdrop-filter: blur(10px);
10
13
  }
11
14
 
12
15
  .ui-tooltip__arrow {
13
16
  color: var(--tooltip-arrow-color);
14
- filter: drop-shadow(0 1px 0 var(--tooltip-border));
17
+ filter:
18
+ drop-shadow(0 1px 0 var(--tooltip-border))
19
+ drop-shadow(0 0 0.5px color-mix(in srgb, var(--tooltip-border) 55%, transparent));
15
20
  }
16
21
 
17
22
  @keyframes tooltip-in {
@@ -10,11 +10,11 @@
10
10
  --color-n400: #3f3f46;
11
11
  --color-n300: #27272a;
12
12
 
13
- --color-brand-primary: #e11d48;
14
- --color-brand-primary-hover: #f43f5e;
15
- --color-brand-accent: #fb7185;
13
+ --color-brand-primary: #c6c6c7;
14
+ --color-brand-primary-hover: #d4d4d8;
15
+ --color-brand-accent: #a1a1aa;
16
16
 
17
- --color-surface-canvas: #09090b;
17
+ --color-surface-canvas: #0e0e0e;
18
18
  --color-surface-base: #18181b;
19
19
  --color-surface-subtle: #1c1c1f;
20
20
  --color-surface-raised: #27272a;
@@ -28,7 +28,7 @@
28
28
  --color-highlight-soft: rgba(255, 255, 255, 0.06);
29
29
  --color-highlight-sheen: rgba(255, 255, 255, 0.08);
30
30
 
31
- --color-text-on-brand: #ffffff;
31
+ --color-text-on-brand: #1a1a1a;
32
32
 
33
33
  --color-code-block-bg: #1e1e22;
34
34
  --color-code-block-border: #2d2d32;
@@ -1,7 +1,69 @@
1
- @import "./tokens.css";
1
+ @import "./styles/tokens.css";
2
2
 
3
+ /* ================================================================== */
4
+ /* Light theme — all --color-* primitives + --theme-* mappings */
5
+ /* */
6
+ /* :root (bare) is included so light acts as the default when no */
7
+ /* explicit data-theme is set. */
8
+ /* ================================================================== */
9
+
10
+ :root,
3
11
  :root[data-theme="light"],
4
12
  .owoui-theme-light {
13
+ /* Neutral scale */
14
+ --color-n900: #1a1a1a;
15
+ --color-n800: #2d2d2d;
16
+ --color-n700: #4a4a4a;
17
+ --color-n600: #71717a;
18
+ --color-n500: #a1a1aa;
19
+ --color-n400: #d4d4d8;
20
+ --color-n300: #e4e4e7;
21
+
22
+ /* Brand */
23
+ --color-brand-primary: #1a1a1a;
24
+ --color-brand-primary-hover: #000000;
25
+ --color-brand-accent: #4a4a4a;
26
+
27
+ /* Surfaces */
28
+ --color-surface-canvas: #ffffff;
29
+ --color-surface-base: #ffffff;
30
+ --color-surface-subtle: #fafaf9;
31
+ --color-surface-raised: #ffffff;
32
+ --color-surface-inset: #f5f5f4;
33
+ --color-surface-border: #e5e7eb;
34
+ --color-surface-ring: #d6d3d1;
35
+ --color-surface-overlay: rgba(0, 0, 0, 0.4);
36
+
37
+ /* Overlays & highlights */
38
+ --color-overlay-soft: rgba(244, 238, 230, 0.56);
39
+ --color-overlay-strong: rgba(15, 23, 42, 0.18);
40
+ --color-highlight-soft: rgba(255, 255, 255, 0.56);
41
+ --color-highlight-sheen: rgba(255, 255, 255, 0.34);
42
+
43
+ /* Text on brand */
44
+ --color-text-on-brand: #ffffff;
45
+
46
+ /* Code blocks */
47
+ --color-code-block-bg: #f4f4f5;
48
+ --color-code-block-border: #e4e4e7;
49
+ --color-code-block-divider: #ececed;
50
+ --color-code-inline-bg: #f4f4f5;
51
+
52
+ /* Status */
53
+ --color-admin-success-bg: rgba(16, 185, 129, 0.10);
54
+ --color-admin-success-border: rgba(16, 185, 129, 0.20);
55
+ --color-admin-success-text: #047857;
56
+ --color-admin-warning-bg: rgba(245, 158, 11, 0.10);
57
+ --color-admin-warning-border: rgba(245, 158, 11, 0.20);
58
+ --color-admin-warning-text: #b45309;
59
+ --color-admin-danger-bg: rgba(239, 68, 68, 0.10);
60
+ --color-admin-danger-border: rgba(239, 68, 68, 0.20);
61
+ --color-admin-danger-text: #b91c1c;
62
+ --color-admin-info-bg: rgba(14, 165, 233, 0.10);
63
+ --color-admin-info-border: rgba(14, 165, 233, 0.20);
64
+ --color-admin-info-text: #0369a1;
65
+
66
+ /* ---- Theme semantic mappings (--color-* → --theme-*) ---- */
5
67
  --theme-surface-canvas: var(--color-surface-canvas);
6
68
  --theme-surface-base: var(--color-surface-base);
7
69
  --theme-surface-subtle: var(--color-surface-subtle);
@@ -38,4 +100,3 @@
38
100
  --theme-control-focus-ring: var(--color-surface-ring);
39
101
  --theme-control-focus-ring-offset: var(--color-surface-base);
40
102
  }
41
-
@@ -1,34 +0,0 @@
1
- .ui-empty-state {
2
- --empty-state-bg: var(--ui-surface-bg-raised);
3
- --empty-state-border: var(--ui-surface-border);
4
- --empty-state-title: var(--ui-text-primary);
5
- --empty-state-text: var(--ui-text-muted);
6
- --empty-state-icon: var(--ui-text-muted);
7
- background: var(--empty-state-bg);
8
- border-color: var(--empty-state-border);
9
- color: var(--empty-state-text);
10
- }
11
-
12
- .ui-empty-state__icon {
13
- color: var(--empty-state-icon);
14
- }
15
-
16
- .ui-empty-state__title {
17
- color: var(--empty-state-title);
18
- }
19
-
20
- .ui-empty-state[data-tone="notice"] {
21
- --empty-state-bg: var(--ui-info-bg);
22
- --empty-state-border: var(--ui-info-border);
23
- --empty-state-title: var(--ui-info-text);
24
- --empty-state-text: var(--ui-info-text);
25
- --empty-state-icon: var(--ui-info-text);
26
- }
27
-
28
- .ui-empty-state[data-tone="warning"] {
29
- --empty-state-bg: var(--ui-warning-bg);
30
- --empty-state-border: var(--ui-warning-border);
31
- --empty-state-title: var(--ui-warning-text);
32
- --empty-state-text: var(--ui-warning-text);
33
- --empty-state-icon: var(--ui-warning-text);
34
- }