@cupped/tokens 0.1.0 → 0.2.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/README.md CHANGED
@@ -5,9 +5,9 @@ community-first coffee-logging platform. The canonical source is
5
5
  platform-neutral [DTCG](https://www.designtokens.org/TR/drafts/format/)-style
6
6
  JSON under [`tokens/`](./tokens); every consumable artifact in
7
7
  [`dist/`](./dist) is **generated** from it and committed. The package is
8
- published to **GitHub Packages** (`@cupped` scope), and because `dist/` is
9
- committed it also works as a plain git dependency no registry auth, no
10
- install-time build for consumers that prefer that.
8
+ published **public on npm** (`npm install @cupped/tokens` — no auth), and
9
+ because `dist/` is committed it also works as a plain git dependency with no
10
+ install-time build, for consumers that prefer pinning a commit.
11
11
 
12
12
  > Never hard-code a hex or pixel value that exists as a token.
13
13
 
@@ -28,7 +28,7 @@ fonts are self-hosted per platform (documented).
28
28
  ## Consuming
29
29
 
30
30
  - **Phoenix LiveView (Tailwind v4):** [docs/phoenix.md](./docs/phoenix.md) —
31
- pinned CSS from the GitHub Release, npm git-dep, or zero-npm vendor mode;
31
+ pinned CSS from the GitHub Release, npm dependency, or zero-npm vendor mode;
32
32
  fonts, lint recipe.
33
33
  - **Expo / React Native (SDK 53+):** [docs/expo.md](./docs/expo.md) — the
34
34
  `theme.ts` pattern, expo-font, ESLint recipe.
@@ -71,7 +71,7 @@ npm run check # build, fail on dist/ drift, then test — what CI runs
71
71
  ## Releasing & versioning
72
72
 
73
73
  Releases are automated with [Changesets](https://github.com/changesets/changesets)
74
- and published to GitHub Packages; each release also attaches version-pinned CSS
74
+ and published to public npm; each release also attaches version-pinned CSS
75
75
  to its GitHub Release. Add a changeset with `npx changeset` in any PR that
76
76
  changes tokens.
77
77
 
@@ -94,6 +94,7 @@
94
94
  /* ——— Inputs ——— */
95
95
  .input {
96
96
  width: 100%;
97
+ min-height: var(--hit-target-min); /* ≥44pt tap target — matches .btn */
97
98
  padding: 12px 14px;
98
99
  border: 1px solid var(--canvas-border);
99
100
  border-radius: var(--radius-md);
@@ -103,21 +104,28 @@
103
104
  color: var(--ink);
104
105
  transition: border-color .15s, box-shadow .15s;
105
106
  }
106
- .input::placeholder { color: var(--ink-muted); }
107
+ /* Placeholder is essential text — ink-secondary clears AA; ink-muted does not. */
108
+ .input::placeholder { color: var(--ink-secondary); }
109
+ .input:hover:not(:focus):not([disabled]) { border-color: var(--ink-muted); }
107
110
  .input:focus {
108
111
  outline: none;
109
- border-color: var(--primary);
110
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent);
112
+ border-color: var(--primary-strong); /* #C05539, ≥3:1 vs field — carries the contrast */
113
+ box-shadow: 0 0 6px 2px var(--focus-glow); /* soft glow, decorative; buttons keep the two-tone ring */
111
114
  }
112
- .input.error {
115
+ .input.error,
116
+ .input.error:focus {
113
117
  border-color: var(--error);
114
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--error) 12%, transparent);
118
+ box-shadow: 0 0 6px 2px var(--error-glow); /* soft glow, error color — shown focused or not */
115
119
  }
116
120
  .input[disabled] { background: var(--canvas); color: var(--ink-muted); cursor: not-allowed; }
117
121
  .input-row { display: flex; flex-direction: column; gap: 6px; }
118
- .input-label { font-size: 12px; font-weight: 500; color: var(--ink-secondary); }
119
- .input-hint { font-size: 12px; color: var(--ink-secondary); }
122
+ .input-label { font-size: var(--text-caption); font-weight: 500; color: var(--ink-secondary); }
123
+ /* Hint: neutral helper by default; .error turns it red + pairs an icon (never color alone, WCAG 1.4.1). */
124
+ .input-hint { display: flex; align-items: center; gap: 6px; font-size: var(--text-caption); color: var(--ink-secondary); }
125
+ .input-hint .icon { width: 14px; height: 14px; flex-shrink: 0; }
120
126
  .input-hint.error { color: var(--error-ink); }
