@bsuite/theme 0.6.0 → 0.7.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/react/BrandingProvider.js +1 -1
- package/dist/react/ThemeProvider.d.ts +1 -1
- package/dist/react/ThemeProvider.d.ts.map +1 -1
- package/dist/react/ThemeProvider.js +1 -1
- package/dist/react/components/StatusBadge.d.ts +5 -2
- package/dist/react/components/StatusBadge.d.ts.map +1 -1
- package/dist/react/components/StatusBadge.js +18 -8
- package/dist/react/index.d.ts +12 -12
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +7 -7
- package/dist/react/useBranding.d.ts +1 -1
- package/dist/react/useBranding.d.ts.map +1 -1
- package/dist/react/useBranding.js +1 -1
- package/dist/react/usePlatformLogo.d.ts +1 -1
- package/dist/react/usePlatformLogo.d.ts.map +1 -1
- package/dist/react/usePlatformLogo.js +1 -1
- package/dist/react/useTheme.d.ts +1 -1
- package/dist/react/useTheme.d.ts.map +1 -1
- package/dist/react/useTheme.js +1 -1
- package/dist/ssr/index.js +1 -1
- package/package.json +1 -3
- package/src/css/braden.css +4 -4
- package/src/css/utilities.css +8 -5
- package/src/css/vars.css +147 -90
- package/src/preset-v4.css +123 -113
- package/src/tailwind-preset.js +0 -150
|
@@ -43,7 +43,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
43
43
|
* </BrandingProvider>
|
|
44
44
|
*/
|
|
45
45
|
import { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
46
|
-
import { sanitizeBrandingUrl, sanitizeFontFamily, toCssUrl, } from './branding-sanitize';
|
|
46
|
+
import { sanitizeBrandingUrl, sanitizeFontFamily, toCssUrl, } from './branding-sanitize.js';
|
|
47
47
|
export const BRANDING_STORAGE_KEY = 'bsuite_tenant_branding';
|
|
48
48
|
export const BRANDING_OVERRIDE_FLAG = 'VITE_ENABLE_BRANDING_OVERRIDE';
|
|
49
49
|
export const BrandingContext = createContext(undefined);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import { type ThemeContextValue, type ThemeMode } from '../index';
|
|
2
|
+
import { type ThemeContextValue, type ThemeMode } from '../index.js';
|
|
3
3
|
export declare const ThemeContext: import("react").Context<ThemeContextValue | undefined>;
|
|
4
4
|
export interface ThemeProviderProps {
|
|
5
5
|
children: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/react/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAyC,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/react/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAyC,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAA;AAE3G,eAAO,MAAM,YAAY,wDAA0D,CAAA;AAEnF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAA;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AA6BD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAuB,EACvB,UAA8B,GAC/B,EAAE,kBAAkB,+BA4DpB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
-
import { THEME_STORAGE_KEY } from '../index';
|
|
3
|
+
import { THEME_STORAGE_KEY } from '../index.js';
|
|
4
4
|
export const ThemeContext = createContext(undefined);
|
|
5
5
|
/**
|
|
6
6
|
* Resolve a stored ThemeMode to the effective ResolvedTheme.
|
|
@@ -30,8 +30,11 @@ export type BadgeVariant =
|
|
|
30
30
|
| 'error'
|
|
31
31
|
/** Blue — Draft, New, Scheduled */
|
|
32
32
|
| 'info'
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/** Deep blue — Converted, Promoted, Exported, Paid: terminal states that
|
|
34
|
+
* have moved past success. Was `purple`, renamed 0.7.0: the variant was
|
|
35
|
+
* named for a colour rather than a role, and that colour is quarantined
|
|
36
|
+
* from semantics (purple collapses onto primary blue under protanopia). */
|
|
37
|
+
| 'secondary'
|
|
35
38
|
/** Gray — Inactive, Archived */
|
|
36
39
|
| 'neutral';
|
|
37
40
|
export interface StatusBadgeProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBadge.d.ts","sourceRoot":"","sources":["../../../src/react/components/StatusBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3D,MAAM,MAAM,YAAY;AACtB,yCAAyC;AACvC,SAAS;AACX,mCAAmC;GACjC,SAAS;AACX,sCAAsC;GACpC,OAAO;AACT,mCAAmC;GACjC,MAAM;AACR
|
|
1
|
+
{"version":3,"file":"StatusBadge.d.ts","sourceRoot":"","sources":["../../../src/react/components/StatusBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3D,MAAM,MAAM,YAAY;AACtB,yCAAyC;AACvC,SAAS;AACX,mCAAmC;GACjC,SAAS;AACX,sCAAsC;GACpC,OAAO;AACT,mCAAmC;GACjC,MAAM;AACR;;;4EAG4E;GAC1E,WAAW;AACb,gCAAgC;GAC9B,SAAS,CAAC;AAEd,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA2BD,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAK,EACL,IAAW,EACX,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,GACtB,EAAE,gBAAgB,GAAG,SAAS,CAc9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,GAChD,YAAY,CAoCd;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CASxD;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,OAAO,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC1D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,GAAG,IAAI,EACR,EAAE,oBAAoB,GAAG,SAAS,CAIlC"}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Role-bound, not palette-bound. Until 0.7.0 these were raw Tailwind palette
|
|
4
|
+
* classes (`bg-emerald-50`, `bg-red-50`, …), which meant the design-system
|
|
5
|
+
* component every app imports was invisible to tenant white-labelling —
|
|
6
|
+
* BrandingProvider mutates the role layer, and these bound below it.
|
|
7
|
+
*
|
|
8
|
+
* Tint is derived from the role colour with a slash-opacity fill plus the
|
|
9
|
+
* AA-safe `*-text` variant for type, so one definition covers light and dark
|
|
10
|
+
* and no `dark:` duplicate is needed.
|
|
11
|
+
*/
|
|
2
12
|
const variantClasses = {
|
|
3
|
-
success: 'bg-
|
|
4
|
-
warning: 'bg-
|
|
5
|
-
error: 'bg-
|
|
6
|
-
info: 'bg-
|
|
7
|
-
|
|
13
|
+
success: 'bg-role-success/10 text-success-text border-role-success/30',
|
|
14
|
+
warning: 'bg-role-warning/10 text-warning-text border-role-warning/30',
|
|
15
|
+
error: 'bg-role-error/10 text-error-text border-role-error/30',
|
|
16
|
+
info: 'bg-role-info/10 text-accent-text border-role-info/30',
|
|
17
|
+
secondary: 'bg-role-secondary/10 text-primary-text border-role-secondary/30',
|
|
8
18
|
neutral: 'bg-muted text-muted-foreground border-border',
|
|
9
19
|
};
|
|
10
20
|
const sizeClasses = {
|
|
@@ -57,7 +67,7 @@ export function getStatusVariant(status, overrides) {
|
|
|
57
67
|
'draft', 'new', 'scheduled', 'open',
|
|
58
68
|
'applicant', 'interviewing', 'reported',
|
|
59
69
|
];
|
|
60
|
-
const
|
|
70
|
+
const SECONDARY = ['converted', 'promoted', 'shortlisted', 'exported', 'paid', 'qualified'];
|
|
61
71
|
if (SUCCESS.includes(normalized))
|
|
62
72
|
return 'success';
|
|
63
73
|
if (WARNING.includes(normalized))
|
|
@@ -66,8 +76,8 @@ export function getStatusVariant(status, overrides) {
|
|
|
66
76
|
return 'error';
|
|
67
77
|
if (INFO.includes(normalized))
|
|
68
78
|
return 'info';
|
|
69
|
-
if (
|
|
70
|
-
return '
|
|
79
|
+
if (SECONDARY.includes(normalized))
|
|
80
|
+
return 'secondary';
|
|
71
81
|
return 'neutral';
|
|
72
82
|
}
|
|
73
83
|
/**
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export { ThemeProvider } from './ThemeProvider';
|
|
2
|
-
export type { ThemeProviderProps } from './ThemeProvider';
|
|
3
|
-
export { useTheme } from './useTheme';
|
|
4
|
-
export type { ThemeContextValue, ThemeMode, ResolvedTheme } from '../index';
|
|
5
|
-
export { THEME_STORAGE_KEY } from '../index';
|
|
6
|
-
export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider';
|
|
7
|
-
export type { TenantBranding, BrandingContextValue } from './BrandingProvider';
|
|
8
|
-
export { useBranding } from './useBranding';
|
|
9
|
-
export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo';
|
|
10
|
-
export type { PlatformLogoHookResult, PlatformLogoOptions, PlatformLogoScheme, PlatformLogoSlot, PlatformLogoSource, ResolvedPlatformLogo, } from './usePlatformLogo';
|
|
11
|
-
export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge';
|
|
12
|
-
export type { BadgeVariant, StatusBadgeProps, AutoStatusBadgeProps, } from './components/StatusBadge';
|
|
1
|
+
export { ThemeProvider } from './ThemeProvider.js';
|
|
2
|
+
export type { ThemeProviderProps } from './ThemeProvider.js';
|
|
3
|
+
export { useTheme } from './useTheme.js';
|
|
4
|
+
export type { ThemeContextValue, ThemeMode, ResolvedTheme } from '../index.js';
|
|
5
|
+
export { THEME_STORAGE_KEY } from '../index.js';
|
|
6
|
+
export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider.js';
|
|
7
|
+
export type { TenantBranding, BrandingContextValue } from './BrandingProvider.js';
|
|
8
|
+
export { useBranding } from './useBranding.js';
|
|
9
|
+
export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo.js';
|
|
10
|
+
export type { PlatformLogoHookResult, PlatformLogoOptions, PlatformLogoScheme, PlatformLogoSlot, PlatformLogoSource, ResolvedPlatformLogo, } from './usePlatformLogo.js';
|
|
11
|
+
export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge.js';
|
|
12
|
+
export type { BadgeVariant, StatusBadgeProps, AutoStatusBadgeProps, } from './components/StatusBadge.js';
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3E,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,6BAA6B,CAAA;AACpC,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,6BAA6B,CAAA"}
|
package/dist/react/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { ThemeProvider } from './ThemeProvider';
|
|
2
|
-
export { useTheme } from './useTheme';
|
|
3
|
-
export { THEME_STORAGE_KEY } from '../index';
|
|
4
|
-
export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider';
|
|
5
|
-
export { useBranding } from './useBranding';
|
|
6
|
-
export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo';
|
|
1
|
+
export { ThemeProvider } from './ThemeProvider.js';
|
|
2
|
+
export { useTheme } from './useTheme.js';
|
|
3
|
+
export { THEME_STORAGE_KEY } from '../index.js';
|
|
4
|
+
export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider.js';
|
|
5
|
+
export { useBranding } from './useBranding.js';
|
|
6
|
+
export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo.js';
|
|
7
7
|
// Components — see ./components/<Name>.tsx
|
|
8
|
-
export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge';
|
|
8
|
+
export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge.js';
|
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
* const { branding, isLoading } = useBranding()
|
|
8
8
|
* const logoUrl = branding?.logo_url ?? '/logos/default-logo.svg'
|
|
9
9
|
*/
|
|
10
|
-
export declare function useBranding(): import("./BrandingProvider").BrandingContextValue;
|
|
10
|
+
export declare function useBranding(): import("./BrandingProvider.js").BrandingContextValue;
|
|
11
11
|
//# sourceMappingURL=useBranding.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBranding.d.ts","sourceRoot":"","sources":["../../src/react/useBranding.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,WAAW,
|
|
1
|
+
{"version":3,"file":"useBranding.d.ts","sourceRoot":"","sources":["../../src/react/useBranding.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,WAAW,yDAM1B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TenantBranding } from './BrandingProvider';
|
|
1
|
+
import type { TenantBranding } from './BrandingProvider.js';
|
|
2
2
|
export type PlatformLogoSlot = 'header' | 'sidebar' | 'auth' | 'favicon' | 'mark';
|
|
3
3
|
export type PlatformLogoScheme = 'light' | 'dark';
|
|
4
4
|
export type PlatformLogoSource = 'branding' | 'fallback' | 'none';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePlatformLogo.d.ts","sourceRoot":"","sources":["../../src/react/usePlatformLogo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"usePlatformLogo.d.ts","sourceRoot":"","sources":["../../src/react/usePlatformLogo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAG3D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AACjF,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,CAAA;AACjD,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAEjE,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,gBAAgB,CAAA;IACvB,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;IACjE,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,gBAAgB,CAAA;IACtB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,MAAM,EAAE,kBAAkB,CAAA;IAC1B,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAA;IAC/B,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAqDD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,GAAE,mBAAwB,GAChC,oBAAoB,CAiBtB;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,sBAAsB,CAczF"}
|
package/dist/react/useTheme.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/react/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/react/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAU5C"}
|
package/dist/react/useTheme.js
CHANGED
package/dist/ssr/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsuite/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"src/css",
|
|
18
|
-
"src/tailwind-preset.js",
|
|
19
18
|
"src/preset-v4.css"
|
|
20
19
|
],
|
|
21
20
|
"main": "dist/index.js",
|
|
@@ -33,7 +32,6 @@
|
|
|
33
32
|
"import": "./dist/ssr/index.js",
|
|
34
33
|
"types": "./dist/ssr/index.d.ts"
|
|
35
34
|
},
|
|
36
|
-
"./tailwind-preset": "./src/tailwind-preset.js",
|
|
37
35
|
"./preset-v4.css": "./src/preset-v4.css",
|
|
38
36
|
"./css": "./src/css/index.css",
|
|
39
37
|
"./vars.css": "./src/css/vars.css",
|
package/src/css/braden.css
CHANGED
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
============================================================ */
|
|
79
79
|
--braden-light-bg-body: oklch(0.980 0.002 50); /* warm white */
|
|
80
80
|
--braden-light-bg-surface: oklch(0.996 0.001 50); /* near white */
|
|
81
|
-
--braden-light-bg-panel: oklch(
|
|
81
|
+
--braden-light-bg-panel: oklch(0.994 0.002 250); /* near-white; pure white is banned in every role */
|
|
82
82
|
--braden-light-bg-input: oklch(0.972 0.003 250); /* cool light grey */
|
|
83
83
|
|
|
84
84
|
/* Braden light text scale — hue 250 (navy cast), capped L=0.22 */
|
|
@@ -161,9 +161,9 @@
|
|
|
161
161
|
/* ============================================================
|
|
162
162
|
SHADOWS — corporate subtle, no neon glow
|
|
163
163
|
============================================================ */
|
|
164
|
-
--shadow-sm: 0 1px 2px oklch(0 0
|
|
165
|
-
--shadow-md: 0 4px 6px oklch(0 0
|
|
166
|
-
--shadow-lg: 0 10px 15px oklch(0 0
|
|
164
|
+
--shadow-sm: 0 1px 2px oklch(0.30 0.03 250 / 0.08);
|
|
165
|
+
--shadow-md: 0 4px 6px oklch(0.30 0.03 250 / 0.10), 0 2px 4px oklch(0.30 0.03 250 / 0.06);
|
|
166
|
+
--shadow-lg: 0 10px 15px oklch(0.30 0.03 250 / 0.10), 0 4px 6px oklch(0.30 0.03 250 / 0.05);
|
|
167
167
|
|
|
168
168
|
/* Card glow is a dark-mode-only device (see .dark below); light mode
|
|
169
169
|
stays border-only, consistent with the corporate "no neon glow" rule. */
|
package/src/css/utilities.css
CHANGED
|
@@ -74,18 +74,21 @@
|
|
|
74
74
|
(braden/src/index.css) so the corporate and D2C marketing surfaces
|
|
75
75
|
share one visual language for this specific device.
|
|
76
76
|
============================================================ */
|
|
77
|
+
/* Grid lines are hue-matched to the surface, never pure black/white — the
|
|
78
|
+
contract bans both endpoints in every role, alpha forms included. Light
|
|
79
|
+
mode stays neutral and quiet; dark mode takes a faint accent cast, which
|
|
80
|
+
is where the cyber register lives. 32px = the pre-auth marketing tile. */
|
|
77
81
|
.bsuite-hero-grid {
|
|
78
82
|
position: absolute;
|
|
79
83
|
inset: 0;
|
|
84
|
+
--grid-line: oklch(0.40 0.030 258 / 0.07);
|
|
80
85
|
background-image:
|
|
81
|
-
linear-gradient(
|
|
82
|
-
linear-gradient(90deg,
|
|
86
|
+
linear-gradient(var(--grid-line) 1px, transparent 1px),
|
|
87
|
+
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
|
|
83
88
|
background-size: 32px 32px;
|
|
84
89
|
}
|
|
85
90
|
.dark .bsuite-hero-grid {
|
|
86
|
-
|
|
87
|
-
linear-gradient(oklch(1 0 0 / 0.03) 1px, transparent 1px),
|
|
88
|
-
linear-gradient(90deg, oklch(1 0 0 / 0.03) 1px, transparent 1px);
|
|
91
|
+
--grid-line: oklch(0.82 0.020 262 / 0.055);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
/* ===== prefers-reduced-motion — cap animation duration ===== */
|
package/src/css/vars.css
CHANGED
|
@@ -12,13 +12,27 @@
|
|
|
12
12
|
* Consumers should bind to Layer 3 (roles) or Layer 4 (shadcn) — never
|
|
13
13
|
* directly to palette primitives. Roles make white-labelling safe.
|
|
14
14
|
*
|
|
15
|
-
* Colourblind policy (WCAG 1.4.1
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Colourblind policy (WCAG 1.4.1) — REWRITTEN 2026-08-02, contract 0.7.0:
|
|
16
|
+
* The invariant is SEPARATION, not a fixed hue. --role-error must be
|
|
17
|
+
* maximally separated from --role-primary under deuteranopia and
|
|
18
|
+
* protanopia. D2C's primary is blue, so error is RED.
|
|
19
|
+
* The previous "error = purple" rule was actively harmful: under
|
|
20
|
+
* protanopia purple measured DeltaE 0.006 against primary blue — the
|
|
21
|
+
* destructive colour and the primary action colour were the SAME swatch.
|
|
22
|
+
* Purple and indigo are therefore quarantined from semantics entirely.
|
|
23
|
+
* Warm states (red/amber) separate by LIGHTNESS, not hue — under
|
|
24
|
+
* deuteranopia everything warm collapses to yellow, so error is the dark
|
|
25
|
+
* one and warning the light one. Never put two cool hues in opposition.
|
|
26
|
+
* Colour is never the sole signifier: shape + label always.
|
|
27
|
+
* TENANT OVERRIDE BLOCKED on --role-error / --role-destructive.
|
|
18
28
|
*
|
|
19
|
-
* Eye-strain policy:
|
|
20
|
-
*
|
|
21
|
-
* text
|
|
29
|
+
* Eye-strain / pure-endpoint policy:
|
|
30
|
+
* Pure white (L=1.0) and pure black (L=0) are BANNED in EVERY role —
|
|
31
|
+
* text, surface, border, ring and shadow alike (operator ruling
|
|
32
|
+
* 2026-08-02). The prior text-only scoping of this rule is what let
|
|
33
|
+
* --light-bg-accent ship as oklch(1 0 0.5) and render every shadcn card
|
|
34
|
+
* and popover pure white. "White" here means oklch(0.982 0.002 248)
|
|
35
|
+
* (#f8f9fa); the lightest surface is bg-panel at L=0.994.
|
|
22
36
|
*
|
|
23
37
|
* OKLCH format is MANDATORY for all new tokens. No hex/rgb/hsl.
|
|
24
38
|
* Syntax: oklch(L C H) — L=lightness 0–1, C=chroma 0–0.4, H=hue 0–360.
|
|
@@ -41,6 +55,17 @@
|
|
|
41
55
|
--neon-electric-green: oklch(0.723 0.192 149.6);
|
|
42
56
|
--neon-electric-lavender: oklch(0.736 0.141 285.6);
|
|
43
57
|
|
|
58
|
+
/* Semantic hues — added 2026-08-02 (contract 0.7.0). The 11 above were
|
|
59
|
+
chosen for looks; these four were chosen for SEPARATION, measured via
|
|
60
|
+
Vienot-Brettel dichromat simulation. Worst-case DeltaE(OKLab) across
|
|
61
|
+
normal/deuteranopia/protanopia for every semantic pair is >= 0.156;
|
|
62
|
+
the pairing these replace scored 0.006. Never bind a component to
|
|
63
|
+
these directly — bind to the --role-* alias. */
|
|
64
|
+
--neon-electric-red: oklch(0.580 0.230 25); /* error / destructive */
|
|
65
|
+
--neon-electric-amber: oklch(0.800 0.150 75); /* warning */
|
|
66
|
+
--neon-electric-teal: oklch(0.600 0.130 195); /* success */
|
|
67
|
+
--neon-electric-deep: oklch(0.380 0.140 270); /* secondary action */
|
|
68
|
+
|
|
44
69
|
/* ============================================================
|
|
45
70
|
LAYER 2 — SURFACE PRIMITIVES (light mode)
|
|
46
71
|
============================================================ */
|
|
@@ -49,7 +74,10 @@
|
|
|
49
74
|
--light-bg-primary: oklch(0.961 0 0.5);
|
|
50
75
|
--light-bg-secondary: oklch(0.982 0.002 248);
|
|
51
76
|
--light-bg-tertiary: oklch(0.963 0.003 228.9);
|
|
52
|
-
|
|
77
|
+
/* bg-panel. Was oklch(1 0 0.5) — pure white, and since --card and
|
|
78
|
+
--popover bridge to it, every shadcn card and popover in all five D2C
|
|
79
|
+
apps rendered pure white in light mode from this one line. */
|
|
80
|
+
--light-bg-accent: oklch(0.994 0.002 260);
|
|
53
81
|
|
|
54
82
|
/* D2C light text scale — hue 260 (cool blue-grey), capped L=0.22.
|
|
55
83
|
Measured WCAG contrast vs --light-bg-primary oklch(0.961 0 0.5), OKLCH ->
|
|
@@ -63,9 +91,6 @@
|
|
|
63
91
|
--light-text-muted: oklch(0.52 0.018 260); /* 4.92:1 ✓ AA (normal, 4.5:1 floor) */
|
|
64
92
|
--light-text-subtle: oklch(0.60 0.012 260); /* 3.52:1 ✓ AA large only (3:1) — ✗ AA normal */
|
|
65
93
|
--light-text-disabled: oklch(0.72 0.010 260); /* 2.21:1 ✗ fails AA at any size — MUST pair with icon cue */
|
|
66
|
-
/* Legacy aliases (kept for consumers that haven't migrated) */
|
|
67
|
-
--light-text-tertiary: var(--light-text-muted);
|
|
68
|
-
--light-text-quaternary: var(--light-text-subtle);
|
|
69
94
|
|
|
70
95
|
--light-border: oklch(0.942 0.005 247.9);
|
|
71
96
|
--light-hover: oklch(0.963 0.003 228.9);
|
|
@@ -83,19 +108,33 @@
|
|
|
83
108
|
|
|
84
109
|
/* Action colours */
|
|
85
110
|
--role-primary: var(--neon-electric-blue); /* oklch(0.546 0.215 262.9) */
|
|
86
|
-
--role-secondary: var(--neon-electric-
|
|
111
|
+
--role-secondary: var(--neon-electric-deep); /* was indigo — 0.037 from primary */
|
|
87
112
|
--role-accent: var(--neon-electric-cyan); /* oklch(0.769 0.132 191.7) */
|
|
88
113
|
|
|
89
|
-
/* ⚠️
|
|
90
|
-
|
|
91
|
-
|
|
114
|
+
/* ⚠️ SEPARATION POLICY (contract 0.7.0). The invariant is NOT a fixed hue —
|
|
115
|
+
it is that error must be maximally separated from PRIMARY under
|
|
116
|
+
deuteranopia and protanopia. D2C's primary is blue, so error is RED.
|
|
117
|
+
Purple scored DeltaE 0.006 against primary under protanopia: the
|
|
118
|
+
destructive colour and the primary action colour were the same swatch.
|
|
119
|
+
Purple and indigo are quarantined from semantics entirely.
|
|
120
|
+
Warm states separate by LIGHTNESS (under deuteranopia red and amber
|
|
121
|
+
both read yellow — error is the dark one, warning the light one).
|
|
92
122
|
TENANT OVERRIDE BLOCKED: BrandingProvider rejects --role-error changes. */
|
|
93
|
-
--role-error: var(--neon-electric-
|
|
94
|
-
--role-destructive: var(--neon-electric-
|
|
95
|
-
--role-warning: var(--neon-electric-
|
|
96
|
-
--role-success: var(--neon-electric-
|
|
123
|
+
--role-error: var(--neon-electric-red); /* was purple — 0.006 from primary */
|
|
124
|
+
--role-destructive: var(--neon-electric-red); /* synonym — same value */
|
|
125
|
+
--role-warning: var(--neon-electric-amber); /* was orange h22.5 — 0.059 from red */
|
|
126
|
+
--role-success: var(--neon-electric-teal); /* was green — 0.043 from red */
|
|
97
127
|
--role-info: var(--neon-electric-cyan); /* oklch(0.769 0.132 191.7) */
|
|
98
128
|
|
|
129
|
+
/* AA-safe text renderings of the saturated roles on light surfaces.
|
|
130
|
+
A saturated fill colour is not a legible text colour; these are the
|
|
131
|
+
text variants and are the ONLY correct token for coloured type. */
|
|
132
|
+
--role-primary-text: oklch(0.541 0.215 262.9); /* 4.71:1 ✓ AA */
|
|
133
|
+
--role-accent-text: oklch(0.499 0.132 191.7); /* 4.70:1 ✓ AA */
|
|
134
|
+
--role-error-text: oklch(0.556 0.230 25); /* 4.69:1 ✓ AA */
|
|
135
|
+
--role-warning-text: oklch(0.535 0.150 75); /* 4.70:1 ✓ AA */
|
|
136
|
+
--role-success-text: oklch(0.501 0.130 195); /* 4.70:1 ✓ AA */
|
|
137
|
+
|
|
99
138
|
/* Text roles — six-tier scale (W3 §3.1 contract). Every tier below is
|
|
100
139
|
measured against --role-bg-body (the conservative floor); all tiers
|
|
101
140
|
score HIGHER against --role-bg-panel/--role-bg-surface. */
|
|
@@ -107,27 +146,24 @@
|
|
|
107
146
|
--role-text-disabled: var(--light-text-disabled); /* 2.21:1 ✗ icon cue required */
|
|
108
147
|
|
|
109
148
|
/* Surface roles */
|
|
110
|
-
--role-bg-body:
|
|
111
|
-
--role-bg-surface:
|
|
112
|
-
--role-bg-panel:
|
|
113
|
-
--role-bg-input:
|
|
114
|
-
--role-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
--text-on-primary: oklch(0.99 0 0); /* on blue L≈0.55 — 5.9:1 ✓ AA */
|
|
118
|
-
--text-on-accent: oklch(0.17 0.02 260); /* on cyan L≈0.77 — 6.1:1 ✓ AA */
|
|
119
|
-
--text-on-error: oklch(0.99 0 0); /* on purple L≈0.57 */
|
|
120
|
-
--text-on-success: oklch(0.17 0.02 260); /* on green L≈0.72 — dark text */
|
|
121
|
-
--text-on-warning: oklch(0.17 0.02 260); /* on amber L≈0.82 — dark text */
|
|
149
|
+
--role-bg-body: var(--light-bg-primary);
|
|
150
|
+
--role-bg-surface: var(--light-bg-secondary);
|
|
151
|
+
--role-bg-panel: var(--light-bg-accent);
|
|
152
|
+
--role-bg-input: var(--light-bg-tertiary);
|
|
153
|
+
--role-bg-sunken: oklch(0.938 0.004 250);
|
|
154
|
+
--role-border: var(--light-border);
|
|
155
|
+
--role-border-strong: oklch(0.880 0.008 250);
|
|
122
156
|
|
|
123
|
-
/*
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
--
|
|
128
|
-
--
|
|
129
|
-
--
|
|
130
|
-
--
|
|
157
|
+
/* Inverse text on coloured fills. Two values only — the fill is either
|
|
158
|
+
light enough to need dark text, or dark enough to need light text.
|
|
159
|
+
Neither is a pure endpoint. */
|
|
160
|
+
--text-on-light-fill: oklch(0.98 0.006 260);
|
|
161
|
+
--text-on-dark-fill: oklch(0.19 0.020 255);
|
|
162
|
+
--text-on-primary: var(--text-on-light-fill); /* on blue L≈0.55 — 4.88:1 ✓ AA */
|
|
163
|
+
--text-on-error: var(--text-on-light-fill); /* on red L≈0.58 — 4.55:1 ✓ AA */
|
|
164
|
+
--text-on-accent: var(--text-on-dark-fill); /* on cyan L≈0.77 — 9.38:1 ✓ AAA */
|
|
165
|
+
--text-on-warning: var(--text-on-dark-fill); /* on amber L≈0.80 — 9.68:1 ✓ AAA */
|
|
166
|
+
--text-on-success: var(--text-on-dark-fill); /* on teal L≈0.60 — 5.17:1 ✓ AA */
|
|
131
167
|
|
|
132
168
|
/* ============================================================
|
|
133
169
|
LAYER 4 — SHADCN/UI BRIDGE (light mode)
|
|
@@ -154,13 +190,6 @@
|
|
|
154
190
|
--input: var(--role-border);
|
|
155
191
|
--ring: var(--role-primary);
|
|
156
192
|
|
|
157
|
-
/* ============================================================
|
|
158
|
-
WCAG AA compliant text pairs for raw neon on light bg
|
|
159
|
-
(neon cyan L=0.77 on light bg is only 1.76:1 — fails 4.5:1)
|
|
160
|
-
============================================================ */
|
|
161
|
-
--color-accent-text: oklch(0.486 0.084 191.5); /* Dark cyan — AA on light bg */
|
|
162
|
-
--color-primary-text: oklch(0.485 0.243 263.6); /* Saturated blue — AA on light bg */
|
|
163
|
-
|
|
164
193
|
/* ============================================================
|
|
165
194
|
CANONICAL ACCENT GRADIENT (W3 §3.1) — exactly ONE gradient
|
|
166
195
|
exists suite-wide. Marketing/pre-auth heroes ONLY — never on
|
|
@@ -190,44 +219,72 @@
|
|
|
190
219
|
}
|
|
191
220
|
|
|
192
221
|
/* ============================================================
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
Deliberately declared at the TOP LEVEL, not nested inside another
|
|
204
|
-
`:root { }` block: engines that lack `oklch()` support predate CSS
|
|
205
|
-
nesting too, so a `@supports` block nested inside `:root` would be
|
|
206
|
-
silently dropped by exactly the browsers it's meant to serve when
|
|
207
|
-
this file is consumed raw (unbundled). It works when bundled
|
|
208
|
-
through the Tailwind v4 / LightningCSS pipeline only because that
|
|
209
|
-
pipeline hoists nested at-rules — this top-level form is correct
|
|
210
|
-
for both the raw and the bundled case.
|
|
222
|
+
LAYER 5 — PER-APP ACCENT
|
|
223
|
+
Added 2026-08-02: the 0.7.0 contract specifies these blocks but the
|
|
224
|
+
package had never shipped them — only a `var(--app-accent, …)` fallback
|
|
225
|
+
reference, so every app resolved to the shared cyan and the per-app
|
|
226
|
+
identity existed on paper only.
|
|
227
|
+
|
|
228
|
+
Set `data-app` on <body>. The FILL is the brand hue; the TEXT variants
|
|
229
|
+
are solved per mode, because a saturated fill colour is not a legible
|
|
230
|
+
text colour and the accent must never render below AA.
|
|
211
231
|
============================================================ */
|
|
212
|
-
|
|
213
|
-
:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
--role-destructive: #6c5ce7;
|
|
227
|
-
--light-text-primary: #171b22;
|
|
228
|
-
--dark-text-primary: #e8eaf6;
|
|
229
|
-
}
|
|
232
|
+
[data-app="crm7"] {
|
|
233
|
+
--app-accent: oklch(0.769 0.132 191.7);
|
|
234
|
+
--app-accent-text-l: oklch(0.505 0.132 191.7);
|
|
235
|
+
--app-accent-text-d: oklch(0.769 0.132 191.7);
|
|
236
|
+
}
|
|
237
|
+
[data-app="bsu"] {
|
|
238
|
+
--app-accent: oklch(0.541 0.247 293);
|
|
239
|
+
--app-accent-text-l: oklch(0.564 0.247 293);
|
|
240
|
+
--app-accent-text-d: oklch(0.745 0.247 293);
|
|
241
|
+
}
|
|
242
|
+
[data-app="conduit"] {
|
|
243
|
+
--app-accent: oklch(0.723 0.192 149.6);
|
|
244
|
+
--app-accent-text-l: oklch(0.505 0.192 149.6);
|
|
245
|
+
--app-accent-text-d: oklch(0.723 0.192 149.6);
|
|
230
246
|
}
|
|
247
|
+
[data-app="r80"] {
|
|
248
|
+
--app-accent: oklch(0.666 0.157 58.3);
|
|
249
|
+
--app-accent-text-l: oklch(0.546 0.157 58.3);
|
|
250
|
+
--app-accent-text-d: oklch(0.703 0.157 58.3);
|
|
251
|
+
}
|
|
252
|
+
/* R8.04 — the rates engine replacing R80.3. Deliberately REUSES r80's
|
|
253
|
+
orange: it serves the same users doing the same job, and a rates engine
|
|
254
|
+
is not where people should be re-learning which app they are in.
|
|
255
|
+
Requested by the r804 lane 2026-08-02. */
|
|
256
|
+
[data-app="r804"] {
|
|
257
|
+
--app-accent: oklch(0.666 0.157 58.3);
|
|
258
|
+
--app-accent-text-l: oklch(0.546 0.157 58.3);
|
|
259
|
+
--app-accent-text-d: oklch(0.703 0.157 58.3);
|
|
260
|
+
}
|
|
261
|
+
[data-app="throughput"] {
|
|
262
|
+
--app-accent: oklch(0.656 0.212 354.3);
|
|
263
|
+
--app-accent-text-l: oklch(0.564 0.212 354.3);
|
|
264
|
+
--app-accent-text-d: oklch(0.731 0.212 354.3);
|
|
265
|
+
}
|
|
266
|
+
/* Light/dark rebinding of the text variant. */
|
|
267
|
+
:root { --app-accent-text: var(--app-accent-text-l); }
|
|
268
|
+
.dark { --app-accent-text: var(--app-accent-text-d); }
|
|
269
|
+
|
|
270
|
+
/* ============================================================
|
|
271
|
+
NO sRGB FALLBACK — DELIBERATELY REMOVED 2026-08-02.
|
|
272
|
+
Precedent: precedent__bsuite__20260802__theme_conformance_is_absolute.
|
|
273
|
+
|
|
274
|
+
The `@supports not (color: oklch(0 0 0))` block that stood here shipped
|
|
275
|
+
a parallel hex palette. It is gone, and must not be reinstated:
|
|
276
|
+
|
|
277
|
+
· OKLCH has been Baseline-available in every evergreen engine since
|
|
278
|
+
Firefox 113 (May 2023), after Safari 15.4 (2022) and Chrome 111
|
|
279
|
+
(Mar 2023). It guarded a population that no longer exists.
|
|
280
|
+
· It was a second source of truth for the same colours, so it drifted:
|
|
281
|
+
it still bound --role-error to purple after the semantic set moved
|
|
282
|
+
to red. A fallback that disagrees with the tokens is worse than none.
|
|
283
|
+
|
|
284
|
+
If a colour needs to exist in hex (email HTML, PDF, canvas, manifest),
|
|
285
|
+
derive it at that call site from the oklch token — do not re-introduce a
|
|
286
|
+
second palette here.
|
|
287
|
+
============================================================ */
|
|
231
288
|
|
|
232
289
|
/* ============================================================
|
|
233
290
|
DARK MODE — Layer 2 surface overrides + Layer 3 role rebind
|
|
@@ -253,9 +310,6 @@
|
|
|
253
310
|
--dark-text-muted: oklch(0.68 0.018 260); /* metadata — 6.69:1 ✓ AA (normal) */
|
|
254
311
|
--dark-text-subtle: oklch(0.56 0.015 260); /* placeholders — 4.14:1 ✓ AA large only — ✗ AA normal */
|
|
255
312
|
--dark-text-disabled: oklch(0.44 0.010 260); /* disabled — 2.48:1 ✗ fails AA at any size — MUST pair with icon cue */
|
|
256
|
-
/* Legacy aliases */
|
|
257
|
-
--dark-text-tertiary: var(--dark-text-muted);
|
|
258
|
-
--dark-text-quaternary: var(--dark-text-disabled);
|
|
259
313
|
|
|
260
314
|
--dark-border: oklch(0.428 0.015 248.2);
|
|
261
315
|
--dark-hover: oklch(0.39 0.035 265);
|
|
@@ -270,14 +324,17 @@
|
|
|
270
324
|
|
|
271
325
|
--role-bg-body: var(--dark-bg-primary);
|
|
272
326
|
--role-bg-surface: var(--dark-bg-secondary);
|
|
273
|
-
--role-bg-panel: oklch(0.
|
|
274
|
-
--role-bg-input: oklch(0.
|
|
327
|
+
--role-bg-panel: oklch(0.190 0.020 260);
|
|
328
|
+
--role-bg-input: oklch(0.240 0.020 260);
|
|
329
|
+
--role-bg-sunken: oklch(0.145 0.022 268);
|
|
275
330
|
--role-border: var(--dark-border);
|
|
276
331
|
|
|
277
|
-
/*
|
|
278
|
-
|
|
279
|
-
--
|
|
280
|
-
--
|
|
332
|
+
/* Role text variants rebind for the dark surface — all AAA on navy. */
|
|
333
|
+
--role-primary-text: oklch(0.721 0.215 262.9); /* 7.01:1 ✓ AAA */
|
|
334
|
+
--role-accent-text: var(--neon-electric-cyan); /* 9.78:1 ✓ AAA */
|
|
335
|
+
--role-error-text: oklch(0.786 0.230 25); /* 7.00:1 ✓ AAA */
|
|
336
|
+
--role-warning-text: var(--neon-electric-amber);/* 10.10:1 ✓ AAA */
|
|
337
|
+
--role-success-text: oklch(0.671 0.130 195); /* 6.99:1 ✓ AAA */
|
|
281
338
|
|
|
282
339
|
/* Glow/shadow scale up in dark mode */
|
|
283
340
|
--glow-strength: 0.6;
|
package/src/preset-v4.css
CHANGED
|
@@ -1,134 +1,143 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* @bsuite/theme — Tailwind v4 @theme
|
|
3
|
-
* Version 0.
|
|
2
|
+
* @bsuite/theme — Tailwind v4 @theme bridge
|
|
3
|
+
* Version 0.7.0
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* Import this before any app-specific @theme overrides:
|
|
5
|
+
* Usage (every D2C app; braden imports braden-css instead of css):
|
|
7
6
|
*
|
|
8
7
|
* @import 'tailwindcss';
|
|
9
|
-
* @import '@bsuite/theme/
|
|
8
|
+
* @import '@bsuite/theme/css'; ← defines --role-* (vars.css)
|
|
9
|
+
* @import '@bsuite/theme/preset-v4.css'; ← this file, maps them to utilities
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
12
|
+
* WHY `@theme inline` AND NOT `@theme`
|
|
13
|
+
*
|
|
14
|
+
* Until 0.7.0 this file used a plain `@theme` block containing hardcoded
|
|
15
|
+
* oklch literals — a full second copy of every value in vars.css. Two
|
|
16
|
+
* consequences, both real bugs:
|
|
17
|
+
*
|
|
18
|
+
* 1. DARK MODE DID NOT REACH THESE UTILITIES. Plain `@theme` emits
|
|
19
|
+
* `--color-card: <literal>` at :root and makes `bg-card` resolve to
|
|
20
|
+
* `var(--color-card)`. vars.css rebinds `--role-bg-panel` under
|
|
21
|
+
* `.dark`, but nothing rebound `--color-card`, so `bg-card` stayed on
|
|
22
|
+
* its light-mode literal in dark mode.
|
|
23
|
+
* 2. IT DRIFTED. The duplicate copy still said `--color-card: oklch(1 0
|
|
24
|
+
* 0.5)` (pure white) and `--color-destructive: <purple>` after the
|
|
25
|
+
* token source had moved on from both.
|
|
26
|
+
*
|
|
27
|
+
* `@theme inline` emits the `var()` reference into the utility itself, so
|
|
28
|
+
* `bg-card` resolves through `--role-bg-panel` and follows every `.dark`
|
|
29
|
+
* and BrandingProvider rebinding for free. vars.css is the ONLY source of
|
|
30
|
+
* truth for values; this file contains no colour literals at all.
|
|
31
|
+
*
|
|
32
|
+
* Adding a colour literal to this file re-creates both bugs. Don't.
|
|
33
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
14
34
|
*
|
|
15
35
|
* Token naming: `--color-{name}` → Tailwind generates `bg-{name}`,
|
|
16
36
|
* `text-{name}`, `border-{name}` etc. automatically.
|
|
17
|
-
*
|
|
18
|
-
* Layer order matches vars.css:
|
|
19
|
-
* 1. Palette — --color-neon-electric-*
|
|
20
|
-
* 2. Surface — --color-{light|dark}-{bg|text}-*
|
|
21
|
-
* 3. Role — --color-role-* ← bind to these in components
|
|
22
|
-
* 4. Shadcn — --color-background, --color-foreground, etc.
|
|
23
|
-
* 5. Text-on — --color-text-on-*
|
|
24
37
|
*/
|
|
25
38
|
|
|
26
|
-
@theme {
|
|
27
|
-
/* ============================================================
|
|
28
|
-
LAYER 1 — Neon Electric palette (11 colours, FROZEN)
|
|
29
|
-
============================================================ */
|
|
30
|
-
--color-neon-electric-blue: oklch(0.546 0.215 262.9);
|
|
31
|
-
--color-neon-electric-cyan: oklch(0.769 0.132 191.7);
|
|
32
|
-
--color-neon-electric-indigo: oklch(0.511 0.23 277);
|
|
33
|
-
--color-neon-electric-purple: oklch(0.568 0.202 283.1);
|
|
34
|
-
--color-neon-electric-magenta: oklch(0.742 0.167 359.5);
|
|
35
|
-
--color-neon-electric-pink: oklch(0.656 0.212 354.3);
|
|
36
|
-
--color-neon-electric-coral: oklch(0.669 0.219 20.9);
|
|
37
|
-
--color-neon-electric-orange: oklch(0.728 0.168 22.5);
|
|
38
|
-
--color-neon-electric-yellow: oklch(0.868 0.125 81.4);
|
|
39
|
-
--color-neon-electric-green: oklch(0.723 0.192 149.6);
|
|
40
|
-
--color-neon-electric-lavender: oklch(0.736 0.141 285.6);
|
|
41
|
-
|
|
39
|
+
@theme inline {
|
|
42
40
|
/* ============================================================
|
|
43
|
-
LAYER
|
|
41
|
+
LAYER 1 — Palette. Exposed for decorative use only.
|
|
42
|
+
Bind components to the role tokens below, never to these:
|
|
43
|
+
white-labelling mutates roles, so a palette-bound component
|
|
44
|
+
silently ignores tenant branding.
|
|
44
45
|
============================================================ */
|
|
45
|
-
--color-
|
|
46
|
-
--color-
|
|
47
|
-
--color-
|
|
48
|
-
--color-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
--color-
|
|
52
|
-
--color-
|
|
53
|
-
--color-
|
|
54
|
-
--color-
|
|
55
|
-
--color-
|
|
46
|
+
--color-neon-electric-blue: var(--neon-electric-blue);
|
|
47
|
+
--color-neon-electric-cyan: var(--neon-electric-cyan);
|
|
48
|
+
--color-neon-electric-indigo: var(--neon-electric-indigo);
|
|
49
|
+
--color-neon-electric-purple: var(--neon-electric-purple);
|
|
50
|
+
--color-neon-electric-magenta: var(--neon-electric-magenta);
|
|
51
|
+
--color-neon-electric-pink: var(--neon-electric-pink);
|
|
52
|
+
--color-neon-electric-coral: var(--neon-electric-coral);
|
|
53
|
+
--color-neon-electric-orange: var(--neon-electric-orange);
|
|
54
|
+
--color-neon-electric-yellow: var(--neon-electric-yellow);
|
|
55
|
+
--color-neon-electric-green: var(--neon-electric-green);
|
|
56
|
+
--color-neon-electric-lavender: var(--neon-electric-lavender);
|
|
57
|
+
--color-neon-electric-red: var(--neon-electric-red);
|
|
58
|
+
--color-neon-electric-amber: var(--neon-electric-amber);
|
|
59
|
+
--color-neon-electric-teal: var(--neon-electric-teal);
|
|
60
|
+
--color-neon-electric-deep: var(--neon-electric-deep);
|
|
56
61
|
|
|
57
62
|
/* ============================================================
|
|
58
|
-
LAYER 2 —
|
|
63
|
+
LAYER 2 — Surfaces. Role-bound, so they flip with .dark.
|
|
59
64
|
============================================================ */
|
|
60
|
-
--color-
|
|
61
|
-
--color-
|
|
62
|
-
--color-
|
|
63
|
-
--color-
|
|
64
|
-
--color-
|
|
65
|
-
|
|
66
|
-
/* Eye-strain-safe dark text scale (L capped at 0.94, hue 260) */
|
|
67
|
-
--color-dark-text-primary: oklch(0.94 0.012 260); /* 13.9:1 AAA */
|
|
68
|
-
--color-dark-text-secondary: oklch(0.82 0.015 260); /* 9.8:1 AAA */
|
|
69
|
-
--color-dark-text-muted: oklch(0.68 0.018 260); /* 5.6:1 AA */
|
|
70
|
-
--color-dark-text-subtle: oklch(0.56 0.015 260); /* 3.6:1 AA large */
|
|
71
|
-
--color-dark-text-disabled: oklch(0.44 0.010 260);
|
|
65
|
+
--color-bg-body: var(--role-bg-body);
|
|
66
|
+
--color-bg-surface: var(--role-bg-surface);
|
|
67
|
+
--color-bg-panel: var(--role-bg-panel);
|
|
68
|
+
--color-bg-input: var(--role-bg-input);
|
|
69
|
+
--color-bg-sunken: var(--role-bg-sunken);
|
|
70
|
+
--color-border-strong: var(--role-border-strong);
|
|
72
71
|
|
|
73
72
|
/* ============================================================
|
|
74
|
-
LAYER 3 —
|
|
75
|
-
Consumers should only reference these — never palette names.
|
|
73
|
+
LAYER 3 — Text scale
|
|
76
74
|
============================================================ */
|
|
77
|
-
--color-
|
|
78
|
-
--color-
|
|
79
|
-
--color-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
--color-
|
|
83
|
-
--color-role-destructive: oklch(0.568 0.202 283.1); /* synonym */
|
|
84
|
-
--color-role-warning: oklch(0.728 0.168 22.5); /* electric orange */
|
|
85
|
-
--color-role-success: oklch(0.723 0.192 149.6); /* electric green */
|
|
86
|
-
--color-role-info: oklch(0.769 0.132 191.7); /* electric cyan */
|
|
87
|
-
|
|
88
|
-
/* Semantic status aliases (deprecated: prefer role-*) */
|
|
89
|
-
--color-status-success: oklch(0.723 0.192 149.6);
|
|
90
|
-
--color-status-warning: oklch(0.728 0.168 22.5);
|
|
91
|
-
--color-status-error: oklch(0.568 0.202 283.1); /* purple — colourblind policy */
|
|
92
|
-
--color-status-info: oklch(0.769 0.132 191.7);
|
|
75
|
+
--color-text-heading: var(--role-text-heading);
|
|
76
|
+
--color-text-body: var(--role-text-body);
|
|
77
|
+
--color-text-secondary: var(--role-text-secondary);
|
|
78
|
+
--color-text-muted: var(--role-text-muted);
|
|
79
|
+
--color-text-subtle: var(--role-text-subtle);
|
|
80
|
+
--color-text-disabled: var(--role-text-disabled);
|
|
93
81
|
|
|
94
82
|
/* ============================================================
|
|
95
|
-
LAYER
|
|
96
|
-
|
|
83
|
+
LAYER 3 — Semantic roles.
|
|
84
|
+
Error is RED because D2C's primary is blue and error must be
|
|
85
|
+
maximally separated from primary under dichromacy — see the
|
|
86
|
+
separation policy in vars.css. Not a fixed-hue rule.
|
|
97
87
|
============================================================ */
|
|
98
|
-
--color-
|
|
99
|
-
--color-
|
|
100
|
-
--color-
|
|
101
|
-
--color-
|
|
102
|
-
--color-
|
|
103
|
-
--color-
|
|
104
|
-
--color-
|
|
105
|
-
--color-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
--color-
|
|
110
|
-
--color-accent:
|
|
111
|
-
--color-
|
|
112
|
-
--color-
|
|
113
|
-
--color-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
88
|
+
--color-role-primary: var(--role-primary);
|
|
89
|
+
--color-role-secondary: var(--role-secondary);
|
|
90
|
+
--color-role-accent: var(--role-accent);
|
|
91
|
+
--color-role-error: var(--role-error);
|
|
92
|
+
--color-role-destructive: var(--role-destructive);
|
|
93
|
+
--color-role-warning: var(--role-warning);
|
|
94
|
+
--color-role-success: var(--role-success);
|
|
95
|
+
--color-role-info: var(--role-info);
|
|
96
|
+
|
|
97
|
+
/* AA-safe text variants — the only correct token for coloured type.
|
|
98
|
+
A saturated fill colour is not a legible text colour. */
|
|
99
|
+
--color-primary-text: var(--role-primary-text);
|
|
100
|
+
--color-accent-text: var(--role-accent-text);
|
|
101
|
+
--color-error-text: var(--role-error-text);
|
|
102
|
+
--color-warning-text: var(--role-warning-text);
|
|
103
|
+
--color-success-text: var(--role-success-text);
|
|
104
|
+
|
|
105
|
+
/* Per-app accent (Layer 5). Resolves through [data-app] on <body>,
|
|
106
|
+
falling back to the shared accent when no app is declared. */
|
|
107
|
+
--color-app-accent: var(--app-accent, var(--role-accent));
|
|
108
|
+
--color-app-accent-text: var(--app-accent-text, var(--role-accent-text));
|
|
117
109
|
|
|
118
110
|
/* ============================================================
|
|
119
|
-
LAYER
|
|
111
|
+
LAYER 4 — shadcn/ui bridge
|
|
120
112
|
============================================================ */
|
|
121
|
-
--color-
|
|
122
|
-
--color-text-
|
|
123
|
-
--color-
|
|
124
|
-
--color-
|
|
125
|
-
--color-
|
|
113
|
+
--color-background: var(--role-bg-body);
|
|
114
|
+
--color-foreground: var(--role-text-body);
|
|
115
|
+
--color-card: var(--role-bg-panel);
|
|
116
|
+
--color-card-foreground: var(--role-text-body);
|
|
117
|
+
--color-popover: var(--role-bg-panel);
|
|
118
|
+
--color-popover-foreground: var(--role-text-body);
|
|
119
|
+
--color-primary: var(--role-primary);
|
|
120
|
+
--color-primary-foreground: var(--text-on-primary);
|
|
121
|
+
--color-secondary: var(--role-secondary);
|
|
122
|
+
--color-secondary-foreground: var(--text-on-primary);
|
|
123
|
+
--color-muted: var(--role-bg-input);
|
|
124
|
+
--color-muted-foreground: var(--role-text-muted);
|
|
125
|
+
--color-accent: var(--role-accent);
|
|
126
|
+
--color-accent-foreground: var(--text-on-accent);
|
|
127
|
+
--color-destructive: var(--role-destructive);
|
|
128
|
+
--color-destructive-foreground: var(--text-on-error);
|
|
129
|
+
--color-border: var(--role-border);
|
|
130
|
+
--color-input: var(--role-border);
|
|
131
|
+
--color-ring: var(--role-primary);
|
|
126
132
|
|
|
127
133
|
/* ============================================================
|
|
128
|
-
|
|
134
|
+
LAYER 5 — Inverse text on coloured fills
|
|
129
135
|
============================================================ */
|
|
130
|
-
--color-
|
|
131
|
-
--color-
|
|
136
|
+
--color-text-on-primary: var(--text-on-primary);
|
|
137
|
+
--color-text-on-accent: var(--text-on-accent);
|
|
138
|
+
--color-text-on-error: var(--text-on-error);
|
|
139
|
+
--color-text-on-success: var(--text-on-success);
|
|
140
|
+
--color-text-on-warning: var(--text-on-warning);
|
|
132
141
|
|
|
133
142
|
/* ============================================================
|
|
134
143
|
ANIMATIONS
|
|
@@ -143,27 +152,28 @@
|
|
|
143
152
|
}
|
|
144
153
|
|
|
145
154
|
/* ============================================================
|
|
146
|
-
KEYFRAMES — outside @theme (v4 doesn't expose them there)
|
|
147
|
-
|
|
155
|
+
KEYFRAMES — outside @theme (v4 doesn't expose them there).
|
|
156
|
+
Colour-bearing frames derive from --role-accent, so they follow
|
|
157
|
+
per-app accent and tenant branding instead of pinning cyan.
|
|
148
158
|
============================================================ */
|
|
149
159
|
@keyframes pulse-soft {
|
|
150
160
|
0%, 100% { opacity: 1; }
|
|
151
|
-
50%
|
|
161
|
+
50% { opacity: 0.7; }
|
|
152
162
|
}
|
|
153
163
|
|
|
154
164
|
@keyframes glow {
|
|
155
|
-
0% { box-shadow: 0 0 5px oklch(
|
|
156
|
-
100% { box-shadow: 0 0 20px oklch(
|
|
165
|
+
0% { box-shadow: 0 0 5px oklch(from var(--role-accent) l c h / 0.2); }
|
|
166
|
+
100% { box-shadow: 0 0 20px oklch(from var(--role-accent) l c h / 0.6); }
|
|
157
167
|
}
|
|
158
168
|
|
|
159
169
|
@keyframes neon-pulse {
|
|
160
|
-
0%, 100% { text-shadow: 0 0 10px oklch(
|
|
161
|
-
50%
|
|
170
|
+
0%, 100% { text-shadow: 0 0 10px oklch(from var(--role-accent) l c h / 0.3); }
|
|
171
|
+
50% { text-shadow: 0 0 20px oklch(from var(--role-accent) l c h / 0.8); }
|
|
162
172
|
}
|
|
163
173
|
|
|
164
174
|
@keyframes float {
|
|
165
175
|
0%, 100% { transform: translateY(0px); }
|
|
166
|
-
50%
|
|
176
|
+
50% { transform: translateY(-10px); }
|
|
167
177
|
}
|
|
168
178
|
|
|
169
179
|
@keyframes shimmer {
|
|
@@ -173,7 +183,7 @@
|
|
|
173
183
|
|
|
174
184
|
@keyframes typing {
|
|
175
185
|
0%, 60% { opacity: 1; }
|
|
176
|
-
30%
|
|
186
|
+
30% { opacity: 0.4; }
|
|
177
187
|
}
|
|
178
188
|
|
|
179
189
|
@keyframes shine {
|
package/src/tailwind-preset.js
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @bsuite/theme — Tailwind v3 preset (oklch edition)
|
|
3
|
-
*
|
|
4
|
-
* Consume via:
|
|
5
|
-
* // tailwind.config.js (CommonJS)
|
|
6
|
-
* module.exports = {
|
|
7
|
-
* presets: [require('@bsuite/theme/tailwind-preset')],
|
|
8
|
-
* content: ['./src/**\/*.{js,ts,jsx,tsx}'],
|
|
9
|
-
* }
|
|
10
|
-
*
|
|
11
|
-
* Extends Tailwind's theme with the D2C Neon Electric palette, light/dark
|
|
12
|
-
* surface tokens, semantic status colours, gradients, glow shadows, and
|
|
13
|
-
* the six canonical animations. Does not override Tailwind's default scale.
|
|
14
|
-
*
|
|
15
|
-
* Colour values are inline oklch so the preset is self-contained — no
|
|
16
|
-
* dependency on any `--*-rgb` CSS custom property. Tailwind v3 injects
|
|
17
|
-
* `<alpha-value>` into any valid CSS colour function, and `oklch(L C H / A)`
|
|
18
|
-
* is valid CSS Color 4 syntax (supported in all evergreen browsers:
|
|
19
|
-
* Chrome ≥111, Safari ≥15.4, Firefox ≥113). Keeps bg-neon-electric-blue/40
|
|
20
|
-
* and friends working without the RGB-triplet variable indirection.
|
|
21
|
-
*
|
|
22
|
-
* Values are kept in sync with `preset-v4.css` — editing one without the
|
|
23
|
-
* other will cause v3 and v4 consumers to diverge. See README.
|
|
24
|
-
*
|
|
25
|
-
* NOTE: Tailwind v4 apps should import `@bsuite/theme/preset-v4.css` instead.
|
|
26
|
-
* v4 removed the preset system — presets exist only for v3.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/** @type {import('tailwindcss').Config} */
|
|
30
|
-
module.exports = {
|
|
31
|
-
darkMode: ['class'],
|
|
32
|
-
theme: {
|
|
33
|
-
extend: {
|
|
34
|
-
colors: {
|
|
35
|
-
neon: {
|
|
36
|
-
'electric-blue': 'oklch(0.546 0.215 262.9 / <alpha-value>)',
|
|
37
|
-
'electric-cyan': 'oklch(0.769 0.132 191.7 / <alpha-value>)',
|
|
38
|
-
'electric-indigo': 'oklch(0.511 0.23 277 / <alpha-value>)',
|
|
39
|
-
'electric-purple': 'oklch(0.568 0.202 283.1 / <alpha-value>)',
|
|
40
|
-
'electric-magenta': 'oklch(0.742 0.167 359.5 / <alpha-value>)',
|
|
41
|
-
'electric-pink': 'oklch(0.656 0.212 354.3 / <alpha-value>)',
|
|
42
|
-
'electric-coral': 'oklch(0.669 0.219 20.9 / <alpha-value>)',
|
|
43
|
-
'electric-orange': 'oklch(0.728 0.168 22.5 / <alpha-value>)',
|
|
44
|
-
'electric-yellow': 'oklch(0.868 0.125 81.4 / <alpha-value>)',
|
|
45
|
-
'electric-green': 'oklch(0.726 0.197 145.5 / <alpha-value>)',
|
|
46
|
-
'electric-lavender': 'oklch(0.749 0.115 288.4 / <alpha-value>)',
|
|
47
|
-
},
|
|
48
|
-
light: {
|
|
49
|
-
bg: {
|
|
50
|
-
primary: 'var(--light-bg-primary)',
|
|
51
|
-
secondary: 'var(--light-bg-secondary)',
|
|
52
|
-
tertiary: 'var(--light-bg-tertiary)',
|
|
53
|
-
accent: 'var(--light-bg-accent)',
|
|
54
|
-
},
|
|
55
|
-
text: {
|
|
56
|
-
primary: 'var(--light-text-primary)',
|
|
57
|
-
secondary: 'var(--light-text-secondary)',
|
|
58
|
-
tertiary: 'var(--light-text-tertiary)',
|
|
59
|
-
quaternary: 'var(--light-text-quaternary)',
|
|
60
|
-
},
|
|
61
|
-
border: 'var(--light-border)',
|
|
62
|
-
hover: 'var(--light-hover)',
|
|
63
|
-
},
|
|
64
|
-
dark: {
|
|
65
|
-
bg: {
|
|
66
|
-
primary: 'var(--dark-bg-primary)',
|
|
67
|
-
secondary: 'var(--dark-bg-secondary)',
|
|
68
|
-
tertiary: 'var(--dark-bg-tertiary)',
|
|
69
|
-
quaternary: 'var(--dark-bg-quaternary)',
|
|
70
|
-
accent: 'var(--dark-bg-accent)',
|
|
71
|
-
},
|
|
72
|
-
text: {
|
|
73
|
-
primary: 'var(--dark-text-primary)',
|
|
74
|
-
secondary: 'var(--dark-text-secondary)',
|
|
75
|
-
tertiary: 'var(--dark-text-tertiary)',
|
|
76
|
-
quaternary: 'var(--dark-text-quaternary)',
|
|
77
|
-
},
|
|
78
|
-
border: 'var(--dark-border)',
|
|
79
|
-
hover: 'var(--dark-hover)',
|
|
80
|
-
},
|
|
81
|
-
status: {
|
|
82
|
-
success: 'var(--status-success)',
|
|
83
|
-
warning: 'var(--status-warning)',
|
|
84
|
-
error: 'var(--status-error)',
|
|
85
|
-
info: 'var(--status-info)',
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
backgroundImage: {
|
|
90
|
-
'gradient-brand':
|
|
91
|
-
'linear-gradient(135deg, oklch(0.669 0.219 20.9) 0%, oklch(0.728 0.168 22.5) 25%, oklch(0.868 0.125 81.4) 50%, oklch(0.769 0.132 191.7) 75%, oklch(0.749 0.115 288.4) 100%)',
|
|
92
|
-
'gradient-electric':
|
|
93
|
-
'linear-gradient(135deg, oklch(0.546 0.215 262.9) 0%, oklch(0.769 0.132 191.7) 50%, oklch(0.656 0.212 354.3) 100%)',
|
|
94
|
-
'gradient-neon':
|
|
95
|
-
'linear-gradient(90deg, oklch(0.769 0.132 191.7) 0%, oklch(0.568 0.202 283.1) 50%, oklch(0.669 0.219 20.9) 100%)',
|
|
96
|
-
'gradient-chat-user':
|
|
97
|
-
'linear-gradient(135deg, oklch(0.636 0.153 271.3) 0%, oklch(0.466 0.168 296.3) 100%)',
|
|
98
|
-
'gradient-chat-agent':
|
|
99
|
-
'linear-gradient(135deg, oklch(0.546 0.215 262.9) 0%, oklch(0.656 0.212 354.3) 100%)',
|
|
100
|
-
'gradient-neural':
|
|
101
|
-
'radial-gradient(circle at center, oklch(0.769 0.132 191.7 / 0.1) 0%, transparent 50%)',
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
boxShadow: {
|
|
105
|
-
'glow-electric-blue': '0 0 20px oklch(0.546 0.215 262.9 / var(--glow-strength))',
|
|
106
|
-
'glow-electric-cyan': '0 0 20px oklch(0.769 0.132 191.7 / var(--glow-strength))',
|
|
107
|
-
'glow-electric-purple': '0 0 20px oklch(0.568 0.202 283.1 / var(--glow-strength))',
|
|
108
|
-
'glow-electric-pink': '0 0 20px oklch(0.656 0.212 354.3 / var(--glow-strength))',
|
|
109
|
-
'glow-electric-coral': '0 0 20px oklch(0.669 0.219 20.9 / var(--glow-strength))',
|
|
110
|
-
'glow-electric-magenta': '0 0 20px oklch(0.742 0.167 359.5 / var(--glow-strength))',
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
animation: {
|
|
114
|
-
'pulse-soft': 'pulse-soft 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
115
|
-
glow: 'glow 2s ease-in-out infinite alternate',
|
|
116
|
-
typing: 'typing 1.5s infinite',
|
|
117
|
-
shimmer: 'shimmer 2s infinite',
|
|
118
|
-
float: 'float 3s ease-in-out infinite',
|
|
119
|
-
'neon-pulse': 'neon-pulse 2s ease-in-out infinite',
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
keyframes: {
|
|
123
|
-
'pulse-soft': {
|
|
124
|
-
'0%, 100%': { opacity: '1' },
|
|
125
|
-
'50%': { opacity: '0.7' },
|
|
126
|
-
},
|
|
127
|
-
glow: {
|
|
128
|
-
'0%': { boxShadow: '0 0 5px oklch(0.769 0.132 191.7 / 0.2)' },
|
|
129
|
-
'100%': { boxShadow: '0 0 20px oklch(0.769 0.132 191.7 / 0.6)' },
|
|
130
|
-
},
|
|
131
|
-
typing: {
|
|
132
|
-
'0%, 60%': { opacity: '1' },
|
|
133
|
-
'30%': { opacity: '0.4' },
|
|
134
|
-
},
|
|
135
|
-
shimmer: {
|
|
136
|
-
'0%': { backgroundPosition: '-1000px 0' },
|
|
137
|
-
'100%': { backgroundPosition: '1000px 0' },
|
|
138
|
-
},
|
|
139
|
-
float: {
|
|
140
|
-
'0%, 100%': { transform: 'translateY(0px)' },
|
|
141
|
-
'50%': { transform: 'translateY(-10px)' },
|
|
142
|
-
},
|
|
143
|
-
'neon-pulse': {
|
|
144
|
-
'0%, 100%': { textShadow: '0 0 10px oklch(0.769 0.132 191.7 / 0.3)' },
|
|
145
|
-
'50%': { textShadow: '0 0 20px oklch(0.769 0.132 191.7 / 0.8)' },
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
}
|