@danieldeusing/design 0.1.1 → 0.1.3

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
@@ -32,7 +32,7 @@ Link the built bundle from jsDelivr and you have the whole look. **Pin a release
32
32
  <meta name="viewport" content="width=device-width, initial-scale=1" />
33
33
  <meta name="theme-color" content="#f5efe2" />
34
34
 
35
- <!-- pre-paint: apply the saved theme before first paint to avoid a flash -->
35
+ <!-- pre-paint: apply the saved theme + resolution zoom before first paint -->
36
36
  <script>
37
37
  (() => {
38
38
  const bg = { warm: "#f5efe2", green: "#020604", mono: "#050505", paper: "#fafafa" };
@@ -41,11 +41,16 @@ Link the built bundle from jsDelivr and you have the whole look. **Pin a release
41
41
  document.documentElement.dataset.theme = t;
42
42
  document.querySelector('meta[name=theme-color]')?.setAttribute("content", bg[t]);
43
43
  })();
44
+ // resolution-independent zoom: scale the whole layout up past a 1920px reference
45
+ (() => {
46
+ const z = () => { document.documentElement.style.zoom = String(Math.max(1, innerWidth / 1920)); };
47
+ z(); addEventListener("resize", z);
48
+ })();
44
49
  </script>
45
50
 
46
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/danieldeusing/danieldeusing-design@v0.1.1/dist/danieldeusing-design.min.css" />
51
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@danieldeusing/design@0.1.2/dist/danieldeusing-design.min.css" />
47
52
  <!-- optional: the real JetBrains Mono webfont (otherwise falls back to Menlo) -->
48
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/danieldeusing/danieldeusing-design@v0.1.1/src/fonts.css" />
53
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@danieldeusing/design@0.1.2/src/fonts.css" />
49
54
  </head>
50
55
  <body>
51
56
  <p class="prompt">cat hello.txt</p>
@@ -54,7 +59,7 @@ Link the built bundle from jsDelivr and you have the whole look. **Pin a release
54
59
 
55
60
  <script type="module">
56
61
  import { initThemeSwitcher, initDropdowns, initTerminal } from
57
- "https://cdn.jsdelivr.net/gh/danieldeusing/danieldeusing-design@v0.1.1/runtime/index.js";
62
+ "https://cdn.jsdelivr.net/npm/@danieldeusing/design@0.1.2/runtime/index.js";
58
63
  initThemeSwitcher();
59
64
  initDropdowns();
60
65
  initTerminal();
@@ -105,14 +110,17 @@ Four dependency-free ES modules, tree-shakeable from `@danieldeusing/design/runt
105
110
  | `setTheme(name)` / `initThemeSwitcher()` | Switch themes and wire `[data-theme-value]` buttons + `[data-theme-label]`. |
106
111
  | `initTerminal()` | The `$ command` typing animation. No-ops under reduced motion / `html.anim-off`. |
107
112
  | `initDropdowns()` | `<details class="dropdown">` behaviour: one-open, click-away, Escape. |
113
+ | `initAnimToggle()` | Wire `[data-anim-toggle]` buttons (`.anim-toggle`) to flip `html.anim-off` + persist it. |
108
114
  | `initResolutionZoom(1920)` | Scale the whole layout up on screens wider than the reference width. |
109
115
 
110
116
  ```js
111
- import { applyStoredTheme, initThemeSwitcher, initDropdowns, initTerminal } from "@danieldeusing/design/runtime";
117
+ import { applyStoredTheme, initThemeSwitcher, initDropdowns, initTerminal, initAnimToggle, initResolutionZoom } from "@danieldeusing/design/runtime";
112
118
  applyStoredTheme(); // ideally inline, pre-paint
119
+ initResolutionZoom(); // ideally inline, pre-paint (no flash)
113
120
  initThemeSwitcher();
114
121
  initDropdowns();
115
122
  initTerminal();
