stylegallery 0.1.6 → 0.1.8
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/AGENTS.md +13 -1
- package/DOMAINS.md +10 -6
- package/GOVERNANCE.md +14 -12
- package/LICENSE +28 -0
- package/LICENSE-DOCS +42 -0
- package/NOTICE +38 -0
- package/README.md +47 -15
- package/consumer-reference/agent-native/README.md +7 -7
- package/consumer-reference/agent-native/v2/admission-policy.json +196 -31
- package/consumer-reference/agent-native/v2/material-registry.json +1 -1
- package/consumer-reference/agent-native/v2/schema/admission-policy.schema.json +3 -3
- package/consumer-reference/agent-native/v2/schema/material-record.schema.json +1 -1
- package/design-engineering/component-contract.md +19 -3
- package/design-engineering/decision-tree.md +1 -0
- package/design-engineering/index.md +48 -0
- package/design-engineering/loading-and-feedback.md +91 -0
- package/design-engineering/native-interaction-contracts.md +94 -0
- package/design-engineering/state-management/decision-tree.md +60 -0
- package/design-engineering/state-management/index.md +61 -0
- package/design-engineering/state-management/patterns/derived-state.md +85 -0
- package/design-engineering/state-management/patterns/draft-and-baseline.md +86 -0
- package/design-engineering/state-management/patterns/id-selection.md +85 -0
- package/design-engineering/state-management/patterns/identity-reset.md +89 -0
- package/design-engineering/state-management/patterns/latest-request-wins.md +94 -0
- package/design-engineering/state-management/patterns/optimistic-overlay.md +98 -0
- package/design-engineering/state-management/patterns/single-flight.md +92 -0
- package/design-engineering/state-management/patterns/single-owner.md +89 -0
- package/design-engineering/state-management/patterns/submitted-snapshot.md +107 -0
- package/design-engineering/state-management/patterns/unsaved-navigation.md +100 -0
- package/design-engineering/state-management/patterns/url-state.md +96 -0
- package/design-engineering/state-management/patterns/versioned-restore.md +95 -0
- package/design-engineering/state-management/recipes/delete-undo.md +65 -0
- package/design-engineering/state-management/recipes/index.md +64 -0
- package/design-engineering/state-management/recipes/multi-step-form.md +65 -0
- package/design-engineering/state-management/recipes/search-detail.md +65 -0
- package/design-engineering/state-management/recipes/settings-save.md +64 -0
- package/design-engineering/state-management/state-brief.md +83 -0
- package/design-engineering/state-management/verification.md +65 -0
- package/design-engineering/text-input-and-internationalization.md +91 -0
- package/design-engineering/worked-examples.md +2 -0
- package/design-terminology/conflict-cases.md +51 -8
- package/design-terminology/index.md +6 -0
- package/design-terminology/interaction-semantics.md +87 -0
- package/design-terminology/source-kinds.md +1 -1
- package/design-terminology/source-vocabularies.md +17 -1
- package/design-terminology/token-semantics.md +90 -0
- package/design-terminology/typography-semantics.md +86 -0
- package/expression/brand-studies.md +50 -0
- package/expression/direction-brief.md +71 -0
- package/expression/directions/nocturne-editorial.md +80 -0
- package/expression/directions/warm-print.md +73 -0
- package/expression/index.md +40 -0
- package/expression/techniques/gradient-atmosphere.md +107 -0
- package/expression/techniques/grain-and-texture.md +83 -0
- package/expression/techniques/webgl-hero.md +123 -0
- package/guides/vocabulary.md +1 -1
- package/index.md +3 -3
- package/log.md +64 -0
- package/motion/accessible-motion.md +90 -0
- package/motion/index.md +9 -0
- package/motion/interaction-recipes.md +8 -2
- package/motion/interruption-and-retargeting.md +90 -0
- package/motion/observed-choreography.md +73 -0
- package/motion/rendering-and-performance.md +89 -0
- package/motion/techniques/kinetic-type.md +145 -0
- package/motion/techniques/scroll-choreography.md +154 -0
- package/package.json +76 -21
- package/platform-guides/adaptive-navigation.md +85 -0
- package/platform-guides/compatibility-matrix.md +1 -1
- package/platform-guides/index.md +6 -0
- package/platform-guides/input-and-focus.md +91 -0
- package/platform-guides/preferences-and-accessibility.md +90 -0
- package/quality/claim-records/stylegallery-multidomain-scope.md +2 -2
- package/quality/evidence/executable-evidence.md +1 -1
- package/quality/index.md +1 -2
- package/scripts/agent-native/v2/material-admission.mjs +1 -1
- package/scripts/agent-native/v2/material-identity.mjs +2 -2
- package/scripts/compiler/README.md +112 -0
- package/scripts/compiler/cli.mjs +51 -0
- package/scripts/compiler/mcp.mjs +53 -0
- package/scripts/compiler/operations.mjs +70 -0
- package/scripts/compiler/runtime.mjs +156 -0
- package/scripts/sg-entry.mjs +20 -0
- package/scripts/sg-server.mjs +20 -0
- package/showcase/README.md +113 -0
- package/game-ui/classification.md +0 -82
- package/game-ui/decision-tree.md +0 -81
- package/game-ui/index.md +0 -45
- package/game-ui/reference-record.md +0 -62
- package/game-ui/screen-hierarchy.md +0 -107
- package/game-ui/screen-recipes.md +0 -101
- package/game-ui/unity/architecture.md +0 -166
- package/game-ui/unity/cli-loop.md +0 -84
- package/game-ui/unity/org-wiki.md +0 -146
- package/game-ui/unity/repository-map.md +0 -102
- package/game-ui/unity/ui-systems.md +0 -85
- package/game-ui/verification-workflow.md +0 -100
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Domain Guide
|
|
3
|
+
title: Motion Rendering And Performance
|
|
4
|
+
description: Diagnose animation cost and choose native transition mechanisms with measurable behavior and complete fallbacks.
|
|
5
|
+
domain: motion
|
|
6
|
+
lifecycle: experimental
|
|
7
|
+
provenance_kind: local
|
|
8
|
+
reviewed_on: 2026-09-21
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Motion Rendering And Performance
|
|
12
|
+
|
|
13
|
+
Primary role: source-backed rendering diagnosis and mechanism selection.
|
|
14
|
+
|
|
15
|
+
## Repository Boundary
|
|
16
|
+
|
|
17
|
+
This guide owns questions about the delivery of product motion. It does not grant reusable Layout CSS animation properties, establish universal frame budgets, or treat a trace from one machine as proof for every device. Use the existing [Practice Reference](practice-reference.md) for the boundary between mechanics and taste.
|
|
18
|
+
|
|
19
|
+
## Reusable Method
|
|
20
|
+
|
|
21
|
+
Describe the visible failure before choosing a faster-looking API: input responds late, geometry jumps, frames arrive irregularly, content is blank during decoding, or the wrong state appears. Record the target browser/device, surface size, concurrent work, and source revision. Select evidence that distinguishes these failures.
|
|
22
|
+
|
|
23
|
+
### Source Findings
|
|
24
|
+
|
|
25
|
+
| Source | What it supports | What it does not establish |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| [web.dev animation guide](https://web.dev/articles/animations-guide) | Rendering work depends on the properties and effects involved; inspect paint and compositing behavior. | That a property or library always runs on a GPU. |
|
|
28
|
+
| [Layout thrashing](https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing) | Interleaved style writes and geometry reads can force synchronous layout; batching can avoid repeated work. | That every geometry read is a defect. |
|
|
29
|
+
| [Chrome runtime performance](https://developer.chrome.com/docs/devtools/performance) | Recorded frames and main-thread work can locate a runtime bottleneck. | Hardware equivalence between throttling and an actual device. |
|
|
30
|
+
| [View Transitions Level 1](https://www.w3.org/TR/css-view-transitions-1/) | Same-document transitions wrap a DOM update and expose distinct update, readiness, and finish promises. | Route state, data consistency, or a universal cross-document contract. |
|
|
31
|
+
| [Scroll-driven Animations](https://www.w3.org/TR/scroll-animations-1/) | Scroll progress and view progress are distinct timeline models. | That a visually scrubbed sequence has correct reading order or accessibility. |
|
|
32
|
+
| [CSS Transitions Level 2](https://www.w3.org/TR/css-transitions-2/#defining-before-change-style) | `@starting-style` supplies entry styling for relevant newly rendered elements. | Correct exit teardown, focus handling, or support in an unspecified runtime. |
|
|
33
|
+
|
|
34
|
+
These are dated source readings, not a compatibility table. The linked standards-track documents include work in progress; check the selected browser and feature combination before making a shipping claim.
|
|
35
|
+
|
|
36
|
+
### Match The Mechanism To The Responsibility
|
|
37
|
+
|
|
38
|
+
| Responsibility | Candidate | First failure probe |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| Animate one local state difference | CSS transition with a static endpoint | Disable transitions; the endpoint must still be correct. |
|
|
41
|
+
| Control an effect's playback lifecycle | Web Animations | Interrupt and dispose it; verify cleanup and promise handling. |
|
|
42
|
+
| Visually connect a replaced DOM state | Same-document View Transition | Skip the transition; the DOM update must still occur once. |
|
|
43
|
+
| Bind presentation to a scroll interval | Native scroll/view timeline where supported | Remove support; content must remain readable in order. |
|
|
44
|
+
| Coordinate media decoding with chapters | Consumer-owned controller | Delay or fail a frame decode; preserve a readable fallback. |
|
|
45
|
+
|
|
46
|
+
This selection table is a local reasoning aid. It does not rank CSS, JavaScript, or native APIs by universal speed.
|
|
47
|
+
|
|
48
|
+
### A Diagnostic Sequence
|
|
49
|
+
|
|
50
|
+
1. Reproduce the failure with representative content and a repeatable input sequence. Save the initial state, not just the final screenshot.
|
|
51
|
+
2. Inspect the slow interval: input queueing, script execution, style/layout, paint, compositing, and media work where the tooling exposes them.
|
|
52
|
+
3. Change one suspected cost while retaining the same task and information. For a suspected layout loop, batch the same reads before writes rather than removing the interaction.
|
|
53
|
+
4. Compare trace intervals and final behavior. Report both improvements and regressions; averaging the entire page can hide the bad interval.
|
|
54
|
+
5. Repeat on a declared target device when the claim concerns that device. Keep emulation and real-device observations separate.
|
|
55
|
+
|
|
56
|
+
For continuous motion, inspect frame delivery during the effect. For input responsiveness, use [Loading And Feedback](../design-engineering/loading-and-feedback.md) and its distinction between next paint and completed work. A responsive first frame can precede an unsuccessful operation.
|
|
57
|
+
|
|
58
|
+
### View Transition Failure Contract
|
|
59
|
+
|
|
60
|
+
Treat the DOM update as the essential operation. `updateCallbackDone` reports that update's result; `ready` can reject when an animation cannot start; visual skipping can still lead to successful completion. Handle the promises relevant to the selected API version and keep route/focus error handling independent of decoration. The [specification interface](https://www.w3.org/TR/css-view-transitions-1/#viewtransition) is the source for these distinctions.
|
|
61
|
+
|
|
62
|
+
Local probes: request a second navigation before the first effect ends, remove a named element, use a duplicate transition name, fail the update callback, and resize during capture. Determine which failures skip only the effect and which prevent the destination update. Do not infer business success from the existence of a transition object.
|
|
63
|
+
|
|
64
|
+
## Opinionated Guidance
|
|
65
|
+
|
|
66
|
+
Choose the smallest effect that explains the state change. Promote an element or retain a large snapshot only when the measured benefit justifies its lifetime and resource cost. Reducing the work is often easier to explain than adding coordination machinery, but retain evidence for the actual tradeoff.
|
|
67
|
+
|
|
68
|
+
## Platform-Specific Guidance
|
|
69
|
+
|
|
70
|
+
DevTools UI and event names change; record tool/browser versions and retain raw traces. A native timeline needs a source-bound fallback, especially for media chapters with independent decoding. Follow [Scroll-driven Story](interaction-recipes.md#scroll-driven-story) for reading, scroll ownership, and runnable examples.
|
|
71
|
+
|
|
72
|
+
## Unsupported Absolutes
|
|
73
|
+
|
|
74
|
+
An average FPS value cannot prove every frame arrived on time. Smooth video playback of a capture cannot establish input latency. A compositor-friendly effect does not remove image decode, memory, script, or accessibility costs.
|
|
75
|
+
|
|
76
|
+
## Verification Contract
|
|
77
|
+
|
|
78
|
+
Report the initial failure, task-preserving comparison, target environment, raw artifact locator, observed difference, and remaining limitations. Keep source-derived expectations separate from measured timings. Test the static path, rapid input, cold and warm media/cache conditions, and reduced motion when relevant.
|
|
79
|
+
|
|
80
|
+
The sequence above is a proposed diagnostic protocol; this documentation change captures no runtime performance evidence. Re-review when the effect, content scale, browser feature, or target hardware changes.
|
|
81
|
+
|
|
82
|
+
## Source, License, And Attribution
|
|
83
|
+
|
|
84
|
+
Locally authored synthesis. The linked official browser guidance and specifications were inspected 2026-09-21; no source code, figures, or tables are reproduced. `consumer_reference: not_applicable` because no consumer implementation or performance record is selected.
|
|
85
|
+
|
|
86
|
+
## IA Navigation
|
|
87
|
+
|
|
88
|
+
Parent: [Motion](index.md).
|
|
89
|
+
Next: [Motion Review Workflow](review-workflow.md).
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Domain Recipe
|
|
3
|
+
title: Kinetic Type Technique
|
|
4
|
+
description: Copy-ready split-word headline rises, scroll-lit paragraphs, count-ups, and marquees that keep accessible text intact.
|
|
5
|
+
domain: motion
|
|
6
|
+
lifecycle: experimental
|
|
7
|
+
provenance_kind: local
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Kinetic Type Technique
|
|
11
|
+
|
|
12
|
+
Primary role: executable motion technique.
|
|
13
|
+
|
|
14
|
+
## Repository Boundary
|
|
15
|
+
|
|
16
|
+
Product-layer script and CSS for `showcase/` works and consumer pages. Setup and the `.motion` enhancement gate come from [Scroll Choreography Technique](scroll-choreography.md).
|
|
17
|
+
|
|
18
|
+
## Reusable Method
|
|
19
|
+
|
|
20
|
+
### Split-Word Rise
|
|
21
|
+
|
|
22
|
+
Each word rises out of its own clipped line box. The heading keeps its full sentence as the accessible name, and the visual word spans are hidden from assistive technology.
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
function splitHeadings() {
|
|
26
|
+
for (const heading of document.querySelectorAll("[data-split]")) {
|
|
27
|
+
heading.setAttribute("aria-label", heading.textContent.replace(/\s+/g, " ").trim());
|
|
28
|
+
const fragment = document.createDocumentFragment();
|
|
29
|
+
for (const node of [...heading.childNodes]) {
|
|
30
|
+
const tag = node.nodeName === "EM" ? "em" : "span";
|
|
31
|
+
for (const word of node.textContent.split(/(\s+)/)) {
|
|
32
|
+
if (!word) continue;
|
|
33
|
+
if (/^\s+$/.test(word)) { fragment.append(" "); continue; }
|
|
34
|
+
const outer = document.createElement("span");
|
|
35
|
+
outer.className = "split_word";
|
|
36
|
+
outer.setAttribute("aria-hidden", "true");
|
|
37
|
+
const inner = document.createElement(tag);
|
|
38
|
+
inner.className = "split_inner";
|
|
39
|
+
inner.textContent = word;
|
|
40
|
+
outer.append(inner);
|
|
41
|
+
fragment.append(outer);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
heading.replaceChildren(fragment);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
splitHeadings();
|
|
48
|
+
gsap.to(".split_inner", { y: 0, duration: 1.3, ease: "expo.out", stagger: 0.06, delay: 0.15 });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```css
|
|
52
|
+
.motion .split_word { display: inline-block; overflow: clip; padding-block-end: 0.08em; vertical-align: top; }
|
|
53
|
+
.motion .split_inner { display: inline-block; transform: translateY(105%); }
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The `padding-block-end` keeps descenders from being clipped. Run the split before measuring anything, and only once.
|
|
57
|
+
|
|
58
|
+
### Scroll-Lit Paragraph
|
|
59
|
+
|
|
60
|
+
Words start dim and light up with scroll progress.
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
for (const paragraph of document.querySelectorAll("[data-words]")) {
|
|
64
|
+
const words = paragraph.textContent.trim().split(/\s+/);
|
|
65
|
+
paragraph.replaceChildren(...words.flatMap((word, index) => {
|
|
66
|
+
const span = Object.assign(document.createElement("span"), { className: "word_dim", textContent: word });
|
|
67
|
+
return index === 0 ? [span] : [" ", span];
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
gsap.to(".word_dim", {
|
|
71
|
+
opacity: 1, ease: "none", stagger: 0.4,
|
|
72
|
+
scrollTrigger: { trigger: "[data-words]", start: "top 78%", end: "bottom 45%", scrub: true },
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
.motion .word_dim { opacity: 0.16; }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Count-Up
|
|
81
|
+
|
|
82
|
+
The final number is in the HTML; motion only animates toward it.
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<dd data-count="41920">41,920</dd>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
for (const element of document.querySelectorAll("[data-count]")) {
|
|
90
|
+
const state = { value: 0 };
|
|
91
|
+
gsap.to(state, {
|
|
92
|
+
value: Number(element.dataset.count), duration: 2, ease: "power3.out",
|
|
93
|
+
onUpdate: () => { element.textContent = Math.round(state.value).toLocaleString("en-US"); },
|
|
94
|
+
scrollTrigger: { trigger: element, start: "top 88%", once: true },
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use `font-variant-numeric: tabular-nums` so the width does not jitter while counting.
|
|
100
|
+
|
|
101
|
+
### Marquee
|
|
102
|
+
|
|
103
|
+
Pure CSS. Duplicate the content once and translate by half.
|
|
104
|
+
|
|
105
|
+
```html
|
|
106
|
+
<div class="marquee" aria-hidden="true">
|
|
107
|
+
<div class="marquee_track"><span>One</span><span>Two</span><span>One</span><span>Two</span></div>
|
|
108
|
+
</div>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```css
|
|
112
|
+
.marquee { overflow: clip; }
|
|
113
|
+
.marquee_track { animation: marquee 32s linear infinite; display: flex; gap: 2.5rem; inline-size: max-content; white-space: nowrap; }
|
|
114
|
+
@keyframes marquee { to { transform: translateX(-50%); } }
|
|
115
|
+
@media (prefers-reduced-motion: reduce) {
|
|
116
|
+
.marquee_track { animation: none; flex-wrap: wrap; inline-size: auto; white-space: normal; }
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The marquee is decorative and `aria-hidden`. Never put the only copy of important text in it.
|
|
121
|
+
|
|
122
|
+
## Opinionated Guidance
|
|
123
|
+
|
|
124
|
+
Animate words, not letters. Letter-by-letter reveals look impressive once and read slowly every time after that.
|
|
125
|
+
|
|
126
|
+
## Platform-Specific Guidance
|
|
127
|
+
|
|
128
|
+
Splitting text breaks browser hyphenation and some `text-wrap: balance` results across word spans; check the split headline at 320px. Screen readers read the `aria-label`, so keep it identical to the visible sentence.
|
|
129
|
+
|
|
130
|
+
## Unsupported Absolutes
|
|
131
|
+
|
|
132
|
+
Stagger and duration values suit short display headlines. Long paragraphs should not rise word by word.
|
|
133
|
+
|
|
134
|
+
## Verification Contract
|
|
135
|
+
|
|
136
|
+
Under reduced motion or with no GSAP, every split heading and lit paragraph is fully visible and the marquee is static. `node scripts/check-showcase.mjs` enforces both.
|
|
137
|
+
|
|
138
|
+
## Source, License, And Attribution
|
|
139
|
+
|
|
140
|
+
Locally authored technique. GSAP is loaded at runtime under its own license; no library source is reproduced.
|
|
141
|
+
|
|
142
|
+
## IA Navigation
|
|
143
|
+
|
|
144
|
+
Parent: [Motion](../index.md).
|
|
145
|
+
Next: [Showcase](../../showcase/README.md).
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Domain Recipe
|
|
3
|
+
title: Scroll Choreography Technique
|
|
4
|
+
description: Copy-ready GSAP ScrollTrigger and Lenis setup, pinned horizontal travel, scrubbed scenes, and a native CSS scroll-timeline equivalent.
|
|
5
|
+
domain: motion
|
|
6
|
+
lifecycle: experimental
|
|
7
|
+
provenance_kind: local
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Scroll Choreography Technique
|
|
11
|
+
|
|
12
|
+
Primary role: executable motion technique.
|
|
13
|
+
|
|
14
|
+
## Repository Boundary
|
|
15
|
+
|
|
16
|
+
Product-layer script and CSS for `showcase/` works and consumer pages. The document keeps vertical scroll ownership; this technique never adds animation to reusable Layout pattern CSS. For scene contracts and briefs, use [Scroll-driven Story](../interaction-recipes.md#scroll-driven-story) and the [Motion Brief](../motion-brief.md).
|
|
17
|
+
|
|
18
|
+
## Reusable Method
|
|
19
|
+
|
|
20
|
+
### 1. Load As Enhancement
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js" defer></script>
|
|
24
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js" defer></script>
|
|
25
|
+
<script src="https://cdn.jsdelivr.net/npm/lenis@1.1.13/dist/lenis.min.js" defer></script>
|
|
26
|
+
<script type="module" src="app.js"></script>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
const reduceMotion = matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
31
|
+
const { gsap, ScrollTrigger, Lenis } = window;
|
|
32
|
+
if (gsap && ScrollTrigger && !reduceMotion) {
|
|
33
|
+
gsap.registerPlugin(ScrollTrigger);
|
|
34
|
+
document.documentElement.classList.add("motion"); // CSS hides pre-animation states only under .motion
|
|
35
|
+
startMotion();
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```css
|
|
40
|
+
.motion [data-reveal] { opacity: 0; transform: translateY(24px); }
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Initial hidden states live behind the `.motion` class. With no script, a failed CDN, or reduced motion, the page stays fully visible.
|
|
44
|
+
|
|
45
|
+
### 2. One Ticker For Smooth Scroll And Triggers
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
const lenis = new Lenis({ lerp: 0.11, wheelMultiplier: 0.9 });
|
|
49
|
+
lenis.on("scroll", ScrollTrigger.update);
|
|
50
|
+
gsap.ticker.add((time) => lenis.raf(time * 1000));
|
|
51
|
+
gsap.ticker.lagSmoothing(0);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Driving Lenis from GSAP's ticker keeps pinned scenes in step with the smoothed scroll. Two separate `requestAnimationFrame` loops make pins jitter.
|
|
55
|
+
|
|
56
|
+
In-page links should go through Lenis and still move focus:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
for (const link of document.querySelectorAll('a[href^="#"]')) {
|
|
60
|
+
link.addEventListener("click", (event) => {
|
|
61
|
+
const target = document.querySelector(link.getAttribute("href"));
|
|
62
|
+
if (!target) return;
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
lenis.scrollTo(target, { duration: 1.4 });
|
|
65
|
+
target.setAttribute("tabindex", "-1");
|
|
66
|
+
target.focus({ preventScroll: true });
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Reveal On Enter
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
gsap.to("[data-reveal]", {
|
|
75
|
+
opacity: 1, y: 0, duration: 1.1, ease: "expo.out", stagger: 0.12,
|
|
76
|
+
scrollTrigger: { trigger: ".section", start: "top 80%" },
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 4. Scrubbed Scene
|
|
81
|
+
|
|
82
|
+
Tie a property directly to scroll progress; `scrub: true` follows exactly, a number adds catch-up smoothing in seconds.
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
gsap.to(".hero_inner", {
|
|
86
|
+
yPercent: -18, opacity: 0.25, ease: "none",
|
|
87
|
+
scrollTrigger: { trigger: ".hero", start: "top top", end: "bottom top", scrub: true },
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 5. Pinned Horizontal Travel
|
|
92
|
+
|
|
93
|
+
Vertical scroll moves a horizontal track while the section is pinned. Enable it only where it fits and keep a vertical list otherwise.
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
const media = gsap.matchMedia();
|
|
97
|
+
media.add("(min-width: 64rem)", () => {
|
|
98
|
+
const track = document.querySelector(".schedule_track");
|
|
99
|
+
const distance = () => track.scrollWidth - document.documentElement.clientWidth;
|
|
100
|
+
gsap.to(track, {
|
|
101
|
+
x: () => -distance(), ease: "none",
|
|
102
|
+
scrollTrigger: { trigger: ".schedule", start: "top top", end: () => `+=${distance()}`, pin: true, scrub: 0.6, invalidateOnRefresh: true },
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```css
|
|
108
|
+
.schedule_viewport { overflow: clip; } /* the track never widens the document */
|
|
109
|
+
@media (min-width: 64rem) { .schedule_track { display: flex; inline-size: max-content; } }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Keep focusable controls out of the moving track, or they can receive focus while translated off-screen.
|
|
113
|
+
|
|
114
|
+
### 6. Native Alternative: CSS Scroll-Driven Animation
|
|
115
|
+
|
|
116
|
+
For a single scrubbed property with no library:
|
|
117
|
+
|
|
118
|
+
```css
|
|
119
|
+
@supports (animation-timeline: view()) {
|
|
120
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
121
|
+
.reveal {
|
|
122
|
+
animation: reveal linear both;
|
|
123
|
+
animation-range: entry 10% cover 35%;
|
|
124
|
+
animation-timeline: view();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
@keyframes reveal { from { opacity: 0; transform: translateY(40px); } }
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Opinionated Guidance
|
|
132
|
+
|
|
133
|
+
Choose three or four scroll scenes per page and make each one say something. A page where everything fades up on scroll has no choreography, only delay.
|
|
134
|
+
|
|
135
|
+
## Platform-Specific Guidance
|
|
136
|
+
|
|
137
|
+
Lenis smooths wheel input but leaves native touch scrolling alone by default, which is the right choice on phones. `ScrollTrigger.refresh()` runs on resize; functions for `x` and `end` plus `invalidateOnRefresh` let pinned distances recompute. CSS `animation-timeline` is not available in every engine; wrap it in `@supports`.
|
|
138
|
+
|
|
139
|
+
## Unsupported Absolutes
|
|
140
|
+
|
|
141
|
+
Durations, easings, and trigger offsets here were tuned for one page. Pinning is not appropriate for content that must be read at the reader's own pace.
|
|
142
|
+
|
|
143
|
+
## Verification Contract
|
|
144
|
+
|
|
145
|
+
A page using this technique passes `node scripts/check-showcase.mjs`: no horizontal overflow while pinned, focus order intact with Lenis active, and all text visible under reduced motion. Review the middle-scroll screenshot to confirm the pinned section clears any fixed header.
|
|
146
|
+
|
|
147
|
+
## Source, License, And Attribution
|
|
148
|
+
|
|
149
|
+
Locally authored technique. GSAP and Lenis are loaded at runtime under their own licenses; no library source is reproduced.
|
|
150
|
+
|
|
151
|
+
## IA Navigation
|
|
152
|
+
|
|
153
|
+
Parent: [Motion](../index.md).
|
|
154
|
+
Next: [Kinetic Type Technique](kinetic-type.md).
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stylegallery",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "A governed gallery of portable interface knowledge with
|
|
3
|
+
"version": "0.1.8",
|
|
4
|
+
"description": "A governed gallery of portable interface knowledge with knowledge CLIs, website compilation, and MCP servers.",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
6
7
|
"homepage": "https://github.com/changeroa/StyleGallery#readme",
|
|
7
8
|
"bugs": {
|
|
8
9
|
"url": "https://github.com/changeroa/StyleGallery/issues"
|
|
@@ -22,12 +23,16 @@
|
|
|
22
23
|
"engines": {
|
|
23
24
|
"node": ">=22"
|
|
24
25
|
},
|
|
26
|
+
"packageManager": "bun@1.3.14",
|
|
25
27
|
"files": [
|
|
26
28
|
"AGENTS.md",
|
|
27
29
|
"CATALOG.md",
|
|
28
30
|
"DOMAINS.md",
|
|
29
31
|
"GOVERNANCE.md",
|
|
30
32
|
"GUIDE.md",
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"LICENSE-DOCS",
|
|
35
|
+
"NOTICE",
|
|
31
36
|
"README.md",
|
|
32
37
|
"consumer-reference/agent-native/README.md",
|
|
33
38
|
"consumer-reference/agent-native/registry.json",
|
|
@@ -52,29 +57,52 @@
|
|
|
52
57
|
"design-engineering/decision-tree.md",
|
|
53
58
|
"design-engineering/index.md",
|
|
54
59
|
"design-engineering/interface-craft.md",
|
|
60
|
+
"design-engineering/loading-and-feedback.md",
|
|
61
|
+
"design-engineering/native-interaction-contracts.md",
|
|
55
62
|
"design-engineering/reference-profiles/governed-local/editorial/profile.json",
|
|
56
63
|
"design-engineering/reference-profiles/governed-local/index.md",
|
|
57
64
|
"design-engineering/reference-profiles/index.md",
|
|
65
|
+
"design-engineering/state-management/decision-tree.md",
|
|
66
|
+
"design-engineering/state-management/index.md",
|
|
67
|
+
"design-engineering/state-management/patterns/derived-state.md",
|
|
68
|
+
"design-engineering/state-management/patterns/draft-and-baseline.md",
|
|
69
|
+
"design-engineering/state-management/patterns/id-selection.md",
|
|
70
|
+
"design-engineering/state-management/patterns/identity-reset.md",
|
|
71
|
+
"design-engineering/state-management/patterns/latest-request-wins.md",
|
|
72
|
+
"design-engineering/state-management/patterns/optimistic-overlay.md",
|
|
73
|
+
"design-engineering/state-management/patterns/single-flight.md",
|
|
74
|
+
"design-engineering/state-management/patterns/single-owner.md",
|
|
75
|
+
"design-engineering/state-management/patterns/submitted-snapshot.md",
|
|
76
|
+
"design-engineering/state-management/patterns/unsaved-navigation.md",
|
|
77
|
+
"design-engineering/state-management/patterns/url-state.md",
|
|
78
|
+
"design-engineering/state-management/patterns/versioned-restore.md",
|
|
79
|
+
"design-engineering/state-management/recipes/delete-undo.md",
|
|
80
|
+
"design-engineering/state-management/recipes/index.md",
|
|
81
|
+
"design-engineering/state-management/recipes/multi-step-form.md",
|
|
82
|
+
"design-engineering/state-management/recipes/search-detail.md",
|
|
83
|
+
"design-engineering/state-management/recipes/settings-save.md",
|
|
84
|
+
"design-engineering/state-management/state-brief.md",
|
|
85
|
+
"design-engineering/state-management/verification.md",
|
|
86
|
+
"design-engineering/text-input-and-internationalization.md",
|
|
58
87
|
"design-engineering/worked-examples.md",
|
|
59
88
|
"design-terminology/comparison-workflow.md",
|
|
60
89
|
"design-terminology/concept-families.md",
|
|
61
90
|
"design-terminology/conflict-cases.md",
|
|
62
91
|
"design-terminology/index.md",
|
|
92
|
+
"design-terminology/interaction-semantics.md",
|
|
63
93
|
"design-terminology/relation-types.md",
|
|
64
94
|
"design-terminology/source-kinds.md",
|
|
65
95
|
"design-terminology/source-vocabularies.md",
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"game-ui/unity/ui-systems.md",
|
|
77
|
-
"game-ui/verification-workflow.md",
|
|
96
|
+
"design-terminology/token-semantics.md",
|
|
97
|
+
"design-terminology/typography-semantics.md",
|
|
98
|
+
"expression/brand-studies.md",
|
|
99
|
+
"expression/direction-brief.md",
|
|
100
|
+
"expression/directions/nocturne-editorial.md",
|
|
101
|
+
"expression/directions/warm-print.md",
|
|
102
|
+
"expression/index.md",
|
|
103
|
+
"expression/techniques/gradient-atmosphere.md",
|
|
104
|
+
"expression/techniques/grain-and-texture.md",
|
|
105
|
+
"expression/techniques/webgl-hero.md",
|
|
78
106
|
"guides/decision-tree.md",
|
|
79
107
|
"guides/documentation-mode-taxonomy.md",
|
|
80
108
|
"guides/layout-brief.md",
|
|
@@ -83,12 +111,18 @@
|
|
|
83
111
|
"index.md",
|
|
84
112
|
"layout/index.md",
|
|
85
113
|
"log.md",
|
|
114
|
+
"motion/accessible-motion.md",
|
|
86
115
|
"motion/decision-tree.md",
|
|
87
116
|
"motion/index.md",
|
|
88
117
|
"motion/interaction-recipes.md",
|
|
118
|
+
"motion/interruption-and-retargeting.md",
|
|
89
119
|
"motion/motion-brief.md",
|
|
120
|
+
"motion/observed-choreography.md",
|
|
90
121
|
"motion/practice-reference.md",
|
|
122
|
+
"motion/rendering-and-performance.md",
|
|
91
123
|
"motion/review-workflow.md",
|
|
124
|
+
"motion/techniques/kinetic-type.md",
|
|
125
|
+
"motion/techniques/scroll-choreography.md",
|
|
92
126
|
"motion/vocabulary.md",
|
|
93
127
|
"patterns/centering/center.md",
|
|
94
128
|
"patterns/centering/index.md",
|
|
@@ -147,10 +181,13 @@
|
|
|
147
181
|
"patterns/viewport-shell/sticky-footer.md",
|
|
148
182
|
"patterns/viewport-shell/sticky-header.md",
|
|
149
183
|
"platform-guides/adaptation-workflow.md",
|
|
184
|
+
"platform-guides/adaptive-navigation.md",
|
|
150
185
|
"platform-guides/android-interaction.md",
|
|
151
186
|
"platform-guides/apple-interaction.md",
|
|
152
187
|
"platform-guides/compatibility-matrix.md",
|
|
153
188
|
"platform-guides/index.md",
|
|
189
|
+
"platform-guides/input-and-focus.md",
|
|
190
|
+
"platform-guides/preferences-and-accessibility.md",
|
|
154
191
|
"platform-guides/windows-interaction.md",
|
|
155
192
|
"quality/claim-records/design-terminology-domain-scope.md",
|
|
156
193
|
"quality/claim-records/index.md",
|
|
@@ -214,19 +251,27 @@
|
|
|
214
251
|
"scripts/agent-native/v2/material-operation-registry.mjs",
|
|
215
252
|
"scripts/agent-native/v2/material-queries.mjs",
|
|
216
253
|
"scripts/agent-native/v2/material-registry.mjs",
|
|
254
|
+
"scripts/compiler/README.md",
|
|
255
|
+
"scripts/compiler/cli.mjs",
|
|
256
|
+
"scripts/compiler/mcp.mjs",
|
|
257
|
+
"scripts/compiler/operations.mjs",
|
|
258
|
+
"scripts/compiler/runtime.mjs",
|
|
259
|
+
"scripts/sg-entry.mjs",
|
|
217
260
|
"scripts/sg-material-mcp.mjs",
|
|
218
261
|
"scripts/sg-material.mjs",
|
|
219
262
|
"scripts/sg-mcp.mjs",
|
|
263
|
+
"scripts/sg-server.mjs",
|
|
220
264
|
"scripts/sg.mjs",
|
|
221
|
-
"scripts/strict-json.mjs"
|
|
265
|
+
"scripts/strict-json.mjs",
|
|
266
|
+
"showcase/README.md"
|
|
222
267
|
],
|
|
223
268
|
"bin": {
|
|
224
|
-
"sg": "scripts/sg.mjs",
|
|
269
|
+
"sg": "scripts/sg-entry.mjs",
|
|
225
270
|
"sg-material": "scripts/sg-material.mjs",
|
|
226
|
-
"stylegallery": "scripts/sg.mjs",
|
|
271
|
+
"stylegallery": "scripts/sg-entry.mjs",
|
|
227
272
|
"stylegallery-material": "scripts/sg-material.mjs",
|
|
228
273
|
"stylegallery-material-mcp": "scripts/sg-material-mcp.mjs",
|
|
229
|
-
"stylegallery-mcp": "scripts/sg-
|
|
274
|
+
"stylegallery-mcp": "scripts/sg-server.mjs"
|
|
230
275
|
},
|
|
231
276
|
"publishConfig": {
|
|
232
277
|
"access": "public"
|
|
@@ -251,13 +296,20 @@
|
|
|
251
296
|
"test:material": "node scripts/agent-native/v2/test-material-admission.mjs && node scripts/agent-native/v2/test-material-registry.mjs && node scripts/agent-native/v2/test-material-query.mjs && node scripts/agent-native/v2/test-material-context.mjs && node scripts/agent-native/v2/test-sg-material-cli.mjs && node scripts/agent-native/v2/test-material-mcp.mjs && node scripts/agent-native/v2/test-material-mcp-stdio.mjs && node scripts/agent-native/v2/test-sg-material-package.mjs",
|
|
252
297
|
"test:lifecycle-dispositions": "node scripts/test-lifecycle-disposition.mjs",
|
|
253
298
|
"validate:lifecycle-dispositions": "node scripts/validate-lifecycle-disposition.mjs --json",
|
|
254
|
-
"sg": "node scripts/sg.mjs",
|
|
299
|
+
"sg": "node scripts/sg-entry.mjs",
|
|
255
300
|
"sg:material": "node scripts/sg-material.mjs",
|
|
256
301
|
"sg:material:mcp": "node scripts/sg-material-mcp.mjs",
|
|
257
|
-
"sg:mcp": "node scripts/sg-
|
|
302
|
+
"sg:mcp": "node scripts/sg-server.mjs",
|
|
258
303
|
"test:agent-native": "node scripts/test-agent-knowledge-kernel.mjs --json && node scripts/test-agent-execution-kernel.mjs --json && node scripts/test-agent-execution-safety.mjs --json && node scripts/test-agent-events.mjs --json && node scripts/test-agent-learning.mjs --json && node scripts/test-agent-native-schemas.mjs --json && node scripts/test-sg-cli.mjs --json && node scripts/test-agent-conformance-receipt.mjs --json && node scripts/test-agent-mcp.mjs --json && node scripts/test-agent-registry-mcp-integrity.mjs --json && node scripts/test-agent-registry-mutations.mjs --json && node scripts/test-agent-adapter-conformance.mjs --json && node scripts/agent-native/v2/test-agent-extension-boundary.mjs && node scripts/test-agent-projections.mjs --json && node scripts/agent-native/v2/test-agent-v1-compatibility.mjs",
|
|
259
304
|
"validate": "node scripts/validate-reference-artifacts.mjs --manifest consumer-reference/generated/manifest.json --json",
|
|
260
|
-
"validate:component-state": "node scripts/validate-component-state.mjs --json && node scripts/generate-consumer-reference-evidence.mjs --check --json"
|
|
305
|
+
"validate:component-state": "node scripts/validate-component-state.mjs --json && node scripts/generate-consumer-reference-evidence.mjs --check --json",
|
|
306
|
+
"test:state-management": "node --test scripts/test-state-management-examples.mjs",
|
|
307
|
+
"test:showcase": "node scripts/check-showcase.mjs",
|
|
308
|
+
"test:showcase:self": "node scripts/test-check-showcase.mjs",
|
|
309
|
+
"showcase:serve": "node scripts/serve-showcase.mjs",
|
|
310
|
+
"test:compiler": "node --test scripts/test-sg-compiler.mjs",
|
|
311
|
+
"sg:v1": "node scripts/sg.mjs",
|
|
312
|
+
"sg:mcp:v1": "node scripts/sg-mcp.mjs"
|
|
261
313
|
},
|
|
262
314
|
"devDependencies": {
|
|
263
315
|
"@axe-core/playwright": "4.12.1",
|
|
@@ -270,5 +322,8 @@
|
|
|
270
322
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
271
323
|
"style-dictionary": "5.5.0",
|
|
272
324
|
"zod": "4.4.3"
|
|
325
|
+
},
|
|
326
|
+
"overrides": {
|
|
327
|
+
"brace-expansion": "5.0.9"
|
|
273
328
|
}
|
|
274
329
|
}
|