@strategicnerds/slide-nerds 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/dist/cli/commands/analytics.d.ts +6 -0
- package/dist/cli/commands/analytics.d.ts.map +1 -0
- package/dist/cli/commands/analytics.js +44 -0
- package/dist/cli/commands/analytics.js.map +1 -0
- package/dist/cli/commands/create.d.ts +4 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +87 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/export.d.ts +6 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +109 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +12 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/template-path.d.ts +4 -0
- package/dist/cli/template-path.d.ts.map +1 -0
- package/dist/cli/template-path.js +13 -0
- package/dist/cli/template-path.js.map +1 -0
- package/dist/runtime/export-api.d.ts +15 -0
- package/dist/runtime/export-api.d.ts.map +1 -0
- package/dist/runtime/export-api.js +21 -0
- package/dist/runtime/export-api.js.map +1 -0
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/light-table.d.ts +8 -0
- package/dist/runtime/light-table.d.ts.map +1 -0
- package/dist/runtime/light-table.js +104 -0
- package/dist/runtime/light-table.js.map +1 -0
- package/dist/runtime/presenter-view.d.ts +7 -0
- package/dist/runtime/presenter-view.d.ts.map +1 -0
- package/dist/runtime/presenter-view.js +62 -0
- package/dist/runtime/presenter-view.js.map +1 -0
- package/dist/runtime/slide-context.d.ts +16 -0
- package/dist/runtime/slide-context.d.ts.map +1 -0
- package/dist/runtime/slide-context.js +18 -0
- package/dist/runtime/slide-context.js.map +1 -0
- package/dist/runtime/slide-controls.d.ts +3 -0
- package/dist/runtime/slide-controls.d.ts.map +1 -0
- package/dist/runtime/slide-controls.js +177 -0
- package/dist/runtime/slide-controls.js.map +1 -0
- package/dist/runtime/slide-dom.d.ts +17 -0
- package/dist/runtime/slide-dom.d.ts.map +1 -0
- package/dist/runtime/slide-dom.js +89 -0
- package/dist/runtime/slide-dom.js.map +1 -0
- package/dist/runtime/slide-runtime.d.ts +7 -0
- package/dist/runtime/slide-runtime.d.ts.map +1 -0
- package/dist/runtime/slide-runtime.js +125 -0
- package/dist/runtime/slide-runtime.js.map +1 -0
- package/dist/runtime/slide-shape.d.ts +21 -0
- package/dist/runtime/slide-shape.d.ts.map +1 -0
- package/dist/runtime/slide-shape.js +115 -0
- package/dist/runtime/slide-shape.js.map +1 -0
- package/dist/runtime/types.d.ts +150 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +38 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/use-presenter-mode.d.ts +14 -0
- package/dist/runtime/use-presenter-mode.d.ts.map +1 -0
- package/dist/runtime/use-presenter-mode.js +52 -0
- package/dist/runtime/use-presenter-mode.js.map +1 -0
- package/dist/runtime/use-slide-navigation.d.ts +13 -0
- package/dist/runtime/use-slide-navigation.d.ts.map +1 -0
- package/dist/runtime/use-slide-navigation.js +230 -0
- package/dist/runtime/use-slide-navigation.js.map +1 -0
- package/package.json +64 -0
- package/skills/accessibility/SKILL.md +236 -0
- package/skills/advanced-layouts/SKILL.md +429 -0
- package/skills/analytics/SKILL.md +97 -0
- package/skills/animation/SKILL.md +364 -0
- package/skills/brand/SKILL.md +200 -0
- package/skills/data-visualization/SKILL.md +533 -0
- package/skills/deck-templates/SKILL.md +93 -0
- package/skills/diagrams/SKILL.md +395 -0
- package/skills/export/SKILL.md +119 -0
- package/skills/interactive/SKILL.md +292 -0
- package/skills/layout/SKILL.md +178 -0
- package/skills/narrative-frameworks/SKILL.md +250 -0
- package/skills/react-component-embeds/SKILL.md +73 -0
- package/skills/slide-types/SKILL.md +384 -0
- package/skills/slidenerds-runtime/SKILL.md +163 -0
- package/skills/speaker-notes/SKILL.md +128 -0
- package/skills/strategic-frameworks/SKILL.md +392 -0
- package/skills/visual-design/SKILL.md +373 -0
- package/templates/analytics/custom.tsx.tmpl +20 -0
- package/templates/analytics/ga4.tsx.tmpl +15 -0
- package/templates/analytics/gtm.tsx.tmpl +9 -0
- package/templates/analytics/plausible.tsx.tmpl +10 -0
- package/templates/analytics/posthog.tsx.tmpl +14 -0
- package/templates/next-app/CLAUDE.md.tmpl +574 -0
- package/templates/next-app/README.md.tmpl +35 -0
- package/templates/next-app/app/globals.css.tmpl +274 -0
- package/templates/next-app/app/layout.tsx.tmpl +31 -0
- package/templates/next-app/app/page.tsx.tmpl +38 -0
- package/templates/next-app/brand.config.ts.tmpl +32 -0
- package/templates/next-app/package.json.tmpl +25 -0
- package/templates/next-app/postcss.config.mjs.tmpl +8 -0
- package/templates/next-app/tsconfig.json.tmpl +21 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: interactive
|
|
3
|
+
description: Embedded video, QR codes, clickable links, live data, and audience interaction patterns for slidenerds slides
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Interactive elements skill
|
|
7
|
+
|
|
8
|
+
Use this skill when slides need dynamic or interactive content beyond static text and charts. Each pattern here produces a functional component that works within the slidenerds runtime.
|
|
9
|
+
|
|
10
|
+
## Embedded video
|
|
11
|
+
|
|
12
|
+
Use for: product demos, customer testimonials, recorded walkthroughs.
|
|
13
|
+
|
|
14
|
+
### YouTube / Vimeo embed
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
<section data-slide="">
|
|
18
|
+
<div className="flex flex-col justify-center items-center w-full min-h-screen"
|
|
19
|
+
style={{ padding: '4rem 6rem' }}>
|
|
20
|
+
<p className="section-label mb-3">Demo</p>
|
|
21
|
+
<h2 className="text-[2.5rem] font-bold mb-10">See it in action</h2>
|
|
22
|
+
<div data-step="" className="step-fade w-full" style={{ maxWidth: 900 }}>
|
|
23
|
+
<div className="card-surface overflow-hidden" style={{ aspectRatio: '16/9' }}>
|
|
24
|
+
<iframe
|
|
25
|
+
src="https://www.youtube.com/embed/VIDEO_ID?rel=0&modestbranding=1"
|
|
26
|
+
title="Product demo"
|
|
27
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
|
|
28
|
+
allowFullScreen
|
|
29
|
+
style={{ width: '100%', height: '100%', border: 'none' }}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<div data-notes="">
|
|
34
|
+
Play the video. Pause at 1:45 to highlight the auto-scaling feature.
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</section>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Self-hosted video
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<div className="card-surface overflow-hidden" style={{ aspectRatio: '16/9' }}>
|
|
44
|
+
<video
|
|
45
|
+
src="/demo.mp4"
|
|
46
|
+
controls
|
|
47
|
+
playsInline
|
|
48
|
+
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
|
49
|
+
/>
|
|
50
|
+
</div>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Video rules
|
|
54
|
+
|
|
55
|
+
- Always wrap in a card surface with 16:9 aspect ratio.
|
|
56
|
+
- Use `rel=0&modestbranding=1` for YouTube to hide related videos and branding.
|
|
57
|
+
- Never autoplay. The presenter controls playback.
|
|
58
|
+
- Keep videos under 2 minutes for live presentations.
|
|
59
|
+
- Include speaker notes that describe what to narrate during the video.
|
|
60
|
+
|
|
61
|
+
## QR code
|
|
62
|
+
|
|
63
|
+
Use for: audience participation, resource links, app downloads, feedback forms.
|
|
64
|
+
|
|
65
|
+
Install `qrcode.react`:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install qrcode.react
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { QRCodeSVG } from 'qrcode.react'
|
|
73
|
+
|
|
74
|
+
<section data-slide="">
|
|
75
|
+
<div className="flex items-center justify-center w-full min-h-screen"
|
|
76
|
+
style={{ padding: '4rem 6rem' }}>
|
|
77
|
+
<div className="flex items-center gap-16">
|
|
78
|
+
<div>
|
|
79
|
+
<p className="section-label mb-3">Try it now</p>
|
|
80
|
+
<h2 className="text-[2.5rem] font-bold mb-4">Scan to get started</h2>
|
|
81
|
+
<p className="text-lg" style={{ color: 'var(--color-text-secondary)' }}>
|
|
82
|
+
Free trial, no credit card required.
|
|
83
|
+
</p>
|
|
84
|
+
<p className="mt-6 text-sm font-mono" style={{ color: 'var(--color-text-tertiary)' }}>
|
|
85
|
+
acme.dev/start
|
|
86
|
+
</p>
|
|
87
|
+
</div>
|
|
88
|
+
<div className="card-surface p-6">
|
|
89
|
+
<QRCodeSVG
|
|
90
|
+
value="https://acme.dev/start"
|
|
91
|
+
size={200}
|
|
92
|
+
bgColor="transparent"
|
|
93
|
+
fgColor="var(--color-text)"
|
|
94
|
+
level="M"
|
|
95
|
+
/>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</section>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### QR code rules
|
|
103
|
+
|
|
104
|
+
- Size: at least 200x200px on screen. Must be scannable from 3 meters.
|
|
105
|
+
- Always include the URL in plain text below or beside the QR code.
|
|
106
|
+
- Use `level="M"` (medium error correction) for reliability.
|
|
107
|
+
- Place the QR code on the right side of the slide (audience's eye tracks left-to-right, reads context first, then scans).
|
|
108
|
+
- Use `bgColor="transparent"` to match the slide background.
|
|
109
|
+
|
|
110
|
+
## Clickable links
|
|
111
|
+
|
|
112
|
+
Use for: resources, documentation, signup pages within the deck.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<a
|
|
116
|
+
href="https://docs.acme.dev"
|
|
117
|
+
target="_blank"
|
|
118
|
+
rel="noopener noreferrer"
|
|
119
|
+
className="inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium"
|
|
120
|
+
style={{
|
|
121
|
+
background: 'var(--color-accent-dim)',
|
|
122
|
+
color: 'var(--color-accent)',
|
|
123
|
+
textDecoration: 'none',
|
|
124
|
+
transition: 'background 150ms ease',
|
|
125
|
+
}}
|
|
126
|
+
>
|
|
127
|
+
View documentation
|
|
128
|
+
<svg width={14} height={14} viewBox="0 0 24 24" fill="none"
|
|
129
|
+
stroke="currentColor" strokeWidth={2} strokeLinecap="round">
|
|
130
|
+
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" />
|
|
131
|
+
<polyline points="15 3 21 3 21 9" />
|
|
132
|
+
<line x1="10" y1="14" x2="21" y2="3" />
|
|
133
|
+
</svg>
|
|
134
|
+
</a>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Link rules
|
|
138
|
+
|
|
139
|
+
- Style links as pill buttons, not underlined text. Underlines are hard to see at projection distance.
|
|
140
|
+
- Always use `target="_blank"` and `rel="noopener noreferrer"`.
|
|
141
|
+
- Include an external-link icon to signal the link opens a new tab.
|
|
142
|
+
- Place links at the bottom of slides, not inline with body text.
|
|
143
|
+
- Limit to 1-2 links per slide.
|
|
144
|
+
|
|
145
|
+
## Embedded web content
|
|
146
|
+
|
|
147
|
+
Use for: live dashboards, interactive prototypes, web apps.
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
<section data-slide="">
|
|
151
|
+
<div className="flex flex-col justify-center w-full min-h-screen"
|
|
152
|
+
style={{ padding: '4rem 6rem' }}>
|
|
153
|
+
<p className="section-label mb-3">Live</p>
|
|
154
|
+
<h2 className="text-[2.5rem] font-bold mb-8">Real-time dashboard</h2>
|
|
155
|
+
<div className="card-surface overflow-hidden flex-1" style={{ minHeight: 400 }}>
|
|
156
|
+
<iframe
|
|
157
|
+
src="https://dashboard.acme.dev/embed?token=xyz"
|
|
158
|
+
title="Live metrics dashboard"
|
|
159
|
+
sandbox="allow-scripts allow-same-origin"
|
|
160
|
+
style={{ width: '100%', height: '100%', border: 'none' }}
|
|
161
|
+
/>
|
|
162
|
+
</div>
|
|
163
|
+
<div data-notes="">
|
|
164
|
+
This is a live embed. Refresh if data looks stale. Have a screenshot backup ready.
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</section>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Embed rules
|
|
171
|
+
|
|
172
|
+
- Always use the `sandbox` attribute to restrict iframe capabilities.
|
|
173
|
+
- Have a static screenshot as a fallback in case of network issues.
|
|
174
|
+
- Test the embed before presenting -- auth tokens, CORS, and CSP can block iframes.
|
|
175
|
+
- Include a note in speaker notes about fallback behavior.
|
|
176
|
+
|
|
177
|
+
## Presenter timer with alerts
|
|
178
|
+
|
|
179
|
+
The runtime's presenter view shows elapsed time. For more control, add configurable alerts:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
const ALERT_TIMES = [
|
|
183
|
+
{ seconds: 15 * 60, label: '15 min remaining', color: '#22c55e' },
|
|
184
|
+
{ seconds: 18 * 60, label: '2 min remaining', color: '#f59e0b' },
|
|
185
|
+
{ seconds: 19 * 60, label: '1 min remaining', color: '#ef4444' },
|
|
186
|
+
]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Display these as toast notifications in the presenter view when the timer crosses each threshold.
|
|
190
|
+
|
|
191
|
+
## Click-to-zoom on charts and images
|
|
192
|
+
|
|
193
|
+
For detailed charts that need closer inspection:
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
const [zoomed, setZoomed] = useState(false)
|
|
197
|
+
|
|
198
|
+
<div onClick={() => setZoomed(!zoomed)}
|
|
199
|
+
style={{
|
|
200
|
+
cursor: 'zoom-in',
|
|
201
|
+
transition: 'transform 300ms ease',
|
|
202
|
+
transform: zoomed ? 'scale(1.5)' : 'scale(1)',
|
|
203
|
+
transformOrigin: 'center',
|
|
204
|
+
zIndex: zoomed ? 100 : 'auto',
|
|
205
|
+
position: 'relative',
|
|
206
|
+
}}>
|
|
207
|
+
<ResponsiveContainer width="100%" height={400}>
|
|
208
|
+
{/* Chart */}
|
|
209
|
+
</ResponsiveContainer>
|
|
210
|
+
</div>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Zoom rules
|
|
214
|
+
|
|
215
|
+
- Only use on data-dense charts that benefit from closer inspection.
|
|
216
|
+
- Scale factor: 1.5x (not more -- it pushes content off screen).
|
|
217
|
+
- Click to zoom in, click again to zoom out.
|
|
218
|
+
- Not appropriate for keynote-style presentations. Use only for working sessions and reviews.
|
|
219
|
+
|
|
220
|
+
## Audience interaction patterns
|
|
221
|
+
|
|
222
|
+
### Live poll (requires backend)
|
|
223
|
+
|
|
224
|
+
For real-time polling during presentations, integrate with a polling service or build a custom WebSocket solution:
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
<section data-slide="">
|
|
228
|
+
<div className="flex flex-col items-center justify-center w-full min-h-screen"
|
|
229
|
+
style={{ padding: '4rem 6rem' }}>
|
|
230
|
+
<h2 className="text-[2.5rem] font-bold mb-4">Quick poll</h2>
|
|
231
|
+
<p className="text-lg mb-10" style={{ color: 'var(--color-text-secondary)' }}>
|
|
232
|
+
What is your biggest deployment challenge?
|
|
233
|
+
</p>
|
|
234
|
+
<div className="card-surface p-6 w-full" style={{ maxWidth: 600 }}>
|
|
235
|
+
{/* Poll results render here -- driven by real-time data */}
|
|
236
|
+
<div className="space-y-3">
|
|
237
|
+
{['Speed', 'Reliability', 'Cost', 'Complexity'].map((option) => (
|
|
238
|
+
<div key={option} className="flex items-center gap-3">
|
|
239
|
+
<div className="h-8 rounded"
|
|
240
|
+
style={{ width: `${Math.random() * 80 + 20}%`, background: 'var(--color-accent)', opacity: 0.6 }} />
|
|
241
|
+
<span className="text-sm">{option}</span>
|
|
242
|
+
</div>
|
|
243
|
+
))}
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
<p className="mt-8 text-sm" style={{ color: 'var(--color-text-tertiary)' }}>
|
|
247
|
+
Vote at acme.dev/poll
|
|
248
|
+
</p>
|
|
249
|
+
</div>
|
|
250
|
+
</section>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Feedback / Q&A prompt
|
|
254
|
+
|
|
255
|
+
Simple pattern for soliciting audience questions:
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
<section data-slide="">
|
|
259
|
+
<div className="flex flex-col items-center justify-center w-full min-h-screen text-center"
|
|
260
|
+
style={{ padding: '4rem 6rem' }}>
|
|
261
|
+
<h2 className="text-[3.5rem] font-bold mb-4">Questions?</h2>
|
|
262
|
+
<p className="text-lg" style={{ color: 'var(--color-text-secondary)' }}>
|
|
263
|
+
Submit at acme.dev/ask or raise your hand.
|
|
264
|
+
</p>
|
|
265
|
+
<div className="mt-10 card-surface p-6">
|
|
266
|
+
<QRCodeSVG value="https://acme.dev/ask" size={160}
|
|
267
|
+
bgColor="transparent" fgColor="var(--color-text)" level="M" />
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
</section>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Interactive element selection guide
|
|
274
|
+
|
|
275
|
+
| Need | Element | Dependency |
|
|
276
|
+
|---|---|---|
|
|
277
|
+
| Product walkthrough | YouTube/Vimeo embed | None (iframe) |
|
|
278
|
+
| Recorded demo | Self-hosted video | None (HTML5 video) |
|
|
279
|
+
| Resource link | Pill button with icon | None |
|
|
280
|
+
| Audience participation | QR code | `qrcode.react` |
|
|
281
|
+
| Live metrics | Embedded iframe | Backend/dashboard service |
|
|
282
|
+
| Data inspection | Click-to-zoom chart | None (CSS transform) |
|
|
283
|
+
| Audience voting | Live poll | WebSocket backend |
|
|
284
|
+
| Feedback collection | Q&A QR code slide | `qrcode.react` |
|
|
285
|
+
|
|
286
|
+
## What to avoid
|
|
287
|
+
|
|
288
|
+
- Autoplay on any media. The presenter controls pacing.
|
|
289
|
+
- More than one interactive element per slide.
|
|
290
|
+
- Relying on network connectivity without a fallback.
|
|
291
|
+
- Interactive prototypes without a pre-recorded backup video.
|
|
292
|
+
- Polls or live data in the first half of a presentation. Build credibility before asking for participation.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: layout
|
|
3
|
+
description: Alignment, grid, and arrangement patterns for slidenerds slides using Tailwind CSS
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Layout skill
|
|
7
|
+
|
|
8
|
+
Alignment and arrangement primitives for slide content. Use these patterns instead of guessing at Tailwind classes.
|
|
9
|
+
|
|
10
|
+
## Alignment
|
|
11
|
+
|
|
12
|
+
### Center content (horizontal and vertical)
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
<section data-slide="">
|
|
16
|
+
<div className="flex items-center justify-center min-h-screen">
|
|
17
|
+
<div className="text-center">
|
|
18
|
+
<h1 className="text-5xl font-bold">Centered title</h1>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</section>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Left-align a group of elements
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
<div className="flex flex-col items-start gap-4" style={{ padding: 'var(--slide-padding)' }}>
|
|
28
|
+
<h2 className="text-3xl font-semibold">Left-aligned heading</h2>
|
|
29
|
+
<p className="text-lg">Body text aligned to the left edge</p>
|
|
30
|
+
<img src="/chart.png" alt="Chart" className="w-full max-w-md" />
|
|
31
|
+
</div>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Right-align a group of elements
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<div className="flex flex-col items-end gap-4" style={{ padding: 'var(--slide-padding)' }}>
|
|
38
|
+
<p className="text-lg">Right-aligned caption</p>
|
|
39
|
+
<p className="text-sm opacity-70">Source: Company data</p>
|
|
40
|
+
</div>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Bottom-align content
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<section data-slide="">
|
|
47
|
+
<div className="flex flex-col justify-end min-h-screen" style={{ padding: 'var(--slide-padding)' }}>
|
|
48
|
+
<h2 className="text-3xl font-semibold">Pinned to bottom</h2>
|
|
49
|
+
</div>
|
|
50
|
+
</section>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Grid arrangements
|
|
54
|
+
|
|
55
|
+
### Two-column layout
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<section data-slide="">
|
|
59
|
+
<div className="grid grid-cols-2 gap-8 min-h-screen items-center" style={{ padding: 'var(--slide-padding)' }}>
|
|
60
|
+
<div>
|
|
61
|
+
<h2 className="text-3xl font-semibold">Left column</h2>
|
|
62
|
+
<p className="mt-4 text-lg">Explanation text</p>
|
|
63
|
+
</div>
|
|
64
|
+
<div>
|
|
65
|
+
<img src="/visual.png" alt="Visual" className="w-full rounded-lg" />
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</section>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Three-column layout
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
<div className="grid grid-cols-3 gap-6" style={{ padding: 'var(--slide-padding)' }}>
|
|
75
|
+
<div className="text-center">
|
|
76
|
+
<p className="text-4xl font-bold">$4.2M</p>
|
|
77
|
+
<p className="text-sm opacity-70 mt-2">ARR</p>
|
|
78
|
+
</div>
|
|
79
|
+
<div className="text-center">
|
|
80
|
+
<p className="text-4xl font-bold">142%</p>
|
|
81
|
+
<p className="text-sm opacity-70 mt-2">Growth</p>
|
|
82
|
+
</div>
|
|
83
|
+
<div className="text-center">
|
|
84
|
+
<p className="text-4xl font-bold">98%</p>
|
|
85
|
+
<p className="text-sm opacity-70 mt-2">Retention</p>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Four-column layout
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
<div className="grid grid-cols-4 gap-4" style={{ padding: 'var(--slide-padding)' }}>
|
|
94
|
+
{/* Four equal columns */}
|
|
95
|
+
</div>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Distribute elements evenly
|
|
99
|
+
|
|
100
|
+
### Horizontal distribution
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
<div className="flex justify-between items-center" style={{ padding: 'var(--slide-padding)' }}>
|
|
104
|
+
<div>Item 1</div>
|
|
105
|
+
<div>Item 2</div>
|
|
106
|
+
<div>Item 3</div>
|
|
107
|
+
</div>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Vertical distribution
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<div className="flex flex-col justify-between min-h-screen" style={{ padding: 'var(--slide-padding)' }}>
|
|
114
|
+
<div>Top</div>
|
|
115
|
+
<div>Middle</div>
|
|
116
|
+
<div>Bottom</div>
|
|
117
|
+
</div>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Hero + body layout
|
|
121
|
+
|
|
122
|
+
Large heading at top, body content below:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<section data-slide="">
|
|
126
|
+
<div className="flex flex-col min-h-screen" style={{ padding: 'var(--slide-padding)' }}>
|
|
127
|
+
<h1 className="text-6xl font-bold">Hero headline</h1>
|
|
128
|
+
<div className="mt-auto">
|
|
129
|
+
<p className="text-xl">Supporting body content goes here</p>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</section>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Full-bleed vs. contained
|
|
136
|
+
|
|
137
|
+
### Full-bleed (edge to edge)
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<section data-slide="">
|
|
141
|
+
<div className="relative min-h-screen">
|
|
142
|
+
<img src="/bg.jpg" alt="" className="absolute inset-0 w-full h-full object-cover" />
|
|
143
|
+
<div className="relative z-10 flex items-center justify-center min-h-screen">
|
|
144
|
+
<h1 className="text-5xl font-bold text-white">Full-bleed image</h1>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
</section>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Contained (with slide padding)
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
<section data-slide="">
|
|
154
|
+
<div style={{ padding: 'var(--slide-padding)' }}>
|
|
155
|
+
<h2 className="text-3xl font-semibold">Contained content</h2>
|
|
156
|
+
</div>
|
|
157
|
+
</section>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Spacing tokens
|
|
161
|
+
|
|
162
|
+
Always use the spacing tokens from `brand.config.ts` via CSS custom properties:
|
|
163
|
+
|
|
164
|
+
- `var(--slide-padding)` for the outer slide padding (default: 4rem)
|
|
165
|
+
- Tailwind gap utilities (`gap-4`, `gap-8`) for element spacing within a slide
|
|
166
|
+
- Never hardcode pixel or rem values for slide-level spacing
|
|
167
|
+
|
|
168
|
+
## Aspect ratio preservation
|
|
169
|
+
|
|
170
|
+
For media elements that need to maintain aspect ratio:
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
<div className="aspect-video w-full">
|
|
174
|
+
<img src="/screenshot.png" alt="Screenshot" className="w-full h-full object-contain" />
|
|
175
|
+
</div>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Common aspect ratios: `aspect-video` (16:9), `aspect-square` (1:1), `aspect-[4/3]` (4:3).
|