@brunosouzas/design-system 0.3.0 → 0.3.1

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
@@ -143,7 +143,8 @@ Thirteen pieces draw a metro map and its page diagrams, for [stackledger](https:
143
143
  - `surface: "light" | "dark"` picks the background they sit on (`surface.*` tokens); every map and diagram piece takes it except `pipe`; `ledgerMark` takes only `surface`. On dark the hard shadow takes `surface.dark.shadow` and the outline gets a light rim ([ADR 0003](docs/adr/0003-visual-language-and-colour-meaning.md), amendment of AB#157).
144
144
  - `inkScale` (0.25 to 8) thickens the outline, rim and shadow without changing the geometry, on `lineBadge`, `stationMarker`, `countBadge` and the three nodes; the map uses 1, the page diagrams 1.6. A shape's height (a marker's diameter) must be at least four outlines; a placeholder node, which draws no ink, is exempt.
145
145
  - A line's colour comes from the map's data, so `pipe.fill`, `lineBadge.fill` and `zone.fill` also accept `#RRGGBB`. Every other colour is a token path, and a cover spec rejects any hex.
146
- - The `map.*` tokens hold the measures (outline 3, shadow 3.5, line 12, casing 6, badge 20, node 46, ring 3, halo 1.5, licence 10, zone padding 32…), `surface.*.zoneOpacity` the zone's opacity (0.12, dark 0.22), and `site.*` the page palette, fonts and type scale of brunosouzas.com in light and dark.
146
+ - `map.bendRadius` (32) is the radius of a bundle's centre line at a 45° or 90° bend; no piece reads it, the map engine draws the arcs (`pipe.d` takes `A`).
147
+ - The `map.*` tokens hold the measures (outline 3, shadow 3.5, line 12, casing 6, badge 20, node 46, ring 3, halo 1.5, licence 10, zone padding 32, bend radius 32…), `surface.*.zoneOpacity` the zone's opacity (0.12, dark 0.22), and `site.*` the page palette, fonts and type scale of brunosouzas.com in light and dark.
147
148
 
148
149
  ```ts
149
150
  import { lineBadge, pipe, stationMarker, toSvg } from "@brunosouzas/design-system";
@@ -191,7 +192,7 @@ Add it to `src/pieces/library.ts` (or `src/pieces/metro.ts` for a map or diagram
191
192
 
192
193
  ### UI and link icons
193
194
 
194
- - `uiIcon({ name, x, y, size, colour })` draws one of seven glyphs of the sites' chrome in a 24-unit box and one token colour: `sun`, `moon`, `zoomIn`, `zoomOut`, `reset`, `calendar`, `download` (data in `UI_ICONS`).
195
+ - `uiIcon({ name, x, y, size, colour })` draws one of seven glyphs of the sites' chrome in a 24-unit box and one token colour: `sun`, `moon`, `zoomIn`, `zoomOut`, `reset`, `calendar`, `download` (data in `UI_ICONS`). `colour: "currentColor"` makes the icon follow its element's text colour (a button that inverts on hover, say); it only works when the SVG is inline in the page, since an `<img>` does not inherit the page's colour, and a cover spec refuses it.
195
196
  - `linkIcon({ icon, x, y, size, surface })` draws a link sticker as brunosouzas.com draws its social icons (46-unit box, light or dark frame): `github`, `linkedin`, `email`, `website` (data in `LINK_ICONS`). The GitHub mark is from [Font Awesome](https://fontawesome.com/), licensed [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
196
197
  - Neither holds a link, a style, a script or a URL, so a consumer can write one with `toSvg` inside its own `<svg xmlns=…>` and ship it as a static file.
197
198
 
@@ -10,7 +10,7 @@
10
10
  import { tokens } from "../../tokens/generated/tokens.js";
11
11
  import { PIECE_NAMES, PIECES, rings } from "./library.js";
12
12
  import { el, g } from "./node.js";
13
- import { COLOUR_TOKENS, checkParams, isColourLiteral, MAX_SIZE, PATH_DATA } from "./params.js";
13
+ import { COLOUR_TOKENS, CURRENT_COLOUR, checkParams, isColourLiteral, MAX_SIZE, PATH_DATA } from "./params.js";
14
14
  export const SAFE_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
15
15
  const TOP_LEVEL = ["id", "title", "description", "format", "background", "rings", "pieces", "custom"];
16
16
  /** Cover (800x420, the default) or banner (1200x420, rounded corners): spec cover-cli, "Banner output". */
@@ -191,6 +191,12 @@ export const validateCoverSpec = (spec) => {
191
191
  return void out.push({ path: `${at}.piece`, message: "rings belong to the cover's rings field" });
192
192
  const definition = PIECES[piece];
193
193
  const own = checkParams(definition.schema, params, at);
194
+ // A cover is a standalone image: currentColor (accepted by uiIcon for inline page icons) is refused.
195
+ for (const [name, spec] of Object.entries(definition.schema)) {
196
+ if (spec.kind === "color" && spec.currentColor && params[name] === CURRENT_COLOUR) {
197
+ own.push({ path: `${at}.${name}`, message: "currentColor is for icons inline in a page; a cover uses a token path" });
198
+ }
199
+ }
194
200
  out.push(...own);
195
201
  // Limits between parameters are reported with the schema's problems, except on a parameter
196
202
  // already reported; a relation that cannot read a broken parameter reports nothing.
@@ -5,9 +5,12 @@ export type ParamSpec = {
5
5
  exclusiveMin?: boolean;
6
6
  max?: number;
7
7
  integer?: boolean;
8
- } | {
8
+ }
9
+ /** A token path; with `currentColor`, also that exact keyword (uiIcon.colour only, card 170). */
10
+ | {
9
11
  kind: "color";
10
12
  required?: boolean;
13
+ currentColor?: boolean;
11
14
  }
12
15
  /** A token path, or a colour from the consumer's data (#RRGGBB): pipe and lineBadge fills only. */
13
16
  | {
@@ -72,6 +75,10 @@ export declare const size: (required?: boolean, min?: number) => ParamSpec;
72
75
  /** A position: any finite number, because a map position has no maximum. */
73
76
  export declare const pos: () => ParamSpec;
74
77
  export declare const col: () => ParamSpec;
78
+ /** The paint keyword that follows the text colour of an inline SVG's element. */
79
+ export declare const CURRENT_COLOUR = "currentColor";
80
+ /** A token path or `currentColor`: for icons written inline in a page. */
81
+ export declare const colOrCurrent: () => ParamSpec;
75
82
  /** SVG path data: commands, digits, signs, dots, commas and spaces only. */
76
83
  export declare const PATH_DATA: RegExp;
77
84
  export declare const label: (required?: boolean) => ParamSpec;
@@ -55,6 +55,8 @@ const checkValue = (spec, value, path, out) => {
55
55
  return;
56
56
  }
57
57
  case "color":
58
+ if (spec.currentColor && value === CURRENT_COLOUR)
59
+ return;
58
60
  if (typeof value !== "string")
59
61
  return report(`expected a colour token path, found ${describe(value)}`);
60
62
  if (isColourLiteral(value))
@@ -144,6 +146,10 @@ export const size = (required = false, min) => min === undefined ? { kind: "numb
144
146
  /** A position: any finite number, because a map position has no maximum. */
145
147
  export const pos = () => ({ kind: "number", required: true });
146
148
  export const col = () => ({ kind: "color" });
149
+ /** The paint keyword that follows the text colour of an inline SVG's element. */
150
+ export const CURRENT_COLOUR = "currentColor";
151
+ /** A token path or `currentColor`: for icons written inline in a page. */
152
+ export const colOrCurrent = () => ({ kind: "color", currentColor: true });
147
153
  /** SVG path data: commands, digits, signs, dots, commas and spaces only. */
148
154
  export const PATH_DATA = /^[MmLlHhVvCcSsQqTtAaZz0-9eE.,+\-\s]+$/;
149
155
  export const label = (required = true) => ({ kind: "string", nonEmpty: true, required });
@@ -16,5 +16,6 @@ export type UiIconParams = {
16
16
  size?: number;
17
17
  colour?: string;
18
18
  };
19
- /** One UI icon at (x, y), `size` wide (24 by default), in one token colour (`color.ink` by default). */
19
+ /** One UI icon at (x, y), `size` wide (24 by default), in one token colour (`color.ink` by default)
20
+ * or `currentColor`, so an icon inline in a page follows its element's text colour. */
20
21
  export declare const uiIcon: import("./piece.ts").Piece<UiIconParams>;
@@ -1,5 +1,5 @@
1
1
  import { el, g, drawn, r2 } from "./node.js";
2
- import { col, pos, size } from "./params.js";
2
+ import { CURRENT_COLOUR, colOrCurrent, pos, size } from "./params.js";
3
3
  import { definePiece } from "./piece.js";
4
4
  import { colour } from "./params.js";
5
5
  /** Every UI icon draws in a 24x24 box. */
@@ -26,9 +26,10 @@ export const UI_ICONS = [
26
26
  { name: "download", title: "Download", description: "An arrow down into a tray.", nodes: [stroked("M12 3.5v11M7.5 10l4.5 4.5 4.5-4.5M4.5 16.5v3h15v-3")] },
27
27
  ];
28
28
  export const UI_ICON_NAMES = UI_ICONS.map((icon) => icon.name);
29
- /** One UI icon at (x, y), `size` wide (24 by default), in one token colour (`color.ink` by default). */
30
- export const uiIcon = definePiece("uiIcon", { name: { kind: "enum", required: true, values: UI_ICON_NAMES }, x: pos(), y: pos(), size: size(), colour: col() }, ({ name, x, y, size: side = UI_ICON_SIZE, colour: path = "color.ink" }) => {
29
+ /** One UI icon at (x, y), `size` wide (24 by default), in one token colour (`color.ink` by default)
30
+ * or `currentColor`, so an icon inline in a page follows its element's text colour. */
31
+ export const uiIcon = definePiece("uiIcon", { name: { kind: "enum", required: true, values: UI_ICON_NAMES }, x: pos(), y: pos(), size: size(), colour: colOrCurrent() }, ({ name, x, y, size: side = UI_ICON_SIZE, colour: path = "color.ink" }) => {
31
32
  const icon = UI_ICONS.find((candidate) => candidate.name === name);
32
- const paint = colour(path, "colour");
33
+ const paint = path === CURRENT_COLOUR ? CURRENT_COLOUR : colour(path, "colour");
33
34
  return drawn([g({ transform: `translate(${r2(x)} ${r2(y)}) scale(${side / UI_ICON_SIZE})`, fill: paint, stroke: paint }, ...icon.nodes)]);
34
35
  });
@@ -132,6 +132,7 @@ export declare const tokens: {
132
132
  readonly map: {
133
133
  readonly badgeHeight: 20;
134
134
  readonly badgeTextSize: 12;
135
+ readonly bendRadius: 32;
135
136
  readonly casing: 6;
136
137
  readonly countHeight: 16;
137
138
  readonly countTextSize: 11;
@@ -133,6 +133,7 @@ export const tokens = {
133
133
  "map": {
134
134
  "badgeHeight": 20,
135
135
  "badgeTextSize": 12,
136
+ "bendRadius": 32,
136
137
  "casing": 6,
137
138
  "countHeight": 16,
138
139
  "countTextSize": 11,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brunosouzas/design-system",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Design tokens and illustration pieces of brunosouzas.com: tokens as CSS, JSON and TypeScript, pieces that draw SVG (and React), and a cover command.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -78,6 +78,7 @@
78
78
  --ds-illustration-transitional-shade: #E8B830;
79
79
  --ds-map-badge-height: 20px;
80
80
  --ds-map-badge-text-size: 12px;
81
+ --ds-map-bend-radius: 32px;
81
82
  --ds-map-casing: 6px;
82
83
  --ds-map-count-height: 16px;
83
84
  --ds-map-count-text-size: 11px;
@@ -132,6 +132,7 @@
132
132
  "map": {
133
133
  "badgeHeight": 20,
134
134
  "badgeTextSize": 12,
135
+ "bendRadius": 32,
135
136
  "casing": 6,
136
137
  "countHeight": 16,
137
138
  "countTextSize": 11,
@@ -134,6 +134,7 @@ export const tokens = {
134
134
  "map": {
135
135
  "badgeHeight": 20,
136
136
  "badgeTextSize": 12,
137
+ "bendRadius": 32,
137
138
  "casing": 6,
138
139
  "countHeight": 16,
139
140
  "countTextSize": 11,