@techsio/ui-kit 0.12.0 → 0.14.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/dist/.storybook/main.d.ts.map +1 -1
- package/dist/.storybook/preview.d.ts.map +1 -1
- package/dist/src/theme/theme-config.d.ts +41 -0
- package/dist/src/theme/theme-config.d.ts.map +1 -0
- package/dist/src/theme/theme-provider.d.ts +37 -0
- package/dist/src/theme/theme-provider.d.ts.map +1 -0
- package/dist/src/theme/theme-toggle.d.ts +4 -0
- package/dist/src/theme/theme-toggle.d.ts.map +1 -0
- package/dist/theme/theme-config.js +46 -0
- package/dist/theme/theme-provider.js +101 -0
- package/dist/theme/theme-toggle.js +71 -0
- package/package.json +13 -10
- package/src/tokens/_tokens-base.css +6 -0
- package/src/tokens/figma/brand-overrides.css +49 -0
- package/src/tokens/figma/dark/variables.css +1 -1
- package/src/tokens/figma/light/variables.css +1 -1
- package/src/tokens/figma/neo/variables.css +1792 -0
- package/src/tokens/figma/neo-dark/variables.css +1792 -0
- package/src/tokens/figma/variables.css +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../.storybook/main.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAE9D,QAAA,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../.storybook/main.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAE9D,QAAA,MAAM,MAAM,EAAE,eAkBb,CAAA;AAED,eAAe,MAAM,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../.storybook/preview.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../.storybook/preview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAU1D,OAAO,yBAAyB,CAAA;AA2ChC,QAAA,MAAM,OAAO,EAAE,OA0Dd,CAAA;AAED,eAAe,OAAO,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type ColorMode = "light" | "dark";
|
|
2
|
+
/** What the user can pick for the mode axis. `system` follows the OS. */
|
|
3
|
+
export type ModeSetting = ColorMode | "system";
|
|
4
|
+
export type BrandConfig = {
|
|
5
|
+
/** Human label shown in togglers. */
|
|
6
|
+
label: string;
|
|
7
|
+
/** Concrete modes this brand ships. Light-only brands omit "dark". */
|
|
8
|
+
modes: ColorMode[];
|
|
9
|
+
/**
|
|
10
|
+
* `data-theme` attribute value for this brand. Omitted for the base brand,
|
|
11
|
+
* which is the default `:root` / `@theme` and needs no attribute.
|
|
12
|
+
*/
|
|
13
|
+
attr?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare const THEMES: {
|
|
16
|
+
readonly base: {
|
|
17
|
+
readonly label: "Default";
|
|
18
|
+
readonly modes: ["light", "dark"];
|
|
19
|
+
};
|
|
20
|
+
readonly neo: {
|
|
21
|
+
readonly label: "Neo (Red)";
|
|
22
|
+
readonly modes: ["light", "dark"];
|
|
23
|
+
readonly attr: "neo";
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export type BrandKey = keyof typeof THEMES;
|
|
27
|
+
export declare const DEFAULT_BRAND: BrandKey;
|
|
28
|
+
export declare const DEFAULT_MODE: ModeSetting;
|
|
29
|
+
/** localStorage keys used by the provider for persistence. */
|
|
30
|
+
export declare const BRAND_STORAGE_KEY = "ui-brand";
|
|
31
|
+
export declare const MODE_STORAGE_KEY = "ui-mode";
|
|
32
|
+
export declare function brandKeys(): BrandKey[];
|
|
33
|
+
export declare function getBrand(key: BrandKey): BrandConfig;
|
|
34
|
+
export declare function isBrandKey(value: string): value is BrandKey;
|
|
35
|
+
/** `data-theme` value for a brand, or `undefined` for the attribute-less base. */
|
|
36
|
+
export declare function brandAttr(key: BrandKey): string | undefined;
|
|
37
|
+
/** Whether a brand ships a dark variant (and therefore allows mode switching). */
|
|
38
|
+
export declare function brandSupportsDark(key: BrandKey): boolean;
|
|
39
|
+
/** Mode settings a brand allows in a toggler. Light-only brands get just light. */
|
|
40
|
+
export declare function availableModeSettings(key: BrandKey): ModeSetting[];
|
|
41
|
+
//# sourceMappingURL=theme-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-config.d.ts","sourceRoot":"","sources":["../../../src/theme/theme-config.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;AAExC,yEAAyE;AACzE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE9C,MAAM,MAAM,WAAW,GAAG;IACxB,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,sEAAsE;IACtE,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,MAAM;;;;;;;;;;CAG6B,CAAA;AAEhD,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,MAAM,CAAA;AAE1C,eAAO,MAAM,aAAa,EAAE,QAAiB,CAAA;AAC7C,eAAO,MAAM,YAAY,EAAE,WAAsB,CAAA;AAEjD,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB,aAAa,CAAA;AAC3C,eAAO,MAAM,gBAAgB,YAAY,CAAA;AAEzC,wBAAgB,SAAS,IAAI,QAAQ,EAAE,CAEtC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAEnD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAE3D;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAExD;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,EAAE,CAElE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type PropsWithChildren } from "react";
|
|
2
|
+
import { type BrandKey, type ColorMode, type ModeSetting } from "./theme-config";
|
|
3
|
+
type AppThemeProviderProps = PropsWithChildren<{
|
|
4
|
+
defaultBrand?: BrandKey;
|
|
5
|
+
defaultMode?: ModeSetting;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function AppThemeProvider({ defaultBrand, defaultMode, children, }: AppThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export type UseAppThemeResult = {
|
|
9
|
+
/** Active brand key. */
|
|
10
|
+
brand: BrandKey;
|
|
11
|
+
/** All brand keys, for building a brand toggler. */
|
|
12
|
+
brands: BrandKey[];
|
|
13
|
+
setBrand: (brand: BrandKey) => void;
|
|
14
|
+
/** Current mode setting (may be "system"). */
|
|
15
|
+
mode: ModeSetting;
|
|
16
|
+
/** Resolved concrete mode after applying "system". */
|
|
17
|
+
resolvedMode: ColorMode;
|
|
18
|
+
setMode: (mode: ModeSetting) => void;
|
|
19
|
+
/** Mode settings allowed for the active brand (light-only brands get just light). */
|
|
20
|
+
availableModes: ModeSetting[];
|
|
21
|
+
/** False during SSR and the first client render; gate brand-dependent UI on it. */
|
|
22
|
+
mounted: boolean;
|
|
23
|
+
};
|
|
24
|
+
export declare function useAppTheme(): UseAppThemeResult;
|
|
25
|
+
/**
|
|
26
|
+
* Pre-hydration script that applies the persisted brand's `data-theme` before
|
|
27
|
+
* the page paints, preventing a flash of the default brand. Render it as early
|
|
28
|
+
* as possible: in `<head>`, or — for the Next.js App Router, which does not
|
|
29
|
+
* allow arbitrary `<head>` children in a layout — as the first child of
|
|
30
|
+
* `<body>`, where it still runs synchronously before any body content renders.
|
|
31
|
+
* better-themes injects its own equivalent script for the mode axis.
|
|
32
|
+
*/
|
|
33
|
+
export declare function BrandThemeScript({ defaultBrand, }: {
|
|
34
|
+
defaultBrand?: BrandKey;
|
|
35
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=theme-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../../src/theme/theme-provider.tsx"],"names":[],"mappings":"AAaA,OAAO,EAEL,KAAK,iBAAiB,EAIvB,MAAM,OAAO,CAAA;AACd,OAAO,EAGL,KAAK,QAAQ,EAIb,KAAK,SAAS,EAKd,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAA;AAmFvB,KAAK,qBAAqB,GAAG,iBAAiB,CAAC;IAC7C,YAAY,CAAC,EAAE,QAAQ,CAAA;IACvB,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAC,CAAA;AAEF,wBAAgB,gBAAgB,CAAC,EAC/B,YAA4B,EAC5B,WAA0B,EAC1B,QAAQ,GACT,EAAE,qBAAqB,2CAavB;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wBAAwB;IACxB,KAAK,EAAE,QAAQ,CAAA;IACf,oDAAoD;IACpD,MAAM,EAAE,QAAQ,EAAE,CAAA;IAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;IACnC,8CAA8C;IAC9C,IAAI,EAAE,WAAW,CAAA;IACjB,sDAAsD;IACtD,YAAY,EAAE,SAAS,CAAA;IACvB,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAA;IACpC,qFAAqF;IACrF,cAAc,EAAE,WAAW,EAAE,CAAA;IAC7B,mFAAmF;IACnF,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,wBAAgB,WAAW,IAAI,iBAAiB,CA4B/C;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,YAA4B,GAC7B,EAAE;IACD,YAAY,CAAC,EAAE,QAAQ,CAAA;CACxB,2CAoBA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-toggle.d.ts","sourceRoot":"","sources":["../../../src/theme/theme-toggle.tsx"],"names":[],"mappings":"AA6BA,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CA6ChE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const THEMES = {
|
|
2
|
+
base: {
|
|
3
|
+
label: "Default",
|
|
4
|
+
modes: [
|
|
5
|
+
"light",
|
|
6
|
+
"dark"
|
|
7
|
+
]
|
|
8
|
+
},
|
|
9
|
+
neo: {
|
|
10
|
+
label: "Neo (Red)",
|
|
11
|
+
modes: [
|
|
12
|
+
"light",
|
|
13
|
+
"dark"
|
|
14
|
+
],
|
|
15
|
+
attr: "neo"
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const DEFAULT_BRAND = "base";
|
|
19
|
+
const DEFAULT_MODE = "system";
|
|
20
|
+
const BRAND_STORAGE_KEY = "ui-brand";
|
|
21
|
+
const MODE_STORAGE_KEY = "ui-mode";
|
|
22
|
+
function brandKeys() {
|
|
23
|
+
return Object.keys(THEMES);
|
|
24
|
+
}
|
|
25
|
+
function getBrand(key) {
|
|
26
|
+
return THEMES[key];
|
|
27
|
+
}
|
|
28
|
+
function isBrandKey(value) {
|
|
29
|
+
return Object.hasOwn(THEMES, value);
|
|
30
|
+
}
|
|
31
|
+
function brandAttr(key) {
|
|
32
|
+
return getBrand(key).attr;
|
|
33
|
+
}
|
|
34
|
+
function brandSupportsDark(key) {
|
|
35
|
+
return getBrand(key).modes.includes("dark");
|
|
36
|
+
}
|
|
37
|
+
function availableModeSettings(key) {
|
|
38
|
+
return brandSupportsDark(key) ? [
|
|
39
|
+
"light",
|
|
40
|
+
"dark",
|
|
41
|
+
"system"
|
|
42
|
+
] : [
|
|
43
|
+
"light"
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
export { BRAND_STORAGE_KEY, DEFAULT_BRAND, DEFAULT_MODE, MODE_STORAGE_KEY, THEMES, availableModeSettings, brandAttr, brandKeys, brandSupportsDark, getBrand, isBrandKey };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { ThemeProvider, useTheme } from "better-themes";
|
|
4
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
5
|
+
import { BRAND_STORAGE_KEY, DEFAULT_BRAND, DEFAULT_MODE, MODE_STORAGE_KEY, availableModeSettings, brandAttr, brandKeys, brandSupportsDark, isBrandKey } from "./theme-config.js";
|
|
6
|
+
function readStoredBrand() {
|
|
7
|
+
if ("undefined" == typeof window) return null;
|
|
8
|
+
try {
|
|
9
|
+
const value = window.localStorage.getItem(BRAND_STORAGE_KEY);
|
|
10
|
+
return value && isBrandKey(value) ? value : null;
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function persistBrand(brand) {
|
|
16
|
+
if ("undefined" == typeof window) return;
|
|
17
|
+
try {
|
|
18
|
+
window.localStorage.setItem(BRAND_STORAGE_KEY, brand);
|
|
19
|
+
} catch {}
|
|
20
|
+
}
|
|
21
|
+
function applyBrandAttr(brand) {
|
|
22
|
+
if ("undefined" == typeof document) return;
|
|
23
|
+
const attr = brandAttr(brand);
|
|
24
|
+
const root = document.documentElement;
|
|
25
|
+
if (attr) root.setAttribute("data-theme", attr);
|
|
26
|
+
else root.removeAttribute("data-theme");
|
|
27
|
+
}
|
|
28
|
+
const BrandContext = /*#__PURE__*/ createContext(null);
|
|
29
|
+
function BrandProvider({ defaultBrand, children }) {
|
|
30
|
+
const { setTheme } = useTheme();
|
|
31
|
+
const [brand, setBrandState] = useState(()=>readStoredBrand() ?? defaultBrand);
|
|
32
|
+
const [mounted, setMounted] = useState(false);
|
|
33
|
+
useEffect(()=>{
|
|
34
|
+
setMounted(true);
|
|
35
|
+
}, []);
|
|
36
|
+
useEffect(()=>{
|
|
37
|
+
applyBrandAttr(brand);
|
|
38
|
+
persistBrand(brand);
|
|
39
|
+
if (!brandSupportsDark(brand)) setTheme("light");
|
|
40
|
+
}, [
|
|
41
|
+
brand,
|
|
42
|
+
setTheme
|
|
43
|
+
]);
|
|
44
|
+
return /*#__PURE__*/ jsx(BrandContext.Provider, {
|
|
45
|
+
value: {
|
|
46
|
+
brand,
|
|
47
|
+
setBrand: setBrandState,
|
|
48
|
+
mounted
|
|
49
|
+
},
|
|
50
|
+
children: children
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function AppThemeProvider({ defaultBrand = DEFAULT_BRAND, defaultMode = DEFAULT_MODE, children }) {
|
|
54
|
+
return /*#__PURE__*/ jsx(ThemeProvider, {
|
|
55
|
+
attribute: "class",
|
|
56
|
+
defaultTheme: defaultMode,
|
|
57
|
+
disableTransitionOnChange: true,
|
|
58
|
+
enableSystem: true,
|
|
59
|
+
storageKey: MODE_STORAGE_KEY,
|
|
60
|
+
themes: [
|
|
61
|
+
"light",
|
|
62
|
+
"dark"
|
|
63
|
+
],
|
|
64
|
+
children: /*#__PURE__*/ jsx(BrandProvider, {
|
|
65
|
+
defaultBrand: defaultBrand,
|
|
66
|
+
children: children
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function useAppTheme() {
|
|
71
|
+
const brandCtx = useContext(BrandContext);
|
|
72
|
+
if (!brandCtx) throw new Error("useAppTheme must be used within AppThemeProvider");
|
|
73
|
+
const { theme, systemTheme, setTheme } = useTheme();
|
|
74
|
+
const { brand, setBrand, mounted } = brandCtx;
|
|
75
|
+
const mode = theme ?? DEFAULT_MODE;
|
|
76
|
+
const resolvedMode = "system" === mode ? systemTheme ?? "light" : mode;
|
|
77
|
+
return {
|
|
78
|
+
brand,
|
|
79
|
+
brands: brandKeys(),
|
|
80
|
+
setBrand,
|
|
81
|
+
mode,
|
|
82
|
+
resolvedMode,
|
|
83
|
+
setMode: (next)=>{
|
|
84
|
+
if ("light" === next || brandSupportsDark(brand)) setTheme(next);
|
|
85
|
+
},
|
|
86
|
+
availableModes: availableModeSettings(brand),
|
|
87
|
+
mounted
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function BrandThemeScript({ defaultBrand = DEFAULT_BRAND }) {
|
|
91
|
+
const attrByBrand = {};
|
|
92
|
+
for (const key of brandKeys())attrByBrand[key] = brandAttr(key);
|
|
93
|
+
const script = `(function(){try{var d=${JSON.stringify(defaultBrand)};var m=${JSON.stringify(attrByBrand)};var k=localStorage.getItem(${JSON.stringify(BRAND_STORAGE_KEY)});if(!k||!Object.prototype.hasOwnProperty.call(m,k)){k=d;}var a=m[k];var e=document.documentElement;if(a){e.setAttribute('data-theme',a);}else{e.removeAttribute('data-theme');}}catch(e){}})();`;
|
|
94
|
+
return /*#__PURE__*/ jsx("script", {
|
|
95
|
+
dangerouslySetInnerHTML: {
|
|
96
|
+
__html: script
|
|
97
|
+
},
|
|
98
|
+
suppressHydrationWarning: true
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export { AppThemeProvider, BrandThemeScript, useAppTheme };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Button } from "../atoms/button.js";
|
|
4
|
+
import { tv } from "../utils.js";
|
|
5
|
+
import { getBrand } from "./theme-config.js";
|
|
6
|
+
import { useAppTheme } from "./theme-provider.js";
|
|
7
|
+
const themeToggle = tv({
|
|
8
|
+
slots: {
|
|
9
|
+
root: "",
|
|
10
|
+
group: "flex flex-col gap-100",
|
|
11
|
+
modeGroup: "mt-150 flex flex-col gap-100",
|
|
12
|
+
label: "text-sm",
|
|
13
|
+
row: "flex gap-50"
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
const MODE_LABELS = {
|
|
17
|
+
light: "Light",
|
|
18
|
+
dark: "Dark",
|
|
19
|
+
system: "System"
|
|
20
|
+
};
|
|
21
|
+
function ThemeToggle({ className }) {
|
|
22
|
+
const { brand, brands, setBrand, mode, setMode, availableModes, mounted } = useAppTheme();
|
|
23
|
+
const showModes = availableModes.length > 1;
|
|
24
|
+
const { root, group, modeGroup, label, row } = themeToggle();
|
|
25
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
26
|
+
className: root({
|
|
27
|
+
className
|
|
28
|
+
}),
|
|
29
|
+
children: [
|
|
30
|
+
/*#__PURE__*/ jsxs("div", {
|
|
31
|
+
className: group(),
|
|
32
|
+
children: [
|
|
33
|
+
/*#__PURE__*/ jsx("span", {
|
|
34
|
+
className: label(),
|
|
35
|
+
children: "Brand"
|
|
36
|
+
}),
|
|
37
|
+
/*#__PURE__*/ jsx("div", {
|
|
38
|
+
className: row(),
|
|
39
|
+
children: brands.map((key)=>/*#__PURE__*/ jsx(Button, {
|
|
40
|
+
onClick: ()=>setBrand(key),
|
|
41
|
+
size: "sm",
|
|
42
|
+
theme: mounted && key === brand ? "solid" : "outlined",
|
|
43
|
+
variant: "primary",
|
|
44
|
+
children: getBrand(key).label
|
|
45
|
+
}, key))
|
|
46
|
+
})
|
|
47
|
+
]
|
|
48
|
+
}),
|
|
49
|
+
showModes && /*#__PURE__*/ jsxs("div", {
|
|
50
|
+
className: modeGroup(),
|
|
51
|
+
children: [
|
|
52
|
+
/*#__PURE__*/ jsx("span", {
|
|
53
|
+
className: label(),
|
|
54
|
+
children: "Mode"
|
|
55
|
+
}),
|
|
56
|
+
/*#__PURE__*/ jsx("div", {
|
|
57
|
+
className: row(),
|
|
58
|
+
children: availableModes.map((value)=>/*#__PURE__*/ jsx(Button, {
|
|
59
|
+
onClick: ()=>setMode(value),
|
|
60
|
+
size: "sm",
|
|
61
|
+
theme: mounted && value === mode ? "solid" : "outlined",
|
|
62
|
+
variant: "secondary",
|
|
63
|
+
children: MODE_LABELS[value]
|
|
64
|
+
}, value))
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
export { ThemeToggle };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techsio/ui-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,6 +44,10 @@
|
|
|
44
44
|
"types": "./dist/src/templates/*.d.ts",
|
|
45
45
|
"import": "./dist/templates/*.js"
|
|
46
46
|
},
|
|
47
|
+
"./theme/*": {
|
|
48
|
+
"types": "./dist/src/theme/*.d.ts",
|
|
49
|
+
"import": "./dist/theme/*.js"
|
|
50
|
+
},
|
|
47
51
|
"./utils": {
|
|
48
52
|
"types": "./dist/src/utils.d.ts",
|
|
49
53
|
"import": "./dist/utils.js"
|
|
@@ -99,6 +103,7 @@
|
|
|
99
103
|
"@zag-js/toast": "^1.41.2",
|
|
100
104
|
"@zag-js/tooltip": "^1.41.2",
|
|
101
105
|
"@zag-js/tree-view": "^1.41.2",
|
|
106
|
+
"better-themes": "^1.1.0",
|
|
102
107
|
"libphonenumber-js": "^1.13.2",
|
|
103
108
|
"tailwind-merge": "^3.4.0",
|
|
104
109
|
"tailwind-variants": "^3.1.1",
|
|
@@ -117,12 +122,10 @@
|
|
|
117
122
|
"@semantic-release/github": "^12.0.2",
|
|
118
123
|
"@semantic-release/npm": "^13.1.2",
|
|
119
124
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
120
|
-
"@storybook/addon-a11y": "^10.
|
|
121
|
-
"@storybook/addon-
|
|
122
|
-
"@storybook/
|
|
123
|
-
"@storybook/
|
|
124
|
-
"@storybook/react": "^10.0.2",
|
|
125
|
-
"@storybook/test-runner": "^0.24.2",
|
|
125
|
+
"@storybook/addon-a11y": "^10.4.4",
|
|
126
|
+
"@storybook/addon-themes": "^10.4.4",
|
|
127
|
+
"@storybook/react": "^10.4.4",
|
|
128
|
+
"@storybook/test-runner": "^0.24.4",
|
|
126
129
|
"@tailwindcss/postcss": "^4.1.17",
|
|
127
130
|
"@techsio/storybook-a11y-reporter": "0.1.3",
|
|
128
131
|
"@techsio/storybook-better-a11y": "0.1.3",
|
|
@@ -133,9 +136,9 @@
|
|
|
133
136
|
"postcss": "^8.5.6",
|
|
134
137
|
"rsbuild-plugin-publint": "^0.3.3",
|
|
135
138
|
"semantic-release": "^25.0.2",
|
|
136
|
-
"storybook": "^10.
|
|
137
|
-
"storybook-addon-rslib": "^
|
|
138
|
-
"storybook-react-rsbuild": "^
|
|
139
|
+
"storybook": "^10.4.4",
|
|
140
|
+
"storybook-addon-rslib": "^3.3.4",
|
|
141
|
+
"storybook-react-rsbuild": "^3.3.4",
|
|
139
142
|
"tailwindcss": "^4.1.17",
|
|
140
143
|
"typescript": "^5.9.3"
|
|
141
144
|
},
|
|
@@ -20,6 +20,12 @@
|
|
|
20
20
|
* Generated by merge-figma-themes.mjs from figma/{light,dark}/variables.css. */
|
|
21
21
|
@import "./figma/variables.css";
|
|
22
22
|
|
|
23
|
+
/* Brand theme overrides ([data-theme="…"]). Imported AFTER variables.css so
|
|
24
|
+
* the unlayered selectors win over the @theme base values, while their
|
|
25
|
+
* light-dark() halves still follow `color-scheme`. Only non-base brands
|
|
26
|
+
* (e.g. neo) emit tokens here; base is the default @theme above. */
|
|
27
|
+
@import "./figma/brand-overrides.css";
|
|
28
|
+
|
|
23
29
|
/* Base styles */
|
|
24
30
|
:root {
|
|
25
31
|
color-scheme: light dark;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Brand theme overrides — non-base brands keyed by [data-theme].
|
|
3
|
+
* Generated by merge-figma-themes.mjs. DO NOT EDIT BY HAND.
|
|
4
|
+
*
|
|
5
|
+
* Only tokens whose merged value differs from the base brand are
|
|
6
|
+
* emitted; everything else inherits base via var() chains. Plain
|
|
7
|
+
* (unlayered) selectors so they win over @theme while still
|
|
8
|
+
* respecting `color-scheme` for the light-dark() halves.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
[data-theme="neo"] {
|
|
12
|
+
--color-badge-fg-primary: var(--color-fg-reverse);
|
|
13
|
+
--color-bg-light-primary-active: var(--color-primary-300);
|
|
14
|
+
--color-bg-light-primary-base: var(--color-primary-100);
|
|
15
|
+
--color-bg-light-primary-hover: var(--color-primary-200);
|
|
16
|
+
--color-bg-outlined-primary-active: var(--color-primary-200);
|
|
17
|
+
--color-bg-outlined-primary-hover: var(--color-primary-100);
|
|
18
|
+
--color-bg-primary-active: var(--color-primary-800);
|
|
19
|
+
--color-bg-primary-base: var(--color-primary-600);
|
|
20
|
+
--color-bg-primary-hover: var(--color-primary-700);
|
|
21
|
+
--color-button-fg-primary: var(--color-fg-reverse);
|
|
22
|
+
--color-fg-accent-primary: var(--color-primary-600);
|
|
23
|
+
--color-primary-100: oklch(0.936 0.032 17.738);
|
|
24
|
+
--color-primary-200: oklch(0.883 0.062 18.386);
|
|
25
|
+
--color-primary-300: oklch(0.805 0.111 19.782);
|
|
26
|
+
--color-primary-400: light-dark(oklch(0.702 0.189 22.228), oklch(0.745 0.155 20.548));
|
|
27
|
+
--color-primary-500: light-dark(oklch(0.638 0.237 25.436), oklch(0.702 0.189 22.228));
|
|
28
|
+
--color-primary-600: oklch(0.581 0.238 29.234);
|
|
29
|
+
--color-primary-700: light-dark(oklch(0.509 0.209 28.513), oklch(0.583 0.239 28.476));
|
|
30
|
+
--color-primary-800: light-dark(oklch(0.445 0.177 26.787), oklch(0.509 0.209 28.513));
|
|
31
|
+
--color-primary-900: light-dark(oklch(0.397 0.141 25.714), oklch(0.445 0.177 26.787));
|
|
32
|
+
--color-primary-alpha-10: oklch(0.581 0.238 29.234 / 0.1);
|
|
33
|
+
--color-product-card-button-cart-fg: var(--color-fg-reverse);
|
|
34
|
+
--color-radio-card-addon-fg-solid-checked: var(--color-fg-reverse);
|
|
35
|
+
--color-radio-card-item-description-fg-solid-checked: var(--color-fg-reverse);
|
|
36
|
+
--color-radio-card-item-indicator-bg-solid-checked: var(--color-fg-reverse);
|
|
37
|
+
--color-radio-card-item-indicator-border-solid-checked: var(--color-fg-reverse);
|
|
38
|
+
--color-secondary-100: #fef3c7;
|
|
39
|
+
--color-secondary-200: #fde68a;
|
|
40
|
+
--color-secondary-300: #fcd34d;
|
|
41
|
+
--color-secondary-400: #fbbf24;
|
|
42
|
+
--color-secondary-500: #f59e0b;
|
|
43
|
+
--color-secondary-600: #d97706;
|
|
44
|
+
--color-secondary-700: #b45309;
|
|
45
|
+
--color-secondary-800: #92400e;
|
|
46
|
+
--color-secondary-900: #78350f;
|
|
47
|
+
--color-steps-indicator-fg-solid: var(--color-fg-reverse);
|
|
48
|
+
--color-tabs-trigger-fg-solid-selected: var(--color-fg-reverse);
|
|
49
|
+
}
|