@estebanruano/design-tokens 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,379 @@
1
+ # Design System Tokens
2
+
3
+ Single source of truth for all design tokens. One `pnpm run build` generates platform-specific outputs for Web, Android, iOS, Flutter, and Compose Multiplatform.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ pnpm install
9
+
10
+ # Full pipeline: markdown → token JSONs → all platform outputs
11
+ pnpm run sync
12
+
13
+ # Or run each step separately:
14
+ pnpm run parse # markdown → token JSONs only
15
+ pnpm run build # token JSONs → platform outputs only
16
+ ```
17
+
18
+ Outputs land in `dist/` (Gradle uses `./build/`, so token outputs use `dist/` to avoid clashes):
19
+
20
+ ```
21
+ dist/
22
+ ├── web/
23
+ │ ├── tokens.css # CSS custom properties
24
+ │ └── tokens.js # ES6 JavaScript constants
25
+ ├── android/
26
+ │ ├── colors.xml # Android color resources
27
+ │ ├── dimens.xml # Android dimension resources
28
+ │ └── font_dimens.xml # Android font dimensions
29
+ ├── ios/
30
+ │ └── DesignTokens.swift # Swift constants (UIColor)
31
+ ├── flutter/
32
+ │ └── design_tokens.dart # Dart constants (Color)
33
+ ├── compose/
34
+ │ └── DesignTokens.kt # Kotlin object (Compose Color/Dp)
35
+ └── json/
36
+ └── tokens.json # Flat JSON (debugging / other tools)
37
+ ```
38
+
39
+ ## How It Works
40
+
41
+ The pipeline has two stages:
42
+
43
+ **Stage 1 — `pnpm run parse`** runs `md-to-tokens.mjs`, which reads `design-system-foundations.md`, copies the `**Version:**` semver into `package.json`, extracts every JSON code block, converts to DTCG format (`$value` / `$type`), and writes each token category to its own file under `tokens/`.
44
+
45
+ **Stage 2 — `pnpm run build`** runs Style Dictionary, which reads all `tokens/**/*.json` files and generates platform-specific outputs in `dist/`.
46
+
47
+ **`pnpm run sync`** runs both stages in sequence — this is the single command the design team needs.
48
+
49
+ ### Workflow
50
+
51
+ ```
52
+ design-system-foundations.md ← Designers edit this (the human-readable source)
53
+
54
+ ▼ pnpm run parse
55
+ tokens/**/*.json ← DTCG-format JSON (auto-generated)
56
+
57
+ ▼ pnpm run build
58
+ dist/ ← Platform outputs (auto-generated; commit with PR)
59
+ ├── web/tokens.css
60
+ ├── web/tokens.js
61
+ ├── android/colors.xml
62
+ ├── android/dimens.xml
63
+ ├── ios/DesignTokens.swift
64
+ ├── flutter/design_tokens.dart
65
+ ├── compose/DesignTokens.kt
66
+ └── json/tokens.json
67
+ ```
68
+
69
+ ### Versioning (releases)
70
+
71
+ Release numbers for **npm** (`@estebanruano/design-tokens`), **Android Maven** (`tokensVersion`), and the `version` field in `package.json` all come from the `**Version:** x.y.z` line at the top of `design-system-foundations.md`. **`pnpm run parse`** and **`pnpm run sync`** write that value into `package.json`; Gradle uses `package.json` when `-PtokensVersion` / `TOKENS_VERSION` are unset. Bump `**Version:**` for each release (npm and GitHub Packages reject duplicate versions).
72
+
73
+ ## Using tokens on the web
74
+
75
+ Web artifacts are **`dist/web/tokens.css`** (CSS custom properties on `:root`) and **`dist/web/tokens.js`** (named ES module exports, e.g. `ColorPrimary500`). **`dist/json/tokens.json`** is a flat JSON dump for scripts or design tooling.
76
+
77
+ ### In this monorepo / locally
78
+
79
+ Point your app at the folder (or run `pnpm run sync` after token edits):
80
+
81
+ ```bash
82
+ pnpm add "design-tokens@file:../design-system"
83
+ # or: npm install file:../path/to/design-system
84
+ ```
85
+
86
+ Then import CSS once (global variables) and/or use JS constants:
87
+
88
+ ```ts
89
+ import '@estebanruano/design-tokens/css';
90
+ import { ColorPrimary500, Spacing4 } from '@estebanruano/design-tokens';
91
+ ```
92
+
93
+ ```css
94
+ /* Bundlers that resolve package exports */
95
+ @import '@estebanruano/design-tokens/css';
96
+
97
+ .my-button {
98
+ background: var(--color-primary-500);
99
+ padding: var(--spacing-4);
100
+ }
101
+ ```
102
+
103
+ ### Published npm package (recommended for apps)
104
+
105
+ The package name is **`@estebanruano/design-tokens`**. The published version is the `**Version:**` line in `design-system-foundations.md` (copied into `package.json` when you run **`pnpm run sync`** before **Publish web tokens (npm)**). Install from the public npm registry:
106
+
107
+ ```bash
108
+ pnpm add @estebanruano/design-tokens
109
+ # or: npm install @estebanruano/design-tokens
110
+ ```
111
+
112
+ Use the same **`import '@estebanruano/design-tokens/css'`** and **`import { … } from '@estebanruano/design-tokens'`** paths; **`@estebanruano/design-tokens/json`** resolves to the flat **`tokens.json`** if you need it in Node or build scripts.
113
+
114
+ #### npm release checklist (maintainers)
115
+
116
+ 1. Bump **`**Version:**`** in **`design-system-foundations.md`** (and merge so **`main`** has the release).
117
+ 2. Run **`pnpm run sync`** locally or rely on CI / **Sync tokens from markdown** so **`package.json`**, **`tokens/`**, and **`dist/`** match the doc; commit any changes.
118
+ 3. **First time only:** bootstrap the package with **`npm publish --access public`** from a machine logged into npm (see **[First publish on npm (bootstrap)](#first-publish-on-npm-bootstrap)**), then configure **Trusted publishing** on npm for workflow **`publish-web.yml`**.
119
+ 4. **Ongoing:** GitHub → **Actions** → **Publish web tokens (npm)** → **Run workflow** on **`main`** (OIDC; no **`NPM_TOKEN`**).
120
+
121
+ ### Fetching without a package manager (CDN)
122
+
123
+ After a version is on [npm](https://www.npmjs.com/), CDNs mirror tarballs, for example:
124
+
125
+ - `https://cdn.jsdelivr.net/npm/@estebanruano/design-tokens@x.y.z/dist/web/tokens.css`
126
+ - `https://cdn.jsdelivr.net/npm/@estebanruano/design-tokens@x.y.z/dist/web/tokens.js` (ES module; use `type="module"` in a script tag only if your page setup supports it)
127
+
128
+ Pin the version in the URL for reproducible builds. For production SPAs, prefer installing the package so your bundler fingerprints assets and you stay on supported import semantics.
129
+
130
+ ## Token Structure
131
+
132
+ ```
133
+ tokens/
134
+ ├── color/
135
+ │ ├── primary.json # Brand primary scale (00–800)
136
+ │ ├── secondary.json # Brand secondary scale (00–800)
137
+ │ ├── neutral.json # Gray scale (0–1000)
138
+ │ └── semantic.json # Success, warning, error, info
139
+ ├── typography/
140
+ │ └── scale.json # Font families, weights, sizes, line heights
141
+ ├── spacing/
142
+ │ └── spacing.json # 4px base unit scale (0–40)
143
+ ├── radius/
144
+ │ └── radius.json # Border radii (none–full)
145
+ ├── shadow/
146
+ │ └── shadow.json # Elevation levels (sm–xl)
147
+ ├── motion/
148
+ │ └── motion.json # Duration + easing curves
149
+ └── opacity/
150
+ └── opacity.json # Disabled, hover, pressed, focus, scrim
151
+ ```
152
+
153
+ ## How to Update Tokens
154
+
155
+ ### For engineers (Claude Code)
156
+ ```bash
157
+ claude "Update primary-500 to #EA580C in tokens/color/primary.json, rebuild, commit and push"
158
+ ```
159
+
160
+ ### For designers (GitHub Web UI)
161
+ 1. Generate updated JSON in Claude chat/Claude Design
162
+ 2. Go to the file on GitHub → Edit → paste new content
163
+ 3. Create branch + open PR → CI validates → reviewer merges
164
+
165
+ ### For non-technical team (Cloud automation)
166
+ 1. Save updated JSON file to shared OneDrive/Google Drive folder
167
+ 2. n8n automation validates and opens a PR automatically
168
+
169
+ ## Adding a New Token
170
+
171
+ 1. Add the token to the appropriate JSON file under `tokens/`
172
+ 2. Follow the DTCG-compatible format:
173
+ ```json
174
+ {
175
+ "token-name": {
176
+ "$value": "#F97316",
177
+ "$type": "color",
178
+ "$description": "Optional description"
179
+ }
180
+ }
181
+ ```
182
+ 3. Run `pnpm run sync` to verify all platforms generate correctly
183
+ 4. Commit and push — CI validates; merge to `main`, then run **Publish Android library** and/or **Publish web tokens (npm)** manually when you want a Maven or npm release (see below)
184
+
185
+ ## Automation (GitHub Actions)
186
+
187
+ This repo can run the full “edit markdown → tokens → PR → registries” loop on GitHub:
188
+
189
+ | Workflow | When | What it does |
190
+ |----------|------|----------------|
191
+ | **Sync tokens from markdown** | Push that changes `design-system-foundations.md` | Runs `pnpm run sync`, commits `tokens/`, `dist/`, and `package.json` (when changed) to the same branch, then opens a PR into `main` if the branch is not `main` and no open PR exists. On `main`, it pushes the sync commit directly. |
192
+ | **CI** | Pull requests to `main` | `pnpm run sync` then fails if anything drifts from the commit; builds `:design-tokens-android` with Gradle. |
193
+ | **Publish Android library** | Manual only: Actions → workflow → **Run workflow** (typically from `main`) | `pnpm run sync`, then `./gradlew :design-tokens-android:publish` to **GitHub Packages**. Maven **groupId**, **artifactId**, and Android **namespace** are set in **`gradle.properties`**. **Version** = `**Version:**` in `design-system-foundations.md` (via `package.json` after sync; override with `-PtokensVersion` / `TOKENS_VERSION` if needed). |
194
+ | **Publish web tokens (npm)** | Manual only: Actions → workflow → **Run workflow** (typically from `main`) | `pnpm run sync`, then **`npm publish`** (npm ≥ 11.5.1) to **registry.npmjs.org** using **[Trusted Publishing](https://docs.npmjs.com/trusted-publishers/)** (OIDC). Requires **`id-token: write`** in the workflow (already set) and a one-time **Trusted Publisher** config on npm for workflow file **`publish-web.yml`**. **Version** comes from the foundations markdown (see **Versioning** above). |
195
+
196
+ ### Deployment workflow
197
+
198
+ Deployments are **manual** for Android (Maven) and web (npm). Nothing publishes automatically when you merge to `main`. Use this sequence when you want consumers to pick up a new release.
199
+
200
+ **Workflow files** (under `.github/workflows/`):
201
+
202
+ | File | Role |
203
+ |------|------|
204
+ | `sync-tokens-from-md.yml` | Regenerates artifacts after markdown edits (automatic on push). |
205
+ | `ci.yml` | Validates PRs: regenerated tree must match the commit. |
206
+ | `publish-android.yml` | Publishes the Android AAR to **GitHub Packages** (Maven). |
207
+ | `publish-web.yml` | Publishes **`@estebanruano/design-tokens`** to **npm** via **OIDC** ([Trusted publishing](https://docs.npmjs.com/trusted-publishers/)). |
208
+
209
+ **Recommended release path**
210
+
211
+ 1. **Change tokens or version** in `design-system-foundations.md` (including `**Version:**` when you intend a new Maven/npm release — see **Versioning (releases)** above).
212
+ 2. **Push** your branch. **Sync tokens from markdown** runs: it executes `pnpm run sync`, commits generated files, and either **opens a PR to `main`** (feature branches) or **pushes to `main`** (if you edited on `main` directly).
213
+ 3. **Review and merge** the PR when CI is green (or confirm the direct push on `main` if you used that path).
214
+ 4. **Publish** — only after `main` contains the version and artifacts you want live:
215
+ - **Android:** GitHub → **Actions** → **Publish Android library** → **Run workflow**, select **`main`** (or a release branch if you use one). Uses `GITHUB_TOKEN`; no extra secret.
216
+ - **Web:** GitHub → **Actions** → **Publish web tokens (npm)** → **Run workflow**, select **`main`**. Uses **OIDC trusted publishing** (no `NPM_TOKEN`); complete the [one-time npm setup](#npm-trusted-publishing-setup) below.
217
+
218
+ Both publish workflows run **`pnpm run sync`** first, so the published bits always match the checked-out commit (including `**Version:**` → `package.json`). The npm job then runs **`npm publish`** so the npm CLI can use OIDC (see [Trusted publishing](https://docs.npmjs.com/trusted-publishers/)).
219
+
220
+ **If publish fails with 409 / duplicate version**
221
+
222
+ The Maven or npm coordinate for that version already exists. Bump `**Version:**` in the foundations doc, merge a sync commit, then run the publish workflow again.
223
+
224
+ ```mermaid
225
+ flowchart TD
226
+ A[Edit design-system-foundations.md] --> B[Push]
227
+ B --> C[Sync tokens from markdown]
228
+ C --> D{Branch is main?}
229
+ D -->|No| E[Bot commits + opens PR to main]
230
+ D -->|Yes| F[Bot commits to main]
231
+ E --> G[Merge PR after CI]
232
+ F --> H[main up to date]
233
+ G --> H
234
+ H --> I[Run publish workflows from main when ready]
235
+ I --> J[Publish Android library → GitHub Packages Maven]
236
+ I --> K[Publish web tokens npm → registry.npmjs.org]
237
+ ```
238
+
239
+ **Repo settings you need**
240
+
241
+ 1. **Actions → General → Workflow permissions**: allow **Read and write** so the sync job can push commits and open PRs.
242
+ 2. **Android publishing**: GitHub Packages Maven uses `GITHUB_TOKEN` from Actions (`packages: write` on the Android publish workflow). Bump `**Version:**` in `design-system-foundations.md` for every new Maven release — **the same version cannot be published twice** (Gradle will fail with **HTTP 409 Conflict** if you try).
243
+
244
+ #### npm: Trusted publishing setup
245
+
246
+ Web publishes use **[npm Trusted Publishing](https://docs.npmjs.com/trusted-publishers/)** from GitHub Actions (no long-lived **`NPM_TOKEN`**). Requirements from npm: **Node ≥ 22.14**, **npm CLI ≥ 11.5.1** (the workflow upgrades npm before publish).
247
+
248
+ ##### First publish on npm (bootstrap)
249
+
250
+ The public registry has no **`@estebanruano/design-tokens`** until the first successful **`npm publish`**. Do this **before** opening Trusted publishing in the npm UI (that screen needs an existing package). Run as an npm user (or org) that is allowed to publish under the **`@estebanruano`** scope. Use **Node ≥ 18.12** for `pnpm`:
251
+
252
+ ```bash
253
+ cd /path/to/design-system
254
+ nvm use 22 # or another Node ≥ 18.12 (pnpm); ≥ 22.14 to match CI
255
+ pnpm install --frozen-lockfile
256
+ pnpm run sync
257
+ npm login # browser login, or use a granular publish token (see npm docs)
258
+ npm publish --access public # creates the package; version = package.json (from **Version:** in the MD)
259
+ ```
260
+
261
+ Check with **`npm view @estebanruano/design-tokens version`**. If publish fails with **403**, your npm user does not own the **`estebanruano`** scope — create an npm org or change **`package.json` → `name`** to a scope you control. If you see **404 Scope not found**, the **`@estebanruano`** scope does not exist on npm yet: create an organization named **`estebanruano`** at [npmjs.com/org/create](https://www.npmjs.com/org/create) (and add your user), **or** rename the package to a scope you already have (for example **`@<your-npm-username>/design-tokens`**) and update imports in apps + Trusted publishing after the first publish.
262
+
263
+ ##### Connect GitHub Actions (Trusted publishing)
264
+
265
+ After the package exists on npm:
266
+
267
+ 1. On **[npmjs.com](https://www.npmjs.com/)** → package **`@estebanruano/design-tokens`** → **Settings** → **Trusted publishing** → choose **GitHub Actions**.
268
+ 2. Set the publisher so values match **exactly** (npm does not validate until publish):
269
+ - **Repository:** `esteban505r/design-system` (or your fork’s `owner/name` — then set **`package.json` → `repository.url`** to that repo’s HTTPS URL, [required by npm](https://docs.npmjs.com/trusted-publishers/)).
270
+ - **Workflow filename:** `publish-web.yml` (filename only, including `.yml`).
271
+ 3. Run **Actions → Publish web tokens (npm)** on **`main`** to confirm OIDC works; then you can [revoke](https://docs.npmjs.com/revoking-access-tokens) any bootstrap publish token you no longer need.
272
+ 4. Optional hardening: under package **Publishing access**, npm recommends restricting token-based publishes ([docs](https://docs.npmjs.com/trusted-publishers/)).
273
+
274
+ If **Publish web tokens (npm)** fails with **ENEEDAUTH** or trusted-publisher errors, re-check the workflow filename, repository name, and **`repository.url`** in **`package.json`** (`https://github.com/esteban505r/design-system.git` for this upstream repo).
275
+
276
+ **Android apps** add the GitHub Packages Maven URL and dependency (replace `OWNER/REPO`):
277
+
278
+ ```kotlin
279
+ repositories {
280
+ maven {
281
+ url = uri("https://maven.pkg.github.com/OWNER/REPO")
282
+ credentials {
283
+ username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
284
+ password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
285
+ }
286
+ }
287
+ }
288
+
289
+ dependencies {
290
+ implementation("com.estebanruano:tokens-android:1.0.2")
291
+ }
292
+ ```
293
+
294
+ Use the same **`mavenGroupId`**, **`mavenArtifactId`**, and release version (`**Version:**` / `package.json`) as in this design-system repo’s **`gradle.properties`** / **`design-system-foundations.md`** (e.g. `com.estebanruano:tokens-android`).
295
+
296
+ **Authenticate for GitHub Packages** (local machine): add to `~/.gradle/gradle.properties` (do not commit):
297
+
298
+ ```properties
299
+ gpr.user=YOUR_GITHUB_USERNAME
300
+ gpr.key=YOUR_PAT_WITH_read:packages
301
+ ```
302
+
303
+ In **CI** for the consuming app, inject the same values (e.g. repository secrets mapped to env vars or `ORG_GRADLE_PROJECT_gpr.*` so Gradle picks them up).
304
+
305
+ ### Using tokens in Android app code
306
+
307
+ The **`tokens-android`** artifact is a normal **`com.android.library`**: it ships **resource XML** only (colors, dimens, font dimens, etc.). After `implementation(...)`, those resources are **merged** into your app module, so you reference them like any other library resource.
308
+
309
+ **Resource names** match the generated files in this repo under **`dist/android/`** (e.g. `colors.xml`, `dimens.xml`). Typical names look like `color_primary_500`, `color_neutral_500`, `spacing_4`, `radius_md` — always confirm the exact `name="…"` in those files when you add or rename tokens.
310
+
311
+ **XML layouts**
312
+
313
+ ```xml
314
+ <TextView
315
+ android:layout_width="wrap_content"
316
+ android:layout_height="wrap_content"
317
+ android:textColor="@color/color_primary_500"
318
+ android:padding="@dimen/spacing_4" />
319
+ ```
320
+
321
+ **`styles.xml` / Material theme**
322
+
323
+ ```xml
324
+ <style name="Theme.MyApp" parent="Theme.Material3.DayNight.NoActionBar">
325
+ <item name="colorPrimary">@color/color_primary_500</item>
326
+ <item name="colorOnPrimary">@color/color_neutral_0</item>
327
+ </style>
328
+ ```
329
+
330
+ **Kotlin (Views, no Compose)** — use your **application module** `R` (it includes merged library resources):
331
+
332
+ ```kotlin
333
+ import androidx.core.content.ContextCompat
334
+ import com.yourapp.R
335
+
336
+ val color = ContextCompat.getColor(context, R.color.color_primary_500)
337
+ view.setBackgroundColor(color)
338
+
339
+ val paddingPx = resources.getDimensionPixelSize(R.dimen.spacing_4)
340
+ ```
341
+
342
+ **Jetpack Compose**
343
+
344
+ ```kotlin
345
+ import androidx.compose.ui.res.colorResource
346
+ import androidx.compose.ui.res.dimensionResource
347
+ import com.yourapp.R
348
+
349
+ @Composable
350
+ fun BrandSurface() {
351
+ Surface(color = colorResource(R.color.color_primary_500)) {
352
+ // …
353
+ }
354
+ }
355
+ ```
356
+
357
+ `dimensionResource(R.dimen.…)` follows normal Android `dimen` semantics; check the AndroidX Compose docs for your BOM to see how values map to **`Dp`** in composables.
358
+
359
+ **`R` class / non-transitive R**
360
+
361
+ With **`android.nonTransitiveRClass=true`**, you still normally use **`com.yourapp.R`** in the **app** module for merged resources from dependencies. The library’s own namespace (`tokensAndroidNamespace` in `gradle.properties`) is mainly for the AAR’s internal `R` / manifest, not something you must import in app code unless you choose to.
362
+
363
+ **Name clashes**
364
+
365
+ If your app defines the same resource name (e.g. `color_primary_500`) in `res/values/`, the **app resource overrides** the library. To avoid collisions long-term, add a stable prefix in the token build (e.g. `ds_color_primary_500`) in Style Dictionary / naming convention.
366
+
367
+ Local Gradle in **this** repo copies `dist/android/*.xml` into `design-tokens-android` on each `preBuild` — run **`pnpm run sync`** before `./gradlew` if `dist/android` is missing.
368
+
369
+ ## Adding a New Platform
370
+
371
+ Edit `sd.config.mjs` and add a new platform entry. See [Style Dictionary docs](https://styledictionary.com) for available formats and transform groups.
372
+
373
+ ## Semver guidelines (token changes)
374
+
375
+ When you bump `**Version:**` in the foundations doc for a release, align the bump with the kind of token change (same ideas as [semver](https://semver.org/)):
376
+
377
+ - **Major** (2.0.0): Breaking change — token renamed or removed
378
+ - **Minor** (1.1.0): New tokens added
379
+ - **Patch** (1.0.1): Token value changed
@@ -0,0 +1,104 @@
1
+ {
2
+ "ColorNeutral0": "#fffaf7",
3
+ "ColorNeutral50": "#f7efea",
4
+ "ColorNeutral100": "#eadfd5",
5
+ "ColorNeutral200": "#d9c8bb",
6
+ "ColorNeutral300": "#bea89a",
7
+ "ColorNeutral400": "#948272",
8
+ "ColorNeutral500": "#6f5e52",
9
+ "ColorNeutral600": "#51443c",
10
+ "ColorNeutral700": "#3a302a",
11
+ "ColorNeutral800": "#241e1a",
12
+ "ColorNeutral900": "#0f0d0b",
13
+ "ColorNeutral1000": "#000000",
14
+ "ColorPrimary50": "#ffedd5",
15
+ "ColorPrimary100": "#fed7aa",
16
+ "ColorPrimary200": "#fdba74",
17
+ "ColorPrimary300": "#fb923c",
18
+ "ColorPrimary400": "#f97316",
19
+ "ColorPrimary500": "#ea580c",
20
+ "ColorPrimary600": "#c2410c",
21
+ "ColorPrimary700": "#9a3412",
22
+ "ColorPrimary800": "#7c2d12",
23
+ "ColorPrimary00": "#fff8f3",
24
+ "ColorSecondary50": "#fef3c7",
25
+ "ColorSecondary100": "#fde68a",
26
+ "ColorSecondary200": "#fcd34d",
27
+ "ColorSecondary300": "#fbbf24",
28
+ "ColorSecondary400": "#f59e0b",
29
+ "ColorSecondary500": "#d97706",
30
+ "ColorSecondary600": "#b45309",
31
+ "ColorSecondary700": "#92400e",
32
+ "ColorSecondary800": "#78350f",
33
+ "ColorSecondary00": "#fffbeb",
34
+ "ColorSemanticSuccessLight": "#fce7d4",
35
+ "ColorSemanticSuccess": "#c45c26",
36
+ "ColorSemanticSuccessDark": "#7a3a18",
37
+ "ColorSemanticWarningLight": "#fef9c3",
38
+ "ColorSemanticWarning": "#f59e0b",
39
+ "ColorSemanticWarningDark": "#b45309",
40
+ "ColorSemanticErrorLight": "#ffdad6",
41
+ "ColorSemanticError": "#d84315",
42
+ "ColorSemanticErrorDark": "#8b2500",
43
+ "ColorSemanticInfoLight": "#fff4e6",
44
+ "ColorSemanticInfo": "#ff8f00",
45
+ "ColorSemanticInfoDark": "#e65100",
46
+ "DurationInstant": "100ms",
47
+ "DurationFast": "150ms",
48
+ "DurationNormal": "300ms",
49
+ "DurationSlow": "500ms",
50
+ "EasingDefault": "cubic-bezier(0.4, 0, 0.2, 1)",
51
+ "EasingIn": "cubic-bezier(0.4, 0, 1, 1)",
52
+ "EasingOut": "cubic-bezier(0, 0, 0.2, 1)",
53
+ "OpacityDisabled": 0.38,
54
+ "OpacityHover": 0.08,
55
+ "OpacityPressed": 0.12,
56
+ "OpacityFocus": 0.12,
57
+ "OpacityScrim": 0.32,
58
+ "RadiusNone": 0,
59
+ "RadiusSm": "4px",
60
+ "RadiusMd": "8px",
61
+ "RadiusLg": "12px",
62
+ "RadiusXl": "16px",
63
+ "Radius2xl": "24px",
64
+ "RadiusFull": "9999px",
65
+ "ElevationHairline": "0px 1px 2px rgba(0,0,0,0.05)",
66
+ "ElevationCard": "0px 2px 8px rgba(0,0,0,0.08)",
67
+ "ElevationPopover": "0px 4px 16px rgba(0,0,0,0.10)",
68
+ "ElevationModal": "0px 8px 32px rgba(0,0,0,0.12)",
69
+ "ShadowSm": "0 1px 2px rgba(0,0,0,0.05)",
70
+ "ShadowMd": "0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06)",
71
+ "ShadowLg": "0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05)",
72
+ "ShadowXl": "0 20px 25px rgba(0,0,0,0.1), 0 8px 10px rgba(0,0,0,0.04)",
73
+ "Spacing1": "4px",
74
+ "Spacing2": "8px",
75
+ "Spacing3": "12px",
76
+ "Spacing4": "16px",
77
+ "Spacing5": "20px",
78
+ "Spacing6": "24px",
79
+ "Spacing8": "32px",
80
+ "Spacing10": "40px",
81
+ "Spacing12": "48px",
82
+ "Spacing16": "64px",
83
+ "Spacing24": "96px",
84
+ "FontFamilyDisplay": "Montserrat",
85
+ "FontFamilyBody": "Montserrat",
86
+ "FontFamilyMono": "Montserrat",
87
+ "FontSizeHero": "72px",
88
+ "FontSizeH1": "40px",
89
+ "FontSizeH2": "32px",
90
+ "FontSizeH3": "24px",
91
+ "FontSizeH4": "20px",
92
+ "FontSizeH5": "16px",
93
+ "FontSizeBodyLg": "16px",
94
+ "FontSizeBodyMd": "14px",
95
+ "FontSizeBodySm": "12px",
96
+ "FontSizeLabel": "14px",
97
+ "FontSizeButton": "14px",
98
+ "FontSizeOverline": "12px",
99
+ "FontSizeCaptionItalic": "12px",
100
+ "FontWeightRegular": 400,
101
+ "FontWeightMedium": 500,
102
+ "FontWeightSemibold": 600,
103
+ "FontWeightBold": 700
104
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Do not edit directly, this file was auto-generated.
3
+ */
4
+
5
+ :root {
6
+ --color-neutral-0: #fffaf7;
7
+ --color-neutral-50: #f7efea;
8
+ --color-neutral-100: #eadfd5;
9
+ --color-neutral-200: #d9c8bb;
10
+ --color-neutral-300: #bea89a;
11
+ --color-neutral-400: #948272;
12
+ --color-neutral-500: #6f5e52;
13
+ --color-neutral-600: #51443c;
14
+ --color-neutral-700: #3a302a;
15
+ --color-neutral-800: #241e1a;
16
+ --color-neutral-900: #0f0d0b;
17
+ --color-neutral-1000: #000000;
18
+ --color-primary-50: #ffedd5;
19
+ --color-primary-100: #fed7aa;
20
+ --color-primary-200: #fdba74;
21
+ --color-primary-300: #fb923c;
22
+ --color-primary-400: #f97316;
23
+ --color-primary-500: #ea580c;
24
+ --color-primary-600: #c2410c;
25
+ --color-primary-700: #9a3412;
26
+ --color-primary-800: #7c2d12;
27
+ --color-primary-00: #fff8f3;
28
+ --color-secondary-50: #fef3c7;
29
+ --color-secondary-100: #fde68a;
30
+ --color-secondary-200: #fcd34d;
31
+ --color-secondary-300: #fbbf24;
32
+ --color-secondary-400: #f59e0b;
33
+ --color-secondary-500: #d97706;
34
+ --color-secondary-600: #b45309;
35
+ --color-secondary-700: #92400e;
36
+ --color-secondary-800: #78350f;
37
+ --color-secondary-00: #fffbeb;
38
+ --color-semantic-success-light: #fce7d4;
39
+ --color-semantic-success: #c45c26;
40
+ --color-semantic-success-dark: #7a3a18;
41
+ --color-semantic-warning-light: #fef9c3;
42
+ --color-semantic-warning: #f59e0b;
43
+ --color-semantic-warning-dark: #b45309;
44
+ --color-semantic-error-light: #ffdad6;
45
+ --color-semantic-error: #d84315;
46
+ --color-semantic-error-dark: #8b2500;
47
+ --color-semantic-info-light: #fff4e6;
48
+ --color-semantic-info: #ff8f00;
49
+ --color-semantic-info-dark: #e65100;
50
+ --duration-instant: 100ms; /** Micro-interactions */
51
+ --duration-fast: 150ms; /** Hover states */
52
+ --duration-normal: 300ms; /** Transitions */
53
+ --duration-slow: 500ms; /** Page transitions */
54
+ --easing-default: cubic-bezier(0.4, 0, 0.2, 1);
55
+ --easing-in: cubic-bezier(0.4, 0, 1, 1);
56
+ --easing-out: cubic-bezier(0, 0, 0.2, 1);
57
+ --opacity-disabled: 0.38; /** Disabled elements */
58
+ --opacity-hover: 0.08; /** Hover overlay */
59
+ --opacity-pressed: 0.12; /** Pressed state */
60
+ --opacity-focus: 0.12; /** Focus ring */
61
+ --opacity-scrim: 0.32; /** Modal backdrop */
62
+ --radius-none: 0;
63
+ --radius-sm: 4px;
64
+ --radius-md: 8px;
65
+ --radius-lg: 12px;
66
+ --radius-xl: 16px;
67
+ --radius-2xl: 24px;
68
+ --radius-full: 9999px;
69
+ --elevation-hairline: 0px 1px 2px rgba(0,0,0,0.05);
70
+ --elevation-card: 0px 2px 8px rgba(0,0,0,0.08);
71
+ --elevation-popover: 0px 4px 16px rgba(0,0,0,0.10);
72
+ --elevation-modal: 0px 8px 32px rgba(0,0,0,0.12);
73
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.05); /** Subtle lift */
74
+ --shadow-md: 0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06); /** Cards */
75
+ --shadow-lg: 0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05); /** Dropdowns */
76
+ --shadow-xl: 0 20px 25px rgba(0,0,0,0.1), 0 8px 10px rgba(0,0,0,0.04); /** Modals */
77
+ --spacing-1: 4px;
78
+ --spacing-2: 8px;
79
+ --spacing-3: 12px;
80
+ --spacing-4: 16px;
81
+ --spacing-5: 20px;
82
+ --spacing-6: 24px;
83
+ --spacing-8: 32px;
84
+ --spacing-10: 40px;
85
+ --spacing-12: 48px;
86
+ --spacing-16: 64px;
87
+ --spacing-24: 96px;
88
+ --font-family-display: Montserrat;
89
+ --font-family-body: Montserrat;
90
+ --font-family-mono: Montserrat;
91
+ --font-size-hero: 72px;
92
+ --font-size-h1: 40px;
93
+ --font-size-h2: 32px;
94
+ --font-size-h3: 24px;
95
+ --font-size-h4: 20px;
96
+ --font-size-h5: 16px;
97
+ --font-size-body-lg: 16px;
98
+ --font-size-body-md: 14px;
99
+ --font-size-body-sm: 12px;
100
+ --font-size-label: 14px;
101
+ --font-size-button: 14px;
102
+ --font-size-overline: 12px;
103
+ --font-size-caption-italic: 12px;
104
+ --font-weight-regular: 400;
105
+ --font-weight-medium: 500;
106
+ --font-weight-semibold: 600;
107
+ --font-weight-bold: 700;
108
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Do not edit directly, this file was auto-generated.
3
+ */
4
+
5
+ export const ColorNeutral0 = "#fffaf7";
6
+ export const ColorNeutral50 = "#f7efea";
7
+ export const ColorNeutral100 = "#eadfd5";
8
+ export const ColorNeutral200 = "#d9c8bb";
9
+ export const ColorNeutral300 = "#bea89a";
10
+ export const ColorNeutral400 = "#948272";
11
+ export const ColorNeutral500 = "#6f5e52";
12
+ export const ColorNeutral600 = "#51443c";
13
+ export const ColorNeutral700 = "#3a302a";
14
+ export const ColorNeutral800 = "#241e1a";
15
+ export const ColorNeutral900 = "#0f0d0b";
16
+ export const ColorNeutral1000 = "#000000";
17
+ export const ColorPrimary50 = "#ffedd5";
18
+ export const ColorPrimary100 = "#fed7aa";
19
+ export const ColorPrimary200 = "#fdba74";
20
+ export const ColorPrimary300 = "#fb923c";
21
+ export const ColorPrimary400 = "#f97316";
22
+ export const ColorPrimary500 = "#ea580c";
23
+ export const ColorPrimary600 = "#c2410c";
24
+ export const ColorPrimary700 = "#9a3412";
25
+ export const ColorPrimary800 = "#7c2d12";
26
+ export const ColorPrimary00 = "#fff8f3";
27
+ export const ColorSecondary50 = "#fef3c7";
28
+ export const ColorSecondary100 = "#fde68a";
29
+ export const ColorSecondary200 = "#fcd34d";
30
+ export const ColorSecondary300 = "#fbbf24";
31
+ export const ColorSecondary400 = "#f59e0b";
32
+ export const ColorSecondary500 = "#d97706";
33
+ export const ColorSecondary600 = "#b45309";
34
+ export const ColorSecondary700 = "#92400e";
35
+ export const ColorSecondary800 = "#78350f";
36
+ export const ColorSecondary00 = "#fffbeb";
37
+ export const ColorSemanticSuccessLight = "#fce7d4";
38
+ export const ColorSemanticSuccess = "#c45c26";
39
+ export const ColorSemanticSuccessDark = "#7a3a18";
40
+ export const ColorSemanticWarningLight = "#fef9c3";
41
+ export const ColorSemanticWarning = "#f59e0b";
42
+ export const ColorSemanticWarningDark = "#b45309";
43
+ export const ColorSemanticErrorLight = "#ffdad6";
44
+ export const ColorSemanticError = "#d84315";
45
+ export const ColorSemanticErrorDark = "#8b2500";
46
+ export const ColorSemanticInfoLight = "#fff4e6";
47
+ export const ColorSemanticInfo = "#ff8f00";
48
+ export const ColorSemanticInfoDark = "#e65100";
49
+ export const DurationInstant = "100ms"; // Micro-interactions
50
+ export const DurationFast = "150ms"; // Hover states
51
+ export const DurationNormal = "300ms"; // Transitions
52
+ export const DurationSlow = "500ms"; // Page transitions
53
+ export const EasingDefault = "cubic-bezier(0.4, 0, 0.2, 1)";
54
+ export const EasingIn = "cubic-bezier(0.4, 0, 1, 1)";
55
+ export const EasingOut = "cubic-bezier(0, 0, 0.2, 1)";
56
+ export const OpacityDisabled = 0.38; // Disabled elements
57
+ export const OpacityHover = 0.08; // Hover overlay
58
+ export const OpacityPressed = 0.12; // Pressed state
59
+ export const OpacityFocus = 0.12; // Focus ring
60
+ export const OpacityScrim = 0.32; // Modal backdrop
61
+ export const RadiusNone = 0;
62
+ export const RadiusSm = "4px";
63
+ export const RadiusMd = "8px";
64
+ export const RadiusLg = "12px";
65
+ export const RadiusXl = "16px";
66
+ export const Radius2xl = "24px";
67
+ export const RadiusFull = "9999px";
68
+ export const ElevationHairline = "0px 1px 2px rgba(0,0,0,0.05)";
69
+ export const ElevationCard = "0px 2px 8px rgba(0,0,0,0.08)";
70
+ export const ElevationPopover = "0px 4px 16px rgba(0,0,0,0.10)";
71
+ export const ElevationModal = "0px 8px 32px rgba(0,0,0,0.12)";
72
+ export const ShadowSm = "0 1px 2px rgba(0,0,0,0.05)"; // Subtle lift
73
+ export const ShadowMd =
74
+ "0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06)"; // Cards
75
+ export const ShadowLg =
76
+ "0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05)"; // Dropdowns
77
+ export const ShadowXl =
78
+ "0 20px 25px rgba(0,0,0,0.1), 0 8px 10px rgba(0,0,0,0.04)"; // Modals
79
+ export const Spacing1 = "4px";
80
+ export const Spacing2 = "8px";
81
+ export const Spacing3 = "12px";
82
+ export const Spacing4 = "16px";
83
+ export const Spacing5 = "20px";
84
+ export const Spacing6 = "24px";
85
+ export const Spacing8 = "32px";
86
+ export const Spacing10 = "40px";
87
+ export const Spacing12 = "48px";
88
+ export const Spacing16 = "64px";
89
+ export const Spacing24 = "96px";
90
+ export const FontFamilyDisplay = "Montserrat";
91
+ export const FontFamilyBody = "Montserrat";
92
+ export const FontFamilyMono = "Montserrat";
93
+ export const FontSizeHero = "72px";
94
+ export const FontSizeH1 = "40px";
95
+ export const FontSizeH2 = "32px";
96
+ export const FontSizeH3 = "24px";
97
+ export const FontSizeH4 = "20px";
98
+ export const FontSizeH5 = "16px";
99
+ export const FontSizeBodyLg = "16px";
100
+ export const FontSizeBodyMd = "14px";
101
+ export const FontSizeBodySm = "12px";
102
+ export const FontSizeLabel = "14px";
103
+ export const FontSizeButton = "14px";
104
+ export const FontSizeOverline = "12px";
105
+ export const FontSizeCaptionItalic = "12px";
106
+ export const FontWeightRegular = 400;
107
+ export const FontWeightMedium = 500;
108
+ export const FontWeightSemibold = 600;
109
+ export const FontWeightBold = 700;
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@estebanruano/design-tokens",
3
+ "version": "1.0.2",
4
+ "packageManager": "pnpm@10.33.4",
5
+ "description": "Design system tokens — single source of truth for all platforms",
6
+ "type": "module",
7
+ "files": [
8
+ "dist/web",
9
+ "dist/json"
10
+ ],
11
+ "exports": {
12
+ ".": "./dist/web/tokens.js",
13
+ "./css": "./dist/web/tokens.css",
14
+ "./json": "./dist/json/tokens.json"
15
+ },
16
+ "sideEffects": [
17
+ "**/*.css"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/esteban505r/design-system.git"
25
+ },
26
+ "homepage": "https://github.com/esteban505r/design-system#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/esteban505r/design-system/issues"
29
+ },
30
+ "engines": {
31
+ "node": ">=18.12.0"
32
+ },
33
+ "keywords": [
34
+ "design-tokens",
35
+ "design-system",
36
+ "css-variables",
37
+ "style-dictionary"
38
+ ],
39
+ "scripts": {
40
+ "sync": "node md-to-tokens.mjs design-system-foundations.md --out tokens && node sd.config.mjs",
41
+ "build": "node sd.config.mjs",
42
+ "parse": "node md-to-tokens.mjs design-system-foundations.md --out tokens",
43
+ "clean": "rm -rf dist/ tokens/"
44
+ },
45
+ "author": "",
46
+ "license": "ISC",
47
+ "devDependencies": {
48
+ "style-dictionary": "^5.4.0"
49
+ }
50
+ }