@motir/design-system 0.19.0 → 0.21.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 +150 -5
- package/dist/components/theme/AppearancePickers.js +30 -2
- package/dist/components/theme/AppearancePickers.js.map +1 -1
- package/dist/components/ui/DatePicker.d.ts +31 -0
- package/dist/components/ui/DatePicker.js +442 -0
- package/dist/components/ui/DatePicker.js.map +1 -0
- package/dist/components/ui/DatePickerFormatContext.d.ts +26 -0
- package/dist/components/ui/DatePickerFormatContext.js +58 -0
- package/dist/components/ui/DatePickerFormatContext.js.map +1 -0
- package/dist/components/ui/Modal.d.ts +23 -1
- package/dist/components/ui/Modal.js +17 -3
- package/dist/components/ui/Modal.js.map +1 -1
- package/dist/components/ui/datePickerFormat.d.ts +40 -0
- package/dist/components/ui/datePickerFormat.js +30 -0
- package/dist/components/ui/datePickerFormat.js.map +1 -0
- package/dist/contexts/theme-context.js +30 -2
- package/dist/contexts/theme-context.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -0
- package/dist/mock/index.js +30 -2
- package/dist/mock/index.js.map +1 -1
- package/dist/mock/renderMock.js +30 -2
- package/dist/mock/renderMock.js.map +1 -1
- package/dist/specimen/TokensSpecimen.js +2 -2
- package/dist/specimen/TokensSpecimen.js.map +1 -1
- package/dist/theme/appearance-resolution.js +30 -2
- package/dist/theme/appearance-resolution.js.map +1 -1
- package/dist/theme/init-script.js +30 -2
- package/dist/theme/init-script.js.map +1 -1
- package/dist/theme/styles.d.ts +1 -1
- package/dist/theme/styles.js +2 -2
- package/dist/theme/styles.js.map +1 -1
- package/dist/theme/types.js +2 -2
- package/dist/theme/types.js.map +1 -1
- package/dist/theme/typography.d.ts +46 -3
- package/dist/theme/typography.js +28 -0
- package/dist/theme/typography.js.map +1 -1
- package/package.json +1 -1
- package/theme.css +119 -1
package/dist/theme/typography.js
CHANGED
|
@@ -41,6 +41,34 @@ var TYPE_REGISTRY = {
|
|
|
41
41
|
tagline: "IBM Plex Mono throughout \u2014 a precise, developer-grade UI.",
|
|
42
42
|
faces: "IBM Plex Mono headlines + body/UI + meta/code.",
|
|
43
43
|
designDoc: "docs/typography/mono-technical.md"
|
|
44
|
+
},
|
|
45
|
+
marker: {
|
|
46
|
+
id: "marker",
|
|
47
|
+
name: "Marker",
|
|
48
|
+
tagline: "Hand-lettered marker headlines over a clean sans body \u2014 sketchy, friendly, human.",
|
|
49
|
+
faces: "Caveat marker headlines \xB7 Inter body \xB7 JetBrains Mono meta.",
|
|
50
|
+
designDoc: "docs/typography/marker.md"
|
|
51
|
+
},
|
|
52
|
+
rounded: {
|
|
53
|
+
id: "rounded",
|
|
54
|
+
name: "Rounded",
|
|
55
|
+
tagline: "A soft rounded sans across the whole UI \u2014 friendly and approachable.",
|
|
56
|
+
faces: "Nunito headlines + body/UI \xB7 JetBrains Mono meta.",
|
|
57
|
+
designDoc: "docs/typography/rounded.md"
|
|
58
|
+
},
|
|
59
|
+
slab: {
|
|
60
|
+
id: "slab",
|
|
61
|
+
name: "Slab",
|
|
62
|
+
tagline: "Sturdy slab-serif headlines over a clean sans body \u2014 confident, print-like.",
|
|
63
|
+
faces: "Roboto Slab headlines \xB7 Inter body \xB7 JetBrains Mono meta.",
|
|
64
|
+
designDoc: "docs/typography/slab.md"
|
|
65
|
+
},
|
|
66
|
+
humanist: {
|
|
67
|
+
id: "humanist",
|
|
68
|
+
name: "Humanist",
|
|
69
|
+
tagline: "A warm humanist sans across the whole UI \u2014 open and readable.",
|
|
70
|
+
faces: "Fira Sans headlines + body/UI \xB7 JetBrains Mono meta.",
|
|
71
|
+
designDoc: "docs/typography/humanist.md"
|
|
44
72
|
}
|
|
45
73
|
};
|
|
46
74
|
var TYPE_IDS = Object.keys(TYPE_REGISTRY);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/theme/typography.ts"],"names":[],"mappings":";AAuFO,IAAM,aAAA,GAAgB;AAAA,EAC3B,KAAA,EAAO;AAAA,IACL,EAAA,EAAI,OAAA;AAAA,IACJ,IAAA,EAAM,OAAA;AAAA,IACN,OAAA,EAAS,4EAAA;AAAA,IACT,KAAA,EAAO,oEAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,EAAA,EAAI,YAAA;AAAA,IACJ,IAAA,EAAM,YAAA;AAAA,IACN,OAAA,EAAS,qEAAA;AAAA,IACT,KAAA,EAAO,kDAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,EAAA,EAAI,YAAA;AAAA,IACJ,IAAA,EAAM,YAAA;AAAA,IACN,OAAA,EAAS,wEAAA;AAAA,IACT,KAAA,EAAO,4CAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,OAAA,EAAS;AAAA,IACP,EAAA,EAAI,SAAA;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS,iFAAA;AAAA,IACT,KAAA,EAAO,6DAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,SAAA,EAAW;AAAA,IACT,EAAA,EAAI,WAAA;AAAA,IACJ,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS,gFAAA;AAAA,IACT,KAAA,EAAO,sEAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,gBAAA,EAAkB;AAAA,IAChB,EAAA,EAAI,gBAAA;AAAA,IACJ,IAAA,EAAM,gBAAA;AAAA,IACN,OAAA,EAAS,gEAAA;AAAA,IACT,KAAA,EAAO,gDAAA;AAAA,IACP,SAAA,EAAW;AAAA;AAEf;AAMO,IAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,aAAa;AAM1C,IAAM,eAAA,GAA0B;AAGhC,SAAS,SAAS,KAAA,EAAiC;AACxD,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,MAAA,CAAO,UAAU,cAAA,CAAe,IAAA,CAAK,eAAe,KAAK,CAAA;AAC/F;AAGO,SAAS,YAAY,KAAA,EAAsC;AAChE,EAAA,OAAO,aAAA,CAAc,QAAA,CAAS,KAAK,CAAA,GAAI,QAAQ,eAAe,CAAA;AAChE","file":"typography.js","sourcesContent":["/**\n * The Motir TYPOGRAPHY LIBRARY — the named-pairing registry (Subtask 7.3.53).\n *\n * A \"type pairing\" is a named TYPOGRAPHY scheme the whole UI can swap to at\n * runtime — the THIRD design axis, completing the token decomposition\n * (Colour `data-palette` · Type `data-type` · Shape/feel `data-style`). It is\n * deliberately INDEPENDENT of the other two: a pairing decides which TYPEFACES\n * the product wears (the headline / body / mono role mapping); it never touches\n * a hue (palette axis) or a radius (style axis).\n *\n * ── The three-axis runtime contract ─────────────────────────────────────\n * data-type=\"<type-id>\" — THIS axis. A `[data-type='<id>']` block in\n * app/globals.css re-points the `--font-*`\n * role tokens (sans / serif / mono) — and ONLY\n * font tokens, never colour or shape.\n * data-palette=\"<palette-id>\" — the INDEPENDENT colour axis (`--el-*`).\n * data-style=\"<style-id>\" — the INDEPENDENT shape/feel axis.\n *\n * The shared `--font-size-*` SCALE stays common across pairings — sizes are\n * layout, not brand; a pairing remaps the FACES, not the type scale.\n *\n * ── A style declares a DEFAULT pairing (overridable) ────────────────────\n * Typography used to be BUNDLED into the style axis: `swiss-minimal-flat`,\n * `neo-brutalism` and `cybercore-y2k` each re-pointed `--font-serif` inside\n * their own `[data-style]` block. That is now a disjointness violation (two\n * axes setting `--font-*`). The fix: each style declares a `defaultTypeId`\n * (see ./styles.ts) — the pairing applied when the user has NOT pinned an\n * explicit type — and the per-style font overrides move here, as pairings.\n * So out-of-the-box looks are UNCHANGED; the new freedom is that type is now\n * independently overridable (e.g. Swiss shape + a serif pairing).\n *\n * ── v1 — the base faces only (no new payload) ───────────────────────────\n * v1 registered three pairings built from the THREE already-loaded next/font\n * faces (Inter · Source Serif 4 · JetBrains Mono) — so they add ZERO font\n * payload and carry NO new-typeface design decision:\n * - `motir` — the base: editorial serif headlines over a sans body.\n * - `motir-sans` — all-sans (Inter headlines); reproduces the Swiss look.\n * - `motir-mono` — mono THROUGHOUT (headlines + body/UI); a code-native UI.\n * `motir` is the base — like the `motir` palette / `warm-editorial` style it\n * needs NO `[data-type]` override block; the base `--font-*` tokens already are\n * it.\n *\n * ── New-typeface pairings (Grotesk / Editorial / Mono-Technical, 7.3.54–56) ──\n * Each adds a real type-design decision and loads its own next/font face(s),\n * re-pointing a role in its own `[data-type]` block:\n * - `grotesk` (7.3.54) — Space Grotesk THROUGHOUT (headlines + body/UI).\n * - `editorial` (7.3.55) — Fraunces display-serif headlines over the Inter\n * body; a magazine, considered pairing (one new face — Inter + JetBrains reused).\n * Body STAYS Inter — a display serif is unreadable as UI, so this pairing\n * re-types headlines only (the legibility exception to whole-UI re-typing).\n * - `mono-technical` (7.3.56) — IBM Plex Mono THROUGHOUT (headlines + body/UI +\n * meta); a precise, developer-grade UI (one new face — Inter reused for nothing\n * now, kept as the ultimate fallback).\n *\n * ── Whole-UI re-typing (Yue, 2026-06-19) ────────────────────────────────\n * A type pairing re-types the WHOLE app, chrome included (nav, header, buttons),\n * not just headlines: a pairing whose signature face reads as a UI sans/mono\n * (`grotesk`, `motir-mono`, `mono-technical`) ALSO re-points the body/UI role\n * (`--font-sans`) in its `[data-type]` block. The display-serif `editorial` and\n * the all-Inter `motir` / `motir-sans` keep the Inter body for legibility.\n * Each later \"Type: …\" subtask ADDS its entry here + a `[data-type]` block (its\n * face loaded in `app/layout.tsx`) + its `docs/typography/<id>.md`.\n */\n\n/** A registered, runtime-selectable type pairing. */\nexport interface TypographyDefinition {\n /** The `data-type` attribute value. Stable; used as the localStorage value. */\n id: string;\n /** Display name shown in the gallery / `/tokens` toggle. */\n name: string;\n /** One-line characterization of the typographic feel. */\n tagline: string;\n /** The headline / body / mono face mapping (credit / what it loads). */\n faces: string;\n /**\n * Repo-relative path to this pairing's doc — the type-role reference a later\n * getdesign-style swap or the `/tokens` composer reads. Every registered\n * pairing maps to exactly one.\n */\n designDoc: string;\n}\n\n/**\n * The registry. Insertion order is the gallery order. Each non-base `id`\n * matches a `[data-type='<id>']` block in app/globals.css (`motir` is the base,\n * so its block is the Tier-0 `--font-*` defaults — no override block needed).\n */\nexport const TYPE_REGISTRY = {\n motir: {\n id: 'motir',\n name: 'Motir',\n tagline: 'Editorial serif headlines over a clean sans body — the house pairing.',\n faces: 'Source Serif 4 headlines · Inter body · JetBrains Mono meta.',\n designDoc: 'docs/typography/motir.md',\n },\n 'motir-sans': {\n id: 'motir-sans',\n name: 'Motir Sans',\n tagline: 'All-sans — Inter for headlines and body; structural, no serif.',\n faces: 'Inter headlines + body · JetBrains Mono meta.',\n designDoc: 'docs/typography/motir-sans.md',\n },\n 'motir-mono': {\n id: 'motir-mono',\n name: 'Motir Mono',\n tagline: 'Monospace throughout — a code-native UI, headlines, body and all.',\n faces: 'JetBrains Mono headlines + body/UI + meta.',\n designDoc: 'docs/typography/motir-mono.md',\n },\n grotesk: {\n id: 'grotesk',\n name: 'Grotesk',\n tagline: 'Geometric neo-grotesque across the whole UI — tight, confident, product-y.',\n faces: 'Space Grotesk headlines + body/UI · JetBrains Mono meta.',\n designDoc: 'docs/typography/grotesk.md',\n },\n editorial: {\n id: 'editorial',\n name: 'Editorial',\n tagline: 'A characterful display serif over a humanist sans — magazine, considered.',\n faces: 'Fraunces display headlines · Inter body · JetBrains Mono meta.',\n designDoc: 'docs/typography/editorial.md',\n },\n 'mono-technical': {\n id: 'mono-technical',\n name: 'Mono-Technical',\n tagline: 'IBM Plex Mono throughout — a precise, developer-grade UI.',\n faces: 'IBM Plex Mono headlines + body/UI + meta/code.',\n designDoc: 'docs/typography/mono-technical.md',\n },\n} satisfies Record<string, TypographyDefinition>;\n\n/** The id of every registered pairing — `data-type` value space. */\nexport type TypeId = keyof typeof TYPE_REGISTRY;\n\n/** All registered pairing ids, in gallery order. */\nexport const TYPE_IDS = Object.keys(TYPE_REGISTRY) as TypeId[];\n\n/**\n * The default pairing a fresh install / unset preference resolves to when the\n * active style declares none. Motir is the house pairing and the Tier-0 base.\n */\nexport const DEFAULT_TYPE_ID: TypeId = 'motir';\n\n/** Narrowing guard — is an arbitrary string a registered pairing id? */\nexport function isTypeId(value: unknown): value is TypeId {\n return typeof value === 'string' && Object.prototype.hasOwnProperty.call(TYPE_REGISTRY, value);\n}\n\n/** Resolve a (possibly stale / unknown) value to a valid pairing definition. */\nexport function resolveType(value: unknown): TypographyDefinition {\n return TYPE_REGISTRY[isTypeId(value) ? value : DEFAULT_TYPE_ID];\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/theme/typography.ts"],"names":[],"mappings":";AAsGO,IAAM,aAAA,GAAgB;AAAA,EAC3B,KAAA,EAAO;AAAA,IACL,EAAA,EAAI,OAAA;AAAA,IACJ,IAAA,EAAM,OAAA;AAAA,IACN,OAAA,EAAS,4EAAA;AAAA,IACT,KAAA,EAAO,oEAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,EAAA,EAAI,YAAA;AAAA,IACJ,IAAA,EAAM,YAAA;AAAA,IACN,OAAA,EAAS,qEAAA;AAAA,IACT,KAAA,EAAO,kDAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,EAAA,EAAI,YAAA;AAAA,IACJ,IAAA,EAAM,YAAA;AAAA,IACN,OAAA,EAAS,wEAAA;AAAA,IACT,KAAA,EAAO,4CAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,OAAA,EAAS;AAAA,IACP,EAAA,EAAI,SAAA;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS,iFAAA;AAAA,IACT,KAAA,EAAO,6DAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,SAAA,EAAW;AAAA,IACT,EAAA,EAAI,WAAA;AAAA,IACJ,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS,gFAAA;AAAA,IACT,KAAA,EAAO,sEAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,gBAAA,EAAkB;AAAA,IAChB,EAAA,EAAI,gBAAA;AAAA,IACJ,IAAA,EAAM,gBAAA;AAAA,IACN,OAAA,EAAS,gEAAA;AAAA,IACT,KAAA,EAAO,gDAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,EAAA,EAAI,QAAA;AAAA,IACJ,IAAA,EAAM,QAAA;AAAA,IACN,OAAA,EAAS,wFAAA;AAAA,IACT,KAAA,EAAO,mEAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,OAAA,EAAS;AAAA,IACP,EAAA,EAAI,SAAA;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS,2EAAA;AAAA,IACT,KAAA,EAAO,sDAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,EAAA,EAAI,MAAA;AAAA,IACJ,IAAA,EAAM,MAAA;AAAA,IACN,OAAA,EAAS,kFAAA;AAAA,IACT,KAAA,EAAO,iEAAA;AAAA,IACP,SAAA,EAAW;AAAA,GACb;AAAA,EACA,QAAA,EAAU;AAAA,IACR,EAAA,EAAI,UAAA;AAAA,IACJ,IAAA,EAAM,UAAA;AAAA,IACN,OAAA,EAAS,oEAAA;AAAA,IACT,KAAA,EAAO,yDAAA;AAAA,IACP,SAAA,EAAW;AAAA;AAEf;AAMO,IAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,aAAa;AAM1C,IAAM,eAAA,GAA0B;AAGhC,SAAS,SAAS,KAAA,EAAiC;AACxD,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,MAAA,CAAO,UAAU,cAAA,CAAe,IAAA,CAAK,eAAe,KAAK,CAAA;AAC/F;AAGO,SAAS,YAAY,KAAA,EAAsC;AAChE,EAAA,OAAO,aAAA,CAAc,QAAA,CAAS,KAAK,CAAA,GAAI,QAAQ,eAAe,CAAA;AAChE","file":"typography.js","sourcesContent":["/**\n * The Motir TYPOGRAPHY LIBRARY — the named-pairing registry (Subtask 7.3.53).\n *\n * A \"type pairing\" is a named TYPOGRAPHY scheme the whole UI can swap to at\n * runtime — the THIRD design axis, completing the token decomposition\n * (Colour `data-palette` · Type `data-type` · Shape/feel `data-style`). It is\n * deliberately INDEPENDENT of the other two: a pairing decides which TYPEFACES\n * the product wears (the headline / body / mono role mapping); it never touches\n * a hue (palette axis) or a radius (style axis).\n *\n * ── The three-axis runtime contract ─────────────────────────────────────\n * data-type=\"<type-id>\" — THIS axis. A `[data-type='<id>']` block in\n * app/globals.css re-points the `--font-*`\n * role tokens (sans / serif / mono) — and ONLY\n * font tokens, never colour or shape.\n * data-palette=\"<palette-id>\" — the INDEPENDENT colour axis (`--el-*`).\n * data-style=\"<style-id>\" — the INDEPENDENT shape/feel axis.\n *\n * The shared `--font-size-*` SCALE stays common across pairings — sizes are\n * layout, not brand; a pairing remaps the FACES, not the type scale.\n *\n * ── A style declares a DEFAULT pairing (overridable) ────────────────────\n * Typography used to be BUNDLED into the style axis: `swiss-minimal-flat`,\n * `neo-brutalism` and `cybercore-y2k` each re-pointed `--font-serif` inside\n * their own `[data-style]` block. That is now a disjointness violation (two\n * axes setting `--font-*`). The fix: each style declares a `defaultTypeId`\n * (see ./styles.ts) — the pairing applied when the user has NOT pinned an\n * explicit type — and the per-style font overrides move here, as pairings.\n * So out-of-the-box looks are UNCHANGED; the new freedom is that type is now\n * independently overridable (e.g. Swiss shape + a serif pairing).\n *\n * ── v1 — the base faces only (no new payload) ───────────────────────────\n * v1 registered three pairings built from the THREE already-loaded next/font\n * faces (Inter · Source Serif 4 · JetBrains Mono) — so they add ZERO font\n * payload and carry NO new-typeface design decision:\n * - `motir` — the base: editorial serif headlines over a sans body.\n * - `motir-sans` — all-sans (Inter headlines); reproduces the Swiss look.\n * - `motir-mono` — mono THROUGHOUT (headlines + body/UI); a code-native UI.\n * `motir` is the base — like the `motir` palette / `warm-editorial` style it\n * needs NO `[data-type]` override block; the base `--font-*` tokens already are\n * it.\n *\n * ── New-typeface pairings (Grotesk / Editorial / Mono-Technical, 7.3.54–56) ──\n * Each adds a real type-design decision and loads its own next/font face(s),\n * re-pointing a role in its own `[data-type]` block:\n * - `grotesk` (7.3.54) — Space Grotesk THROUGHOUT (headlines + body/UI).\n * - `editorial` (7.3.55) — Fraunces display-serif headlines over the Inter\n * body; a magazine, considered pairing (one new face — Inter + JetBrains reused).\n * Body STAYS Inter — a display serif is unreadable as UI, so this pairing\n * re-types headlines only (the legibility exception to whole-UI re-typing).\n * - `mono-technical` (7.3.56) — IBM Plex Mono THROUGHOUT (headlines + body/UI +\n * meta); a precise, developer-grade UI (one new face — Inter reused for nothing\n * now, kept as the ultimate fallback).\n *\n * ── New-typeface pairings (Story MOTIR-10548) ─────────────────────────────\n * - `marker` (MOTIR-10553) — Caveat hand-lettered marker headlines over the\n * Inter body; Hand-Drawn / Indie's default. Display-only, like `editorial`: a\n * marker hand is unreadable as UI text, so only the headline role is re-typed.\n * - `rounded` (MOTIR-10554) — Nunito THROUGHOUT (headlines + body/UI); a\n * soft, friendly rounded sans that reads cleanly as UI text, so it re-types\n * the whole UI like `grotesk`.\n * - `slab` (MOTIR-10555) — Roboto Slab headlines over the Inter body;\n * sturdy and print-like. Display-only, like `editorial`: heavy slab serifs\n * crowd UI text, so only the headline role is re-typed.\n * - `humanist` (MOTIR-10556) — Fira Sans THROUGHOUT (headlines + body/UI); a\n * warm humanist sans drawn as a screen UI face, so it re-types the whole UI\n * like `grotesk`.\n *\n * ── Whole-UI re-typing (Yue, 2026-06-19) ────────────────────────────────\n * A type pairing re-types the WHOLE app, chrome included (nav, header, buttons),\n * not just headlines: a pairing whose signature face reads as a UI sans/mono\n * (`grotesk`, `motir-mono`, `mono-technical`, `rounded`, `humanist`) ALSO\n * re-points the body/UI role (`--font-sans`) in its `[data-type]` block. The\n * display-serif `editorial` and `slab`, the display-only `marker` and the\n * all-Inter `motir` / `motir-sans` keep the Inter body for legibility.\n * Each later \"Type: …\" subtask ADDS its entry here + a `[data-type]` block (its\n * face loaded in `app/layout.tsx`) + its `docs/typography/<id>.md`.\n */\n\n/** A registered, runtime-selectable type pairing. */\nexport interface TypographyDefinition {\n /** The `data-type` attribute value. Stable; used as the localStorage value. */\n id: string;\n /** Display name shown in the gallery / `/tokens` toggle. */\n name: string;\n /** One-line characterization of the typographic feel. */\n tagline: string;\n /** The headline / body / mono face mapping (credit / what it loads). */\n faces: string;\n /**\n * Repo-relative path to this pairing's doc — the type-role reference a later\n * getdesign-style swap or the `/tokens` composer reads. Every registered\n * pairing maps to exactly one.\n */\n designDoc: string;\n}\n\n/**\n * The registry. Insertion order is the gallery order. Each non-base `id`\n * matches a `[data-type='<id>']` block in app/globals.css (`motir` is the base,\n * so its block is the Tier-0 `--font-*` defaults — no override block needed).\n */\nexport const TYPE_REGISTRY = {\n motir: {\n id: 'motir',\n name: 'Motir',\n tagline: 'Editorial serif headlines over a clean sans body — the house pairing.',\n faces: 'Source Serif 4 headlines · Inter body · JetBrains Mono meta.',\n designDoc: 'docs/typography/motir.md',\n },\n 'motir-sans': {\n id: 'motir-sans',\n name: 'Motir Sans',\n tagline: 'All-sans — Inter for headlines and body; structural, no serif.',\n faces: 'Inter headlines + body · JetBrains Mono meta.',\n designDoc: 'docs/typography/motir-sans.md',\n },\n 'motir-mono': {\n id: 'motir-mono',\n name: 'Motir Mono',\n tagline: 'Monospace throughout — a code-native UI, headlines, body and all.',\n faces: 'JetBrains Mono headlines + body/UI + meta.',\n designDoc: 'docs/typography/motir-mono.md',\n },\n grotesk: {\n id: 'grotesk',\n name: 'Grotesk',\n tagline: 'Geometric neo-grotesque across the whole UI — tight, confident, product-y.',\n faces: 'Space Grotesk headlines + body/UI · JetBrains Mono meta.',\n designDoc: 'docs/typography/grotesk.md',\n },\n editorial: {\n id: 'editorial',\n name: 'Editorial',\n tagline: 'A characterful display serif over a humanist sans — magazine, considered.',\n faces: 'Fraunces display headlines · Inter body · JetBrains Mono meta.',\n designDoc: 'docs/typography/editorial.md',\n },\n 'mono-technical': {\n id: 'mono-technical',\n name: 'Mono-Technical',\n tagline: 'IBM Plex Mono throughout — a precise, developer-grade UI.',\n faces: 'IBM Plex Mono headlines + body/UI + meta/code.',\n designDoc: 'docs/typography/mono-technical.md',\n },\n marker: {\n id: 'marker',\n name: 'Marker',\n tagline: 'Hand-lettered marker headlines over a clean sans body — sketchy, friendly, human.',\n faces: 'Caveat marker headlines · Inter body · JetBrains Mono meta.',\n designDoc: 'docs/typography/marker.md',\n },\n rounded: {\n id: 'rounded',\n name: 'Rounded',\n tagline: 'A soft rounded sans across the whole UI — friendly and approachable.',\n faces: 'Nunito headlines + body/UI · JetBrains Mono meta.',\n designDoc: 'docs/typography/rounded.md',\n },\n slab: {\n id: 'slab',\n name: 'Slab',\n tagline: 'Sturdy slab-serif headlines over a clean sans body — confident, print-like.',\n faces: 'Roboto Slab headlines · Inter body · JetBrains Mono meta.',\n designDoc: 'docs/typography/slab.md',\n },\n humanist: {\n id: 'humanist',\n name: 'Humanist',\n tagline: 'A warm humanist sans across the whole UI — open and readable.',\n faces: 'Fira Sans headlines + body/UI · JetBrains Mono meta.',\n designDoc: 'docs/typography/humanist.md',\n },\n} satisfies Record<string, TypographyDefinition>;\n\n/** The id of every registered pairing — `data-type` value space. */\nexport type TypeId = keyof typeof TYPE_REGISTRY;\n\n/** All registered pairing ids, in gallery order. */\nexport const TYPE_IDS = Object.keys(TYPE_REGISTRY) as TypeId[];\n\n/**\n * The default pairing a fresh install / unset preference resolves to when the\n * active style declares none. Motir is the house pairing and the Tier-0 base.\n */\nexport const DEFAULT_TYPE_ID: TypeId = 'motir';\n\n/** Narrowing guard — is an arbitrary string a registered pairing id? */\nexport function isTypeId(value: unknown): value is TypeId {\n return typeof value === 'string' && Object.prototype.hasOwnProperty.call(TYPE_REGISTRY, value);\n}\n\n/** Resolve a (possibly stale / unknown) value to a valid pairing definition. */\nexport function resolveType(value: unknown): TypographyDefinition {\n return TYPE_REGISTRY[isTypeId(value) ? value : DEFAULT_TYPE_ID];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motir/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Motir's 3-axis design system (colour · style · type): distributable token CSS, the axis registries, the theme-apply API, and framework-agnostic React primitives. Shared by motir-core and planner-scaffolded products.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"repository": {
|
package/theme.css
CHANGED
|
@@ -189,6 +189,12 @@
|
|
|
189
189
|
--shadow-elevated: 0 8px 24px rgba(15, 15, 15, 0.12);
|
|
190
190
|
--shadow-modal: 0 16px 48px -8px rgba(15, 15, 15, 0.16);
|
|
191
191
|
--shadow-hero-mockup: 0 24px 48px -8px rgba(15, 15, 15, 0.2);
|
|
192
|
+
/* How far the SOLID edge of `--shadow-elevated` falls below the box that casts
|
|
193
|
+
it. A soft, blurred lift has none (0); a hard-offset style sets its Y offset.
|
|
194
|
+
A control hung over other content (the canvas card's next-action button,
|
|
195
|
+
MOTIR-10631) lifts itself by this much more, so its shadow clears what it
|
|
196
|
+
floats above as its box does. */
|
|
197
|
+
--spacing-shadow-elevated-drop: 0px;
|
|
192
198
|
|
|
193
199
|
/* ── Spacing ────────────────────────────────────────────────────── */
|
|
194
200
|
--spacing-xxs: 4px;
|
|
@@ -481,6 +487,7 @@
|
|
|
481
487
|
--shadow-subtle: 0 1px 2px rgba(15, 15, 15, 0.04);
|
|
482
488
|
--shadow-card: 0 4px 12px rgba(15, 15, 15, 0.08);
|
|
483
489
|
--shadow-elevated: 0 8px 24px rgba(15, 15, 15, 0.12);
|
|
490
|
+
--spacing-shadow-elevated-drop: 0px;
|
|
484
491
|
--shadow-modal: 0 16px 48px -8px rgba(15, 15, 15, 0.16);
|
|
485
492
|
--shadow-hero-mockup: 0 24px 48px -8px rgba(15, 15, 15, 0.2);
|
|
486
493
|
--spacing-xxs: 4px;
|
|
@@ -897,6 +904,7 @@
|
|
|
897
904
|
--shadow-subtle: 2px 2px 0 0 rgba(15, 15, 15, 1);
|
|
898
905
|
--shadow-card: 4px 4px 0 0 rgba(15, 15, 15, 1);
|
|
899
906
|
--shadow-elevated: 6px 6px 0 0 rgba(15, 15, 15, 1);
|
|
907
|
+
--spacing-shadow-elevated-drop: 6px; /* the Y offset of --shadow-elevated above */
|
|
900
908
|
--shadow-modal: 8px 8px 0 0 rgba(15, 15, 15, 1);
|
|
901
909
|
--shadow-hero-mockup: 12px 12px 0 0 rgba(15, 15, 15, 1);
|
|
902
910
|
|
|
@@ -1994,7 +2002,7 @@
|
|
|
1994
2002
|
hover/press bounce. Colour stays the palette axis: the token block sets no
|
|
1995
2003
|
`--color-` / `--el-` colour token (AA preserved), and the rough-border rule
|
|
1996
2004
|
takes its ink from the palette (var(--el-border-strong)). Out-of-the-box type
|
|
1997
|
-
is the
|
|
2005
|
+
is the hand-lettered Marker (Caveat) pairing via `defaultTypeId`. See
|
|
1998
2006
|
docs/styles/hand-drawn-indie.md. */
|
|
1999
2007
|
[data-style='hand-drawn-indie'] {
|
|
2000
2008
|
/* Silhouette — WONKY hand-drawn corners. The slash splits horizontal /
|
|
@@ -3703,6 +3711,20 @@
|
|
|
3703
3711
|
colour. NOT danger: nothing was lost or destroyed — the repository exists and
|
|
3704
3712
|
the plan is safe; the user simply cannot open it yet. */
|
|
3705
3713
|
--el-notif-access-refused: var(--color-warning);
|
|
3714
|
+
/* An organisation owner or admin HIBERNATED the recipient's agent (MOTIR-10368,
|
|
3715
|
+
per design/org-admin/design-notes.md, the Fleet delta's one token). Info, not
|
|
3716
|
+
warning or danger: nothing was lost — the files are kept and the owner can
|
|
3717
|
+
wake it — but somebody else acted on their agent and they should know. */
|
|
3718
|
+
--el-notif-agent-hibernated: var(--color-info);
|
|
3719
|
+
/* A review waits for the routed person's OWN agent (Story MOTIR-10327 · MOTIR-10340).
|
|
3720
|
+
--color-warning, the hue of the review markers' loud "awaiting" form, because the row
|
|
3721
|
+
says the same thing they do: something is waiting on you. Its own slot, as the
|
|
3722
|
+
access row has its own, so a palette can move one without the other. */
|
|
3723
|
+
--el-notif-review-to-run: var(--color-warning);
|
|
3724
|
+
/* An agent SENT BACK the recipient's card (Story MOTIR-10327 · MOTIR-10338).
|
|
3725
|
+
--color-destructive, the hue of the To fix tag the send-back puts on the card: the row
|
|
3726
|
+
says the card was refused and is now theirs to repair. Its own slot, as above. */
|
|
3727
|
+
--el-notif-review-sent-back: var(--color-destructive);
|
|
3706
3728
|
/* The EXECUTOR badge on a Workbench row's assignee avatar (Story MOTIR-2649 ·
|
|
3707
3729
|
Subtask MOTIR-2653, per design/workbench/design-notes.md §"The agent state"
|
|
3708
3730
|
— that area was renamed with the surface by MOTIR-4779).
|
|
@@ -6210,6 +6232,102 @@
|
|
|
6210
6232
|
--font-sans-tail: monospace;
|
|
6211
6233
|
}
|
|
6212
6234
|
|
|
6235
|
+
[data-type='marker'] {
|
|
6236
|
+
/* Marker (MOTIR-10553) — hand-lettered marker headlines over the Inter body.
|
|
6237
|
+
Adds one new face: Caveat, loaded in app/fonts.ts as --font-marker-source.
|
|
6238
|
+
Re-point the headline (serif) role at it; body (Inter, --font-sans) and meta
|
|
6239
|
+
(JetBrains, --font-mono) keep the base roles. Display-only, like editorial:
|
|
6240
|
+
a marker hand is unreadable as UI or body text, so only headlines re-type.
|
|
6241
|
+
The pairing chain names no generic keyword (the FONT SETS rule below slots
|
|
6242
|
+
the CJK face between it and the `cursive` tail). ONLY --font-* role tokens
|
|
6243
|
+
here (the disjointness guard): no colour (--el/--color) or shape
|
|
6244
|
+
(--radius/--spacing/--shadow) token. */
|
|
6245
|
+
--font-serif-pairing: var(--font-marker-source), 'Caveat';
|
|
6246
|
+
--font-serif-tail: cursive;
|
|
6247
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
6248
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
6249
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
6250
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
6251
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
6252
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
6253
|
+
--font-sans-pairing: var(--font-sans-source, 'Segoe UI'), 'Segoe UI', Roboto;
|
|
6254
|
+
--font-sans-tail: -apple-system, BlinkMacSystemFont, sans-serif;
|
|
6255
|
+
--font-mono-pairing: var(--font-mono-source, 'SF Mono'), 'SF Mono', Menlo;
|
|
6256
|
+
--font-mono-tail: monospace;
|
|
6257
|
+
}
|
|
6258
|
+
|
|
6259
|
+
[data-type='rounded'] {
|
|
6260
|
+
/* Rounded (MOTIR-10554) — a soft rounded sans across headlines AND body/UI.
|
|
6261
|
+
Re-point BOTH the headline (serif) role AND the body/UI (sans) role at
|
|
6262
|
+
Nunito (loaded in app/fonts.ts as --font-rounded-source), so the WHOLE app
|
|
6263
|
+
(nav, header, buttons, content) re-types — Nunito reads cleanly as a UI sans
|
|
6264
|
+
(Yue, 2026-06-19: the type axis must re-type the whole UI, chrome included).
|
|
6265
|
+
Meta stays JetBrains Mono (--font-mono). The pairing chains name no generic
|
|
6266
|
+
keyword, so the FONT SETS rule below slots the CJK face behind Nunito. ONLY
|
|
6267
|
+
font tokens here (the disjointness guard): no colour (--el / --color) or
|
|
6268
|
+
shape token. */
|
|
6269
|
+
--font-serif-pairing: var(--font-rounded-source), 'Nunito';
|
|
6270
|
+
--font-serif-tail: ui-sans-serif, system-ui, sans-serif;
|
|
6271
|
+
--font-sans-pairing: var(--font-rounded-source), 'Nunito';
|
|
6272
|
+
--font-sans-tail: ui-sans-serif, system-ui, sans-serif;
|
|
6273
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
6274
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
6275
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
6276
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
6277
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
6278
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
6279
|
+
--font-mono-pairing: var(--font-mono-source, 'SF Mono'), 'SF Mono', Menlo;
|
|
6280
|
+
--font-mono-tail: monospace;
|
|
6281
|
+
}
|
|
6282
|
+
|
|
6283
|
+
[data-type='slab'] {
|
|
6284
|
+
/* Slab (MOTIR-10555) — sturdy slab-serif headlines over the Inter body. Adds
|
|
6285
|
+
one new face: Roboto Slab, loaded in app/fonts.ts as --font-slab-source.
|
|
6286
|
+
Re-point the headline (serif) role at it; body (Inter, --font-sans) and meta
|
|
6287
|
+
(JetBrains, --font-mono) keep the base roles. Display-only, like editorial:
|
|
6288
|
+
heavy rectangular serifs crowd dense UI text at 12–14px, so only headlines
|
|
6289
|
+
re-type. The pairing chain names no generic keyword (the FONT SETS rule
|
|
6290
|
+
below slots the CJK face between it and the `serif` tail). ONLY --font-*
|
|
6291
|
+
role tokens here (the disjointness guard): no colour (--el/--color) or shape
|
|
6292
|
+
(--radius/--spacing/--shadow) token. */
|
|
6293
|
+
--font-serif-pairing: var(--font-slab-source), 'Roboto Slab', Rockwell;
|
|
6294
|
+
--font-serif-tail: serif;
|
|
6295
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
6296
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
6297
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
6298
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
6299
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
6300
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
6301
|
+
--font-sans-pairing: var(--font-sans-source, 'Segoe UI'), 'Segoe UI', Roboto;
|
|
6302
|
+
--font-sans-tail: -apple-system, BlinkMacSystemFont, sans-serif;
|
|
6303
|
+
--font-mono-pairing: var(--font-mono-source, 'SF Mono'), 'SF Mono', Menlo;
|
|
6304
|
+
--font-mono-tail: monospace;
|
|
6305
|
+
}
|
|
6306
|
+
|
|
6307
|
+
[data-type='humanist'] {
|
|
6308
|
+
/* Humanist (MOTIR-10556) — a warm humanist sans across headlines AND body/UI.
|
|
6309
|
+
Re-point BOTH the headline (serif) role AND the body/UI (sans) role at Fira
|
|
6310
|
+
Sans (loaded in app/fonts.ts as --font-humanist-source), so the WHOLE app
|
|
6311
|
+
(nav, header, buttons, content) re-types — Fira Sans was drawn as a screen UI
|
|
6312
|
+
face (Yue, 2026-06-19: the type axis must re-type the whole UI, chrome
|
|
6313
|
+
included). Meta stays JetBrains Mono (--font-mono). The pairing chains name
|
|
6314
|
+
no generic keyword, so the FONT SETS rule below slots the CJK face behind
|
|
6315
|
+
Fira Sans. ONLY font tokens here (the disjointness guard): no colour
|
|
6316
|
+
(--el / --color) or shape token. */
|
|
6317
|
+
--font-serif-pairing: var(--font-humanist-source), 'Fira Sans';
|
|
6318
|
+
--font-serif-tail: ui-sans-serif, system-ui, sans-serif;
|
|
6319
|
+
--font-sans-pairing: var(--font-humanist-source), 'Fira Sans';
|
|
6320
|
+
--font-sans-tail: ui-sans-serif, system-ui, sans-serif;
|
|
6321
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
6322
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
6323
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
6324
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
6325
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
6326
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
6327
|
+
--font-mono-pairing: var(--font-mono-source, 'SF Mono'), 'SF Mono', Menlo;
|
|
6328
|
+
--font-mono-tail: monospace;
|
|
6329
|
+
}
|
|
6330
|
+
|
|
6213
6331
|
/* ═══════════════════════════════════════════════════════════════════════
|
|
6214
6332
|
FONT SETS — the script face behind the pairing (Story MOTIR-7733 · MOTIR-7845)
|
|
6215
6333
|
A Type pairing (the [data-type] blocks above) decides each role's LATIN
|