127
+ /* Validating — async check (e.g. "checking bean name"); pair with .spinner.spinner-ink */
128
+ .input-hint.validating { color: var(--ink-secondary); }
121
129
 
122
130
  /* ——— Cards ——— */
123
131
  .card {
@@ -177,7 +185,13 @@
177
185
  }
178
186
  @keyframes cupped-spin { to { transform: rotate(360deg); } }
179
187
 
188
+ /* Dark spinner for light surfaces (input validating, secondary/ghost buttons) */
189
+ .spinner-ink {
190
+ border-color: color-mix(in srgb, var(--ink) 18%, transparent);
191
+ border-top-color: var(--ink-secondary);
192
+ }
193
+
180
194
  @media (prefers-reduced-motion: reduce) {
181
- .btn { transition: none; }
195
+ .btn, .input { transition: none; }
182
196
  .spinner { animation: none; }
183
197
  }
@@ -119,6 +119,8 @@
119
119
  --shimmer-duration: 1.5s;
120
120
  --motion-reduced: 120ms;
121
121
  --focus-ring: 0 0 0 2px var(--card), 0 0 0 4px var(--primary-strong);
122
+ --focus-glow: color-mix(in srgb, var(--primary-strong) 22%, transparent);
123
+ --error-glow: color-mix(in srgb, var(--error) 22%, transparent);
122
124
  --hit-target-min: 44px;
123
125
 
124
126
  /* ── Materials ── */
@@ -1304,6 +1304,28 @@
1304
1304
  "outerWidthPx": 2
1305
1305
  }
1306
1306
  }
1307
+ },
1308
+ "glow": {
1309
+ "$type": "color",
1310
+ "$value": "rgba(192, 85, 57, 0.22)",
1311
+ "$description": "Decorative input focus halo — primary-strong @ 22%. The primary-strong border carries the ≥3:1 contrast; this glow is decorative. Buttons keep the two-tone focus ring.",
1312
+ "$extensions": {
1313
+ "app.cupped": {
1314
+ "cssName": "focus-glow",
1315
+ "cssValue": "color-mix(in srgb, var(--primary-strong) 22%, transparent)"
1316
+ }
1317
+ }
1318
+ },
1319
+ "errorGlow": {
1320
+ "$type": "color",
1321
+ "$value": "rgba(239, 68, 68, 0.22)",
1322
+ "$description": "Decorative input error halo — error @ 22%. Pairs with the error border; shown whether or not the field is focused.",
1323
+ "$extensions": {
1324
+ "app.cupped": {
1325
+ "cssName": "error-glow",
1326
+ "cssValue": "color-mix(in srgb, var(--error) 22%, transparent)"
1327
+ }
1328
+ }
1307
1329
  }
1308
1330
  },
