@luster-ui/ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PUBLISHING.md +469 -0
- package/README.md +423 -0
- package/dist/cjs/index-Couc0LVo.js +1571 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/loader.cjs.js +12 -0
- package/dist/cjs/luster-accordion_19.cjs.entry.js +555 -0
- package/dist/cjs/luster-card.cjs.entry.js +25 -0
- package/dist/cjs/luster.cjs.js +24 -0
- package/dist/collection/collection-manifest.json +32 -0
- package/dist/collection/components/luster-accordion/luster-accordion.css +76 -0
- package/dist/collection/components/luster-accordion/luster-accordion.js +160 -0
- package/dist/collection/components/luster-accordion/luster-accordion.stories.js +88 -0
- package/dist/collection/components/luster-activity-item/luster-activity-item.css +102 -0
- package/dist/collection/components/luster-activity-item/luster-activity-item.js +188 -0
- package/dist/collection/components/luster-activity-item/luster-activity-item.stories.js +94 -0
- package/dist/collection/components/luster-alert/luster-alert.css +71 -0
- package/dist/collection/components/luster-alert/luster-alert.js +171 -0
- package/dist/collection/components/luster-alert/luster-alert.stories.js +82 -0
- package/dist/collection/components/luster-article-card/luster-article-card.css +120 -0
- package/dist/collection/components/luster-article-card/luster-article-card.js +192 -0
- package/dist/collection/components/luster-article-card/luster-article-card.stories.js +82 -0
- package/dist/collection/components/luster-badge/luster-badge.css +38 -0
- package/dist/collection/components/luster-badge/luster-badge.js +87 -0
- package/dist/collection/components/luster-badge/luster-badge.stories.js +86 -0
- package/dist/collection/components/luster-button/luster-button.css +121 -0
- package/dist/collection/components/luster-button/luster-button.js +179 -0
- package/dist/collection/components/luster-button/luster-button.stories.js +103 -0
- package/dist/collection/components/luster-card/luster-card.css +29 -0
- package/dist/collection/components/luster-card/luster-card.js +92 -0
- package/dist/collection/components/luster-card/luster-card.stories.js +67 -0
- package/dist/collection/components/luster-checkbox/luster-checkbox.css +42 -0
- package/dist/collection/components/luster-checkbox/luster-checkbox.js +162 -0
- package/dist/collection/components/luster-checkbox/luster-checkbox.stories.js +78 -0
- package/dist/collection/components/luster-color-swatch/luster-color-swatch.css +33 -0
- package/dist/collection/components/luster-color-swatch/luster-color-swatch.js +108 -0
- package/dist/collection/components/luster-color-swatch/luster-color-swatch.stories.js +58 -0
- package/dist/collection/components/luster-feature-quote/luster-feature-quote.css +84 -0
- package/dist/collection/components/luster-feature-quote/luster-feature-quote.js +108 -0
- package/dist/collection/components/luster-feature-quote/luster-feature-quote.stories.js +52 -0
- package/dist/collection/components/luster-hero/luster-hero.css +119 -0
- package/dist/collection/components/luster-hero/luster-hero.js +129 -0
- package/dist/collection/components/luster-hero/luster-hero.stories.js +72 -0
- package/dist/collection/components/luster-input/luster-input.css +72 -0
- package/dist/collection/components/luster-input/luster-input.js +332 -0
- package/dist/collection/components/luster-input/luster-input.stories.js +106 -0
- package/dist/collection/components/luster-modal/luster-modal.css +103 -0
- package/dist/collection/components/luster-modal/luster-modal.js +215 -0
- package/dist/collection/components/luster-modal/luster-modal.stories.js +78 -0
- package/dist/collection/components/luster-navbar/luster-navbar.css +151 -0
- package/dist/collection/components/luster-navbar/luster-navbar.js +87 -0
- package/dist/collection/components/luster-navbar/luster-navbar.stories.js +41 -0
- package/dist/collection/components/luster-profile-card/luster-profile-card.css +89 -0
- package/dist/collection/components/luster-profile-card/luster-profile-card.js +194 -0
- package/dist/collection/components/luster-profile-card/luster-profile-card.stories.js +56 -0
- package/dist/collection/components/luster-resource-table/luster-resource-table.css +141 -0
- package/dist/collection/components/luster-resource-table/luster-resource-table.js +78 -0
- package/dist/collection/components/luster-resource-table/luster-resource-table.stories.js +44 -0
- package/dist/collection/components/luster-sidebar/luster-sidebar.css +152 -0
- package/dist/collection/components/luster-sidebar/luster-sidebar.js +78 -0
- package/dist/collection/components/luster-sidebar/luster-sidebar.stories.js +34 -0
- package/dist/collection/components/luster-stat-card/luster-stat-card.css +82 -0
- package/dist/collection/components/luster-stat-card/luster-stat-card.js +194 -0
- package/dist/collection/components/luster-stat-card/luster-stat-card.stories.js +75 -0
- package/dist/collection/components/luster-tabs/luster-tabs.css +35 -0
- package/dist/collection/components/luster-tabs/luster-tabs.js +116 -0
- package/dist/collection/components/luster-tabs/luster-tabs.stories.js +56 -0
- package/dist/collection/components/luster-toggle/luster-toggle.css +48 -0
- package/dist/collection/components/luster-toggle/luster-toggle.js +120 -0
- package/dist/collection/components/luster-toggle/luster-toggle.stories.js +66 -0
- package/dist/components/index.d.ts +33 -0
- package/dist/components/index.js +1 -0
- package/dist/components/luster-accordion.d.ts +11 -0
- package/dist/components/luster-accordion.js +1 -0
- package/dist/components/luster-activity-item.d.ts +11 -0
- package/dist/components/luster-activity-item.js +1 -0
- package/dist/components/luster-alert.d.ts +11 -0
- package/dist/components/luster-alert.js +1 -0
- package/dist/components/luster-article-card.d.ts +11 -0
- package/dist/components/luster-article-card.js +1 -0
- package/dist/components/luster-badge.d.ts +11 -0
- package/dist/components/luster-badge.js +1 -0
- package/dist/components/luster-badge2.js +1 -0
- package/dist/components/luster-button.d.ts +11 -0
- package/dist/components/luster-button.js +1 -0
- package/dist/components/luster-button2.js +1 -0
- package/dist/components/luster-card.d.ts +11 -0
- package/dist/components/luster-card.js +1 -0
- package/dist/components/luster-checkbox.d.ts +11 -0
- package/dist/components/luster-checkbox.js +1 -0
- package/dist/components/luster-color-swatch.d.ts +11 -0
- package/dist/components/luster-color-swatch.js +1 -0
- package/dist/components/luster-feature-quote.d.ts +11 -0
- package/dist/components/luster-feature-quote.js +1 -0
- package/dist/components/luster-hero.d.ts +11 -0
- package/dist/components/luster-hero.js +1 -0
- package/dist/components/luster-input.d.ts +11 -0
- package/dist/components/luster-input.js +1 -0
- package/dist/components/luster-modal.d.ts +11 -0
- package/dist/components/luster-modal.js +1 -0
- package/dist/components/luster-navbar.d.ts +11 -0
- package/dist/components/luster-navbar.js +1 -0
- package/dist/components/luster-profile-card.d.ts +11 -0
- package/dist/components/luster-profile-card.js +1 -0
- package/dist/components/luster-resource-table.d.ts +11 -0
- package/dist/components/luster-resource-table.js +1 -0
- package/dist/components/luster-sidebar.d.ts +11 -0
- package/dist/components/luster-sidebar.js +1 -0
- package/dist/components/luster-stat-card.d.ts +11 -0
- package/dist/components/luster-stat-card.js +1 -0
- package/dist/components/luster-tabs.d.ts +11 -0
- package/dist/components/luster-tabs.js +1 -0
- package/dist/components/luster-toggle.d.ts +11 -0
- package/dist/components/luster-toggle.js +1 -0
- package/dist/components/luster-toggle2.js +1 -0
- package/dist/esm/index-CeYIN8dN.js +1563 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/loader.js +10 -0
- package/dist/esm/luster-accordion_19.entry.js +535 -0
- package/dist/esm/luster-card.entry.js +23 -0
- package/dist/esm/luster.js +20 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/luster/index.esm.js +0 -0
- package/dist/luster/luster.css +313 -0
- package/dist/luster/luster.esm.js +1 -0
- package/dist/luster/p-3c4ce897.entry.js +1 -0
- package/dist/luster/p-CeYIN8dN.js +2 -0
- package/dist/luster/p-e368ec08.entry.js +1 -0
- package/dist/types/.stencil/luster-accordion/luster-accordion.d.ts +13 -0
- package/dist/types/.stencil/luster-accordion/luster-accordion.stories.d.ts +10 -0
- package/dist/types/.stencil/luster-activity-item/luster-activity-item.d.ts +11 -0
- package/dist/types/.stencil/luster-activity-item/luster-activity-item.stories.d.ts +9 -0
- package/dist/types/.stencil/luster-alert/luster-alert.d.ts +13 -0
- package/dist/types/.stencil/luster-alert/luster-alert.stories.d.ts +10 -0
- package/dist/types/.stencil/luster-article-card/luster-article-card.d.ts +11 -0
- package/dist/types/.stencil/luster-article-card/luster-article-card.stories.d.ts +8 -0
- package/dist/types/.stencil/luster-badge/luster-badge.d.ts +6 -0
- package/dist/types/.stencil/luster-badge/luster-badge.stories.d.ts +12 -0
- package/dist/types/.stencil/luster-button/luster-button.d.ts +12 -0
- package/dist/types/.stencil/luster-button/luster-button.stories.d.ts +13 -0
- package/dist/types/.stencil/luster-card/luster-card.d.ts +6 -0
- package/dist/types/.stencil/luster-card/luster-card.stories.d.ts +10 -0
- package/dist/types/.stencil/luster-checkbox/luster-checkbox.d.ts +13 -0
- package/dist/types/.stencil/luster-checkbox/luster-checkbox.stories.d.ts +10 -0
- package/dist/types/.stencil/luster-color-swatch/luster-color-swatch.d.ts +7 -0
- package/dist/types/.stencil/luster-color-swatch/luster-color-swatch.stories.d.ts +8 -0
- package/dist/types/.stencil/luster-feature-quote/luster-feature-quote.d.ts +7 -0
- package/dist/types/.stencil/luster-feature-quote/luster-feature-quote.stories.d.ts +8 -0
- package/dist/types/.stencil/luster-hero/luster-hero.d.ts +8 -0
- package/dist/types/.stencil/luster-hero/luster-hero.stories.d.ts +8 -0
- package/dist/types/.stencil/luster-input/luster-input.d.ts +25 -0
- package/dist/types/.stencil/luster-input/luster-input.stories.d.ts +9 -0
- package/dist/types/.stencil/luster-modal/luster-modal.d.ts +17 -0
- package/dist/types/.stencil/luster-modal/luster-modal.stories.d.ts +8 -0
- package/dist/types/.stencil/luster-navbar/luster-navbar.d.ts +6 -0
- package/dist/types/.stencil/luster-navbar/luster-navbar.stories.d.ts +6 -0
- package/dist/types/.stencil/luster-profile-card/luster-profile-card.d.ts +11 -0
- package/dist/types/.stencil/luster-profile-card/luster-profile-card.stories.d.ts +7 -0
- package/dist/types/.stencil/luster-resource-table/luster-resource-table.d.ts +14 -0
- package/dist/types/.stencil/luster-resource-table/luster-resource-table.stories.d.ts +6 -0
- package/dist/types/.stencil/luster-sidebar/luster-sidebar.d.ts +9 -0
- package/dist/types/.stencil/luster-sidebar/luster-sidebar.stories.d.ts +8 -0
- package/dist/types/.stencil/luster-stat-card/luster-stat-card.d.ts +11 -0
- package/dist/types/.stencil/luster-stat-card/luster-stat-card.stories.d.ts +8 -0
- package/dist/types/.stencil/luster-tabs/luster-tabs.d.ts +15 -0
- package/dist/types/.stencil/luster-tabs/luster-tabs.stories.d.ts +7 -0
- package/dist/types/.stencil/luster-toggle/luster-toggle.d.ts +11 -0
- package/dist/types/.stencil/luster-toggle/luster-toggle.stories.d.ts +9 -0
- package/dist/types/components.d.ts +1355 -0
- package/dist/types/stencil-public-runtime.d.ts +1860 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +73 -0
package/PUBLISHING.md
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
# Publishing & Integration Guide — @yvstudio/luster-ui
|
|
2
|
+
|
|
3
|
+
This guide covers how to build, publish to npm, and integrate `@yvstudio/luster-ui` in any project or framework.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of contents
|
|
8
|
+
|
|
9
|
+
1. [Install in another project](#2-install-in-another-project)
|
|
10
|
+
2. [Vanilla HTML](#3-vanilla-html)
|
|
11
|
+
3. [React](#4-react)
|
|
12
|
+
4. [Vue 3](#5-vue-3)
|
|
13
|
+
5. [Angular](#6-angular)
|
|
14
|
+
6. [Theming — any color in 3 lines](#7-theming--any-color-in-3-lines)
|
|
15
|
+
7. [Light / dark mode](#8-light--dark-mode)
|
|
16
|
+
8. [All design tokens reference](#9-all-design-tokens-reference)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 3. Vanilla HTML
|
|
22
|
+
|
|
23
|
+
### From npm (bundler / Vite / Webpack)
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<!DOCTYPE html>
|
|
27
|
+
<html lang="en">
|
|
28
|
+
<head>
|
|
29
|
+
<meta charset="UTF-8" />
|
|
30
|
+
<title>My App</title>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
|
|
34
|
+
<luster-button variant="primary">Get started</luster-button>
|
|
35
|
+
<luster-input label="Email" placeholder="you@example.com"></luster-input>
|
|
36
|
+
<luster-badge variant="success" dot>Active</luster-badge>
|
|
37
|
+
|
|
38
|
+
<script type="module">
|
|
39
|
+
import { defineCustomElements } from '@yvstudio/luster-ui/loader';
|
|
40
|
+
defineCustomElements();
|
|
41
|
+
</script>
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### From CDN (no install needed)
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<script
|
|
50
|
+
type="module"
|
|
51
|
+
src="https://unpkg.com/@yvstudio/luster-ui/dist/luster/luster.esm.js">
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<luster-button variant="primary">Hello from CDN</luster-button>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 4. React
|
|
60
|
+
|
|
61
|
+
### Setup (`main.tsx` or `index.tsx`)
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { defineCustomElements } from '@yvstudio/luster-ui/loader';
|
|
65
|
+
defineCustomElements();
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Component usage
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
// src/pages/Home.tsx
|
|
72
|
+
export function Home() {
|
|
73
|
+
return (
|
|
74
|
+
<section>
|
|
75
|
+
<luster-hero
|
|
76
|
+
heading="Welcome"
|
|
77
|
+
subtitle="Built with Luster design system"
|
|
78
|
+
section="HOME"
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
<luster-button
|
|
82
|
+
variant="primary"
|
|
83
|
+
onClick={() => console.log('clicked')}
|
|
84
|
+
>
|
|
85
|
+
Launch
|
|
86
|
+
</luster-button>
|
|
87
|
+
|
|
88
|
+
<luster-alert
|
|
89
|
+
variant="success"
|
|
90
|
+
heading="Saved!"
|
|
91
|
+
message="Your changes were published."
|
|
92
|
+
/>
|
|
93
|
+
</section>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### TypeScript — silence unknown element warnings
|
|
99
|
+
|
|
100
|
+
Create `src/luster.d.ts`:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import type { JSX as LusterJSX } from '@yvstudio/luster-ui/dist/types/components';
|
|
104
|
+
|
|
105
|
+
type LusterElements = {
|
|
106
|
+
[K in keyof LusterJSX.IntrinsicElements]: LusterJSX.IntrinsicElements[K];
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
declare global {
|
|
110
|
+
namespace JSX {
|
|
111
|
+
interface IntrinsicElements extends LusterElements {}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Listening to custom events
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { useRef, useEffect } from 'react';
|
|
120
|
+
|
|
121
|
+
function MyModal() {
|
|
122
|
+
const modalRef = useRef<HTMLElement>(null);
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
const el = modalRef.current;
|
|
126
|
+
const handler = () => console.log('modal closed');
|
|
127
|
+
el?.addEventListener('dcClose', handler);
|
|
128
|
+
return () => el?.removeEventListener('dcClose', handler);
|
|
129
|
+
}, []);
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<luster-modal
|
|
133
|
+
ref={modalRef}
|
|
134
|
+
open
|
|
135
|
+
heading="Confirm"
|
|
136
|
+
subtitle="Are you sure?"
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 5. Vue 3
|
|
145
|
+
|
|
146
|
+
### Setup (`main.ts`)
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import { createApp } from 'vue';
|
|
150
|
+
import App from './App.vue';
|
|
151
|
+
import { defineCustomElements } from '@yvstudio/luster-ui/loader';
|
|
152
|
+
|
|
153
|
+
defineCustomElements();
|
|
154
|
+
|
|
155
|
+
createApp(App).mount('#app');
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Tell Vue to ignore custom elements (`vite.config.ts`)
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { defineConfig } from 'vite';
|
|
162
|
+
import vue from '@vitejs/plugin-vue';
|
|
163
|
+
|
|
164
|
+
export default defineConfig({
|
|
165
|
+
plugins: [
|
|
166
|
+
vue({
|
|
167
|
+
template: {
|
|
168
|
+
compilerOptions: {
|
|
169
|
+
// treat every tag starting with "luster-" as a custom element
|
|
170
|
+
isCustomElement: (tag) => tag.startsWith('luster-'),
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
}),
|
|
174
|
+
],
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Component usage
|
|
179
|
+
|
|
180
|
+
```vue
|
|
181
|
+
<script setup lang="ts">
|
|
182
|
+
import { ref } from 'vue';
|
|
183
|
+
const email = ref('');
|
|
184
|
+
</script>
|
|
185
|
+
|
|
186
|
+
<template>
|
|
187
|
+
<div>
|
|
188
|
+
<luster-navbar logo-title="My App" logo-sub="PLATFORM" />
|
|
189
|
+
|
|
190
|
+
<luster-input
|
|
191
|
+
label="Email"
|
|
192
|
+
placeholder="you@example.com"
|
|
193
|
+
:value="email"
|
|
194
|
+
@dc-input="(e: CustomEvent) => email = e.detail"
|
|
195
|
+
/>
|
|
196
|
+
|
|
197
|
+
<luster-button variant="primary" @dc-click="submit">
|
|
198
|
+
Subscribe
|
|
199
|
+
</luster-button>
|
|
200
|
+
</div>
|
|
201
|
+
</template>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 6. Angular
|
|
207
|
+
|
|
208
|
+
### `app.module.ts`
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
212
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
213
|
+
import { AppComponent } from './app.component';
|
|
214
|
+
import { defineCustomElements } from '@yvstudio/luster-ui/loader';
|
|
215
|
+
|
|
216
|
+
defineCustomElements();
|
|
217
|
+
|
|
218
|
+
@NgModule({
|
|
219
|
+
declarations: [AppComponent],
|
|
220
|
+
imports: [BrowserModule],
|
|
221
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
222
|
+
bootstrap: [AppComponent],
|
|
223
|
+
})
|
|
224
|
+
export class AppModule {}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Component usage
|
|
228
|
+
|
|
229
|
+
```html
|
|
230
|
+
<!-- app.component.html -->
|
|
231
|
+
<luster-navbar logo-title="My App" active-link="dashboard"></luster-navbar>
|
|
232
|
+
|
|
233
|
+
<luster-stat-card
|
|
234
|
+
heading="Users"
|
|
235
|
+
description="Active this month"
|
|
236
|
+
version="v2.1"
|
|
237
|
+
status="active"
|
|
238
|
+
users="12.4k"
|
|
239
|
+
[hasToggle]="true"
|
|
240
|
+
[toggleOn]="true"
|
|
241
|
+
></luster-stat-card>
|
|
242
|
+
|
|
243
|
+
<luster-button variant="primary" (dcClick)="onAction()">
|
|
244
|
+
Create report
|
|
245
|
+
</luster-button>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## 7. Theming — any color in 3 lines
|
|
251
|
+
|
|
252
|
+
All hover tints, shadows, focus rings, glass effects, and gradients are computed via `color-mix()` from three tokens. Override them anywhere in your CSS:
|
|
253
|
+
|
|
254
|
+
```css
|
|
255
|
+
/* your-app.css — applied AFTER importing @yvstudio/luster-ui */
|
|
256
|
+
:root {
|
|
257
|
+
--dc-primary: #f97316; /* your brand color */
|
|
258
|
+
--dc-primary-dim: #ea580c; /* darker shade for gradients & shadows */
|
|
259
|
+
--dc-on-primary: #ffffff; /* text color on primary buttons */
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Examples
|
|
264
|
+
|
|
265
|
+
#### Emerald brand
|
|
266
|
+
|
|
267
|
+
```css
|
|
268
|
+
:root {
|
|
269
|
+
--dc-primary: #10b981;
|
|
270
|
+
--dc-primary-dim: #059669;
|
|
271
|
+
--dc-on-primary: #ffffff;
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### Rose / pink brand
|
|
276
|
+
|
|
277
|
+
```css
|
|
278
|
+
:root {
|
|
279
|
+
--dc-primary: #f43f5e;
|
|
280
|
+
--dc-primary-dim: #e11d48;
|
|
281
|
+
--dc-on-primary: #ffffff;
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### Gold / amber brand
|
|
286
|
+
|
|
287
|
+
```css
|
|
288
|
+
:root {
|
|
289
|
+
--dc-primary: #f59e0b;
|
|
290
|
+
--dc-primary-dim: #d97706;
|
|
291
|
+
--dc-on-primary: #1c1200; /* dark text — amber is a light color */
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### Sky blue brand
|
|
296
|
+
|
|
297
|
+
```css
|
|
298
|
+
:root {
|
|
299
|
+
--dc-primary: #0ea5e9;
|
|
300
|
+
--dc-primary-dim: #0284c7;
|
|
301
|
+
--dc-on-primary: #ffffff;
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Scoped theming (per section / component)
|
|
306
|
+
|
|
307
|
+
You can scope a brand to a specific section of the page without affecting everything else:
|
|
308
|
+
|
|
309
|
+
```css
|
|
310
|
+
.sidebar {
|
|
311
|
+
--dc-primary: #10b981;
|
|
312
|
+
--dc-primary-dim: #059669;
|
|
313
|
+
--dc-on-primary: #ffffff;
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Full surface override (custom dark shade)
|
|
318
|
+
|
|
319
|
+
```css
|
|
320
|
+
:root {
|
|
321
|
+
--dc-primary: #f97316;
|
|
322
|
+
--dc-primary-dim: #ea580c;
|
|
323
|
+
--dc-on-primary: #ffffff;
|
|
324
|
+
|
|
325
|
+
/* Custom dark background instead of navy */
|
|
326
|
+
--dc-surface: #1a0500;
|
|
327
|
+
--dc-surface-container-low: #2a0d00;
|
|
328
|
+
--dc-surface-container: #331000;
|
|
329
|
+
--dc-surface-container-high: #3d1400;
|
|
330
|
+
--dc-surface-container-highest:#471800;
|
|
331
|
+
--dc-surface-bright: #5c2000;
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 8. Light / dark mode
|
|
338
|
+
|
|
339
|
+
### Via JavaScript (manual toggle)
|
|
340
|
+
|
|
341
|
+
```js
|
|
342
|
+
const root = document.documentElement;
|
|
343
|
+
|
|
344
|
+
function setTheme(theme) {
|
|
345
|
+
root.setAttribute('data-theme', theme);
|
|
346
|
+
localStorage.setItem('theme', theme);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function toggleTheme() {
|
|
350
|
+
setTheme(root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Restore saved preference on load
|
|
354
|
+
const saved = localStorage.getItem('theme');
|
|
355
|
+
if (saved) setTheme(saved);
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Via OS preference (automatic — no JS needed)
|
|
359
|
+
|
|
360
|
+
Just import `@yvstudio/luster-ui` — it uses `@media (prefers-color-scheme: light)` out of the box. No configuration required.
|
|
361
|
+
|
|
362
|
+
### In React with a hook
|
|
363
|
+
|
|
364
|
+
```tsx
|
|
365
|
+
import { useEffect, useState } from 'react';
|
|
366
|
+
|
|
367
|
+
function useTheme() {
|
|
368
|
+
const [theme, setTheme] = useState<'dark' | 'light'>(() => {
|
|
369
|
+
return (localStorage.getItem('theme') as 'dark' | 'light') ?? 'dark';
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
useEffect(() => {
|
|
373
|
+
document.documentElement.setAttribute('data-theme', theme);
|
|
374
|
+
localStorage.setItem('theme', theme);
|
|
375
|
+
}, [theme]);
|
|
376
|
+
|
|
377
|
+
return { theme, toggle: () => setTheme(t => t === 'dark' ? 'light' : 'dark') };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Usage
|
|
381
|
+
function ThemeToggle() {
|
|
382
|
+
const { theme, toggle } = useTheme();
|
|
383
|
+
return (
|
|
384
|
+
<luster-button variant="secondary" onClick={toggle}>
|
|
385
|
+
Switch to {theme === 'dark' ? 'Light' : 'Dark'}
|
|
386
|
+
</luster-button>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### In Vue with a composable
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
// composables/useTheme.ts
|
|
395
|
+
import { ref, watchEffect } from 'vue';
|
|
396
|
+
|
|
397
|
+
export function useTheme() {
|
|
398
|
+
const theme = ref<'dark' | 'light'>(
|
|
399
|
+
(localStorage.getItem('theme') as 'dark' | 'light') ?? 'dark'
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
watchEffect(() => {
|
|
403
|
+
document.documentElement.setAttribute('data-theme', theme.value);
|
|
404
|
+
localStorage.setItem('theme', theme.value);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
const toggle = () => {
|
|
408
|
+
theme.value = theme.value === 'dark' ? 'light' : 'dark';
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
return { theme, toggle };
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## 9. All design tokens reference
|
|
418
|
+
|
|
419
|
+
### Override levels
|
|
420
|
+
|
|
421
|
+
| Level | How | Scope |
|
|
422
|
+
|---|---|---|
|
|
423
|
+
| Global rebrand | `:root { --dc-primary: ... }` | Entire app |
|
|
424
|
+
| Per section | `.sidebar { --dc-primary: ... }` | Section only |
|
|
425
|
+
| Per instance | `style="--dc-primary: ..."` on the element | One element |
|
|
426
|
+
|
|
427
|
+
### Core brand tokens (most commonly overridden)
|
|
428
|
+
|
|
429
|
+
| Token | Dark default | Light default | Purpose |
|
|
430
|
+
|---|---|---|---|
|
|
431
|
+
| `--dc-primary` | `#a3a6ff` | `#4547ce` | Brand color — buttons, links, accents |
|
|
432
|
+
| `--dc-primary-dim` | `#6063ee` | `#3234b0` | Darker variant — gradients, shadows |
|
|
433
|
+
| `--dc-on-primary` | `#0a0040` | `#ffffff` | Text/icon on primary bg |
|
|
434
|
+
|
|
435
|
+
### Surface tokens
|
|
436
|
+
|
|
437
|
+
| Token | Dark | Light |
|
|
438
|
+
|---|---|---|
|
|
439
|
+
| `--dc-surface` | `#060e20` | `#f5f7ff` |
|
|
440
|
+
| `--dc-surface-container-low` | `#091328` | `#eef0ff` |
|
|
441
|
+
| `--dc-surface-container-high` | `#141f38` | `#e0e3ff` |
|
|
442
|
+
| `--dc-on-surface` | `#dee5ff` | `#0d0f2d` |
|
|
443
|
+
| `--dc-on-surface-variant` | `#a3aac4` | `#3f4263` |
|
|
444
|
+
|
|
445
|
+
### Semantic tokens
|
|
446
|
+
|
|
447
|
+
| Token | Dark | Light | Purpose |
|
|
448
|
+
|---|---|---|---|
|
|
449
|
+
| `--dc-error` | `#ffb4ab` | `#ba1a1a` | Destructive actions, error states |
|
|
450
|
+
| `--dc-success` | `#4cceac` | `#006c4c` | Success feedback |
|
|
451
|
+
| `--dc-warning` | `#ffd166` | `#7c5700` | Warning / caution |
|
|
452
|
+
|
|
453
|
+
### Derived tokens (auto-computed — override only if needed)
|
|
454
|
+
|
|
455
|
+
These are computed via `color-mix()` and update automatically when you change the base tokens. You can still override them for fine-grained control.
|
|
456
|
+
|
|
457
|
+
| Token | Derived from | Use |
|
|
458
|
+
|---|---|---|
|
|
459
|
+
| `--dc-hover-tint` | `--dc-primary` @ 4% | Row/item hover |
|
|
460
|
+
| `--dc-hover-tint-strong` | `--dc-primary` @ 8% | Button hover fill |
|
|
461
|
+
| `--dc-icon-bg` | `--dc-primary` @ 10% | Icon backgrounds |
|
|
462
|
+
| `--dc-focus-ring` | `--dc-primary` @ 12% | Input/button focus |
|
|
463
|
+
| `--dc-border-faint` | `--dc-border-source` @ 20% | Subtle separators |
|
|
464
|
+
| `--dc-border-default` | `--dc-border-source` @ 30% | Card/modal borders |
|
|
465
|
+
| `--dc-glass-nav` | `--dc-surface-bright` @ 65% | Navbar blur effect |
|
|
466
|
+
| `--dc-overlay-modal` | `--dc-surface` @ 80% | Modal backdrop |
|
|
467
|
+
| `--dc-shadow-md` | `--dc-primary-dim` @ 12% | Card elevation |
|
|
468
|
+
| `--dc-error-border` | `--dc-error` @ 30% | Destructive button border |
|
|
469
|
+
| `--dc-error-bg` | `--dc-error` @ 10% | Destructive button hover |
|