@troshab/slidev-theme-troshab 0.1.0
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/CLAUDE.md +537 -0
- package/LICENSE +134 -0
- package/README.md +168 -0
- package/SKILL.md +414 -0
- package/components/AnimatedCounter.vue +35 -0
- package/components/Background.vue +204 -0
- package/components/Callout.vue +135 -0
- package/components/Card.vue +75 -0
- package/components/CardGrid.vue +67 -0
- package/components/CaseStudy.vue +66 -0
- package/components/CodeDiff.vue +229 -0
- package/components/CodeHighlight.vue +337 -0
- package/components/ColorSwatch.vue +114 -0
- package/components/Confetti.vue +292 -0
- package/components/Conversation.vue +405 -0
- package/components/Countdown.vue +476 -0
- package/components/Definition.vue +59 -0
- package/components/DeviceMockup.vue +392 -0
- package/components/Funnel.vue +87 -0
- package/components/Icon.vue +73 -0
- package/components/Iframe.vue +38 -0
- package/components/Image.vue +69 -0
- package/components/ImageCompare.vue +436 -0
- package/components/MatrixGrid.vue +85 -0
- package/components/MermaidChart.vue +299 -0
- package/components/Metric.vue +161 -0
- package/components/PersonCard.vue +165 -0
- package/components/PricingTable.vue +144 -0
- package/components/Progress.vue +100 -0
- package/components/Pyramid.vue +81 -0
- package/components/QRCode.vue +137 -0
- package/components/QuoteBlock.vue +101 -0
- package/components/SpeechBubble.vue +169 -0
- package/components/Stepper.vue +542 -0
- package/components/StyledList.vue +156 -0
- package/components/StyledText.vue +275 -0
- package/components/SwotGrid.vue +99 -0
- package/components/Tags.vue +20 -0
- package/components/Testimonial.vue +243 -0
- package/components/Typewriter.vue +181 -0
- package/components_base/AnimatedCounter.vue +208 -0
- package/components_base/CodeHighlight.vue +364 -0
- package/composables/useColors.ts +101 -0
- package/composables/useShiki.ts +81 -0
- package/example_content.md +371 -0
- package/example_dark.md +10 -0
- package/example_slides/001-cover.md +15 -0
- package/example_slides/002-agenda.md +25 -0
- package/example_slides/003-section-layouts.md +14 -0
- package/example_slides/004-fullscreen-centered.md +7 -0
- package/example_slides/005-fullscreen-align-bottom.md +14 -0
- package/example_slides/006-fullscreen-no-padding.md +14 -0
- package/example_slides/007-fullscreen-bg-image-dark.md +13 -0
- package/example_slides/008-fullscreen-bg-image-light.md +13 -0
- package/example_slides/009-fullscreen-bg-gradient.md +15 -0
- package/example_slides/010-fullscreen-bg-color.md +13 -0
- package/example_slides/011-split-basic.md +17 -0
- package/example_slides/012-split-image-text.md +18 -0
- package/example_slides/013-split-contrast.md +22 -0
- package/example_slides/014-columns-basic.md +13 -0
- package/example_slides/015-columns-two.md +26 -0
- package/example_slides/016-columns-ratios.md +22 -0
- package/example_slides/017-columns-three.md +31 -0
- package/example_slides/018-columns-four.md +22 -0
- package/example_slides/019-columns-alignment.md +23 -0
- package/example_slides/020-columns-styled.md +21 -0
- package/example_slides/021-footnote-prop.md +16 -0
- package/example_slides/022-iframe-fullscreen.md +8 -0
- package/example_slides/023-iframe-split.md +18 -0
- package/example_slides/024-section-components.md +14 -0
- package/example_slides/025-styled-text.md +9 -0
- package/example_slides/026-styled-text.md +15 -0
- package/example_slides/027-text-formatting.md +28 -0
- package/example_slides/028-text-spoiler.md +15 -0
- package/example_slides/029-icon-component.md +47 -0
- package/example_slides/030-metric-component.md +29 -0
- package/example_slides/031-person-card.md +33 -0
- package/example_slides/032-styled-list.md +50 -0
- package/example_slides/033-color-swatch.md +35 -0
- package/example_slides/034-code-highlight.md +9 -0
- package/example_slides/035-iframe-component.md +9 -0
- package/example_slides/036-callout.md +15 -0
- package/example_slides/037-card-grid.md +27 -0
- package/example_slides/038-stepper-variants.md +18 -0
- package/example_slides/039-stepper-clicks.md +49 -0
- package/example_slides/040-stepper-interactive.md +28 -0
- package/example_slides/041-tags-progress.md +21 -0
- package/example_slides/042-speech-bubble.md +30 -0
- package/example_slides/043-conversation.md +13 -0
- package/example_slides/044-device-iphone.md +26 -0
- package/example_slides/045-device-browser.md +7 -0
- package/example_slides/046-qrcode.md +26 -0
- package/example_slides/047-countdown.md +14 -0
- package/example_slides/048-typewriter.md +8 -0
- package/example_slides/049-confetti.md +16 -0
- package/example_slides/050-image-compare.md +13 -0
- package/example_slides/051-code-diff.md +24 -0
- package/example_slides/052-quote-block.md +8 -0
- package/example_slides/053-testimonial.md +26 -0
- package/example_slides/054-testimonial-featured.md +16 -0
- package/example_slides/055-funnel.md +12 -0
- package/example_slides/056-pyramid.md +13 -0
- package/example_slides/057-pricing-table.md +9 -0
- package/example_slides/058-swot-grid.md +12 -0
- package/example_slides/059-matrix-grid.md +12 -0
- package/example_slides/060-case-study.md +11 -0
- package/example_slides/061-definition.md +15 -0
- package/example_slides/062-mermaid-intro.md +34 -0
- package/example_slides/063-mermaid-flowchart.md +19 -0
- package/example_slides/064-mermaid-sequence.md +17 -0
- package/example_slides/065-mermaid-xy-chart.md +16 -0
- package/example_slides/066-mermaid-pie.md +17 -0
- package/example_slides/067-mermaid-class.md +19 -0
- package/example_slides/068-mermaid-state.md +19 -0
- package/example_slides/069-mermaid-er.md +22 -0
- package/example_slides/070-mermaid-gantt.md +24 -0
- package/example_slides/071-mermaid-timeline.md +17 -0
- package/example_slides/072-mermaid-mindmap.md +21 -0
- package/example_slides/073-mermaid-gitgraph.md +20 -0
- package/example_slides/074-mermaid-split.md +30 -0
- package/example_slides/075-mermaid-columns.md +32 -0
- package/example_slides/076-section-addons.md +14 -0
- package/example_slides/077-asciinema.md +27 -0
- package/example_slides/078-fancyarrow.md +31 -0
- package/example_slides/079-fancyarrow-demo.md +23 -0
- package/example_slides/080-section-theme.md +14 -0
- package/example_slides/081-color-architecture.md +22 -0
- package/example_slides/082-semantic-text-colors.md +25 -0
- package/example_slides/083-typography.md +16 -0
- package/example_slides/084-typography-rationale.md +22 -0
- package/example_slides/085-icons.md +24 -0
- package/example_slides/086-tables.md +14 -0
- package/example_slides/087-code-blocks.md +18 -0
- package/example_slides/088-motion-modes.md +35 -0
- package/example_slides/089-slide-transitions.md +31 -0
- package/example_slides/090-v-click-reveals.md +40 -0
- package/example_slides/091-accessibility.md +27 -0
- package/example_slides/092-safe-zone.md +17 -0
- package/example_slides/093-questions.md +8 -0
- package/example_white.md +10 -0
- package/fonts/IBMPlexMono-Medium.woff2 +1449 -0
- package/fonts/IBMPlexMono-Regular.woff2 +1449 -0
- package/fonts/IBMPlexSans-Bold.woff2 +1449 -0
- package/fonts/IBMPlexSans-Medium.woff2 +1449 -0
- package/fonts/IBMPlexSans-Regular.woff2 +1449 -0
- package/fonts/IBMPlexSans-SemiBold.woff2 +1449 -0
- package/fonts/LICENSE.txt +93 -0
- package/layouts/slide.vue +251 -0
- package/package.json +62 -0
- package/public/avatars/alice.png +0 -0
- package/public/avatars/bob.png +0 -0
- package/public/avatars/carol.png +0 -0
- package/scripts/chart-audit.mjs +216 -0
- package/scripts/contrast-audit.mjs +299 -0
- package/scripts/generate-palette.mjs +395 -0
- package/scripts/integrity-audit.mjs +357 -0
- package/scripts/shared/css-utils.mjs +216 -0
- package/scripts/shiki-audit.mjs +300 -0
- package/scripts/typography-audit.mjs +300 -0
- package/setup/main.ts +107 -0
- package/setup/mermaid.ts +237 -0
- package/setup/shiki.ts +40 -0
- package/snippets/demo.ts +26 -0
- package/styles/base.css +1053 -0
- package/styles/colors.css +422 -0
- package/styles/index.css +12 -0
- package/styles/motion.css +486 -0
- package/uno.config.ts +67 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
slidev-theme-troshab — Motion System
|
|
3
|
+
============================================
|
|
4
|
+
|
|
5
|
+
Based on IBM Carbon Design Motion Guidelines
|
|
6
|
+
https://carbondesignsystem.com/elements/motion/overview/
|
|
7
|
+
|
|
8
|
+
PRINCIPLES:
|
|
9
|
+
1. Purposeful — motion guides focus, not distracts
|
|
10
|
+
2. Responsive — motion gives feedback
|
|
11
|
+
3. Natural — follows physics, not linear
|
|
12
|
+
4. Automatic — smart defaults based on content type
|
|
13
|
+
|
|
14
|
+
============================================ */
|
|
15
|
+
|
|
16
|
+
/* ============================================
|
|
17
|
+
1. Motion Tokens
|
|
18
|
+
============================================ */
|
|
19
|
+
|
|
20
|
+
:root {
|
|
21
|
+
/* --- Easing Functions (IBM Carbon) --- */
|
|
22
|
+
/* Standard: default for most animations */
|
|
23
|
+
--ease-standard: cubic-bezier(0.2, 0.0, 0.38, 0.9);
|
|
24
|
+
/* Enter: elements entering the viewport */
|
|
25
|
+
--ease-enter: cubic-bezier(0.0, 0.0, 0.38, 0.9);
|
|
26
|
+
/* Exit: elements leaving the viewport */
|
|
27
|
+
--ease-exit: cubic-bezier(0.2, 0.0, 1.0, 0.9);
|
|
28
|
+
/* Expressive: for decorative/expressive animations */
|
|
29
|
+
--ease-expressive: cubic-bezier(0.4, 0.14, 0.3, 1.0);
|
|
30
|
+
|
|
31
|
+
/* --- Durations (IBM Carbon) --- */
|
|
32
|
+
--dur-fast-01: 70ms; /* micro-interactions */
|
|
33
|
+
--dur-fast-02: 110ms; /* small UI elements */
|
|
34
|
+
--dur-moderate-01: 150ms; /* medium complexity */
|
|
35
|
+
--dur-moderate-02: 240ms; /* opening/closing */
|
|
36
|
+
--dur-slow-01: 400ms; /* large movements */
|
|
37
|
+
--dur-slow-02: 700ms; /* complex sequences */
|
|
38
|
+
|
|
39
|
+
/* --- Exit Timing Modifier (Material Design) --- */
|
|
40
|
+
/* Exit animations should be ~20% faster than enter */
|
|
41
|
+
--dur-exit-modifier: 0.8;
|
|
42
|
+
|
|
43
|
+
/* --- Movement Distances --- */
|
|
44
|
+
--shift-xs: 6px; /* subtle */
|
|
45
|
+
--shift-sm: 12px; /* small */
|
|
46
|
+
--shift-md: 20px; /* medium */
|
|
47
|
+
--shift-lg: 28px; /* large */
|
|
48
|
+
|
|
49
|
+
/* --- Scale Values --- */
|
|
50
|
+
--scale-subtle: 0.985;
|
|
51
|
+
--scale-moderate: 0.95;
|
|
52
|
+
--scale-dramatic: 0.9;
|
|
53
|
+
|
|
54
|
+
/* --- Default Motion Mode (calm) --- */
|
|
55
|
+
--motion-duration: var(--dur-moderate-02);
|
|
56
|
+
--motion-ease: var(--ease-standard);
|
|
57
|
+
--motion-shift: var(--shift-md);
|
|
58
|
+
--motion-scale: var(--scale-subtle);
|
|
59
|
+
|
|
60
|
+
/* --- Stagger Delays --- */
|
|
61
|
+
--stagger-base: 50ms;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* ============================================
|
|
65
|
+
2. Motion Modes
|
|
66
|
+
============================================
|
|
67
|
+
|
|
68
|
+
Apply class to slide or container:
|
|
69
|
+
- (default): calm, minimal motion
|
|
70
|
+
- .motion-crisp: faster, smaller amplitudes
|
|
71
|
+
- .motion-expressive: softer, longer durations
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/* Crisp mode — faster, snappier */
|
|
75
|
+
.motion-crisp {
|
|
76
|
+
--motion-duration: var(--dur-moderate-01);
|
|
77
|
+
--motion-ease: var(--ease-standard);
|
|
78
|
+
--motion-shift: var(--shift-sm);
|
|
79
|
+
--motion-scale: 0.99;
|
|
80
|
+
--stagger-base: 30ms;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Expressive mode — slower, more dramatic */
|
|
84
|
+
.motion-expressive {
|
|
85
|
+
--motion-duration: var(--dur-slow-01);
|
|
86
|
+
--motion-ease: var(--ease-expressive);
|
|
87
|
+
--motion-shift: var(--shift-lg);
|
|
88
|
+
--motion-scale: var(--scale-moderate);
|
|
89
|
+
--stagger-base: 70ms;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* ============================================
|
|
93
|
+
3. v-click Reveal Styles
|
|
94
|
+
============================================
|
|
95
|
+
|
|
96
|
+
Default Slidev v-click behavior is fade + subtle rise.
|
|
97
|
+
|
|
98
|
+
Apply class to container for different effects:
|
|
99
|
+
- (default): fade + subtle rise
|
|
100
|
+
- .reveal-fade: opacity only
|
|
101
|
+
- .reveal-slide: slide from right
|
|
102
|
+
- .reveal-pop: scale up
|
|
103
|
+
|
|
104
|
+
Automatic detection by content type (no class needed):
|
|
105
|
+
- Code blocks: fade only (no movement disrupts alignment)
|
|
106
|
+
- Tables: fade only
|
|
107
|
+
- Lists: subtle slide from left
|
|
108
|
+
- Large text (KPIs): pop effect
|
|
109
|
+
- Blockquotes: fade only
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
/* Default v-click: fade + subtle rise */
|
|
113
|
+
.slidev-vclick-target {
|
|
114
|
+
transition:
|
|
115
|
+
opacity var(--motion-duration) var(--ease-enter),
|
|
116
|
+
transform var(--motion-duration) var(--ease-enter);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.slidev-vclick-hidden {
|
|
120
|
+
opacity: 0;
|
|
121
|
+
transform: translateY(var(--shift-sm));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* reveal-fade: opacity only */
|
|
125
|
+
.slidev-layout.reveal-fade .slidev-vclick-hidden,
|
|
126
|
+
.slidev-layout.reveal-fade li.slidev-vclick-hidden,
|
|
127
|
+
.slidev-layout.reveal-fade pre.slidev-vclick-hidden,
|
|
128
|
+
.slidev-layout.reveal-fade .shiki.slidev-vclick-hidden,
|
|
129
|
+
.slidev-layout.reveal-fade table.slidev-vclick-hidden,
|
|
130
|
+
.slidev-layout.reveal-fade blockquote.slidev-vclick-hidden,
|
|
131
|
+
.slidev-layout.reveal-fade img.slidev-vclick-hidden,
|
|
132
|
+
.slidev-layout.reveal-fade svg.slidev-vclick-hidden {
|
|
133
|
+
opacity: 0;
|
|
134
|
+
transform: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* reveal-slide: slide from right */
|
|
138
|
+
.slidev-layout.reveal-slide .slidev-vclick-hidden,
|
|
139
|
+
.slidev-layout.reveal-slide li.slidev-vclick-hidden,
|
|
140
|
+
.slidev-layout.reveal-slide pre.slidev-vclick-hidden,
|
|
141
|
+
.slidev-layout.reveal-slide .shiki.slidev-vclick-hidden,
|
|
142
|
+
.slidev-layout.reveal-slide table.slidev-vclick-hidden,
|
|
143
|
+
.slidev-layout.reveal-slide blockquote.slidev-vclick-hidden,
|
|
144
|
+
.slidev-layout.reveal-slide img.slidev-vclick-hidden,
|
|
145
|
+
.slidev-layout.reveal-slide svg.slidev-vclick-hidden {
|
|
146
|
+
opacity: 0;
|
|
147
|
+
transform: translateX(var(--motion-shift));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* reveal-pop: scale up */
|
|
151
|
+
.slidev-layout.reveal-pop .slidev-vclick-hidden,
|
|
152
|
+
.slidev-layout.reveal-pop li.slidev-vclick-hidden,
|
|
153
|
+
.slidev-layout.reveal-pop pre.slidev-vclick-hidden,
|
|
154
|
+
.slidev-layout.reveal-pop .shiki.slidev-vclick-hidden,
|
|
155
|
+
.slidev-layout.reveal-pop table.slidev-vclick-hidden,
|
|
156
|
+
.slidev-layout.reveal-pop blockquote.slidev-vclick-hidden,
|
|
157
|
+
.slidev-layout.reveal-pop img.slidev-vclick-hidden,
|
|
158
|
+
.slidev-layout.reveal-pop svg.slidev-vclick-hidden {
|
|
159
|
+
opacity: 0;
|
|
160
|
+
transform: scale(var(--scale-moderate));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* ============================================
|
|
164
|
+
3b. Automatic Content-Type Detection
|
|
165
|
+
============================================
|
|
166
|
+
|
|
167
|
+
Smart v-click reveal based on element type.
|
|
168
|
+
These override the default rise animation for specific content.
|
|
169
|
+
*/
|
|
170
|
+
|
|
171
|
+
/* Code blocks: fade only (no movement disrupts alignment) */
|
|
172
|
+
.slidev-layout pre.slidev-vclick-hidden,
|
|
173
|
+
.slidev-layout .shiki.slidev-vclick-hidden,
|
|
174
|
+
.slidev-layout pre .slidev-vclick-hidden,
|
|
175
|
+
.slidev-layout .shiki .slidev-vclick-hidden {
|
|
176
|
+
transform: none;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* Tables: fade only (preserves alignment) */
|
|
180
|
+
.slidev-layout table.slidev-vclick-hidden,
|
|
181
|
+
.slidev-layout table .slidev-vclick-hidden {
|
|
182
|
+
transform: none;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Blockquotes: fade only (elegant reveal) */
|
|
186
|
+
.slidev-layout blockquote.slidev-vclick-hidden,
|
|
187
|
+
.slidev-layout blockquote .slidev-vclick-hidden {
|
|
188
|
+
transform: none;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* Lists inside v-clicks: subtle slide from left */
|
|
192
|
+
.slidev-layout li.slidev-vclick-hidden {
|
|
193
|
+
transform: translateX(calc(var(--shift-sm) * -1));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Large text (KPIs, metrics): pop effect */
|
|
197
|
+
.slidev-layout .text-4xl.slidev-vclick-hidden,
|
|
198
|
+
.slidev-layout .text-5xl.slidev-vclick-hidden,
|
|
199
|
+
.slidev-layout .text-6xl.slidev-vclick-hidden,
|
|
200
|
+
.slidev-layout .text-7xl.slidev-vclick-hidden,
|
|
201
|
+
.slidev-layout .text-8xl.slidev-vclick-hidden,
|
|
202
|
+
.slidev-layout [class*="font-size-h1"].slidev-vclick-hidden,
|
|
203
|
+
.slidev-layout .fact-value.slidev-vclick-hidden {
|
|
204
|
+
transform: scale(var(--scale-moderate));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Images: fade only */
|
|
208
|
+
.slidev-layout img.slidev-vclick-hidden {
|
|
209
|
+
transform: none;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Diagrams (mermaid, SVG): fade only */
|
|
213
|
+
.slidev-layout .mermaid.slidev-vclick-hidden,
|
|
214
|
+
.slidev-layout svg.slidev-vclick-hidden {
|
|
215
|
+
transform: none;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* ============================================
|
|
219
|
+
3c. List Stagger Pattern
|
|
220
|
+
============================================
|
|
221
|
+
|
|
222
|
+
Natural stagger for v-clicks on list items.
|
|
223
|
+
Limited to 6 items (Material Design: avoid "crawling" effect).
|
|
224
|
+
*/
|
|
225
|
+
|
|
226
|
+
/* Default stagger delays */
|
|
227
|
+
.slidev-layout li.slidev-vclick-target:nth-child(1) { transition-delay: 0ms; }
|
|
228
|
+
.slidev-layout li.slidev-vclick-target:nth-child(2) { transition-delay: var(--stagger-base); }
|
|
229
|
+
.slidev-layout li.slidev-vclick-target:nth-child(3) { transition-delay: calc(var(--stagger-base) * 2); }
|
|
230
|
+
.slidev-layout li.slidev-vclick-target:nth-child(4) { transition-delay: calc(var(--stagger-base) * 3); }
|
|
231
|
+
.slidev-layout li.slidev-vclick-target:nth-child(5) { transition-delay: calc(var(--stagger-base) * 4); }
|
|
232
|
+
.slidev-layout li.slidev-vclick-target:nth-child(6) { transition-delay: calc(var(--stagger-base) * 5); }
|
|
233
|
+
/* Items 7+ get no additional delay to avoid "crawling" */
|
|
234
|
+
.slidev-layout li.slidev-vclick-target:nth-child(n+7) { transition-delay: calc(var(--stagger-base) * 5); }
|
|
235
|
+
|
|
236
|
+
/* Reset delay when item becomes visible (avoid lingering delay) */
|
|
237
|
+
.slidev-layout li.slidev-vclick-target:not(.slidev-vclick-hidden) {
|
|
238
|
+
transition-delay: 0ms;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* ============================================
|
|
242
|
+
4. Layout Entrance Animations
|
|
243
|
+
============================================
|
|
244
|
+
|
|
245
|
+
CSS-based entrance animations for key layouts.
|
|
246
|
+
|
|
247
|
+
SEMANTIC DIRECTION PHILOSOPHY:
|
|
248
|
+
- Headings (h1, h2, h3): "fall" from above ↓
|
|
249
|
+
- Content (single block): "rise" from below ↑
|
|
250
|
+
- Two columns: slide from sides ← →
|
|
251
|
+
- Grid (3-4 cols): all items rise from below ↑
|
|
252
|
+
*/
|
|
253
|
+
|
|
254
|
+
/* --- Fullscreen mode: slide+fade from below, staggered --- */
|
|
255
|
+
.slide-fullscreen .slide-content h1 {
|
|
256
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) both;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.slide-fullscreen .slide-content h2 {
|
|
260
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 2) both;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.slide-fullscreen .slide-content > *:not(h1):not(h2) {
|
|
264
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Fullscreen with bg: fade bg first, content slides up after */
|
|
268
|
+
.slide-no-padding .slide-content {
|
|
269
|
+
animation: entrance-fade var(--dur-moderate-02) var(--ease-enter) both;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.slide-no-padding .slide-content > * {
|
|
273
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* ============================================
|
|
277
|
+
4b. Columns Mode Entrance Animations
|
|
278
|
+
============================================
|
|
279
|
+
|
|
280
|
+
SEQUENCE: title (rise) -> subtitle (rise) -> columns
|
|
281
|
+
- 1/3/4 columns: rise from below, right after title/subtitle
|
|
282
|
+
- 2 columns: left from left, right from right
|
|
283
|
+
If no subtitle, columns appear sooner (delay * 2 instead of * 4)
|
|
284
|
+
*/
|
|
285
|
+
|
|
286
|
+
/* Title: slide+fade from below (first) */
|
|
287
|
+
.slide-title {
|
|
288
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) both;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* Subtitle: slide+fade from below (second) */
|
|
292
|
+
.slide-subtitle {
|
|
293
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 2) both;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* --- Single column: rise from below --- */
|
|
297
|
+
.slide-single {
|
|
298
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* Single col without title+subtitle: faster start */
|
|
302
|
+
.slide-columns > .slide-single:first-child {
|
|
303
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) both;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* Blockquotes in single col: fade only */
|
|
307
|
+
.slide-single > blockquote {
|
|
308
|
+
animation: entrance-fade var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* --- 2 columns: slide from sides toward center --- */
|
|
312
|
+
.slide-grid > .slide-col:first-child:nth-last-child(2) {
|
|
313
|
+
animation: entrance-slide-right var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.slide-grid > .slide-col:last-child:nth-last-child(2) {
|
|
317
|
+
animation: entrance-slide-left var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* --- 3+ columns: all rise from below --- */
|
|
321
|
+
.slide-grid > .slide-col:first-child:nth-last-child(n+3),
|
|
322
|
+
.slide-grid > .slide-col:first-child:nth-last-child(n+3) ~ .slide-col {
|
|
323
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* ============================================
|
|
327
|
+
4c. Split Mode Entrance Animations
|
|
328
|
+
============================================
|
|
329
|
+
|
|
330
|
+
Split panels: left from left, right from right
|
|
331
|
+
*/
|
|
332
|
+
|
|
333
|
+
/* Left half slides from left edge */
|
|
334
|
+
.slide-split > *:first-child {
|
|
335
|
+
animation: entrance-slide-right var(--dur-moderate-02) var(--ease-enter) both;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Right half slides from right edge */
|
|
339
|
+
.slide-split > *:last-child:not(:first-child) {
|
|
340
|
+
animation: entrance-slide-left var(--dur-moderate-02) var(--ease-enter) both;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Split bg-only panel: fade */
|
|
344
|
+
.slide-panel-bg-only {
|
|
345
|
+
animation: entrance-fade var(--dur-moderate-02) var(--ease-enter) both;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Split caption overlay: slides up after */
|
|
349
|
+
.slide-caption-overlay {
|
|
350
|
+
animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/* ============================================
|
|
354
|
+
5. Keyframe Animations
|
|
355
|
+
============================================ */
|
|
356
|
+
|
|
357
|
+
@keyframes entrance-fade {
|
|
358
|
+
from {
|
|
359
|
+
opacity: 0;
|
|
360
|
+
}
|
|
361
|
+
to {
|
|
362
|
+
opacity: 1;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Fall from above — for headings */
|
|
367
|
+
@keyframes entrance-fall {
|
|
368
|
+
from {
|
|
369
|
+
opacity: 0;
|
|
370
|
+
transform: translateY(calc(var(--shift-md) * -1));
|
|
371
|
+
}
|
|
372
|
+
to {
|
|
373
|
+
opacity: 1;
|
|
374
|
+
transform: translateY(0);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/* Rise from below — for content */
|
|
379
|
+
@keyframes entrance-rise {
|
|
380
|
+
from {
|
|
381
|
+
opacity: 0;
|
|
382
|
+
transform: translateY(var(--shift-md));
|
|
383
|
+
}
|
|
384
|
+
to {
|
|
385
|
+
opacity: 1;
|
|
386
|
+
transform: translateY(0);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
@keyframes entrance-scale {
|
|
391
|
+
from {
|
|
392
|
+
opacity: 0;
|
|
393
|
+
transform: scale(var(--scale-moderate));
|
|
394
|
+
}
|
|
395
|
+
to {
|
|
396
|
+
opacity: 1;
|
|
397
|
+
transform: scale(1);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/* Slide from left side (element comes from left) */
|
|
402
|
+
@keyframes entrance-slide-right {
|
|
403
|
+
from {
|
|
404
|
+
opacity: 0;
|
|
405
|
+
transform: translateX(calc(var(--shift-md) * -1));
|
|
406
|
+
}
|
|
407
|
+
to {
|
|
408
|
+
opacity: 1;
|
|
409
|
+
transform: translateX(0);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/* Slide from right side (element comes from right) */
|
|
414
|
+
@keyframes entrance-slide-left {
|
|
415
|
+
from {
|
|
416
|
+
opacity: 0;
|
|
417
|
+
transform: translateX(var(--shift-md));
|
|
418
|
+
}
|
|
419
|
+
to {
|
|
420
|
+
opacity: 1;
|
|
421
|
+
transform: translateX(0);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/* ============================================
|
|
426
|
+
6. Utility Classes
|
|
427
|
+
============================================ */
|
|
428
|
+
|
|
429
|
+
/* Delay utilities for staggered animations */
|
|
430
|
+
.delay-100 { animation-delay: 100ms; }
|
|
431
|
+
.delay-200 { animation-delay: 200ms; }
|
|
432
|
+
.delay-300 { animation-delay: 300ms; }
|
|
433
|
+
.delay-400 { animation-delay: 400ms; }
|
|
434
|
+
.delay-500 { animation-delay: 500ms; }
|
|
435
|
+
|
|
436
|
+
/* Duration utilities */
|
|
437
|
+
.duration-fast { animation-duration: var(--dur-fast-02); }
|
|
438
|
+
.duration-moderate { animation-duration: var(--dur-moderate-02); }
|
|
439
|
+
.duration-slow { animation-duration: var(--dur-slow-01); }
|
|
440
|
+
|
|
441
|
+
/* No animation utility */
|
|
442
|
+
.no-animate {
|
|
443
|
+
animation: none !important;
|
|
444
|
+
transition: none !important;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/* ============================================
|
|
448
|
+
7. Reduced Motion Support (WCAG 2.1)
|
|
449
|
+
============================================
|
|
450
|
+
|
|
451
|
+
Users with vestibular disorders or motion sensitivity
|
|
452
|
+
can enable "Reduce motion" in their OS settings.
|
|
453
|
+
This disables all non-essential animations.
|
|
454
|
+
|
|
455
|
+
TODO: Uncomment when ready to enable reduced motion support
|
|
456
|
+
*/
|
|
457
|
+
|
|
458
|
+
/*
|
|
459
|
+
@media (prefers-reduced-motion: reduce) {
|
|
460
|
+
.slidev-layout *,
|
|
461
|
+
.slide-fullscreen *,
|
|
462
|
+
.slide-content *,
|
|
463
|
+
.slide-columns *,
|
|
464
|
+
.slide-title,
|
|
465
|
+
.slide-single,
|
|
466
|
+
.slide-grid > .slide-col,
|
|
467
|
+
.slide-panel,
|
|
468
|
+
.slide-panel-content,
|
|
469
|
+
.slide-caption-overlay,
|
|
470
|
+
.slidev-layout .grid > * {
|
|
471
|
+
animation: none !important;
|
|
472
|
+
animation-duration: 0.01ms !important;
|
|
473
|
+
animation-delay: 0ms !important;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.slidev-vclick-target {
|
|
477
|
+
transition-duration: 0.01ms !important;
|
|
478
|
+
transition-delay: 0ms !important;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.slidev-vclick-hidden {
|
|
482
|
+
opacity: 0;
|
|
483
|
+
transform: none !important;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
*/
|
package/uno.config.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { defineConfig } from 'unocss'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
// Safelist for dynamic classes that UnoCSS can't detect via static analysis
|
|
5
|
+
safelist: [
|
|
6
|
+
// Column spans for two-cols layout
|
|
7
|
+
'col-span-3', 'col-span-4', 'col-span-5', 'col-span-6', 'col-span-7', 'col-span-8', 'col-span-9',
|
|
8
|
+
// Grid classes
|
|
9
|
+
'grid', 'grid-cols-12',
|
|
10
|
+
// Gap classes
|
|
11
|
+
'gap-0', 'gap-1', 'gap-2', 'gap-4', 'gap-6', 'gap-8',
|
|
12
|
+
// Alignment classes
|
|
13
|
+
'items-start', 'items-center', 'items-end',
|
|
14
|
+
],
|
|
15
|
+
|
|
16
|
+
shortcuts: {
|
|
17
|
+
// 12-column grid system
|
|
18
|
+
'grid-cols': 'grid grid-cols-12 gap-4',
|
|
19
|
+
|
|
20
|
+
// Column width shortcuts (left column width)
|
|
21
|
+
'is-3': 'col-span-3',
|
|
22
|
+
'is-4': 'col-span-4',
|
|
23
|
+
'is-5': 'col-span-5',
|
|
24
|
+
'is-6': 'col-span-6',
|
|
25
|
+
'is-7': 'col-span-7',
|
|
26
|
+
'is-8': 'col-span-8',
|
|
27
|
+
'is-9': 'col-span-9',
|
|
28
|
+
|
|
29
|
+
// Semantic aliases
|
|
30
|
+
'is-half': 'col-span-6',
|
|
31
|
+
'is-one-third': 'col-span-4',
|
|
32
|
+
'is-two-thirds': 'col-span-8',
|
|
33
|
+
'is-one-quarter': 'col-span-3',
|
|
34
|
+
'is-three-quarters': 'col-span-9',
|
|
35
|
+
|
|
36
|
+
// Layout utilities
|
|
37
|
+
'slide-content': 'h-full w-full p-8',
|
|
38
|
+
'slide-content-full': 'h-full w-full',
|
|
39
|
+
'flex-center': 'flex items-center justify-center',
|
|
40
|
+
'flex-col-center': 'flex flex-col items-center justify-center',
|
|
41
|
+
|
|
42
|
+
// Text utilities
|
|
43
|
+
'text-slide-title': 'text-4xl font-bold mb-4',
|
|
44
|
+
'text-slide-subtitle': 'text-2xl opacity-80',
|
|
45
|
+
'text-section-title': 'text-5xl font-bold',
|
|
46
|
+
'text-quote': 'text-3xl italic leading-relaxed',
|
|
47
|
+
'text-quote-author': 'text-xl opacity-70 mt-4',
|
|
48
|
+
|
|
49
|
+
// Note: Block and Theorem component styles are defined in CSS (colors.css + base.css)
|
|
50
|
+
// to properly use CSS variables for theming. Do not add UnoCSS shortcuts for these.
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
rules: [
|
|
54
|
+
// Dynamic column spans
|
|
55
|
+
[/^col-left-(\d+)$/, ([, d]) => ({ 'grid-column': `span ${d}` })],
|
|
56
|
+
[/^col-right-(\d+)$/, ([, d]) => ({ 'grid-column': `span ${12 - parseInt(d)}` })],
|
|
57
|
+
],
|
|
58
|
+
|
|
59
|
+
theme: {
|
|
60
|
+
extend: {
|
|
61
|
+
fontFamily: {
|
|
62
|
+
sans: ['IBM Plex Sans', 'system-ui', '-apple-system', 'sans-serif'],
|
|
63
|
+
mono: ['IBM Plex Mono', 'Consolas', 'Monaco', 'monospace'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
})
|