1309
1331
  "hit-target": {
@@ -77,6 +77,8 @@
77
77
  "shimmer-duration": "1.5s",
78
78
  "motion-reduced": "120ms",
79
79
  "focus-ring": "0 0 0 2px #FFFFFF, 0 0 0 4px #C05539",
80
+ "focus-glow": "rgba(192, 85, 57, 0.22)",
81
+ "error-glow": "rgba(239, 68, 68, 0.22)",
80
82
  "hit-target-min": "44px",
81
83
  "radius-sm": "8px",
82
84
  "radius-md": "12px",
@@ -271,6 +271,8 @@ const tokens = {
271
271
  "innerColor": "#FFFFFF",
272
272
  "color": "#C05539"
273
273
  },
274
+ "focusGlow": "rgba(192, 85, 57, 0.22)",
275
+ "errorGlow": "rgba(239, 68, 68, 0.22)",
274
276
  "material": {
275
277
  "chromeBg": "rgba(255, 255, 255, 0.95)",
276
278
  "scrim": "rgba(15, 23, 42, 0.45)",
@@ -271,6 +271,8 @@ export declare const tokens: {
271
271
  readonly "innerColor": "#FFFFFF";
272
272
  readonly "color": "#C05539";
273
273
  };
274
+ readonly "focusGlow": "rgba(192, 85, 57, 0.22)";
275
+ readonly "errorGlow": "rgba(239, 68, 68, 0.22)";
274
276
  readonly "material": {
275
277
  readonly "chromeBg": "rgba(255, 255, 255, 0.95)";
276
278
  readonly "scrim": "rgba(15, 23, 42, 0.45)";
@@ -270,6 +270,8 @@ export const tokens = {
270
270
  "innerColor": "#FFFFFF",
271
271
  "color": "#C05539"
272
272
  },
273
+ "focusGlow": "rgba(192, 85, 57, 0.22)",
274
+ "errorGlow": "rgba(239, 68, 68, 0.22)",
273
275
  "material": {
274
276
  "chromeBg": "rgba(255, 255, 255, 0.95)",
275
277
  "scrim": "rgba(15, 23, 42, 0.45)",
@@ -143,6 +143,8 @@
143
143
  --shimmer-duration: 1.5s;
144
144
  --motion-reduced: 120ms;
145
145
  --focus-ring: 0 0 0 2px #FFFFFF, 0 0 0 4px #C05539;
146
+ --focus-glow: rgba(192, 85, 57, 0.22);
147
+ --error-glow: rgba(239, 68, 68, 0.22);
146
148
  --hit-target-min: 44px;
147
149
  --material-chrome-bg: rgba(255, 255, 255, 0.95);
148
150
  --material-chrome-blur: saturate(1.4) blur(20px);
package/docs/expo.md CHANGED
@@ -7,15 +7,7 @@ default). The top-level `main`/`types` fallback covers SDK 52. The
7
7
 
8
8
  ## Install
9
9
 
10
- **Primary GitHub Packages.** Map the `@cupped` scope to GitHub Packages in
11
- the app's `.npmrc`:
12
-
13
- ```ini
14
- # .npmrc
15
- @cupped:registry=https://npm.pkg.github.com
16
- # TODO: this registry needs a read token. Add the auth line for your setup, e.g.
17
- # //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
18
- ```
10
+ Published **public on npm** no registry config, no token, no `.npmrc`:
19
11
 
20
12
  ```bash
21
13
  npm install @cupped/tokens
@@ -23,8 +15,8 @@ npm install @cupped/tokens
23
15
 
24
16
  Pin the version in `package.json` as usual (`"@cupped/tokens": "^0.1.0"`).
25
17
 
26
- **Fallback — git dependency (no registry auth).** Because `dist/` is committed,
27
- the package also installs straight from git with no `.npmrc` / token setup:
18
+ **Fallback — git dependency.** Because `dist/` is committed, the package also
19
+ installs straight from git (e.g. to pin an unpublished commit):
28
20
 
29
21
  ```bash
30
22
  npm install github:ybird-labs/cupped-design-system#v0.1.0
package/docs/phoenix.md CHANGED
@@ -38,14 +38,15 @@ gh release download "v${CUPPED_TOKENS_VERSION}" \
38
38
  (`gh release download` needs an authenticated `gh` / token with read access to
39
39
  the package repo. The filenames are stable: `cupped-tokens-<version>.<target>.css`.)
40
40
 
41
- ## Mode 1 — npm git dependency
41
+ ## Mode 1 — npm dependency
42
42
 
43
- Create `assets/package.json` (or add to it):
43
+ Create `assets/package.json` (or add to it) — `@cupped/tokens` is public on npm,
44
+ so no registry auth is needed:
44
45
 
45
46
  ```jsonc
46
47
  {
47
48
  "dependencies": {
48
- "@cupped/tokens": "github:ybird-labs/cupped-design-system#v0.1.0"
49
+ "@cupped/tokens": "^0.1.0"
49
50
  }
50
51
  }
51
52
  ```
package/docs/releasing.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Releasing @cupped/tokens
2
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.
3
+ The package is published **public on npm** as
4
+ [`@cupped/tokens`](https://www.npmjs.com/package/@cupped/tokens) consumers
5
+ install it with no auth. Releases are driven by
6
+ [Changesets](https://github.com/changesets/changesets); the
7
+ [`release.yml`](../.github/workflows/release.yml) workflow does the publish
8
+ (with provenance) and attaches versioned CSS to the GitHub Release.
9
9
 
10
10
  For *what* bump to choose, see [versioning.md](./versioning.md).
11
11
 
@@ -35,7 +35,7 @@ changesets/action sees pending changesets
35
35
  release.yml runs again → no pending changesets, version not yet published
36
36
 
37
37
  ▼ changesets/action runs `npm run release` (changeset publish)
38
- changeset publish → publishes to GitHub Packages + creates the git tag vX.Y.Z
38
+ changeset publish → publishes to npm (public) + creates the git tag vX.Y.Z
39
39
  the changesets/action wrapper then creates the matching GitHub Release
40
40
 
41
41
  ▼ upload step attaches the three CSS files to Release vX.Y.Z:
@@ -47,47 +47,39 @@ changeset publish → publishes to GitHub Packages + creates the git tag vX.Y.Z
47
47
  You never bump `package.json` or write `CHANGELOG.md` by hand — merging the
48
48
  Version Packages PR does it.
49
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.)
50
+ ## CI setup for automated releases (one-time)
51
+
52
+ Automated releases publish to **public npm** via the Release workflow. Two
53
+ one-time setups in repo settings:
54
+
55
+ 1. **`NPM_TOKEN` secret** — create an npm **Automation** token (npmjs.com →
56
+ Access Tokens Generate New Token *Automation*; it bypasses 2FA) on an
57
+ account that owns the `@cupped` npm org, and add it as the repo secret
58
+ **`NPM_TOKEN`** (Settings Secrets and variables Actions). The workflow
59
+ passes it as `NODE_AUTH_TOKEN`.
60
+ 2. **Allow Actions to open PRs** Settings Actions General Workflow
61
+ permissions check *"Allow GitHub Actions to create and approve pull
62
+ requests"* (needed for the Changesets "Version Packages" PR).
63
+
64
+ The workflow also requests `id-token: write`, so npm attaches build
65
+ **provenance** to each public release.
66
+
67
+ ## First publish (already done for 0.1.0)
68
+
69
+ `0.1.0` was published manually once to bootstrap the package:
70
+
71
+ ```bash
72
+ npm login # browser auth to npmjs (owner of the @cupped org)
73
+ npm ci && npm run check
74
+ npm publish # public; prepublishOnly rebuilds dist/ first
75
+ ```
76
+
77
+ Every subsequent release is automated — no manual publish.
87
78
 
88
79
  ## Verifying a published release
89
80
 
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.
81
+ - The version is on npm: <https://www.npmjs.com/package/@cupped/tokens>
82
+ (or `npm view @cupped/tokens version`). Consumers install with no auth.
83
+ - The GitHub Release `vX.Y.Z` exists with the `cupped-tokens-X.Y.Z.*.css`
84
+ assets (+ `.sha256`) attached.
93
85
  - `CHANGELOG.md` has an entry for the version.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cupped/tokens",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Cupped design tokens — canonical DTCG source with generated CSS custom properties, Tailwind v4 @theme, React Native theme object, and raw JSON.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -40,6 +40,24 @@
40
40
  ],
41
41
  "$description": "Opaque dual focus ring (refreshed export) — ≥3:1 non-text contrast on any surface. Outline is never removed without a replacement.",
42
42
  "$extensions": { "app.cupped": { "innerWidthPx": 2, "outerWidthPx": 2 } }
43
+ },
44
+ "glow": {
45
+ "$type": "color",
46
+ "$value": "rgba(192, 85, 57, 0.22)",
47
+ "$description": "Decorative input focus halo — primary-strong @ 22%. The primary-strong border carries the ≥3:1 contrast; this glow is decorative. Buttons keep the two-tone focus ring.",
48
+ "$extensions": { "app.cupped": {
49
+ "cssName": "focus-glow",
50
+ "cssValue": "color-mix(in srgb, var(--primary-strong) 22%, transparent)"
51
+ } }
52
+ },
53
+ "errorGlow": {
54
+ "$type": "color",
55
+ "$value": "rgba(239, 68, 68, 0.22)",
56
+ "$description": "Decorative input error halo — error @ 22%. Pairs with the error border; shown whether or not the field is focused.",
57
+ "$extensions": { "app.cupped": {
58
+ "cssName": "error-glow",
59
+ "cssValue": "color-mix(in srgb, var(--error) 22%, transparent)"
60
+ } }
43
61
  }
44
62
  },
45
63
  "hit-target": {