123
+ initAnimToggle();
116
124
  ```
117
125
 
118
126
  The runtime is **progressive enhancement**: with JS disabled, or `prefers-reduced-motion`, all
@@ -1,4 +1,4 @@
1
- /*! danieldeusing-design v0.1.1 | MIT | https://github.com/danieldeusing/danieldeusing-design */
1
+ /*! danieldeusing-design v0.1.3 | MIT | https://github.com/danieldeusing/danieldeusing-design */
2
2
  /* ===== reset.css ===== */
3
3
  /*
4
4
  * danieldeusing-design — minimal reset.
@@ -352,6 +352,58 @@ body::after {
352
352
  color: var(--primary);
353
353
  }
354
354
 
355
+ /* Animations on/off toggle — a chrome control (footer/status bar). Pairs with
356
+ runtime/anim.js and the html.anim-off kill-switch. The [data-anim-box] glyph
357
+ lights up in the primary colour while animations are enabled. */
358
+ .anim-toggle {
359
+ display: inline-flex;
360
+ align-items: center;
361
+ gap: 6px;
362
+ font: inherit;
363
+ color: var(--muted-foreground);
364
+ background: none;
365
+ border: 0;
366
+ cursor: pointer;
367
+ transition: color 0.15s ease;
368
+ }
369
+ .anim-toggle:hover {
370
+ color: var(--primary);
371
+ }
372
+ .anim-toggle[aria-pressed="true"] [data-anim-box] {
373
+ color: var(--primary);
374
+ }
375
+
376
+ /* ─────────────────────────────────────────────────────────────────────────
377
+ Settings-control icons — centralized so every consuming site shares ONE
378
+ source. These were hardcoded per-site (a half-circle glyph, emoji flags),
379
+ which drifted; keep them here instead. CSS-only (no runtime needed): the
380
+ theme indicator is a dot in currentColor, the language flags are crisp SVG
381
+ data-URIs. Use:
382
+ <span class="dd-dot"></span> theme indicator
383
+ <span class="dd-flag dd-flag-de"></span> language flag (de|en|pt|es)
384
+ ───────────────────────────────────────────────────────────────────────── */
385
+ .dd-dot {
386
+ display: inline-block;
387
+ width: 11px;
388
+ height: 11px;
389
+ flex: none;
390
+ border-radius: 50%;
391
+ background: currentColor;
392
+ }
393
+ .dd-flag {
394
+ display: inline-block;
395
+ width: 15px;
396
+ height: 10px;
397
+ flex: none;
398
+ border: 1px solid var(--border);
399
+ background-size: cover;
400
+ background-repeat: no-repeat;
401
+ }
402
+ .dd-flag-de { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='4' fill='%23262626'/><rect y='4' width='18' height='4' fill='%23c83232'/><rect y='8' width='18' height='4' fill='%23e8be32'/></svg>"); }
403
+ .dd-flag-en { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%23b22234'/><rect y='4' width='18' height='4' fill='%23ececec'/><rect width='8' height='6' fill='%233c3b6e'/></svg>"); }
404
+ .dd-flag-pt { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%231c9148'/><polygon points='9,1.5 15.5,6 9,10.5 2.5,6' fill='%23e8c832'/><rect x='8' y='5' width='2' height='2' fill='%232c3f87'/></svg>"); }
405
+ .dd-flag-es { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='6' height='12' fill='%2315734c'/><rect x='6' width='6' height='12' fill='%23ececec'/><rect x='12' width='6' height='12' fill='%23bf2233'/><rect x='8' y='5' width='2' height='2' fill='%237a5c3a'/></svg>"); }
406
+
355
407
  /* ASCII horizontal rule — a clipped, full-width row of box-drawing dashes that
356
408
  reads like a terminal separator. Use on an <hr> or <div>; the dashes are a
357
409
  decorative ::before clipped to the element width. */
@@ -1,2 +1,2 @@
1
- /*! danieldeusing-design v0.1.1 | MIT | https://github.com/danieldeusing/danieldeusing-design */
2
- *,*::before,*::after{box-sizing: border-box}*{margin: 0}html{-webkit-text-size-adjust: 100%;text-size-adjust: 100%;tab-size: 4}body{min-height: 100vh;min-height: 100dvh;line-height: 1.5}img,picture,video,canvas,svg{display: block;max-width: 100%}input,button,textarea,select{font: inherit;color: inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap: break-word}ul,ol{list-style: none;padding: 0}a{color: inherit;text-decoration: none}table{border-collapse: collapse}:root{--background: #f5efe2;--foreground: #43352a;--card: #efe7d4;--card-foreground: #43352a;--popover: #efe7d4;--popover-foreground: #43352a;--primary: #8a4516;--primary-foreground: #f8f3e8;--secondary: #ece3cf;--secondary-foreground: #43352a;--muted: #ece3cf;--muted-foreground: #71614e;--accent: #8a4516;--accent-foreground: #f8f3e8;--destructive: #a02c2c;--border: #d9cdb6;--input: #d9cdb6;--ring: #8a4516;--glow: rgba(160,82,45,0.1);--glow-soft: rgba(160,82,45,0.05);--scanline-opacity: 0.15;--radius: 0rem;--font-mono: "JetBrains Mono Variable","JetBrains Mono","Menlo",monospace}html[data-theme="green"]{--background: #020604;--foreground: #4fdd7d;--card: #04110a;--card-foreground: #4fdd7d;--popover: #04110a;--popover-foreground: #4fdd7d;--primary: #33ff66;--primary-foreground: #02160a;--secondary: #071509;--secondary-foreground: #4fdd7d;--muted: #071509;--muted-foreground: #3da45e;--accent: #33ff66;--accent-foreground: #02160a;--destructive: #ff5c5c;--border: #1c4a2c;--input: #1c4a2c;--ring: #33ff66;--glow: rgba(51,255,102,0.35);--glow-soft: rgba(51,255,102,0.12);--scanline-opacity: 0.5}html[data-theme="mono"]{--background: #050505;--foreground: #d4d4d4;--card: #0d0d0d;--card-foreground: #d4d4d4;--popover: #0d0d0d;--popover-foreground: #d4d4d4;--primary: #ffffff;--primary-foreground: #050505;--secondary: #111111;--secondary-foreground: #d4d4d4;--muted: #111111;--muted-foreground: #8a8a8a;--accent: #ffffff;--accent-foreground: #050505;--destructive: #ff5c5c;--border: #333333;--input: #333333;--ring: #ffffff;--glow: rgba(255,255,255,0.25);--glow-soft: rgba(255,255,255,0.08);--scanline-opacity: 0.45}html[data-theme="paper"]{--background: #fafafa;--foreground: #1f1f1f;--card: #f1f1f1;--card-foreground: #1f1f1f;--popover: #f1f1f1;--popover-foreground: #1f1f1f;--primary: #000000;--primary-foreground: #fafafa;--secondary: #efefef;--secondary-foreground: #1f1f1f;--muted: #efefef;--muted-foreground: #595959;--accent: #000000;--accent-foreground: #fafafa;--destructive: #b3261e;--border: #d4d4d4;--input: #d4d4d4;--ring: #000000;--glow: rgba(0,0,0,0.06);--glow-soft: rgba(0,0,0,0.04);--scanline-opacity: 0.12}html{scroll-behavior: smooth}*,*::before,*::after{border-color: var(--border)}:focus-visible{outline: 2px solid var(--ring);outline-offset: 2px}body{background: var(--background);color: var(--foreground);font-family: var(--font-mono);font-size: 0.75rem;line-height: 1.5;overflow-x: hidden;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale}button:not(:disabled),summary,[role="button"]{cursor: pointer}body::after{content: "";position: fixed;inset: 0;z-index: 40;pointer-events: none;background: repeating-linear-gradient( 0deg,rgba(0,0,0,0.25) 0px,rgba(0,0,0,0.25) 1px,transparent 1px,transparent 3px );opacity: var(--scanline-opacity)}::selection{background: var(--primary);color: var(--primary-foreground)}.glow{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.glow-lg{color: var(--primary);text-shadow: 0 0 12px var(--glow)}.prompt{font-size: 0.75rem;font-weight: 700;color: var(--muted-foreground)}.prompt::before{content: "$ ";color: var(--primary)}.comment::before{content: "# ";color: var(--border)}.cursor-block{display: inline-block;width: 0.55em;height: 1em;margin-left: 8px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em);animation: ddd-blink 1.1s step-end infinite}@keyframes ddd-blink{50%{opacity: 0}}.btn-terminal{display: inline-block;background: var(--primary);color: var(--primary-foreground);font-weight: 700;padding: 12px 24px;box-shadow: 0 0 16px var(--glow);transition: box-shadow 0.15s ease,transform 0.15s ease}.btn-terminal::before{content: "> "}.btn-terminal:hover{box-shadow: 0 0 28px var(--glow);transform: translateY(-2px)}.link-quiet{color: var(--muted-foreground);text-decoration: underline;text-underline-offset: 4px;transition: color 0.15s ease}.link-quiet:hover{color: var(--primary)}.ascii-rule{margin: 1rem 0;border: 0;color: var(--border);line-height: 1;white-space: nowrap;overflow: hidden;user-select: none}.ascii-rule::before{content: "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"}.card-terminal{background: var(--card);border: 1px solid var(--border);transition: border-color 0.15s ease,box-shadow 0.15s ease}.card-terminal:hover{border-color: var(--primary);box-shadow: 0 0 20px var(--glow-soft)}.dropdown{position: relative}.dropdown>summary{display: inline-flex;align-items: center;gap: 6px;cursor: pointer;user-select: none;list-style: none;color: var(--muted-foreground);transition: color 0.15s ease}.dropdown>summary::-webkit-details-marker{display: none}.dropdown>summary:hover,.dropdown[open]>summary{color: var(--primary)}.dropdown-panel{position: absolute;right: 0;bottom: calc(100% + 12px);z-index: 50;min-width: 128px;margin: 0;padding: 4px 0;list-style: none;background: var(--card);border: 1px solid var(--border);border-radius: 0;box-shadow: 0 0 20px var(--glow-soft)}.dropdown-panel--down{top: calc(100% + 8px);bottom: auto;left: 0;right: auto}.dropdown-item{display: flex;align-items: center;gap: 8px;width: 100%;padding: 5px 14px;text-align: left;font: inherit;line-height: 1.5;background: none;border: 0;color: var(--muted-foreground);cursor: pointer;white-space: nowrap;transition: color 0.15s ease}.dropdown-item:hover{color: var(--primary);background: var(--muted)}.dropdown-item[aria-current="true"],html:not([data-theme]) .dropdown-item[data-theme-value="warm"],html[data-theme="green"] .dropdown-item[data-theme-value="green"],html[data-theme="mono"] .dropdown-item[data-theme-value="mono"],html[data-theme="paper"] .dropdown-item[data-theme-value="paper"],html[data-theme="warm"] .dropdown-item[data-theme-value="warm"]{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.eli5{margin: 1.25em 0;padding: 0.7em 1em;color: var(--foreground);background: color-mix(in srgb,var(--primary) 7%,var(--card));border: 1px solid var(--border);border-left: 3px solid var(--primary);border-radius: var(--radius);font-size: 0.92em;line-height: 1.6}.eli5::before{content: "ELI5";display: inline-flex;align-items: center;justify-content: center;margin-right: 0.6em;vertical-align: 0.08em;font-family: var(--font-mono);font-size: 0.72em;font-weight: 700;line-height: 1;letter-spacing: 0.04em;padding: 0.34em 0.6em;border-radius: 5px;background: #b42318;color: #fff}.eli5-term{font-weight: 700;color: var(--primary)}html.anim-off *,html.anim-off *::before,html.anim-off *::after{animation: none !important}html.anim-off .cursor-block{display: none}@media (prefers-reduced-motion: no-preference){html.term-anim [data-term] .prompt:not(.term-live),html.term-anim [data-term] .prompt:not(.term-live)::before{color: transparent}html.term-anim [data-term] [data-term-out]:not(.term-show){visibility: hidden}html.term-anim [data-term] [data-term-out].term-show{animation: ddd-term-output 0.2s steps(3,end) both}@keyframes ddd-term-output{from{opacity: 0}}html.term-anim [data-term] [data-term-out].term-show>*{animation: ddd-term-output 0.25s steps(3,end) both}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(2){animation-delay: 0.09s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(3){animation-delay: 0.18s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(4){animation-delay: 0.27s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(5){animation-delay: 0.36s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(6){animation-delay: 0.45s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(7){animation-delay: 0.54s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(8){animation-delay: 0.63s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(9){animation-delay: 0.72s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(10){animation-delay: 0.81s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(n + 11){animation-delay: 0.9s}.term-caret{display: inline-block;width: 0.55em;height: 1em;margin-left: 2px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em)}}
1
+ /*! danieldeusing-design v0.1.3 | MIT | https://github.com/danieldeusing/danieldeusing-design */
2
+ *,*::before,*::after{box-sizing: border-box}*{margin: 0}html{-webkit-text-size-adjust: 100%;text-size-adjust: 100%;tab-size: 4}body{min-height: 100vh;min-height: 100dvh;line-height: 1.5}img,picture,video,canvas,svg{display: block;max-width: 100%}input,button,textarea,select{font: inherit;color: inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap: break-word}ul,ol{list-style: none;padding: 0}a{color: inherit;text-decoration: none}table{border-collapse: collapse}:root{--background: #f5efe2;--foreground: #43352a;--card: #efe7d4;--card-foreground: #43352a;--popover: #efe7d4;--popover-foreground: #43352a;--primary: #8a4516;--primary-foreground: #f8f3e8;--secondary: #ece3cf;--secondary-foreground: #43352a;--muted: #ece3cf;--muted-foreground: #71614e;--accent: #8a4516;--accent-foreground: #f8f3e8;--destructive: #a02c2c;--border: #d9cdb6;--input: #d9cdb6;--ring: #8a4516;--glow: rgba(160,82,45,0.1);--glow-soft: rgba(160,82,45,0.05);--scanline-opacity: 0.15;--radius: 0rem;--font-mono: "JetBrains Mono Variable","JetBrains Mono","Menlo",monospace}html[data-theme="green"]{--background: #020604;--foreground: #4fdd7d;--card: #04110a;--card-foreground: #4fdd7d;--popover: #04110a;--popover-foreground: #4fdd7d;--primary: #33ff66;--primary-foreground: #02160a;--secondary: #071509;--secondary-foreground: #4fdd7d;--muted: #071509;--muted-foreground: #3da45e;--accent: #33ff66;--accent-foreground: #02160a;--destructive: #ff5c5c;--border: #1c4a2c;--input: #1c4a2c;--ring: #33ff66;--glow: rgba(51,255,102,0.35);--glow-soft: rgba(51,255,102,0.12);--scanline-opacity: 0.5}html[data-theme="mono"]{--background: #050505;--foreground: #d4d4d4;--card: #0d0d0d;--card-foreground: #d4d4d4;--popover: #0d0d0d;--popover-foreground: #d4d4d4;--primary: #ffffff;--primary-foreground: #050505;--secondary: #111111;--secondary-foreground: #d4d4d4;--muted: #111111;--muted-foreground: #8a8a8a;--accent: #ffffff;--accent-foreground: #050505;--destructive: #ff5c5c;--border: #333333;--input: #333333;--ring: #ffffff;--glow: rgba(255,255,255,0.25);--glow-soft: rgba(255,255,255,0.08);--scanline-opacity: 0.45}html[data-theme="paper"]{--background: #fafafa;--foreground: #1f1f1f;--card: #f1f1f1;--card-foreground: #1f1f1f;--popover: #f1f1f1;--popover-foreground: #1f1f1f;--primary: #000000;--primary-foreground: #fafafa;--secondary: #efefef;--secondary-foreground: #1f1f1f;--muted: #efefef;--muted-foreground: #595959;--accent: #000000;--accent-foreground: #fafafa;--destructive: #b3261e;--border: #d4d4d4;--input: #d4d4d4;--ring: #000000;--glow: rgba(0,0,0,0.06);--glow-soft: rgba(0,0,0,0.04);--scanline-opacity: 0.12}html{scroll-behavior: smooth}*,*::before,*::after{border-color: var(--border)}:focus-visible{outline: 2px solid var(--ring);outline-offset: 2px}body{background: var(--background);color: var(--foreground);font-family: var(--font-mono);font-size: 0.75rem;line-height: 1.5;overflow-x: hidden;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale}button:not(:disabled),summary,[role="button"]{cursor: pointer}body::after{content: "";position: fixed;inset: 0;z-index: 40;pointer-events: none;background: repeating-linear-gradient( 0deg,rgba(0,0,0,0.25) 0px,rgba(0,0,0,0.25) 1px,transparent 1px,transparent 3px );opacity: var(--scanline-opacity)}::selection{background: var(--primary);color: var(--primary-foreground)}.glow{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.glow-lg{color: var(--primary);text-shadow: 0 0 12px var(--glow)}.prompt{font-size: 0.75rem;font-weight: 700;color: var(--muted-foreground)}.prompt::before{content: "$ ";color: var(--primary)}.comment::before{content: "# ";color: var(--border)}.cursor-block{display: inline-block;width: 0.55em;height: 1em;margin-left: 8px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em);animation: ddd-blink 1.1s step-end infinite}@keyframes ddd-blink{50%{opacity: 0}}.btn-terminal{display: inline-block;background: var(--primary);color: var(--primary-foreground);font-weight: 700;padding: 12px 24px;box-shadow: 0 0 16px var(--glow);transition: box-shadow 0.15s ease,transform 0.15s ease}.btn-terminal::before{content: "> "}.btn-terminal:hover{box-shadow: 0 0 28px var(--glow);transform: translateY(-2px)}.link-quiet{color: var(--muted-foreground);text-decoration: underline;text-underline-offset: 4px;transition: color 0.15s ease}.link-quiet:hover{color: var(--primary)}.anim-toggle{display: inline-flex;align-items: center;gap: 6px;font: inherit;color: var(--muted-foreground);background: none;border: 0;cursor: pointer;transition: color 0.15s ease}.anim-toggle:hover{color: var(--primary)}.anim-toggle[aria-pressed="true"] [data-anim-box]{color: var(--primary)}.dd-dot{display: inline-block;width: 11px;height: 11px;flex: none;border-radius: 50%;background: currentColor}.dd-flag{display: inline-block;width: 15px;height: 10px;flex: none;border: 1px solid var(--border);background-size: cover;background-repeat: no-repeat}.dd-flag-de{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='4' fill='%23262626'/><rect y='4' width='18' height='4' fill='%23c83232'/><rect y='8' width='18' height='4' fill='%23e8be32'/></svg>")}.dd-flag-en{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%23b22234'/><rect y='4' width='18' height='4' fill='%23ececec'/><rect width='8' height='6' fill='%233c3b6e'/></svg>")}.dd-flag-pt{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%231c9148'/><polygon points='9,1.5 15.5,6 9,10.5 2.5,6' fill='%23e8c832'/><rect x='8' y='5' width='2' height='2' fill='%232c3f87'/></svg>")}.dd-flag-es{background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='6' height='12' fill='%2315734c'/><rect x='6' width='6' height='12' fill='%23ececec'/><rect x='12' width='6' height='12' fill='%23bf2233'/><rect x='8' y='5' width='2' height='2' fill='%237a5c3a'/></svg>")}.ascii-rule{margin: 1rem 0;border: 0;color: var(--border);line-height: 1;white-space: nowrap;overflow: hidden;user-select: none}.ascii-rule::before{content: "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"}.card-terminal{background: var(--card);border: 1px solid var(--border);transition: border-color 0.15s ease,box-shadow 0.15s ease}.card-terminal:hover{border-color: var(--primary);box-shadow: 0 0 20px var(--glow-soft)}.dropdown{position: relative}.dropdown>summary{display: inline-flex;align-items: center;gap: 6px;cursor: pointer;user-select: none;list-style: none;color: var(--muted-foreground);transition: color 0.15s ease}.dropdown>summary::-webkit-details-marker{display: none}.dropdown>summary:hover,.dropdown[open]>summary{color: var(--primary)}.dropdown-panel{position: absolute;right: 0;bottom: calc(100% + 12px);z-index: 50;min-width: 128px;margin: 0;padding: 4px 0;list-style: none;background: var(--card);border: 1px solid var(--border);border-radius: 0;box-shadow: 0 0 20px var(--glow-soft)}.dropdown-panel--down{top: calc(100% + 8px);bottom: auto;left: 0;right: auto}.dropdown-item{display: flex;align-items: center;gap: 8px;width: 100%;padding: 5px 14px;text-align: left;font: inherit;line-height: 1.5;background: none;border: 0;color: var(--muted-foreground);cursor: pointer;white-space: nowrap;transition: color 0.15s ease}.dropdown-item:hover{color: var(--primary);background: var(--muted)}.dropdown-item[aria-current="true"],html:not([data-theme]) .dropdown-item[data-theme-value="warm"],html[data-theme="green"] .dropdown-item[data-theme-value="green"],html[data-theme="mono"] .dropdown-item[data-theme-value="mono"],html[data-theme="paper"] .dropdown-item[data-theme-value="paper"],html[data-theme="warm"] .dropdown-item[data-theme-value="warm"]{color: var(--primary);text-shadow: 0 0 8px var(--glow)}.eli5{margin: 1.25em 0;padding: 0.7em 1em;color: var(--foreground);background: color-mix(in srgb,var(--primary) 7%,var(--card));border: 1px solid var(--border);border-left: 3px solid var(--primary);border-radius: var(--radius);font-size: 0.92em;line-height: 1.6}.eli5::before{content: "ELI5";display: inline-flex;align-items: center;justify-content: center;margin-right: 0.6em;vertical-align: 0.08em;font-family: var(--font-mono);font-size: 0.72em;font-weight: 700;line-height: 1;letter-spacing: 0.04em;padding: 0.34em 0.6em;border-radius: 5px;background: #b42318;color: #fff}.eli5-term{font-weight: 700;color: var(--primary)}html.anim-off *,html.anim-off *::before,html.anim-off *::after{animation: none !important}html.anim-off .cursor-block{display: none}@media (prefers-reduced-motion: no-preference){html.term-anim [data-term] .prompt:not(.term-live),html.term-anim [data-term] .prompt:not(.term-live)::before{color: transparent}html.term-anim [data-term] [data-term-out]:not(.term-show){visibility: hidden}html.term-anim [data-term] [data-term-out].term-show{animation: ddd-term-output 0.2s steps(3,end) both}@keyframes ddd-term-output{from{opacity: 0}}html.term-anim [data-term] [data-term-out].term-show>*{animation: ddd-term-output 0.25s steps(3,end) both}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(2){animation-delay: 0.09s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(3){animation-delay: 0.18s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(4){animation-delay: 0.27s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(5){animation-delay: 0.36s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(6){animation-delay: 0.45s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(7){animation-delay: 0.54s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(8){animation-delay: 0.63s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(9){animation-delay: 0.72s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(10){animation-delay: 0.81s}html.term-anim [data-term] [data-term-out].term-show>*:nth-child(n + 11){animation-delay: 0.9s}.term-caret{display: inline-block;width: 0.55em;height: 1em;margin-left: 2px;background: var(--primary);vertical-align: baseline;transform: translateY(0.12em)}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danieldeusing/design",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The danieldeusing terminal design system — framework-agnostic CSS tokens, components, and a vanilla-JS runtime for the CRT/JetBrains-Mono look used across danieldeusing.de, seedr, and briefs.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,50 @@
1
+ /*
2
+ * danieldeusing-design — animations on/off toggle.
3
+ *
4
+ * Wires up a footer/chrome control that turns every keyframe animation on or off,
5
+ * persisting the choice so it survives reloads. Pairs with the html.anim-off
6
+ * kill-switch in components.css and the pre-paint gate in terminal.js.
7
+ *
8
+ * Markup contract (style it with the .anim-toggle component class):
9
+ * <button type="button" class="anim-toggle" data-anim-toggle aria-pressed="true">
10
+ * <span data-anim-box aria-hidden="true">[x]</span>
11
+ * <span>anim</span>
12
+ * </button>
13
+ *
14
+ * The persisted key is "anim" ("on" | "off"); apply it pre-paint (inline, in
15
+ * <head>) the same way the theme is applied, so the choice never flashes.
16
+ */
17
+
18
+ export function initAnimToggle() {
19
+ const toggles = Array.from(document.querySelectorAll("[data-anim-toggle]"));
20
+ if (!toggles.length) return;
21
+
22
+ const sync = () => {
23
+ const on = !document.documentElement.classList.contains("anim-off");
24
+ for (const toggle of toggles) {
25
+ toggle.setAttribute("aria-pressed", String(on));
26
+ const box = toggle.querySelector("[data-anim-box]");
27
+ if (box) box.textContent = on ? "[x]" : "[ ]";
28
+ }
29
+ };
30
+ sync();
31
+
32
+ for (const toggle of toggles) {
33
+ toggle.addEventListener("click", () => {
34
+ const html = document.documentElement;
35
+ const turningOff = !html.classList.contains("anim-off");
36
+ if (turningOff) {
37
+ html.classList.add("anim-off");
38
+ html.classList.remove("term-anim"); // stop the terminal typing mid-run
39
+ } else {
40
+ html.classList.remove("anim-off");
41
+ }
42
+ try {
43
+ localStorage.setItem("anim", turningOff ? "off" : "on");
44
+ } catch {
45
+ /* private mode */
46
+ }
47
+ sync();
48
+ });
49
+ }
50
+ }
package/runtime/index.js CHANGED
@@ -13,4 +13,5 @@
13
13
  export * from "./theme.js";
14
14
  export * from "./zoom.js";
15
15
  export * from "./dropdown.js";
16
+ export * from "./anim.js";
16
17
  export * from "./terminal.js";
package/runtime/theme.js CHANGED
@@ -102,6 +102,8 @@ export function initThemeSwitcher(options) {
102
102
  const theme = /** @type {HTMLElement} */ (button).dataset.themeValue;
103
103
  if (theme) setTheme(/** @type {Theme} */ (theme), options);
104
104
  syncLabel();
105
+ // close the enclosing dropdown after a pick (no-op if not inside one)
106
+ button.closest("details.dropdown")?.removeAttribute("open");
105
107
  });
106
108
  });
107
109
  }
@@ -86,6 +86,58 @@
86
86
  color: var(--primary);
87
87
  }
88
88
 
89
+ /* Animations on/off toggle — a chrome control (footer/status bar). Pairs with
90
+ runtime/anim.js and the html.anim-off kill-switch. The [data-anim-box] glyph
91
+ lights up in the primary colour while animations are enabled. */
92
+ .anim-toggle {
93
+ display: inline-flex;
94
+ align-items: center;
95
+ gap: 6px;
96
+ font: inherit;
97
+ color: var(--muted-foreground);
98
+ background: none;
99
+ border: 0;
100
+ cursor: pointer;
101
+ transition: color 0.15s ease;
102
+ }
103
+ .anim-toggle:hover {
104
+ color: var(--primary);
105
+ }
106
+ .anim-toggle[aria-pressed="true"] [data-anim-box] {
107
+ color: var(--primary);
108
+ }
109
+
110
+ /* ─────────────────────────────────────────────────────────────────────────
111
+ Settings-control icons — centralized so every consuming site shares ONE
112
+ source. These were hardcoded per-site (a half-circle glyph, emoji flags),
113
+ which drifted; keep them here instead. CSS-only (no runtime needed): the
114
+ theme indicator is a dot in currentColor, the language flags are crisp SVG
115
+ data-URIs. Use:
116
+ <span class="dd-dot"></span> theme indicator
117
+ <span class="dd-flag dd-flag-de"></span> language flag (de|en|pt|es)
118
+ ───────────────────────────────────────────────────────────────────────── */
119
+ .dd-dot {
120
+ display: inline-block;
121
+ width: 11px;
122
+ height: 11px;
123
+ flex: none;
124
+ border-radius: 50%;
125
+ background: currentColor;
126
+ }
127
+ .dd-flag {
128
+ display: inline-block;
129
+ width: 15px;
130
+ height: 10px;
131
+ flex: none;
132
+ border: 1px solid var(--border);
133
+ background-size: cover;
134
+ background-repeat: no-repeat;
135
+ }
136
+ .dd-flag-de { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='4' fill='%23262626'/><rect y='4' width='18' height='4' fill='%23c83232'/><rect y='8' width='18' height='4' fill='%23e8be32'/></svg>"); }
137
+ .dd-flag-en { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%23b22234'/><rect y='4' width='18' height='4' fill='%23ececec'/><rect width='8' height='6' fill='%233c3b6e'/></svg>"); }
138
+ .dd-flag-pt { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='18' height='12' fill='%231c9148'/><polygon points='9,1.5 15.5,6 9,10.5 2.5,6' fill='%23e8c832'/><rect x='8' y='5' width='2' height='2' fill='%232c3f87'/></svg>"); }
139
+ .dd-flag-es { background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><rect width='6' height='12' fill='%2315734c'/><rect x='6' width='6' height='12' fill='%23ececec'/><rect x='12' width='6' height='12' fill='%23bf2233'/><rect x='8' y='5' width='2' height='2' fill='%237a5c3a'/></svg>"); }
140
+
89
141
  /* ASCII horizontal rule — a clipped, full-width row of box-drawing dashes that
90
142
  reads like a terminal separator. Use on an <hr> or <div>; the dashes are a
91
143
  decorative ::before clipped to the element width. */