@nebutra/tokens 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/brands/gsap/brand.json +17 -64
- package/brands/linear/brand.json +18 -57
- package/brands/notion/brand.json +18 -62
- package/brands/raycast/brand.json +17 -64
- package/brands/stripe/brand.json +16 -72
- package/brands/vanta/brand.json +16 -63
- package/brands/vercel/brand.json +16 -50
- package/dist/brand-package/index.d.ts +123 -0
- package/dist/brand-package/index.js +61 -0
- package/dist/brand-package/index.js.map +1 -0
- package/dist/brand-package/use-brand.d.ts +2 -0
- package/dist/brand-package/use-brand.js +12 -0
- package/dist/brand-package/use-brand.js.map +1 -0
- package/dist/chunk-ALJTP5HL.js +881 -0
- package/dist/chunk-ALJTP5HL.js.map +1 -0
- package/dist/chunk-RGUJQOLH.js +1582 -0
- package/dist/chunk-RGUJQOLH.js.map +1 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +187 -0
- package/dist/index.js.map +1 -0
- package/dist/use-brand-C8d4DPqE.d.ts +371 -0
- package/package.json +34 -9
- package/recipe.css +322 -1
- package/skins/README.md +2 -4
- package/skins/gsap.css +31 -119
- package/skins/linear.css +33 -117
- package/skins/notion.css +27 -117
- package/skins/raycast.css +32 -119
- package/skins/stripe.css +27 -129
- package/skins/vanta.css +27 -122
- package/skins/vercel.css +30 -111
- package/styles.css +388 -113
- package/.turbo/turbo-build.log +0 -8
- package/.turbo/turbo-typecheck.log +0 -4
- package/AGENTS.md +0 -45
- package/DESIGN.md +0 -357
- package/scripts/compile-brand-run.ts +0 -79
- package/scripts/compile-brand.mjs +0 -25
- package/scripts/emit-skins-run.ts +0 -62
- package/scripts/emit-skins.mjs +0 -31
- package/scripts/sync-styles.mjs +0 -29
- package/src/brand-package/__tests__/compile-refero.test.ts +0 -427
- package/src/brand-package/__tests__/emit-css.test.ts +0 -130
- package/src/brand-package/apply-brand.ts +0 -92
- package/src/brand-package/compile-helpers.ts +0 -170
- package/src/brand-package/compile-refero.ts +0 -69
- package/src/brand-package/emit-css.ts +0 -468
- package/src/brand-package/hex-to-hsl.ts +0 -100
- package/src/brand-package/index.ts +0 -71
- package/src/brand-package/infer-recipe.ts +0 -198
- package/src/brand-package/normalize.ts +0 -295
- package/src/brand-package/presets/context.ts +0 -17
- package/src/brand-package/presets/generic.ts +0 -214
- package/src/brand-package/presets/gsap.ts +0 -146
- package/src/brand-package/presets/index.ts +0 -31
- package/src/brand-package/presets/linear.ts +0 -183
- package/src/brand-package/presets/notion.ts +0 -208
- package/src/brand-package/presets/raycast.ts +0 -138
- package/src/brand-package/presets/recipe.ts +0 -61
- package/src/brand-package/presets/stripe.ts +0 -207
- package/src/brand-package/presets/vanta.ts +0 -220
- package/src/brand-package/presets/vercel.ts +0 -187
- package/src/brand-package/types.ts +0 -285
- package/src/brand-package/use-brand.ts +0 -207
- package/src/brand-package/validate.ts +0 -108
- package/src/index.ts +0 -67
- package/src/theme-provider.tsx +0 -246
- package/tsconfig.json +0 -11
- package/turbo.json +0 -15
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic heuristic compile path for unknown brands.
|
|
3
|
-
*/
|
|
4
|
-
import { leafHex, pickDisplayFontFamily, pickUiFontFamily } from "../compile-helpers";
|
|
5
|
-
import { tryHexToHsl } from "../hex-to-hsl";
|
|
6
|
-
import type { BrandPackage } from "../types";
|
|
7
|
-
import type { CompileContext } from "./context";
|
|
8
|
-
import { buildRecipe } from "./recipe";
|
|
9
|
-
|
|
10
|
-
export function buildGeneric(ctx: CompileContext): BrandPackage {
|
|
11
|
-
ctx.warnings.push(
|
|
12
|
-
"Unknown brand layout — compiled with heuristic recipe. Review mapping in Create Center.",
|
|
13
|
-
);
|
|
14
|
-
ctx.warnings.push(...ctx.recipeHints.notes);
|
|
15
|
-
const entries = Object.entries(ctx.colors);
|
|
16
|
-
const pick = (...keys: string[]) => {
|
|
17
|
-
for (const k of keys) {
|
|
18
|
-
if (ctx.colors[k]) return ctx.colors[k];
|
|
19
|
-
}
|
|
20
|
-
return undefined;
|
|
21
|
-
};
|
|
22
|
-
// Page canvas first (warm paper / parchment), then pure white, then dark voids.
|
|
23
|
-
// Notion: paper-warmth is canvas; pure-white is card — never invert.
|
|
24
|
-
const bg =
|
|
25
|
-
pick(
|
|
26
|
-
"paper-warmth",
|
|
27
|
-
"paper-white",
|
|
28
|
-
"page-canvas",
|
|
29
|
-
"parchment",
|
|
30
|
-
"pure-white",
|
|
31
|
-
"paper",
|
|
32
|
-
"background",
|
|
33
|
-
"canvas",
|
|
34
|
-
"void-black",
|
|
35
|
-
"void",
|
|
36
|
-
"just-black",
|
|
37
|
-
"off-black",
|
|
38
|
-
) ?? "#0a0a0a";
|
|
39
|
-
|
|
40
|
-
// Detect light canvas early so fg/primary picks don't invert
|
|
41
|
-
const isLightCanvas = (() => {
|
|
42
|
-
try {
|
|
43
|
-
const m = tryHexToHsl(bg, "0 0% 4%").match(/(\d+)%\s*$/);
|
|
44
|
-
return m ? Number(m[1]) >= 50 : false;
|
|
45
|
-
} catch {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
})();
|
|
49
|
-
|
|
50
|
-
// Light: ink/carbon text — never pure-white; prefer ink-black over decorative midnight.
|
|
51
|
-
const fg = isLightCanvas
|
|
52
|
-
? (pick(
|
|
53
|
-
"ink-black",
|
|
54
|
-
"carbon",
|
|
55
|
-
"charcoal",
|
|
56
|
-
"obsidian",
|
|
57
|
-
"foreground",
|
|
58
|
-
"ink",
|
|
59
|
-
"midnight-ink",
|
|
60
|
-
"deep-violet",
|
|
61
|
-
"slate",
|
|
62
|
-
) ?? "#181822")
|
|
63
|
-
: (pick("pure-white", "paper", "surface-cream", "bone", "mist", "foreground", "white") ??
|
|
64
|
-
"#ffffff");
|
|
65
|
-
|
|
66
|
-
// Chromatic *action* tokens only — never canvas/surface/decorative wash names
|
|
67
|
-
const primary =
|
|
68
|
-
pick(
|
|
69
|
-
"notion-blue",
|
|
70
|
-
"indigo-ink",
|
|
71
|
-
"vivid-violet",
|
|
72
|
-
"primary",
|
|
73
|
-
"acid-lime",
|
|
74
|
-
"obsidian",
|
|
75
|
-
"shockingly-green",
|
|
76
|
-
"brand",
|
|
77
|
-
"accent",
|
|
78
|
-
"mid-violet",
|
|
79
|
-
"amethyst-edge",
|
|
80
|
-
"signal-blue",
|
|
81
|
-
) ??
|
|
82
|
-
entries.find(
|
|
83
|
-
([k]) =>
|
|
84
|
-
!/void|black|canvas|graphite|paper|hairline|ash|parchment|fog|lavender|steel|slate|carbon|mist|frost|smoke|white|midnight|warmth|tint|wash|marigold|coral|saffron|mocha|vermillion|sky/i.test(
|
|
85
|
-
k,
|
|
86
|
-
),
|
|
87
|
-
)?.[1] ??
|
|
88
|
-
(isLightCanvas ? "#171717" : "#3b82f6");
|
|
89
|
-
|
|
90
|
-
// Brand-mark ≠ action: logo inks — not decorative midnight/coral washes by default
|
|
91
|
-
const brandMarkHex =
|
|
92
|
-
pick("ink-black", "coral-pulse", "brand-mark", "logo", "wordmark", "charcoal", "deep-violet") ??
|
|
93
|
-
undefined;
|
|
94
|
-
|
|
95
|
-
const border = isLightCanvas
|
|
96
|
-
? (pick("frost", "hairline", "border", "ash", "carbon", "lilac-border", "slate") ?? "#e5e5e5")
|
|
97
|
-
: (pick("hairline", "border", "slate", "graphite", "surface-25", "smoke") ?? "#333333");
|
|
98
|
-
const mutedFg =
|
|
99
|
-
pick(
|
|
100
|
-
"stone",
|
|
101
|
-
"charcoal",
|
|
102
|
-
"graphite",
|
|
103
|
-
"steel",
|
|
104
|
-
"slate",
|
|
105
|
-
"muted",
|
|
106
|
-
"smoke",
|
|
107
|
-
"ash",
|
|
108
|
-
"fog",
|
|
109
|
-
"surface-50",
|
|
110
|
-
) ?? "#888888";
|
|
111
|
-
const card = isLightCanvas
|
|
112
|
-
? (pick("pure-white", "paper", "card-surface", "card") ?? "#ffffff")
|
|
113
|
-
: (pick("ink", "carbon", "off-black", "obsidian", "card") ?? bg);
|
|
114
|
-
|
|
115
|
-
const quiet = isLightCanvas
|
|
116
|
-
? (pick("sky-tint", "periwinkle-wash", "lavender-wash", "mist", "fog", "ash", "secondary") ??
|
|
117
|
-
border)
|
|
118
|
-
: (pick("graphite", "obsidian", "smoke", "secondary") ?? border);
|
|
119
|
-
|
|
120
|
-
const uiFont = pickUiFontFamily(ctx.font) ?? "Inter";
|
|
121
|
-
const displayFont = pickDisplayFontFamily(ctx.font);
|
|
122
|
-
|
|
123
|
-
let elevationPreset = ctx.recipeHints.elevationPreset ?? "soft";
|
|
124
|
-
if (elevationPreset === "key" && isLightCanvas) elevationPreset = "hairline";
|
|
125
|
-
|
|
126
|
-
const brand: BrandPackage = {
|
|
127
|
-
id: ctx.id,
|
|
128
|
-
name: ctx.siteName,
|
|
129
|
-
darkDefault: !isLightCanvas,
|
|
130
|
-
version: "0.1.0",
|
|
131
|
-
semantic: isLightCanvas
|
|
132
|
-
? {
|
|
133
|
-
background: tryHexToHsl(bg, "0 0% 98%"),
|
|
134
|
-
foreground: tryHexToHsl(fg, "0 0% 9%"),
|
|
135
|
-
card: tryHexToHsl(card, "0 0% 100%"),
|
|
136
|
-
cardForeground: tryHexToHsl(fg, "0 0% 9%"),
|
|
137
|
-
popover: tryHexToHsl(card, "0 0% 100%"),
|
|
138
|
-
popoverForeground: tryHexToHsl(fg, "0 0% 9%"),
|
|
139
|
-
primary: tryHexToHsl(primary, "0 0% 9%"),
|
|
140
|
-
primaryForeground: tryHexToHsl(card, "0 0% 100%"),
|
|
141
|
-
secondary: tryHexToHsl(quiet, "0 0% 92%"),
|
|
142
|
-
secondaryForeground: tryHexToHsl(fg, "0 0% 9%"),
|
|
143
|
-
muted: tryHexToHsl(quiet, "0 0% 92%"),
|
|
144
|
-
mutedForeground: tryHexToHsl(mutedFg, "0 0% 40%"),
|
|
145
|
-
accent: tryHexToHsl(quiet, "0 0% 92%"),
|
|
146
|
-
accentForeground: tryHexToHsl(fg, "0 0% 9%"),
|
|
147
|
-
destructive: "0 72% 51%",
|
|
148
|
-
destructiveForeground: "0 0% 100%",
|
|
149
|
-
border: tryHexToHsl(border, "0 0% 20%"),
|
|
150
|
-
input: tryHexToHsl(card, "0 0% 100%"),
|
|
151
|
-
ring: tryHexToHsl(primary, "0 0% 9%"),
|
|
152
|
-
}
|
|
153
|
-
: {
|
|
154
|
-
background: tryHexToHsl(bg, "0 0% 4%"),
|
|
155
|
-
foreground: tryHexToHsl(fg, "0 0% 98%"),
|
|
156
|
-
card: tryHexToHsl(card, "0 0% 8%"),
|
|
157
|
-
cardForeground: tryHexToHsl(fg, "0 0% 98%"),
|
|
158
|
-
popover: tryHexToHsl(card, "0 0% 8%"),
|
|
159
|
-
popoverForeground: tryHexToHsl(fg, "0 0% 98%"),
|
|
160
|
-
primary: tryHexToHsl(primary, "217 91% 60%"),
|
|
161
|
-
primaryForeground: tryHexToHsl(bg, "0 0% 4%"),
|
|
162
|
-
secondary: tryHexToHsl(border, "0 0% 20%"),
|
|
163
|
-
secondaryForeground: tryHexToHsl(fg, "0 0% 98%"),
|
|
164
|
-
muted: tryHexToHsl(card, "0 0% 8%"),
|
|
165
|
-
mutedForeground: tryHexToHsl(mutedFg, "0 0% 53%"),
|
|
166
|
-
accent: tryHexToHsl(border, "0 0% 20%"),
|
|
167
|
-
accentForeground: tryHexToHsl(primary, "217 91% 60%"),
|
|
168
|
-
destructive: "0 72% 51%",
|
|
169
|
-
destructiveForeground: "0 0% 100%",
|
|
170
|
-
border: tryHexToHsl(border, "0 0% 20%"),
|
|
171
|
-
input: tryHexToHsl(border, "0 0% 20%"),
|
|
172
|
-
ring: tryHexToHsl(primary, "217 91% 60%"),
|
|
173
|
-
},
|
|
174
|
-
recipe: buildRecipe({
|
|
175
|
-
buttonDefault: ctx.recipeHints.buttonDefault ?? "solid",
|
|
176
|
-
radii: {
|
|
177
|
-
button:
|
|
178
|
-
ctx.recipeHints.radii?.button ??
|
|
179
|
-
leafHex(ctx.radius, ["buttons"]) ??
|
|
180
|
-
leafHex(ctx.radius, ["md"]) ??
|
|
181
|
-
"0.375rem",
|
|
182
|
-
card:
|
|
183
|
-
ctx.recipeHints.radii?.card ??
|
|
184
|
-
leafHex(ctx.radius, ["cards"]) ??
|
|
185
|
-
leafHex(ctx.radius, ["xl"]) ??
|
|
186
|
-
leafHex(ctx.radius, ["lg"]) ??
|
|
187
|
-
"0.75rem",
|
|
188
|
-
badge: leafHex(ctx.radius, ["pills"]) ?? leafHex(ctx.radius, ["badges"]) ?? "9999px",
|
|
189
|
-
input: leafHex(ctx.radius, ["inputs"]) ?? ctx.recipeHints.radii?.button ?? "0.375rem",
|
|
190
|
-
},
|
|
191
|
-
elevationPreset,
|
|
192
|
-
density: ctx.recipeHints.density ?? "comfortable",
|
|
193
|
-
outlineBorder: isLightCanvas ? border : fg,
|
|
194
|
-
badgeDefault: brandMarkHex ? "muted" : "match-action",
|
|
195
|
-
}),
|
|
196
|
-
typography: {
|
|
197
|
-
fontSans: `'${uiFont}', ui-sans-serif, system-ui, sans-serif`,
|
|
198
|
-
...(displayFont ? { fontDisplay: `'${displayFont}', ui-serif, Georgia, serif` } : {}),
|
|
199
|
-
headingWeight: isLightCanvas ? 500 : 600,
|
|
200
|
-
},
|
|
201
|
-
extensions: {
|
|
202
|
-
...(typeof ctx.refero.url === "string" ? { sourceUrl: ctx.refero.url } : {}),
|
|
203
|
-
...(brandMarkHex ? { categories: { brand: brandMarkHex } } : {}),
|
|
204
|
-
notes: [
|
|
205
|
-
"Generic compile — verify primary + buttonDefault in Create Center.",
|
|
206
|
-
...(brandMarkHex
|
|
207
|
-
? ["Detected separate brand-mark color (categories.brand → --brand-mark)."]
|
|
208
|
-
: []),
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
return brand;
|
|
214
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* gsap design-language compile preset (stress fixture).
|
|
3
|
-
*/
|
|
4
|
-
import { leafHex } from "../compile-helpers";
|
|
5
|
-
import { tryHexToHsl } from "../hex-to-hsl";
|
|
6
|
-
import type { BrandPackage, ButtonDefaultStyle, Density } from "../types";
|
|
7
|
-
import type { CompileContext } from "./context";
|
|
8
|
-
import { buildRecipe } from "./recipe";
|
|
9
|
-
|
|
10
|
-
export function buildGsap(ctx: CompileContext): BrandPackage {
|
|
11
|
-
const canvas = ctx.colors["just-black"] ?? ctx.colors.canvas ?? "#0e100f";
|
|
12
|
-
const cream = ctx.colors["surface-cream"] ?? ctx.colors["cream-surface"] ?? "#fffce1";
|
|
13
|
-
const muted = ctx.colors["surface-50"] ?? "#7c7c6f";
|
|
14
|
-
const hairline = ctx.colors["surface-25"] ?? "#42433d";
|
|
15
|
-
const nested = ctx.colors["off-black"] ?? ctx.colors["nested-panel"] ?? "#191919";
|
|
16
|
-
const green = ctx.colors["shockingly-green"] ?? "#0ae448";
|
|
17
|
-
// DESIGN: do NOT promote shockingly-green to filled primary CTA
|
|
18
|
-
ctx.warnings.push(
|
|
19
|
-
"GSAP: shockingly-green is accent/link only — buttonDefault=outline (no solid green fill).",
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
const buttonDefault: ButtonDefaultStyle = ctx.recipeHints.buttonDefault ?? "gradient-stroke";
|
|
23
|
-
|
|
24
|
-
const brand: BrandPackage = {
|
|
25
|
-
id: "gsap",
|
|
26
|
-
name: "GSAP",
|
|
27
|
-
darkDefault: true,
|
|
28
|
-
version: "1.0.0",
|
|
29
|
-
semantic: {
|
|
30
|
-
// Primary for *links/accents* — filled solid CTAs are disabled by recipe
|
|
31
|
-
background: tryHexToHsl(canvas, "150 8% 6%"),
|
|
32
|
-
foreground: tryHexToHsl(cream, "54 100% 94%"),
|
|
33
|
-
card: tryHexToHsl(nested, "0 0% 10%"),
|
|
34
|
-
cardForeground: tryHexToHsl(cream, "54 100% 94%"),
|
|
35
|
-
popover: tryHexToHsl(nested, "0 0% 10%"),
|
|
36
|
-
popoverForeground: tryHexToHsl(cream, "54 100% 94%"),
|
|
37
|
-
primary: tryHexToHsl(green, "136 91% 47%"),
|
|
38
|
-
primaryForeground: tryHexToHsl(canvas, "150 8% 6%"),
|
|
39
|
-
secondary: tryHexToHsl(hairline, "60 5% 25%"),
|
|
40
|
-
secondaryForeground: tryHexToHsl(cream, "54 100% 94%"),
|
|
41
|
-
muted: tryHexToHsl(nested, "0 0% 10%"),
|
|
42
|
-
mutedForeground: tryHexToHsl(muted, "60 6% 46%"),
|
|
43
|
-
accent: tryHexToHsl(hairline, "60 5% 25%"),
|
|
44
|
-
accentForeground: tryHexToHsl(green, "136 91% 47%"),
|
|
45
|
-
destructive: tryHexToHsl(ctx.colors["lipstick-pink"] ?? "#f100cb", "310 100% 47%"),
|
|
46
|
-
destructiveForeground: tryHexToHsl(cream, "54 100% 94%"),
|
|
47
|
-
border: tryHexToHsl(hairline, "60 5% 25%"),
|
|
48
|
-
input: tryHexToHsl(hairline, "60 5% 25%"),
|
|
49
|
-
ring: tryHexToHsl(green, "136 91% 47%"),
|
|
50
|
-
info: tryHexToHsl(ctx.colors.blue ?? "#00bae2", "191 100% 44%"),
|
|
51
|
-
infoForeground: tryHexToHsl(canvas, "150 8% 6%"),
|
|
52
|
-
success: tryHexToHsl(green, "136 91% 47%"),
|
|
53
|
-
successForeground: tryHexToHsl(canvas, "150 8% 6%"),
|
|
54
|
-
},
|
|
55
|
-
recipe: buildRecipe({
|
|
56
|
-
buttonDefault,
|
|
57
|
-
radii: {
|
|
58
|
-
button: ctx.recipeHints.radii?.button ?? leafHex(ctx.radius, ["full"]) ?? "100px",
|
|
59
|
-
card: leafHex(ctx.radius, ["lg"]) ?? "8px",
|
|
60
|
-
},
|
|
61
|
-
elevationPreset: ctx.recipeHints.elevationPreset ?? "none",
|
|
62
|
-
density: (ctx.recipeHints.density ?? "comfortable") satisfies Density,
|
|
63
|
-
outlineBorder: cream,
|
|
64
|
-
primaryStrokeGradient: "linear-gradient(114.41deg, #0ae448 20.74%, #abff84 65.5%)",
|
|
65
|
-
}),
|
|
66
|
-
typography: {
|
|
67
|
-
fontSans: `'Mori', 'Inter Tight', 'DM Sans', ui-sans-serif, system-ui, sans-serif`,
|
|
68
|
-
fontDisplay: `'Mori', 'Inter Tight', ui-sans-serif, system-ui, sans-serif`,
|
|
69
|
-
headingWeight: 600,
|
|
70
|
-
faces: [
|
|
71
|
-
{
|
|
72
|
-
family: "Mori",
|
|
73
|
-
// Placeholder — Create Center replaces with tenant-uploaded WOFF2
|
|
74
|
-
src: [{ url: "/brand-assets/mori-regular.woff2", format: "woff2" }],
|
|
75
|
-
weight: 400,
|
|
76
|
-
display: "swap",
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
family: "Mori",
|
|
80
|
-
src: [{ url: "/brand-assets/mori-semibold.woff2", format: "woff2" }],
|
|
81
|
-
weight: 600,
|
|
82
|
-
display: "swap",
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
},
|
|
86
|
-
zones: {
|
|
87
|
-
product: {
|
|
88
|
-
caption: { fontSize: "14px", lineHeight: 1.4, fontWeight: 400, letterSpacing: "-0.14px" },
|
|
89
|
-
bodySm: { fontSize: "16px", lineHeight: 1.15, fontWeight: 400 },
|
|
90
|
-
body: { fontSize: "19px", lineHeight: 1.15, fontWeight: 400 },
|
|
91
|
-
bodyLg: { fontSize: "23px", lineHeight: 1.38, fontWeight: 400, letterSpacing: "-0.23px" },
|
|
92
|
-
subheading: {
|
|
93
|
-
fontSize: "34px",
|
|
94
|
-
lineHeight: 1.2,
|
|
95
|
-
fontWeight: 400,
|
|
96
|
-
letterSpacing: "-0.34px",
|
|
97
|
-
},
|
|
98
|
-
heading: {
|
|
99
|
-
fontSize: "44px",
|
|
100
|
-
lineHeight: 1.2,
|
|
101
|
-
fontWeight: 600,
|
|
102
|
-
letterSpacing: "-0.44px",
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
marketing: {
|
|
106
|
-
body: { fontSize: "19px", lineHeight: 1.15, fontWeight: 400 },
|
|
107
|
-
heading: {
|
|
108
|
-
fontSize: "66px",
|
|
109
|
-
lineHeight: 1.2,
|
|
110
|
-
fontWeight: 600,
|
|
111
|
-
letterSpacing: "-0.66px",
|
|
112
|
-
},
|
|
113
|
-
headingLg: {
|
|
114
|
-
fontSize: "101px",
|
|
115
|
-
lineHeight: 1,
|
|
116
|
-
fontWeight: 600,
|
|
117
|
-
letterSpacing: "-1.11px",
|
|
118
|
-
},
|
|
119
|
-
display: {
|
|
120
|
-
fontSize: "224px",
|
|
121
|
-
lineHeight: 0.9,
|
|
122
|
-
fontWeight: 600,
|
|
123
|
-
letterSpacing: "-4.48px",
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
extensions: {
|
|
128
|
-
categories: {
|
|
129
|
-
gsap: green,
|
|
130
|
-
scroll: ctx.colors.pink ?? "#fec5fb",
|
|
131
|
-
svg: ctx.colors.orangey ?? "#ff8709",
|
|
132
|
-
text: ctx.colors.lilac ?? "#9d95ff",
|
|
133
|
-
ui: ctx.colors.blue ?? "#00bae2",
|
|
134
|
-
other: ctx.colors["light-green"] ?? "#abff84",
|
|
135
|
-
},
|
|
136
|
-
displaySizePx: 224,
|
|
137
|
-
sourceUrl: typeof ctx.refero.url === "string" ? ctx.refero.url : "https://gsap.com",
|
|
138
|
-
notes: [
|
|
139
|
-
"Outline-first product controls; category ctx.colors are marketing extensions.",
|
|
140
|
-
"Replace typography.faces[].src with Create Center hosted ctx.font URLs.",
|
|
141
|
-
'Use data-zone="marketing" for hero/display; product zone for app chrome.',
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
return brand;
|
|
146
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { PresetId } from "../compile-helpers";
|
|
2
|
-
import type { BrandPackage } from "../types";
|
|
3
|
-
import type { CompileContext } from "./context";
|
|
4
|
-
import { buildGeneric } from "./generic";
|
|
5
|
-
import { buildGsap } from "./gsap";
|
|
6
|
-
import { buildLinear } from "./linear";
|
|
7
|
-
import { buildNotion } from "./notion";
|
|
8
|
-
import { buildRaycast } from "./raycast";
|
|
9
|
-
import { buildStripe } from "./stripe";
|
|
10
|
-
import { buildVanta } from "./vanta";
|
|
11
|
-
import { buildVercel } from "./vercel";
|
|
12
|
-
|
|
13
|
-
export type { CompileContext } from "./context";
|
|
14
|
-
|
|
15
|
-
const PRESET_BUILDERS: Record<
|
|
16
|
-
Exclude<PresetId, "generic">,
|
|
17
|
-
(ctx: CompileContext) => BrandPackage
|
|
18
|
-
> = {
|
|
19
|
-
linear: buildLinear,
|
|
20
|
-
gsap: buildGsap,
|
|
21
|
-
raycast: buildRaycast,
|
|
22
|
-
vercel: buildVercel,
|
|
23
|
-
notion: buildNotion,
|
|
24
|
-
stripe: buildStripe,
|
|
25
|
-
vanta: buildVanta,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export function buildPresetBrand(preset: PresetId, ctx: CompileContext): BrandPackage {
|
|
29
|
-
if (preset === "generic") return buildGeneric(ctx);
|
|
30
|
-
return PRESET_BUILDERS[preset](ctx);
|
|
31
|
-
}
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* linear design-language compile preset (stress fixture).
|
|
3
|
-
* Dual-mode: dark void default + light monochrome paper (acid-lime CTA both modes).
|
|
4
|
-
*/
|
|
5
|
-
import { tryHexToHsl } from "../hex-to-hsl";
|
|
6
|
-
import type { BrandPackage, BrandSemanticColors } from "../types";
|
|
7
|
-
import type { CompileContext } from "./context";
|
|
8
|
-
import { buildRecipe } from "./recipe";
|
|
9
|
-
|
|
10
|
-
function linearDarkSemantic(
|
|
11
|
-
voidC: string,
|
|
12
|
-
carbon: string,
|
|
13
|
-
graphite: string,
|
|
14
|
-
ash: string,
|
|
15
|
-
paper: string,
|
|
16
|
-
lime: string,
|
|
17
|
-
coral: string,
|
|
18
|
-
pulse: string,
|
|
19
|
-
colors: Record<string, string>,
|
|
20
|
-
): BrandSemanticColors {
|
|
21
|
-
return {
|
|
22
|
-
background: tryHexToHsl(voidC, "210 11% 4%"),
|
|
23
|
-
foreground: tryHexToHsl(paper, "0 0% 100%"),
|
|
24
|
-
card: tryHexToHsl(carbon, "210 6% 6%"),
|
|
25
|
-
cardForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
26
|
-
popover: tryHexToHsl(colors.obsidian ?? "#161718", "210 5% 9%"),
|
|
27
|
-
popoverForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
28
|
-
primary: tryHexToHsl(lime, "66 89% 54%"),
|
|
29
|
-
primaryForeground: tryHexToHsl(voidC, "210 11% 4%"),
|
|
30
|
-
secondary: tryHexToHsl(graphite, "220 7% 15%"),
|
|
31
|
-
secondaryForeground: tryHexToHsl(colors.mist ?? "#d0d6e0", "220 20% 85%"),
|
|
32
|
-
muted: tryHexToHsl(colors.obsidian ?? "#161718", "210 5% 9%"),
|
|
33
|
-
mutedForeground: tryHexToHsl(ash, "220 5% 41%"),
|
|
34
|
-
accent: tryHexToHsl(graphite, "220 7% 15%"),
|
|
35
|
-
accentForeground: tryHexToHsl(lime, "66 89% 54%"),
|
|
36
|
-
destructive: tryHexToHsl(coral, "0 79% 63%"),
|
|
37
|
-
destructiveForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
38
|
-
border: tryHexToHsl(graphite, "220 7% 15%"),
|
|
39
|
-
input: tryHexToHsl(graphite, "220 7% 15%"),
|
|
40
|
-
ring: tryHexToHsl(lime, "66 89% 54%"),
|
|
41
|
-
success: tryHexToHsl(pulse, "136 61% 40%"),
|
|
42
|
-
successForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
43
|
-
info: tryHexToHsl(colors["signal-teal"] ?? "#02b8cc", "187 98% 40%"),
|
|
44
|
-
infoForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Light shell — paper canvas, same acid-lime CTA, graphite chrome. */
|
|
49
|
-
function linearLightSemantic(
|
|
50
|
-
voidC: string,
|
|
51
|
-
ash: string,
|
|
52
|
-
paper: string,
|
|
53
|
-
lime: string,
|
|
54
|
-
coral: string,
|
|
55
|
-
pulse: string,
|
|
56
|
-
colors: Record<string, string>,
|
|
57
|
-
): BrandSemanticColors {
|
|
58
|
-
return {
|
|
59
|
-
background: "0 0% 100%",
|
|
60
|
-
foreground: tryHexToHsl(voidC, "210 11% 4%"),
|
|
61
|
-
card: "0 0% 98%",
|
|
62
|
-
cardForeground: tryHexToHsl(voidC, "210 11% 4%"),
|
|
63
|
-
popover: "0 0% 100%",
|
|
64
|
-
popoverForeground: tryHexToHsl(voidC, "210 11% 4%"),
|
|
65
|
-
primary: tryHexToHsl(lime, "66 89% 54%"),
|
|
66
|
-
primaryForeground: tryHexToHsl(voidC, "210 11% 4%"),
|
|
67
|
-
secondary: "220 14% 96%",
|
|
68
|
-
secondaryForeground: tryHexToHsl(voidC, "210 11% 4%"),
|
|
69
|
-
muted: "220 14% 96%",
|
|
70
|
-
mutedForeground: tryHexToHsl(ash, "220 5% 41%"),
|
|
71
|
-
accent: "220 14% 96%",
|
|
72
|
-
accentForeground: tryHexToHsl(voidC, "210 11% 4%"),
|
|
73
|
-
destructive: tryHexToHsl(coral, "0 79% 63%"),
|
|
74
|
-
destructiveForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
75
|
-
border: "220 13% 91%",
|
|
76
|
-
input: "0 0% 100%",
|
|
77
|
-
ring: tryHexToHsl(lime, "66 89% 54%"),
|
|
78
|
-
success: tryHexToHsl(pulse, "136 61% 40%"),
|
|
79
|
-
successForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
80
|
-
info: tryHexToHsl(colors["signal-teal"] ?? "#02b8cc", "187 98% 40%"),
|
|
81
|
-
infoForeground: tryHexToHsl(paper, "0 0% 100%"),
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function buildLinear(ctx: CompileContext): BrandPackage {
|
|
86
|
-
const voidC = ctx.colors.void ?? ctx.colors["just-black"] ?? "#08090a";
|
|
87
|
-
const carbon = ctx.colors.carbon ?? "#0f1011";
|
|
88
|
-
const graphite = ctx.colors.graphite ?? "#23252a";
|
|
89
|
-
const ash = ctx.colors.ash ?? "#62666d";
|
|
90
|
-
const paper = ctx.colors.paper ?? "#ffffff";
|
|
91
|
-
const lime = ctx.colors["acid-lime"] ?? "#e4f222";
|
|
92
|
-
const coral = ctx.colors["coral-red"] ?? "#eb5757";
|
|
93
|
-
const pulse = ctx.colors["pulse-green"] ?? "#27a644";
|
|
94
|
-
|
|
95
|
-
const dark = linearDarkSemantic(
|
|
96
|
-
voidC,
|
|
97
|
-
carbon,
|
|
98
|
-
graphite,
|
|
99
|
-
ash,
|
|
100
|
-
paper,
|
|
101
|
-
lime,
|
|
102
|
-
coral,
|
|
103
|
-
pulse,
|
|
104
|
-
ctx.colors,
|
|
105
|
-
);
|
|
106
|
-
const light = linearLightSemantic(voidC, ash, paper, lime, coral, pulse, ctx.colors);
|
|
107
|
-
|
|
108
|
-
const brand: BrandPackage = {
|
|
109
|
-
id: "linear",
|
|
110
|
-
name: "Linear",
|
|
111
|
-
darkDefault: true,
|
|
112
|
-
version: "1.0.0",
|
|
113
|
-
semantic: dark,
|
|
114
|
-
modes: {
|
|
115
|
-
dark: { semantic: dark },
|
|
116
|
-
light: { semantic: light },
|
|
117
|
-
},
|
|
118
|
-
recipe: buildRecipe({
|
|
119
|
-
buttonDefault: "solid",
|
|
120
|
-
radii: { button: "6px", card: "12px" },
|
|
121
|
-
elevationPreset: "soft",
|
|
122
|
-
density: "compact",
|
|
123
|
-
}),
|
|
124
|
-
typography: {
|
|
125
|
-
fontSans: `'Inter Variable', 'Inter', ui-sans-serif, system-ui, sans-serif`,
|
|
126
|
-
fontMono: `'Berkeley Mono', 'JetBrains Mono', ui-monospace, monospace`,
|
|
127
|
-
headingWeight: 510,
|
|
128
|
-
faces: [
|
|
129
|
-
{
|
|
130
|
-
family: "Inter Variable",
|
|
131
|
-
src: [
|
|
132
|
-
{
|
|
133
|
-
url: "https://cdn.jsdelivr.net/fontsource/fonts/inter:vf@latest/latin-wght-normal.woff2",
|
|
134
|
-
format: "woff2",
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
weight: "100 900",
|
|
138
|
-
display: "swap",
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
},
|
|
142
|
-
zones: {
|
|
143
|
-
product: {
|
|
144
|
-
caption: { fontSize: "13px", lineHeight: 1.2, fontWeight: 400 },
|
|
145
|
-
bodySm: { fontSize: "14px", lineHeight: 1.5, fontWeight: 400 },
|
|
146
|
-
body: { fontSize: "14px", lineHeight: 1.5, fontWeight: 400 },
|
|
147
|
-
bodyLg: { fontSize: "16px", lineHeight: 1.5, fontWeight: 400 },
|
|
148
|
-
heading: {
|
|
149
|
-
fontSize: "24px",
|
|
150
|
-
lineHeight: 1.25,
|
|
151
|
-
fontWeight: 510,
|
|
152
|
-
letterSpacing: "-0.012em",
|
|
153
|
-
},
|
|
154
|
-
display: {
|
|
155
|
-
fontSize: "32px",
|
|
156
|
-
lineHeight: 1.15,
|
|
157
|
-
fontWeight: 510,
|
|
158
|
-
letterSpacing: "-0.022em",
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
marketing: {
|
|
162
|
-
body: { fontSize: "15px", lineHeight: 1.6, fontWeight: 400 },
|
|
163
|
-
heading: {
|
|
164
|
-
fontSize: "48px",
|
|
165
|
-
lineHeight: 1,
|
|
166
|
-
fontWeight: 510,
|
|
167
|
-
letterSpacing: "-0.022em",
|
|
168
|
-
},
|
|
169
|
-
display: {
|
|
170
|
-
fontSize: "72px",
|
|
171
|
-
lineHeight: 1,
|
|
172
|
-
fontWeight: 510,
|
|
173
|
-
letterSpacing: "-0.022em",
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
extensions: {
|
|
178
|
-
sourceUrl: typeof ctx.refero.url === "string" ? ctx.refero.url : "https://linear.app",
|
|
179
|
-
notes: ["Dual-mode: dark void default + light paper; acid-lime solid CTA in both modes."],
|
|
180
|
-
},
|
|
181
|
-
};
|
|
182
|
-
return brand;
|
|
183
|
-
}
|