@gainsight-hub/design-tokens 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.
- package/README.md +305 -0
- package/dist/applyTheme.d.ts +14 -0
- package/dist/applyTheme.js +66 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/styles.css +457 -0
- package/dist/tailwind.preset.cjs +289 -0
- package/dist/tailwind.preset.mjs +289 -0
- package/dist/theme-manifest.json +212 -0
- package/dist/themes/antd.css +48 -0
- package/dist/themes/antd.css.d.ts +2 -0
- package/dist/themes/dark.css +47 -0
- package/dist/themes/dark.css.d.ts +2 -0
- package/dist/themes/legacy.css +165 -0
- package/dist/themes/legacy.css.d.ts +2 -0
- package/dist/themes/mui.css +48 -0
- package/dist/themes/mui.css.d.ts +2 -0
- package/dist/themes/spectrum.css +48 -0
- package/dist/themes/spectrum.css.d.ts +2 -0
- package/dist/themes.css +8 -0
- package/dist/token-catalog.json +5107 -0
- package/dist/tokens.d.ts +525 -0
- package/dist/tokens.js +371 -0
- package/dist/tokens.json +617 -0
- package/dist/tokens.scss +360 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# @gainsight-hub/design-tokens
|
|
2
|
+
|
|
3
|
+
Design tokens for the Gainsight Community Hub — CSS custom properties, TypeScript constants, JSON, and a Tailwind v3 preset.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @gainsight-hub/design-tokens
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
Import `styles.css` once at your app entry point. That's it for most apps.
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
// main.js / main.ts
|
|
19
|
+
import "@gainsight-hub/design-tokens/styles.css";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then use tokens anywhere via CSS custom properties:
|
|
23
|
+
|
|
24
|
+
```css
|
|
25
|
+
.button {
|
|
26
|
+
background: var(--color-action-primary-default);
|
|
27
|
+
color: var(--color-content-inverse);
|
|
28
|
+
border-radius: var(--button-radius);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## CSS custom properties
|
|
35
|
+
|
|
36
|
+
### Base (light theme)
|
|
37
|
+
|
|
38
|
+
Defines all tokens as CSS custom properties on `:root`. This is the default light theme.
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
import "@gainsight-hub/design-tokens/styles.css";
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### All themes bundled
|
|
45
|
+
|
|
46
|
+
Includes the base tokens plus all theme overrides in a single file. Use this if you want to switch themes at runtime without loading additional stylesheets.
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
import "@gainsight-hub/design-tokens/themes.css";
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Individual themes
|
|
53
|
+
|
|
54
|
+
Load only the theme you need on top of `styles.css`:
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import "@gainsight-hub/design-tokens/styles.css";
|
|
58
|
+
import "@gainsight-hub/design-tokens/themes/dark.css";
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Available themes:
|
|
62
|
+
|
|
63
|
+
| Import path | Description |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `@gainsight-hub/design-tokens/themes/dark.css` | Gainsight dark mode |
|
|
66
|
+
| `@gainsight-hub/design-tokens/themes/legacy.css` | Legacy variable aliases |
|
|
67
|
+
| `@gainsight-hub/design-tokens/themes/mui.css` | Material UI overrides |
|
|
68
|
+
| `@gainsight-hub/design-tokens/themes/antd.css` | Ant Design overrides |
|
|
69
|
+
| `@gainsight-hub/design-tokens/themes/spectrum.css` | Adobe Spectrum overrides |
|
|
70
|
+
|
|
71
|
+
### Theme switching at runtime
|
|
72
|
+
|
|
73
|
+
All CSS custom properties can be scoped and overridden at any level:
|
|
74
|
+
|
|
75
|
+
```css
|
|
76
|
+
/* Scope to a data attribute */
|
|
77
|
+
[data-theme="dark"] {
|
|
78
|
+
--color-surface-page: #161618;
|
|
79
|
+
--color-content-default: #f4f5f7;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Scope to a tenant / white-label */
|
|
83
|
+
[data-tenant="acme"] {
|
|
84
|
+
--color-action-primary-default: #e63946;
|
|
85
|
+
--button-primary-background-default: #e63946;
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## TypeScript / JavaScript
|
|
92
|
+
|
|
93
|
+
Import typed token constants directly. All exports are fully typed via the bundled `tokens.d.ts`.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import {
|
|
97
|
+
ColorActionPrimaryDefault,
|
|
98
|
+
ColorSurfacePage,
|
|
99
|
+
RadiusFull,
|
|
100
|
+
} from "@gainsight-hub/design-tokens";
|
|
101
|
+
|
|
102
|
+
// Use in JS logic — e.g. canvas drawing, charting libs
|
|
103
|
+
ctx.fillStyle = ColorActionPrimaryDefault; // "#0C66E4"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Tailwind v3
|
|
109
|
+
|
|
110
|
+
### Step 1 — Import the CSS variables
|
|
111
|
+
|
|
112
|
+
The Tailwind preset generates utility classes that reference CSS custom properties. Import `styles.css` so those variables are defined on the page.
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
// main.js / main.ts
|
|
116
|
+
import "@gainsight-hub/design-tokens/styles.css";
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Step 2 — Add the preset to your Tailwind config
|
|
120
|
+
|
|
121
|
+
**ESM** (Vite, Next.js, modern setups):
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
// tailwind.config.js
|
|
125
|
+
import preset from "@gainsight-hub/design-tokens/tailwind";
|
|
126
|
+
|
|
127
|
+
export default {
|
|
128
|
+
content: ["./src/**/*.{html,js,ts,jsx,tsx}"],
|
|
129
|
+
presets: [preset],
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**CJS** (older Tailwind v3 configs):
|
|
134
|
+
|
|
135
|
+
```js
|
|
136
|
+
// tailwind.config.cjs
|
|
137
|
+
const preset = require("@gainsight-hub/design-tokens/tailwind");
|
|
138
|
+
|
|
139
|
+
module.exports = {
|
|
140
|
+
content: ["./src/**/*.{html,js,ts,jsx,tsx}"],
|
|
141
|
+
presets: [preset],
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Step 3 — Use token-based utility classes
|
|
146
|
+
|
|
147
|
+
```html
|
|
148
|
+
<!-- Colors -->
|
|
149
|
+
<div class="bg-action-primary text-content-inverse">Primary button</div>
|
|
150
|
+
<div class="bg-surface-default text-content-default">Card</div>
|
|
151
|
+
<div class="bg-status-success-bold text-content-inverse">Success badge</div>
|
|
152
|
+
|
|
153
|
+
<!-- Spacing -->
|
|
154
|
+
<div class="p-spacing-200 gap-spacing-100">Layout</div>
|
|
155
|
+
|
|
156
|
+
<!-- Border radius -->
|
|
157
|
+
<div class="rounded-radius-100">Small</div>
|
|
158
|
+
<div class="rounded-radius-full">Pill / avatar</div>
|
|
159
|
+
|
|
160
|
+
<!-- Typography -->
|
|
161
|
+
<p class="text-sm leading-normal font-medium">Body text</p>
|
|
162
|
+
|
|
163
|
+
<!-- Shadows -->
|
|
164
|
+
<div class="shadow-elevation-1">Raised card</div>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Color token naming — the `-default` suffix collapses into the base class:
|
|
168
|
+
|
|
169
|
+
| Tailwind class | CSS variable |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `bg-action-primary` | `var(--color-action-primary-default)` |
|
|
172
|
+
| `bg-action-primary-hover` | `var(--color-action-primary-hover)` |
|
|
173
|
+
| `bg-surface-page` | `var(--color-surface-page)` |
|
|
174
|
+
| `text-content-subtle` | `var(--color-content-subtle)` |
|
|
175
|
+
| `border-line-default` | `var(--color-line-default)` |
|
|
176
|
+
|
|
177
|
+
> **Why import both `styles.css` and the preset?**
|
|
178
|
+
> `styles.css` defines the CSS custom property values. The preset generates utility classes that reference those variables with `var(--token-name)`. The preset alone produces no colors — it needs the variables defined on the page. This separation enables runtime theming: change a CSS variable at any scope and every Tailwind class using that token updates automatically, with no rebuild.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Component tokens (CSS Modules)
|
|
183
|
+
|
|
184
|
+
For component internals, use CSS Modules with `var()` directly:
|
|
185
|
+
|
|
186
|
+
```css
|
|
187
|
+
/* Button.module.css */
|
|
188
|
+
.root {
|
|
189
|
+
background: var(--button-primary-background-default);
|
|
190
|
+
color: var(--button-primary-label-default);
|
|
191
|
+
border-radius: var(--button-radius);
|
|
192
|
+
padding: var(--space-100) var(--space-200);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.root:hover {
|
|
196
|
+
background: var(--button-primary-background-hover);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
// Button.tsx
|
|
202
|
+
import styles from "./Button.module.css";
|
|
203
|
+
|
|
204
|
+
export function Button({ children }: { children: React.ReactNode }) {
|
|
205
|
+
return <button className={styles.root}>{children}</button>;
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## JSON
|
|
212
|
+
|
|
213
|
+
Raw token values as nested JSON. Useful for tooling, build scripts, or non-web targets (e.g. React Native, Figma plugins).
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
import tokens from "@gainsight-hub/design-tokens/tokens.json" with { type: "json" };
|
|
217
|
+
|
|
218
|
+
const primary = tokens.color.action.primary.default.value; // "#0C66E4"
|
|
219
|
+
const gutter = tokens.space.layout.gutter.value; // "12px"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Token catalog
|
|
223
|
+
|
|
224
|
+
Structured catalog with resolved values, descriptions, alias chains, and legacy mappings. Used by the design portal and design tooling.
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
import catalog from "@gainsight-hub/design-tokens/token-catalog.json" with { type: "json" };
|
|
228
|
+
|
|
229
|
+
// 224 tokens with cssVar, path, type, value, description, references, legacyMapping
|
|
230
|
+
catalog.all.forEach(token => console.log(token.cssVar, token.value));
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Runtime theme switching
|
|
234
|
+
|
|
235
|
+
Switch the active theme at runtime — no page reload required. `applyThemeConfig` lazy-loads the theme CSS on first use via `import.meta.url`, so only the themes you actually activate are fetched.
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
import "@gainsight-hub/design-tokens/styles.css"; // load base tokens first
|
|
239
|
+
import { applyThemeConfig } from "@gainsight-hub/design-tokens";
|
|
240
|
+
|
|
241
|
+
// Switch to dark mode
|
|
242
|
+
await applyThemeConfig("gainsight-dark");
|
|
243
|
+
|
|
244
|
+
// Dark mode + custom brand color override
|
|
245
|
+
await applyThemeConfig("gainsight-dark", { "--theme-brand-700": "#FF6600" });
|
|
246
|
+
|
|
247
|
+
// Restore default light theme
|
|
248
|
+
await applyThemeConfig("gainsight-light");
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Available theme IDs: `gainsight-light` (default), `dark`, `legacy`, `mui`, `antd`, `spectrum`.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Available exports
|
|
256
|
+
|
|
257
|
+
| Import | Description |
|
|
258
|
+
|---|---|
|
|
259
|
+
| `@gainsight-hub/design-tokens` | `applyThemeConfig` + TypeScript/JS named constants |
|
|
260
|
+
| `@gainsight-hub/design-tokens/styles.css` | CSS custom properties — base light theme |
|
|
261
|
+
| `@gainsight-hub/design-tokens/themes.css` | CSS custom properties — all themes bundled |
|
|
262
|
+
| `@gainsight-hub/design-tokens/themes/*` | Individual theme overrides (load on top of `styles.css`) |
|
|
263
|
+
| `@gainsight-hub/design-tokens/tailwind` | Tailwind v3 preset (ESM + CJS) |
|
|
264
|
+
| `@gainsight-hub/design-tokens/tokens.json` | Nested JSON — raw token values |
|
|
265
|
+
| `@gainsight-hub/design-tokens/token-catalog.json` | Full catalog with resolved values, descriptions, alias chains |
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Package structure
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
packages/design-tokens/
|
|
273
|
+
├── src/ Token source files (Style Dictionary format)
|
|
274
|
+
│ ├── primitive/ Raw scales — color, space, radius, font, shadow
|
|
275
|
+
│ ├── semantic/ Semantic roles — action, surface, content, line, status
|
|
276
|
+
│ └── component/ Component tokens — button, card, feed, navigation, widget
|
|
277
|
+
├── config/ Style Dictionary config and custom formats
|
|
278
|
+
│ └── themes/ Theme override definitions
|
|
279
|
+
├── migration/ Legacy variable mapping tools
|
|
280
|
+
├── build.js Build entry point
|
|
281
|
+
└── dist/ Published output (generated, do not edit)
|
|
282
|
+
├── index.js Root entry — applyThemeConfig + token constants
|
|
283
|
+
├── index.d.ts TypeScript declarations for root entry
|
|
284
|
+
├── applyTheme.js Runtime theme switcher (lazy CSS loading)
|
|
285
|
+
├── applyTheme.d.ts TypeScript declarations for applyThemeConfig
|
|
286
|
+
├── tokens.js JS named constants
|
|
287
|
+
├── tokens.d.ts TypeScript declarations for token constants
|
|
288
|
+
├── styles.css CSS custom properties (base light theme)
|
|
289
|
+
├── themes.css All themes combined (styles.css + all theme overrides)
|
|
290
|
+
├── tokens.json Nested JSON
|
|
291
|
+
├── token-catalog.json Full token catalog
|
|
292
|
+
├── tailwind.preset.mjs Tailwind preset (ESM)
|
|
293
|
+
├── tailwind.preset.cjs Tailwind preset (CJS)
|
|
294
|
+
└── themes/ Individual theme CSS files
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Building and publishing
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# Build from the monorepo root
|
|
301
|
+
turbo run build --filter=@gainsight-hub/design-tokens
|
|
302
|
+
|
|
303
|
+
# Publish
|
|
304
|
+
npm publish --access public -w packages/design-tokens
|
|
305
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Auto-generated — do not edit manually.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Switches the active theme at runtime. Lazy-loads the theme CSS on first use.
|
|
5
|
+
* Import styles.css first to establish the default light theme.
|
|
6
|
+
*
|
|
7
|
+
* @param themeId Theme to activate ("gainsight-dark", "legacy", "theme-mui", …).
|
|
8
|
+
* Pass "gainsight-light" to restore the default.
|
|
9
|
+
* @param overrides Optional CSS variable overrides applied on top of the base theme.
|
|
10
|
+
*/
|
|
11
|
+
export declare function applyThemeConfig(
|
|
12
|
+
themeId: string,
|
|
13
|
+
overrides?: Record<string, string>,
|
|
14
|
+
): Promise<void>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Auto-generated — do not edit manually.
|
|
2
|
+
const THEME_CSS_URLS = {
|
|
3
|
+
"dark": new URL("./themes/dark.css", import.meta.url).href,
|
|
4
|
+
"legacy": new URL("./themes/legacy.css", import.meta.url).href,
|
|
5
|
+
"mui": new URL("./themes/mui.css", import.meta.url).href,
|
|
6
|
+
"antd": new URL("./themes/antd.css", import.meta.url).href,
|
|
7
|
+
"spectrum": new URL("./themes/spectrum.css", import.meta.url).href,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const STYLE_ID = "__gs-theme-overrides";
|
|
11
|
+
const _loaded = new Set();
|
|
12
|
+
|
|
13
|
+
function loadCss(url) {
|
|
14
|
+
if (_loaded.has(url)) return Promise.resolve();
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const link = document.createElement("link");
|
|
17
|
+
link.rel = "stylesheet";
|
|
18
|
+
link.href = url;
|
|
19
|
+
link.onload = () => { _loaded.add(url); resolve(); };
|
|
20
|
+
link.onerror = () => reject(new Error("Failed to load theme CSS: " + url));
|
|
21
|
+
document.head.appendChild(link);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function injectOverrides(overrides) {
|
|
26
|
+
const css = Object.entries(overrides).map(([k, v]) => " " + k + ": " + v + ";").join("\n");
|
|
27
|
+
let el = document.getElementById(STYLE_ID);
|
|
28
|
+
if (!el) { el = document.createElement("style"); el.id = STYLE_ID; document.head.appendChild(el); }
|
|
29
|
+
el.textContent = ":root {\n" + css + "\n}";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function removeOverrides() {
|
|
33
|
+
document.getElementById(STYLE_ID)?.remove();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Switches the active theme at runtime.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} themeId - Theme to activate. Use "gainsight-light" to restore the default.
|
|
40
|
+
* @param {Record<string,string>} [overrides] - Optional CSS variable overrides applied on top.
|
|
41
|
+
* @returns {Promise<void>}
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* import { applyThemeConfig } from "@gainsight-hub/design-tokens";
|
|
45
|
+
*
|
|
46
|
+
* await applyThemeConfig("gainsight-dark");
|
|
47
|
+
* await applyThemeConfig("gainsight-dark", { "--theme-brand-700": "#FF6600" });
|
|
48
|
+
* await applyThemeConfig("gainsight-light"); // restore default
|
|
49
|
+
*/
|
|
50
|
+
export async function applyThemeConfig(themeId, overrides = {}) {
|
|
51
|
+
const cssUrl = THEME_CSS_URLS[themeId];
|
|
52
|
+
|
|
53
|
+
if (!cssUrl) {
|
|
54
|
+
// Default / light theme — remove any active theme attribute
|
|
55
|
+
document.documentElement.removeAttribute("data-theme");
|
|
56
|
+
} else {
|
|
57
|
+
await loadCss(cssUrl);
|
|
58
|
+
document.documentElement.setAttribute("data-theme", themeId);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (Object.keys(overrides).length === 0) {
|
|
62
|
+
removeOverrides();
|
|
63
|
+
} else {
|
|
64
|
+
injectOverrides(overrides);
|
|
65
|
+
}
|
|
66
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED