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.
|
| 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.
|
| 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
|
|
|
|
| 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
|
| 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('.motion-box')</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'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('.motion-box')</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'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.
|
| 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>
|