Z User commited on
Commit
3c2f994
Β·
1 Parent(s): 14218cf

sync work in progress

Browse files
src/components/dssl/SiteRoot.tsx CHANGED
@@ -120,7 +120,7 @@ export default function SiteRoot() {
120
  </nav>
121
 
122
  <div className="nav-side">
123
- <a href="#/changelog" className="ver-badge" onClick={(e) => { e.preventDefault(); go("changelog"); }}>v0.3.4</a>
124
  <button type="button" className="theme-btn" onClick={cycleTheme} aria-label="Toggle color theme" title="Theme: auto / light / dark">
125
  <span className="icon-sun"><SunIcon /></span>
126
  <span className="icon-moon"><MoonIcon /></span>
@@ -148,7 +148,7 @@ export default function SiteRoot() {
148
  <div className="wrap footer-inner">
149
  <div className="footer-col">
150
  <div className="footer-note">
151
- <strong>DSSL</strong> β€” domain specific style language. Built v0.1 β†’ v0.3.4 while
152
  building this site; every feature it needed, it grew, and every bug you sent got
153
  fixed for real. This page runs on its own engine, no CSS files attached β€”
154
  the engine styles this DOM directly.
 
120
  </nav>
121
 
122
  <div className="nav-side">
123
+ <a href="#/changelog" className="ver-badge" onClick={(e) => { e.preventDefault(); go("changelog"); }}>v0.4.0</a>
124
  <button type="button" className="theme-btn" onClick={cycleTheme} aria-label="Toggle color theme" title="Theme: auto / light / dark">
125
  <span className="icon-sun"><SunIcon /></span>
126
  <span className="icon-moon"><MoonIcon /></span>
 
148
  <div className="wrap footer-inner">
149
  <div className="footer-col">
150
  <div className="footer-note">
151
+ <strong>DSSL</strong> β€” domain specific style language. Built v0.1 β†’ v0.4.0 while
152
  building this site; every feature it needed, it grew, and every bug you sent got
153
  fixed for real. This page runs on its own engine, no CSS files attached β€”
154
  the engine styles this DOM directly.
src/components/dssl/views/ChangelogView.tsx CHANGED
@@ -11,6 +11,25 @@ const ENTRIES: {
11
  code?: string;
12
  kind?: "spec" | "vote" | "add";
13
  }[] = [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  {
15
  version: "v0.1",
16
  date: "phase 1 Β· draft",
 
11
  code?: string;
12
  kind?: "spec" | "vote" | "add";
13
  }[] = [
14
+ {
15
+ version: "v0.4.0",
16
+ date: "growth phase Β· power tools",
17
+ title: "Reveal, choreograph, re-scope β€” the power tools release",
18
+ why: "the site wanted scroll-in reveals, and one card to go dangerous",
19
+ kind: "add",
20
+ body:
21
+ "Four features, all grown the honest way β€” something the site itself wanted to do, so the language learned to say it. (1) seen β€” a state that fires once when an element scrolls into view, engine-native because no CSS selector can know that; with no IntersectionObserver everything counts as seen, so content can never be trapped invisible. (2) stagger β€” a parent declaration that offsets each child's animation delay by its DOM position, turning motion blocks into cascading reveals. (3) scoped tokens β€” re-declare color.accent inside one rule and the whole subtree re-resolves, no second stylesheet. (4) per-property transitions β€” transition: 150 snap background-color, 300 transform β€” plus visually-hidden, the accessibility classic as a single word. The docs page got a live seen + stagger demo and a scoped-token box whose dots hover green inside the box and oxblood everywhere else.",
22
+ code: `// the reveal, end to end, zero JavaScript:
23
+ .pt-grid { stagger: 70 } // child i waits i Γ— 70ms
24
+ .pt-card {
25
+ seen { // engine-native scroll state
26
+ animate: rise-in 420 snap
27
+ }
28
+ }
29
+
30
+ // one subtree, different brand:
31
+ .danger { --color.accent: color.err }`,
32
+ },
33
  {
34
  version: "v0.1",
35
  date: "phase 1 Β· draft",
src/components/dssl/views/CheatSheetView.tsx CHANGED
@@ -86,8 +86,13 @@ grow: 1 z: 50`} />
86
  <span className="cheat-k">text & motion</span>
87
  <CodeBlock plain code={`font: 16/1.4 color.ink // size / leading / color
88
  fluid: 16, 24 // clamp() 360β†’1200px
89
- truncate // ellipsis
 
90
  transition: 150 snap // all 150ms, named easing
 
 
 
 
91
  easings: snap smooth bounce ease-in-out…
92
 
93
  motion pop { from { opacity: 0; translate: 0 16 } }
@@ -105,6 +110,7 @@ animate: pop 400 snap both`} />
105
  <CodeBlock plain code={`hover { … } focus { … }
106
  focus-visible { … } active { … }
107
  disabled checked empty open
 
108
 
109
  // states can restyle descendants too
110
  hover { .tip { opacity: 1 } }
@@ -160,7 +166,11 @@ button { use focus-ring }
160
  tokens {
161
  color { accent: oklch(62% 0.19 35) }
162
  space { lg: 24 }
163
- } // β†’ var(--dssl-color-accent), shared across files`} />
 
 
 
 
164
  </div>
165
 
166
  {/* ---------------------------------------------- api */}
 
86
  <span className="cheat-k">text & motion</span>
87
  <CodeBlock plain code={`font: 16/1.4 color.ink // size / leading / color
88
  fluid: 16, 24 // clamp() 360β†’1200px
89
+ truncate
90
+ visually-hidden // a11y: hidden to eyes, read by screen readers
91
  transition: 150 snap // all 150ms, named easing
92
+ transition: 150 snap background-color, 300 transform
93
+ // per-property specs
94
+ stagger: 60 // children cascade in, i Γ— 60ms
95
+
96
  easings: snap smooth bounce ease-in-out…
97
 
98
  motion pop { from { opacity: 0; translate: 0 16 } }
 
110
  <CodeBlock plain code={`hover { … } focus { … }
111
  focus-visible { … } active { … }
112
  disabled checked empty open
113
+ seen { … } // engine-native: fires once on scroll-in
114
 
115
  // states can restyle descendants too
116
  hover { .tip { opacity: 1 } }
 
166
  tokens {
167
  color { accent: oklch(62% 0.19 35) }
168
  space { lg: 24 }
169
+ } // β†’ var(--dssl-color-accent), shared across files
170
+
171
+ .danger {
172
+ --color.accent: color.err // re-declare a token per subtree
173
+ } // descendants re-resolve automatically`} />
174
  </div>
175
 
176
  {/* ---------------------------------------------- api */}
src/components/dssl/views/DocsView.tsx CHANGED
@@ -167,6 +167,39 @@ background: // values can continue
167
  <code>color.*</code> set. Override any of them from your own{" "}
168
  <code>tokens</code> block.
169
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  </section>
171
 
172
  <section className="doc-block" id="selectors">
@@ -199,6 +232,12 @@ background: // values can continue
199
  <b>and leaving</b> a state. Rules inside a state block can target
200
  descendants (tooltips, dropdowns) or the element itself.
201
  </p>
 
 
 
 
 
 
202
  <CodeBlock file="states.dssl" code={`.doc-card {
203
  transition: 200
204
 
@@ -334,9 +373,11 @@ background: // values can continue
334
  <tr><td><code>circle</code></td><td><code>circle: 36</code></td><td>width + height + border-radius: 50%</td></tr>
335
  <tr><td><code>grow</code> / <code>shrink</code> / <code>basis</code></td><td><code>grow: 1</code></td><td>flex-grow / flex-shrink / flex-basis</td></tr>
336
  <tr><td><code>truncate</code></td><td><code>truncate</code></td><td>ellipsis overflow (overflow hidden, nowrap)</td></tr>
 
337
  <tr><td><code>z</code></td><td><code>z: 50</code></td><td>z-index</td></tr>
338
- <tr><td><code>transition</code></td><td><code>transition: 150 snap</code></td><td>all 150ms cubic-bezier(0.2, 0.9, 0.3, 1)</td></tr>
339
  <tr><td><code>animate</code></td><td><code>animate: pop 400 snap</code></td><td>Web Animations API run of a motion block</td></tr>
 
340
  </tbody>
341
  </table>
342
  <p className="tbl-note">Named easings: <code>snap</code>, <code>smooth</code>, <code>bounce</code> + the standard set.</p>
@@ -391,6 +432,45 @@ button { use focus-ring }
391
  <span className="tok-demo"><PlayIcon /> DSSL.replay(&apos;.motion-box&apos;)</span>
392
  </button>
393
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
  </section>
395
 
396
  <section className="doc-block" id="errors">
 
167
  <code>color.*</code> set. Override any of them from your own{" "}
168
  <code>tokens</code> block.
169
  </p>
170
+ <p className="doc-lead" style={{ marginTop: 14 }}>
171
+ <b>v0.4 β€” tokens can be re-declared per element.</b> Assign to a dotted
172
+ token inside any rule and the custom property lands on that element;
173
+ since custom properties inherit, every <code>var()</code> in the subtree
174
+ re-resolves. This is how one card goes dangerous without a second
175
+ stylesheet β€” and the re-declaration is still a validated token name, not
176
+ a free-form string.
177
+ </p>
178
+ <CodeBlock file="scoped-tokens.dssl" code={`.danger {
179
+ --color.accent: color.err // re-declare accent for this subtree
180
+ --radius.md: 4 // sharper corners too, why not
181
+ }
182
+
183
+ // everything below re-resolves automatically:
184
+ .danger .badge {
185
+ color: color.accent-ink
186
+ background: color.accent // ← now the error red
187
+ }`} />
188
+ <div className="demo-box">
189
+ <div className="tok-scope">
190
+ <div className="tok-demo">
191
+ <button type="button" className="tok-dot">accent</button>
192
+ <button type="button" className="tok-dot">err</button>
193
+ <button type="button" className="tok-dot">muted</button>
194
+ </div>
195
+ <p className="doc-lead fine-print">
196
+ Inside this dashed box, <code>--color.accent: color.ok</code> β€” hover
197
+ the dots and their hover accent comes out <i>green</i>, while the same
198
+ dots anywhere else on this page hover oxblood. One declaration, whole
199
+ subtree re-resolved.
200
+ </p>
201
+ </div>
202
+ </div>
203
  </section>
204
 
205
  <section className="doc-block" id="selectors">
 
232
  <b>and leaving</b> a state. Rules inside a state block can target
233
  descendants (tooltips, dropdowns) or the element itself.
234
  </p>
235
+ <p className="doc-lead">
236
+ One state is not CSS at all: <code>seen</code> is engine-native β€” it fires
237
+ once, the first time the element scrolls into the viewport. It is how you
238
+ build reveal-on-scroll without a line of JavaScript (see <b>Motion</b> for
239
+ the full choreography).
240
+ </p>
241
  <CodeBlock file="states.dssl" code={`.doc-card {
242
  transition: 200
243
 
 
373
  <tr><td><code>circle</code></td><td><code>circle: 36</code></td><td>width + height + border-radius: 50%</td></tr>
374
  <tr><td><code>grow</code> / <code>shrink</code> / <code>basis</code></td><td><code>grow: 1</code></td><td>flex-grow / flex-shrink / flex-basis</td></tr>
375
  <tr><td><code>truncate</code></td><td><code>truncate</code></td><td>ellipsis overflow (overflow hidden, nowrap)</td></tr>
376
+ <tr><td><code>visually-hidden</code></td><td><code>visually-hidden</code></td><td>the a11y classic β€” invisible to eyes, announced by screen readers (clip pattern, one word instead of nine lines)</td></tr>
377
  <tr><td><code>z</code></td><td><code>z: 50</code></td><td>z-index</td></tr>
378
+ <tr><td><code>transition</code></td><td><code>transition: 150 snap</code> Β· <code>transition: 150 snap background-color, 300 transform</code></td><td>all 150ms β€” or per-property specs: duration Β· easing Β· property per comma part</td></tr>
379
  <tr><td><code>animate</code></td><td><code>animate: pop 400 snap</code></td><td>Web Animations API run of a motion block</td></tr>
380
+ <tr><td><code>stagger</code></td><td><code>stagger: 60</code> Β· <code>stagger: none</code></td><td>choreography β€” each element child&apos;s animation delay is offset by its DOM position Γ— 60ms (works with <code>seen</code>; see Motion)</td></tr>
381
  </tbody>
382
  </table>
383
  <p className="tbl-note">Named easings: <code>snap</code>, <code>smooth</code>, <code>bounce</code> + the standard set.</p>
 
432
  <span className="tok-demo"><PlayIcon /> DSSL.replay(&apos;.motion-box&apos;)</span>
433
  </button>
434
  </div>
435
+ <p className="doc-lead" style={{ marginTop: 18 }}>
436
+ <b>v0.4 β€” choreography.</b> Two additions turn motion into a
437
+ reveal-on-scroll system, still with zero JavaScript. <code>seen</code> is
438
+ an engine-native state that fires once when the element enters the
439
+ viewport β€” content can never be trapped invisible, because with no
440
+ IntersectionObserver everything counts as seen. And a parent with{" "}
441
+ <code>stagger: 60</code> offsets each element child&apos;s animation delay
442
+ by its DOM position, so grids and lists cascade in instead of arriving as
443
+ one wall.
444
+ </p>
445
+ <CodeBlock file="reveal.dssl" code={`motion rise-in {
446
+ from { opacity: 0; translate: 0 14 }
447
+ }
448
+
449
+ .pt-grid { stagger: 70 } // child i waits i Γ— 70ms
450
+
451
+ .pt-card {
452
+ seen { // engine-native: fires once on scroll-in
453
+ animate: rise-in 420 snap
454
+ }
455
+ }`} />
456
+ <div className="demo-box">
457
+ <div className="pt-grid">
458
+ {["1 parse", "2 resolve", "3 match", "4 style"].map((s) => {
459
+ const [n, ...rest] = s.split(" ");
460
+ return (
461
+ <div key={s} className="pt-card">
462
+ <span className="pt-num">{n}</span>
463
+ <span>{rest.join(" ")}</span>
464
+ </div>
465
+ );
466
+ })}
467
+ </div>
468
+ <p className="doc-lead fine-print">
469
+ These four cards were below your scroll position a moment ago β€” they
470
+ cascaded in via <code>seen</code> + <code>stagger: 70</code>, no JS.
471
+ Reload the page and scroll back here to watch it again.
472
+ </p>
473
+ </div>
474
  </section>
475
 
476
  <section className="doc-block" id="errors">
src/components/dssl/views/SpecView.tsx CHANGED
@@ -11,7 +11,7 @@ export default function SpecView() {
11
  <p className="page-sub">
12
  The v0.1 draft was put to a seven-point vote. This document is the ratified
13
  v0.2 result β€” every decision below is implemented by the engine serving this
14
- page. The engine itself has kept growing since: it is now at v0.3.4 (see the
15
  changelog for what the site demanded).
16
  </p>
17
  </div>
 
11
  <p className="page-sub">
12
  The v0.1 draft was put to a seven-point vote. This document is the ratified
13
  v0.2 result β€” every decision below is implemented by the engine serving this
14
+ page. The engine itself has kept growing since: it is now at v0.4.0 (see the
15
  changelog for what the site demanded).
16
  </p>
17
  </div>