@cupped/tokens 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +79 -0
- package/dist/css/components.css +183 -0
- package/dist/css/tokens.css +144 -0
- package/dist/json/tokens.dtcg.json +1501 -0
- package/dist/json/tokens.flat.json +102 -0
- package/dist/native/index.cjs +281 -0
- package/dist/native/index.d.ts +285 -0
- package/dist/native/index.js +279 -0
- package/dist/tailwind/theme.css +164 -0
- package/docs/expo.md +141 -0
- package/docs/phoenix.md +153 -0
- package/docs/releasing.md +93 -0
- package/docs/rules.md +62 -0
- package/docs/versioning.md +59 -0
- package/package.json +56 -0
- package/tokens/primitive/color.tokens.json +94 -0
- package/tokens/primitive/dimension.tokens.json +18 -0
- package/tokens/primitive/duration.tokens.json +10 -0
- package/tokens/primitive/font.tokens.json +29 -0
- package/tokens/semantic/color.tokens.json +172 -0
- package/tokens/semantic/elevation.tokens.json +38 -0
- package/tokens/semantic/materials.tokens.json +34 -0
- package/tokens/semantic/motion.tokens.json +52 -0
- package/tokens/semantic/radius.tokens.json +11 -0
- package/tokens/semantic/spacing.tokens.json +13 -0
- package/tokens/semantic/typography.tokens.json +60 -0
package/docs/phoenix.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Consuming @cupped/tokens from Phoenix LiveView
|
|
2
|
+
|
|
3
|
+
Three supported modes. All assume Phoenix 1.8 / Tailwind v4 (CSS-first config,
|
|
4
|
+
standalone Tailwind binary — no Node runtime needed at build beyond an
|
|
5
|
+
optional `npm install`).
|
|
6
|
+
|
|
7
|
+
## Mode 0 — pinned CSS from the GitHub Release (recommended)
|
|
8
|
+
|
|
9
|
+
Each release attaches version-pinned CSS to its GitHub Release. Pin the version
|
|
10
|
+
(this string is your lockfile analog) and pull the files before the Tailwind
|
|
11
|
+
build — no npm, no `node_modules`:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# e.g. in a mix alias or a small fetch script, run before tailwind build
|
|
15
|
+
export CUPPED_TOKENS_VERSION=0.1.0
|
|
16
|
+
mkdir -p assets/vendor/cupped
|
|
17
|
+
gh release download "v${CUPPED_TOKENS_VERSION}" \
|
|
18
|
+
--repo ybird-labs/cupped-design-system \
|
|
19
|
+
--pattern "cupped-tokens-${CUPPED_TOKENS_VERSION}.*" \
|
|
20
|
+
--dir assets/vendor/cupped --clobber
|
|
21
|
+
# verify integrity against the published checksum sidecar
|
|
22
|
+
( cd assets/vendor/cupped && sha256sum -c "cupped-tokens-${CUPPED_TOKENS_VERSION}.sha256" )
|
|
23
|
+
# downloads: cupped-tokens-X.Y.Z.theme.css / .tokens.css / .components.css (+ .sha256)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```css
|
|
27
|
+
@import "tailwindcss" source(none);
|
|
28
|
+
@source "../css";
|
|
29
|
+
@source "../js";
|
|
30
|
+
@source "../../lib/my_app_web";
|
|
31
|
+
|
|
32
|
+
@import "../vendor/cupped/cupped-tokens-0.1.0.theme.css";
|
|
33
|
+
/* optional: */
|
|
34
|
+
@import "../vendor/cupped/cupped-tokens-0.1.0.tokens.css";
|
|
35
|
+
@import "../vendor/cupped/cupped-tokens-0.1.0.components.css";
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
(`gh release download` needs an authenticated `gh` / token with read access to
|
|
39
|
+
the package repo. The filenames are stable: `cupped-tokens-<version>.<target>.css`.)
|
|
40
|
+
|
|
41
|
+
## Mode 1 — npm git dependency
|
|
42
|
+
|
|
43
|
+
Create `assets/package.json` (or add to it):
|
|
44
|
+
|
|
45
|
+
```jsonc
|
|
46
|
+
{
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@cupped/tokens": "github:ybird-labs/cupped-design-system#v0.1.0"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Run `npm install` inside `assets/`. The Tailwind v4 binary resolves
|
|
54
|
+
`@import` against `node_modules`, so in `assets/css/app.css`:
|
|
55
|
+
|
|
56
|
+
```css
|
|
57
|
+
@import "tailwindcss" source(none);
|
|
58
|
+
@source "../css";
|
|
59
|
+
@source "../js";
|
|
60
|
+
@source "../../lib/my_app_web";
|
|
61
|
+
|
|
62
|
+
/* Tailwind @theme tokens → utilities (bg-canvas, text-ink-secondary,
|
|
63
|
+
rounded-lg, shadow-primary, p-base, text-card-title…) + CSS variables. */
|
|
64
|
+
@import "@cupped/tokens/tailwind";
|
|
65
|
+
|
|
66
|
+
/* Optional: the alias-preserving raw variables (--ink, --xp: var(--sweet)…)
|
|
67
|
+
if you also write plain CSS against var() names. */
|
|
68
|
+
@import "@cupped/tokens/css";
|
|
69
|
+
|
|
70
|
+
/* Optional: the canonical web component classes (.btn, .input, .chip-flavor,
|
|
71
|
+
.banner, .chrome…) — reference styles, skip if you rebuild components in
|
|
72
|
+
HEEx + utilities. Requires the /css import above. */
|
|
73
|
+
@import "@cupped/tokens/css/components";
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
HEEx then uses utilities or raw variables — no JS framework assumption:
|
|
77
|
+
|
|
78
|
+
```heex
|
|
79
|
+
<button class="bg-primary-strong text-ink-inverse rounded-md shadow-primary
|
|
80
|
+
px-lg py-md min-h-(--hit-target-min) text-(length:--text-body)">
|
|
81
|
+
Log a coffee
|
|
82
|
+
</button>
|
|
83
|
+
|
|
84
|
+
<span style={"color: var(--ink-secondary)"}>SEATTLE · 12 MIN AGO · V60</span>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Mode 2 — vendor mode (zero npm, from a source checkout)
|
|
88
|
+
|
|
89
|
+
Copy the generated files into the app on each upgrade (Mode 0 is the same idea
|
|
90
|
+
but pulls pinned files from the Release instead of a working checkout):
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
cp dist/tailwind/theme.css <app>/assets/vendor/cupped/theme.css
|
|
94
|
+
cp dist/css/tokens.css <app>/assets/vendor/cupped/tokens.css # optional
|
|
95
|
+
cp dist/css/components.css <app>/assets/vendor/cupped/components.css # optional
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```css
|
|
99
|
+
@import "tailwindcss" source(none);
|
|
100
|
+
@import "../vendor/cupped/theme.css";
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Fonts (self-hosted)
|
|
104
|
+
|
|
105
|
+
The package ships no font binaries. Self-host WOFF2 in `priv/static/fonts/`
|
|
106
|
+
(already whitelisted by `static_paths/0`) — Google Fonts CDN is discouraged
|
|
107
|
+
(GDPR; no shared-cache benefit since browser cache partitioning). Inter,
|
|
108
|
+
Instrument Serif, and JetBrains Mono are all OFL-licensed.
|
|
109
|
+
|
|
110
|
+
```css
|
|
111
|
+
@font-face {
|
|
112
|
+
font-family: "Inter";
|
|
113
|
+
src: url("/fonts/InterVariable.woff2") format("woff2");
|
|
114
|
+
font-weight: 100 900;
|
|
115
|
+
font-display: swap;
|
|
116
|
+
}
|
|
117
|
+
@font-face {
|
|
118
|
+
font-family: "Instrument Serif";
|
|
119
|
+
src: url("/fonts/InstrumentSerif-Regular.woff2") format("woff2");
|
|
120
|
+
font-weight: 400;
|
|
121
|
+
font-display: swap;
|
|
122
|
+
}
|
|
123
|
+
@font-face {
|
|
124
|
+
font-family: "Instrument Serif";
|
|
125
|
+
src: url("/fonts/InstrumentSerif-Italic.woff2") format("woff2");
|
|
126
|
+
font-weight: 400;
|
|
127
|
+
font-style: italic;
|
|
128
|
+
font-display: swap;
|
|
129
|
+
}
|
|
130
|
+
@font-face {
|
|
131
|
+
font-family: "JetBrains Mono";
|
|
132
|
+
src: url("/fonts/JetBrainsMono[wght].woff2") format("woff2");
|
|
133
|
+
font-weight: 100 800;
|
|
134
|
+
font-display: swap;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Enforcing "no raw values"
|
|
139
|
+
|
|
140
|
+
*Never hard-code a hex or pixel value that exists as a token.* There is no
|
|
141
|
+
turnkey HEEx linter for this; the practical recipe is a CI grep over
|
|
142
|
+
templates and CSS:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# fails CI when a raw hex sneaks into templates/styles (tokens.css itself is generated)
|
|
146
|
+
grep -rnE '#[0-9a-fA-F]{3,8}\b' lib/my_app_web assets/css --include='*.heex' --include='*.css' \
|
|
147
|
+
| grep -v vendor/ && exit 1 || exit 0
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
For JS in `assets/js`, port the `no-restricted-syntax` patterns from
|
|
151
|
+
[docs/expo.md](./expo.md).
|
|
152
|
+
|
|
153
|
+
A complete example lives at [examples/phoenix/app.css](../examples/phoenix/app.css).
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Releasing @cupped/tokens
|
|
2
|
+
|
|
3
|
+
The package is published to **GitHub Packages** (npm registry
|
|
4
|
+
`https://npm.pkg.github.com`, `@cupped` scope, `restricted` access) under
|
|
5
|
+
[`ybird-labs/cupped-design-system`](https://github.com/ybird-labs/cupped-design-system).
|
|
6
|
+
Releases are driven by [Changesets](https://github.com/changesets/changesets);
|
|
7
|
+
the [`release.yml`](../.github/workflows/release.yml) workflow does the publish
|
|
8
|
+
and attaches versioned CSS to the GitHub Release.
|
|
9
|
+
|
|
10
|
+
For *what* bump to choose, see [versioning.md](./versioning.md).
|
|
11
|
+
|
|
12
|
+
## Day-to-day: adding a changeset
|
|
13
|
+
|
|
14
|
+
Every PR that changes tokens or generated output should include a changeset:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx changeset # pick the bump level, write a summary
|
|
18
|
+
git add .changeset/
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The summary becomes the `CHANGELOG.md` entry, so write it for a consumer.
|
|
22
|
+
|
|
23
|
+
## Automated release flow
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
PR with a .changeset/*.md merged to main
|
|
27
|
+
│
|
|
28
|
+
▼ release.yml runs (npm ci → npm run check)
|
|
29
|
+
changesets/action sees pending changesets
|
|
30
|
+
│
|
|
31
|
+
▼ opens / updates a "Version Packages" PR
|
|
32
|
+
(bumps package.json + writes CHANGELOG.md, deletes consumed changesets)
|
|
33
|
+
│
|
|
34
|
+
▼ merge the Version Packages PR
|
|
35
|
+
release.yml runs again → no pending changesets, version not yet published
|
|
36
|
+
│
|
|
37
|
+
▼ changesets/action runs `npm run release` (changeset publish)
|
|
38
|
+
changeset publish → publishes to GitHub Packages + creates the git tag vX.Y.Z
|
|
39
|
+
the changesets/action wrapper then creates the matching GitHub Release
|
|
40
|
+
│
|
|
41
|
+
▼ upload step attaches the three CSS files to Release vX.Y.Z:
|
|
42
|
+
cupped-tokens-X.Y.Z.theme.css (Tailwind v4 @theme)
|
|
43
|
+
cupped-tokens-X.Y.Z.tokens.css (raw CSS variables)
|
|
44
|
+
cupped-tokens-X.Y.Z.components.css (component classes)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
You never bump `package.json` or write `CHANGELOG.md` by hand — merging the
|
|
48
|
+
Version Packages PR does it.
|
|
49
|
+
|
|
50
|
+
## One-time first publish (manual)
|
|
51
|
+
|
|
52
|
+
The very first publish of a brand-new scoped package usually **cannot** be done
|
|
53
|
+
by the workflow's `GITHUB_TOKEN`, because creating a new package under the org
|
|
54
|
+
typically requires a personal access token. Do this once:
|
|
55
|
+
|
|
56
|
+
1. Create a **fine-grained PAT** scoped to just `ybird-labs/cupped-design-system`
|
|
57
|
+
with **Packages: write** and a short expiry. (A classic PAT with
|
|
58
|
+
`write:packages` works too, but it is org-wide and long-lived — prefer
|
|
59
|
+
fine-grained.)
|
|
60
|
+
2. Point npm at GitHub Packages for the scope, and pass the token via an env
|
|
61
|
+
var so it is never persisted to disk:
|
|
62
|
+
```bash
|
|
63
|
+
echo "@cupped:registry=https://npm.pkg.github.com" >> ~/.npmrc
|
|
64
|
+
echo '//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}' >> ~/.npmrc
|
|
65
|
+
export NODE_AUTH_TOKEN=YOUR_PAT # this shell only — not written to ~/.npmrc
|
|
66
|
+
```
|
|
67
|
+
3. From a clean checkout on the released version:
|
|
68
|
+
```bash
|
|
69
|
+
npm ci
|
|
70
|
+
npm run check
|
|
71
|
+
npm publish # prepublishOnly rebuilds dist/ first
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
After the package exists, the workflow's `GITHUB_TOKEN` can publish every
|
|
75
|
+
subsequent release — no PAT needed in CI.
|
|
76
|
+
|
|
77
|
+
## Granting consumer repos read access
|
|
78
|
+
|
|
79
|
+
Consuming repos in the same org need **read** access to the package:
|
|
80
|
+
|
|
81
|
+
- In the package settings on GitHub → *Package settings* → *Manage Actions
|
|
82
|
+
access* / *Manage access*, grant the consumer repos (e.g. the Phoenix and
|
|
83
|
+
Expo apps) read access.
|
|
84
|
+
- Consumers then authenticate with a token that has `read:packages`. (Consumer
|
|
85
|
+
`.npmrc` setup is documented per-app — see [expo.md](./expo.md). **TODO:**
|
|
86
|
+
finalize and document the consumer read-token model.)
|
|
87
|
+
|
|
88
|
+
## Verifying a published release
|
|
89
|
+
|
|
90
|
+
- The package version appears under the repo's *Packages*.
|
|
91
|
+
- The GitHub Release `vX.Y.Z` exists with the three `cupped-tokens-X.Y.Z.*.css`
|
|
92
|
+
assets attached.
|
|
93
|
+
- `CHANGELOG.md` has an entry for the version.
|
package/docs/rules.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Cupped brand & accessibility invariants
|
|
2
|
+
|
|
3
|
+
The rules the tokens encode but cannot enforce by themselves. The contrast
|
|
4
|
+
rules marked ✓ are machine-checked in CI (`scripts/validate-contrast.mjs`);
|
|
5
|
+
the rest are review rules.
|
|
6
|
+
|
|
7
|
+
## Color
|
|
8
|
+
|
|
9
|
+
- **Coral never carries text below 24px.** `--primary` (#E07A5F) is ~3.0:1
|
|
10
|
+
on white — accents, illustration, ≥24px display only. Small colored text,
|
|
11
|
+
links, and text-bearing fills use `--primary-strong` (4.6:1 on white ✓).
|
|
12
|
+
- **Coral = action; slate = chrome.** Flavor colors tag tasting notes
|
|
13
|
+
*only* — never UI chrome.
|
|
14
|
+
- **Every solid flavor fill carries white text at ≥4.5:1, zero exceptions** ✓
|
|
15
|
+
(the oklch band guarantees it; `--on-flavor` is always white).
|
|
16
|
+
- **Flavor-colored words on white use the `-accessible` text band** (≥5.5:1 ✓,
|
|
17
|
+
with a small hex-quantization tolerance — green lands at 5.496).
|
|
18
|
+
- **Feedback `-ink` variants** are the AA text/icon colors on their `-light`
|
|
19
|
+
backgrounds ✓; banner words stay ink/ink-secondary.
|
|
20
|
+
- **Gamification colors are reserved for reward moments** — never decoration.
|
|
21
|
+
They are aliases (`xp → sweet`, `badge → floral`, `streak → ember`):
|
|
22
|
+
change the source, never the alias.
|
|
23
|
+
- Known nuance (flagged upstream, not encoded): `--ink-inverse` (#F8FAFC) on
|
|
24
|
+
`--primary-strong` is 4.36:1 — the spec's 4.6:1 claim is for pure white.
|
|
25
|
+
|
|
26
|
+
## Type
|
|
27
|
+
|
|
28
|
+
- Inter for all UI; six named sizes only — no ad-hoc sizes.
|
|
29
|
+
- **Serif display max once per screen**, often with an italic coral word;
|
|
30
|
+
tracking −1.5%.
|
|
31
|
+
- Mono is the technical register only (ratios, temps, grind, extraction).
|
|
32
|
+
- Never Lora, Fraunces, or Plus Jakarta. No emoji in product UI — ever.
|
|
33
|
+
|
|
34
|
+
## Layout & interaction
|
|
35
|
+
|
|
36
|
+
- Strict 4pt grid; the seven `--space-*` stops are the only spacing values.
|
|
37
|
+
- **Hit targets ≥44pt, always** (`--hit-target-min`; `.btn` enforces it).
|
|
38
|
+
- **One primary action per screen.**
|
|
39
|
+
- Every interactive element ships all six states before it ships:
|
|
40
|
+
default · hover · pressed · focus · disabled · loading.
|
|
41
|
+
- **Focus is never removed without a replacement** — the dual ring
|
|
42
|
+
`--focus-ring` keeps ≥3:1 non-text contrast on any surface ✓.
|
|
43
|
+
|
|
44
|
+
## Materials & motion
|
|
45
|
+
|
|
46
|
+
- Content surfaces are always opaque. **One chrome layer per screen**
|
|
47
|
+
(`.chrome` — tab bar or sticky header); scrim for sheets is `--scrim`.
|
|
48
|
+
- `prefers-reduced-transparency` collapses chrome to opaque card (built into
|
|
49
|
+
the generated CSS).
|
|
50
|
+
- One shared spring (`response 0.55s · damping 0.75`); tap pulse
|
|
51
|
+
`scale 0.95 · opacity 0.8`; stagger 0.08s; shimmer 1.5s.
|
|
52
|
+
- **Reduced motion keeps the state change and drops the travel** — springs
|
|
53
|
+
and staggers collapse to 120ms crossfades (built into the generated CSS;
|
|
54
|
+
app-side via `useReducedMotion` on native).
|
|
55
|
+
- Never gate content behind an animation. No bounces on content, no
|
|
56
|
+
infinite decorative loops.
|
|
57
|
+
|
|
58
|
+
## The golden rule
|
|
59
|
+
|
|
60
|
+
> Never hard-code a hex or pixel value that exists as a token.
|
|
61
|
+
|
|
62
|
+
Lint recipes per platform: [phoenix.md](./phoenix.md), [expo.md](./expo.md).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Versioning policy
|
|
2
|
+
|
|
3
|
+
`@cupped/tokens` follows [semantic versioning](https://semver.org/), but the
|
|
4
|
+
"public API" is the **token contract**, not just exported types. This page
|
|
5
|
+
defines what counts as a breaking change so consumers can upgrade with
|
|
6
|
+
confidence.
|
|
7
|
+
|
|
8
|
+
## What is the public contract
|
|
9
|
+
|
|
10
|
+
- **`tokens/semantic/`** — the public API. Every semantic token aliases a
|
|
11
|
+
primitive and is what apps consume (via `@cupped/tokens`, `/css`,
|
|
12
|
+
`/tailwind`, …).
|
|
13
|
+
- **`tokens/primitive/`** — internal raw palettes and scales. **Never consumed
|
|
14
|
+
directly**; reshaping a primitive is *not* breaking as long as the semantic
|
|
15
|
+
tokens it feeds keep their resolved values and the contrast invariants hold.
|
|
16
|
+
- The package **subpath exports** (`.`, `./css`, `./css/components`,
|
|
17
|
+
`./tailwind`, `./json`, `./json/dtcg`) and the generated `.d.ts` shape are
|
|
18
|
+
also part of the contract.
|
|
19
|
+
|
|
20
|
+
## Bump levels
|
|
21
|
+
|
|
22
|
+
### MAJOR (breaking)
|
|
23
|
+
- Remove or **rename** a semantic token.
|
|
24
|
+
- Remove or reshape a subpath export, or a breaking change to the emitted
|
|
25
|
+
`.d.ts` types (e.g. narrowing a literal union, changing a shadow shape).
|
|
26
|
+
- A value change that **violates a guaranteed accessibility invariant** — the
|
|
27
|
+
`$extensions["app.cupped"].contrast` data is machine-checked in CI
|
|
28
|
+
(see [README](../README.md#architecture)); shipping a value that breaks a
|
|
29
|
+
documented contrast guarantee is breaking even though the key still exists.
|
|
30
|
+
|
|
31
|
+
### MINOR (additive)
|
|
32
|
+
- Add a token, a new scale step, a new subpath export, or an optional
|
|
33
|
+
`$extensions` block.
|
|
34
|
+
- Add a deprecation alias (see below) ahead of a future removal.
|
|
35
|
+
|
|
36
|
+
### PATCH
|
|
37
|
+
- A value tweak that keeps every invariant (contrast, collisions, parity).
|
|
38
|
+
- Documentation, descriptions, or `$description` fixes.
|
|
39
|
+
|
|
40
|
+
## Softening breaking changes
|
|
41
|
+
|
|
42
|
+
Prefer **deprecate-then-remove** over a hard rename:
|
|
43
|
+
|
|
44
|
+
1. Introduce the new token as a **minor**, keeping the old name as an alias to
|
|
45
|
+
the new one. Mark the old token deprecated in its `$description`.
|
|
46
|
+
2. Remove the deprecated alias in the next **major**, after at least one minor
|
|
47
|
+
cycle, so consumers get a release where both names resolve.
|
|
48
|
+
|
|
49
|
+
## Why Changesets (not fully inferred automation)
|
|
50
|
+
|
|
51
|
+
The bump level for a token change is **human judgment**: a rename is breaking,
|
|
52
|
+
a value tweak usually is not — but a value tweak that crosses a contrast
|
|
53
|
+
threshold *is*. Tools that infer the bump from commit messages
|
|
54
|
+
(semantic-release) or from a fixed convention can't make that call reliably.
|
|
55
|
+
|
|
56
|
+
With [Changesets](https://github.com/changesets/changesets) the author who
|
|
57
|
+
makes the change declares the intent in a reviewed `.changeset/*.md` file,
|
|
58
|
+
which doubles as the changelog entry. See [releasing.md](./releasing.md) for
|
|
59
|
+
the mechanics.
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cupped/tokens",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Cupped design tokens — canonical DTCG source with generated CSS custom properties, Tailwind v4 @theme, React Native theme object, and raw JSON.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/ybird-labs/cupped-design-system.git"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/native/index.cjs",
|
|
16
|
+
"types": "./dist/native/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/native/index.d.ts",
|
|
20
|
+
"react-native": "./dist/native/index.js",
|
|
21
|
+
"import": "./dist/native/index.js",
|
|
22
|
+
"require": "./dist/native/index.cjs",
|
|
23
|
+
"default": "./dist/native/index.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./css": "./dist/css/tokens.css",
|
|
26
|
+
"./css/components": "./dist/css/components.css",
|
|
27
|
+
"./tailwind": "./dist/tailwind/theme.css",
|
|
28
|
+
"./json": "./dist/json/tokens.flat.json",
|
|
29
|
+
"./json/dtcg": "./dist/json/tokens.dtcg.json"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"tokens",
|
|
34
|
+
"docs",
|
|
35
|
+
"README.md",
|
|
36
|
+
"CHANGELOG.md"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "node build/config.js",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"check": "npm run build && git diff --exit-code -- dist/ && test -z \"$(git status --porcelain --untracked-files=all -- dist/)\" && npm test",
|
|
42
|
+
"changeset": "changeset",
|
|
43
|
+
"version": "changeset version",
|
|
44
|
+
"release": "changeset publish",
|
|
45
|
+
"prepublishOnly": "npm run build"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@changesets/changelog-github": "^0.5.1",
|
|
49
|
+
"@changesets/cli": "^2.27.12",
|
|
50
|
+
"colorjs.io": "^0.6.1",
|
|
51
|
+
"postcss": "^8.5.15",
|
|
52
|
+
"style-dictionary": "^5.4.4",
|
|
53
|
+
"typescript": "^6.0.3",
|
|
54
|
+
"vitest": "^4.1.8"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"color": {
|
|
3
|
+
"$type": "color",
|
|
4
|
+
"palette": {
|
|
5
|
+
"$description": "Raw palette values. Never consumed by apps — alias through the semantic layer.",
|
|
6
|
+
"white": { "$value": "#FFFFFF" },
|
|
7
|
+
"slate": {
|
|
8
|
+
"$description": "Cool slate neutrals — carry all UI chrome.",
|
|
9
|
+
"50": { "$value": "#F8FAFC" },
|
|
10
|
+
"100": { "$value": "#F1F5F9" },
|
|
11
|
+
"200": { "$value": "#E2E8F0" },
|
|
12
|
+
"400": { "$value": "#94A3B8" },
|
|
13
|
+
"600": { "$value": "#475569" },
|
|
14
|
+
"900": { "$value": "#0F172A" }
|
|
15
|
+
},
|
|
16
|
+
"coral": {
|
|
17
|
+
"$description": "Warm brand coral — carries action and brand. Coral = action; slate = chrome.",
|
|
18
|
+
"50": { "$value": "#FDF2F0" },
|
|
19
|
+
"500": { "$value": "#E07A5F" },
|
|
20
|
+
"550": { "$value": "#D16A4F" },
|
|
21
|
+
"600": { "$value": "#C05539" },
|
|
22
|
+
"650": { "$value": "#AD4A30" }
|
|
23
|
+
},
|
|
24
|
+
"ember": {
|
|
25
|
+
"$description": "Gamification source hue (streak fire). Promoted to a source token in the refreshed export; --streak aliases it.",
|
|
26
|
+
"fill": { "$value": "#F97316" },
|
|
27
|
+
"text": { "$value": "#C2410C" }
|
|
28
|
+
},
|
|
29
|
+
"green": {
|
|
30
|
+
"50": { "$value": "#F0FDF4" },
|
|
31
|
+
"500": { "$value": "#22C55E" },
|
|
32
|
+
"700": { "$value": "#15803D" }
|
|
33
|
+
},
|
|
34
|
+
"red": {
|
|
35
|
+
"50": { "$value": "#FEF2F2" },
|
|
36
|
+
"500": { "$value": "#EF4444" },
|
|
37
|
+
"700": { "$value": "#B91C1C" }
|
|
38
|
+
},
|
|
39
|
+
"amber": {
|
|
40
|
+
"50": { "$value": "#FFFBEB" },
|
|
41
|
+
"500": { "$value": "#F59E0B" },
|
|
42
|
+
"700": { "$value": "#B45309" }
|
|
43
|
+
},
|
|
44
|
+
"blue": {
|
|
45
|
+
"50": { "$value": "#EFF6FF" },
|
|
46
|
+
"500": { "$value": "#3B82F6" },
|
|
47
|
+
"700": { "$value": "#1D4ED8" }
|
|
48
|
+
},
|
|
49
|
+
"flavor": {
|
|
50
|
+
"$description": "SCA tasting vocabulary — parametric oklch band (\"Espresso\"), not hand-picked hexes. Fill band: L 0.555 · C 0.135 (bright) / 0.062 (earth) / earth ×0.7 (roasted). Text band: L 0.510 · C 0.110 (bright) / 0.060 (earth). Hue carries the flavor; lightness/chroma are shared, so every fill carries white text at ≥4.5:1 with zero exceptions.",
|
|
51
|
+
"fruity": {
|
|
52
|
+
"fill": { "$value": "#B44C54", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.135, "h": 18 }, "band": "fill" } } },
|
|
53
|
+
"text": { "$value": "#9B494E", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.11, "h": 18 }, "band": "text" } } }
|
|
54
|
+
},
|
|
55
|
+
"berry": {
|
|
56
|
+
"fill": { "$value": "#AC4D7B", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.135, "h": 352 }, "band": "fill" } } },
|
|
57
|
+
"text": { "$value": "#94496D", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.11, "h": 352 }, "band": "text" } } }
|
|
58
|
+
},
|
|
59
|
+
"citrus": {
|
|
60
|
+
"fill": { "$value": "#A65F02", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.135, "h": 62 }, "band": "fill" } } },
|
|
61
|
+
"text": { "$value": "#925512", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.11, "h": 62 }, "band": "text" } } }
|
|
62
|
+
},
|
|
63
|
+
"sweet": {
|
|
64
|
+
"fill": { "$value": "#8E6E09", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.135, "h": 88 }, "band": "fill" } } },
|
|
65
|
+
"text": { "$value": "#7E6207", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.11, "h": 88 }, "band": "text" } } }
|
|
66
|
+
},
|
|
67
|
+
"floral": {
|
|
68
|
+
"fill": { "$value": "#865CB2", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.135, "h": 305 }, "band": "fill" } } },
|
|
69
|
+
"text": { "$value": "#755498", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.11, "h": 305 }, "band": "text" } } }
|
|
70
|
+
},
|
|
71
|
+
"green": {
|
|
72
|
+
"fill": { "$value": "#4E8429", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.135, "h": 135 }, "band": "fill" } } },
|
|
73
|
+
"text": { "$value": "#49742E", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.11, "h": 135 }, "band": "text" } } }
|
|
74
|
+
},
|
|
75
|
+
"spice": {
|
|
76
|
+
"fill": { "$value": "#B4503A", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.135, "h": 34 }, "band": "fill" } } },
|
|
77
|
+
"text": { "$value": "#9B4C3A", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.11, "h": 34 }, "band": "text" } } }
|
|
78
|
+
},
|
|
79
|
+
"nutty": {
|
|
80
|
+
"fill": { "$value": "#876F49", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.062, "h": 78 }, "band": "fill" } } },
|
|
81
|
+
"text": { "$value": "#79623E", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.06, "h": 78 }, "band": "text" } } }
|
|
82
|
+
},
|
|
83
|
+
"chocolate": {
|
|
84
|
+
"fill": { "$value": "#916951", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.062, "h": 52 }, "band": "fill" } } },
|
|
85
|
+
"text": { "$value": "#825C46", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.06, "h": 52 }, "band": "text" } } }
|
|
86
|
+
},
|
|
87
|
+
"roasted": {
|
|
88
|
+
"fill": { "$value": "#896B5E", "$extensions": { "app.cupped": { "oklch": { "l": 0.555, "c": 0.0434, "h": 45 }, "band": "fill" } } },
|
|
89
|
+
"text": { "$value": "#7B5F52", "$extensions": { "app.cupped": { "oklch": { "l": 0.51, "c": 0.042, "h": 45 }, "band": "text" } } }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dimension": {
|
|
3
|
+
"$type": "dimension",
|
|
4
|
+
"scale": {
|
|
5
|
+
"$description": "Raw 4pt-grid dimension stops (plus 2px ring width and the 9999px pill radius). Never consumed by apps — alias through the semantic layer.",
|
|
6
|
+
"2": { "$value": "2px" },
|
|
7
|
+
"4": { "$value": "4px" },
|
|
8
|
+
"8": { "$value": "8px" },
|
|
9
|
+
"12": { "$value": "12px" },
|
|
10
|
+
"16": { "$value": "16px" },
|
|
11
|
+
"20": { "$value": "20px" },
|
|
12
|
+
"24": { "$value": "24px" },
|
|
13
|
+
"32": { "$value": "32px" },
|
|
14
|
+
"44": { "$value": "44px" },
|
|
15
|
+
"full": { "$value": "9999px" }
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"duration": {
|
|
3
|
+
"$type": "duration",
|
|
4
|
+
"$description": "Raw durations. Kept in the spec's original units so generated CSS matches the canonical export character-for-character; the native pipeline normalizes to ms numbers.",
|
|
5
|
+
"spring": { "$value": "0.55s" },
|
|
6
|
+
"stagger": { "$value": "0.08s" },
|
|
7
|
+
"shimmer": { "$value": "1.5s" },
|
|
8
|
+
"reduced": { "$value": "120ms" }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"font": {
|
|
3
|
+
"family": {
|
|
4
|
+
"$type": "fontFamily",
|
|
5
|
+
"$description": "Three families, each with a job: Inter for all UI, Instrument Serif for display (max one moment per screen), JetBrains Mono for the technical register. Never Lora, Fraunces, or Plus Jakarta.",
|
|
6
|
+
"sans": { "$value": ["Inter", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "sans-serif"] },
|
|
7
|
+
"serif": { "$value": ["Instrument Serif", "Georgia", "serif"] },
|
|
8
|
+
"mono": { "$value": ["JetBrains Mono", "ui-monospace", "SFMono-Regular", "monospace"] }
|
|
9
|
+
},
|
|
10
|
+
"weight": {
|
|
11
|
+
"$type": "fontWeight",
|
|
12
|
+
"regular": { "$value": 400 },
|
|
13
|
+
"medium": { "$value": 500 },
|
|
14
|
+
"semibold": { "$value": 600 },
|
|
15
|
+
"bold": { "$value": 700 }
|
|
16
|
+
},
|
|
17
|
+
"size": {
|
|
18
|
+
"$type": "dimension",
|
|
19
|
+
"$description": "Raw size stops. Every size shipped in a component has a semantic token name — no ad-hoc sizes.",
|
|
20
|
+
"12": { "$value": "12px" },
|
|
21
|
+
"14": { "$value": "14px" },
|
|
22
|
+
"16": { "$value": "16px" },
|
|
23
|
+
"20": { "$value": "20px" },
|
|
24
|
+
"24": { "$value": "24px" },
|
|
25
|
+
"32": { "$value": "32px" },
|
|
26
|
+
"56": { "$value": "56px" }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|