lazyslides 0.2.0 → 0.2.1
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/README.md +25 -3
- package/_includes/slides/agenda.njk +15 -3
- package/_includes/slides/center.njk +2 -0
- package/_includes/slides/code.njk +2 -0
- package/_includes/slides/columns.njk +2 -0
- package/_includes/slides/comparison.njk +2 -0
- package/_includes/slides/content.njk +2 -0
- package/_includes/slides/funnel.njk +2 -0
- package/_includes/slides/hero.njk +1 -1
- package/_includes/slides/image-overlay.njk +2 -0
- package/_includes/slides/metrics.njk +2 -0
- package/_includes/slides/quote.njk +2 -0
- package/_includes/slides/section.njk +6 -0
- package/_includes/slides/split-wide.njk +2 -0
- package/_includes/slides/split.njk +2 -0
- package/_includes/slides/table.njk +2 -0
- package/_includes/slides/timeline.njk +2 -0
- package/_layouts/presentation.njk +1 -0
- package/index.js +1 -1
- package/package.json +1 -1
- package/scaffold/CLAUDE.md +9 -4
- package/scaffold/README.md +1 -0
- package/scaffold/claude-commands/add-template.md +74 -0
- package/scaffold/claude-commands/add-theme.md +50 -0
- package/src/styles.css +18 -3
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Leverage your favorite AI agent to build simple, yet meaningful slide decks.
|
|
|
10
10
|
|
|
11
11
|
Built on [Eleventy](https://www.11ty.dev/), [Reveal.js](https://revealjs.com), and [Tailwind CSS](https://tailwindcss.com).
|
|
12
12
|
|
|
13
|
-
[Live demo](https://chrisissorry.github.io/lazyslides/)
|
|
13
|
+
[Live demo](https://chrisissorry.github.io/lazyslides/presentations/example/)
|
|
14
14
|
|
|
15
15
|
## Why
|
|
16
16
|
|
|
@@ -148,10 +148,31 @@ Supporting files (outlines, notes, PDFs, images) go alongside `index.md` in the
|
|
|
148
148
|
| `table` | Data table |
|
|
149
149
|
| `code` | Code snippet with syntax highlighting |
|
|
150
150
|
| `image-overlay` | Full image with positioned text box |
|
|
151
|
-
| `agenda` | Clickable table of contents |
|
|
151
|
+
| `agenda` | Clickable table of contents (supports `auto_generate: true`) |
|
|
152
152
|
|
|
153
153
|
See `CLAUDE.md` for the full field reference for each template.
|
|
154
154
|
|
|
155
|
+
## Footer
|
|
156
|
+
|
|
157
|
+
Every slide (except `title`) includes a footer bar with slide numbers, a logo, a brand name, and optional source references.
|
|
158
|
+
|
|
159
|
+
**Visibility** — the footer is shown by default on most templates. Hero and section slides hide it by default.
|
|
160
|
+
|
|
161
|
+
| Level | Field | Effect |
|
|
162
|
+
|-------|-------|--------|
|
|
163
|
+
| Presentation | `show_footer: false` | Hides the footer on all slides |
|
|
164
|
+
| Per slide | `hide_footer: true` | Hides footer on that slide |
|
|
165
|
+
| Per slide (hero/section) | `show_footer: true` | Shows footer on that slide |
|
|
166
|
+
|
|
167
|
+
**Branding** — customize the logo and name via CSS custom properties in a theme file:
|
|
168
|
+
|
|
169
|
+
```css
|
|
170
|
+
:root {
|
|
171
|
+
--footer-brand-name: 'Your Brand';
|
|
172
|
+
--footer-logo-url: url('/path/to/logo.svg');
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
155
176
|
## Slash commands (Claude Code)
|
|
156
177
|
|
|
157
178
|
The scaffolded project includes Claude Code slash commands for the full workflow:
|
|
@@ -164,6 +185,8 @@ The scaffolded project includes Claude Code slash commands for the full workflow
|
|
|
164
185
|
| `/create-outline` | Plan structure before writing YAML |
|
|
165
186
|
| `/refine-slides` | Improve an existing presentation |
|
|
166
187
|
| `/validate` | Check YAML and fix issues |
|
|
188
|
+
| `/add-template` | Create a custom slide template |
|
|
189
|
+
| `/add-theme` | Create a custom CSS theme |
|
|
167
190
|
|
|
168
191
|
The project ships a `CLAUDE.md` with the complete template schema, so Claude Code knows every field of every template.
|
|
169
192
|
|
|
@@ -184,7 +207,6 @@ Drop a CSS file into `themes/` to override design tokens:
|
|
|
184
207
|
```css
|
|
185
208
|
:root {
|
|
186
209
|
--color-primary-500: #your-brand-color;
|
|
187
|
-
--footer-brand-name: 'Your Brand';
|
|
188
210
|
}
|
|
189
211
|
```
|
|
190
212
|
|
|
@@ -1,17 +1,29 @@
|
|
|
1
|
-
{# TEMPLATE: agenda — Clickable table of contents for presentation sections.
|
|
1
|
+
{# TEMPLATE: agenda — Clickable table of contents for presentation sections.
|
|
2
|
+
Set auto_generate: true to build the agenda automatically from section slides.
|
|
3
|
+
Manual mode: provide sections array with title and slide (0-based index). #}
|
|
2
4
|
<section class="slide-agenda">
|
|
3
5
|
<div class="slide-body">
|
|
4
6
|
<div class="slide-header">
|
|
5
7
|
<h2>{{ slide.title | default("Agenda") }}</h2>
|
|
6
8
|
</div>
|
|
7
9
|
<ol class="agenda-list">
|
|
8
|
-
{%
|
|
10
|
+
{% if slide.auto_generate %}
|
|
11
|
+
{% for s in slides %}
|
|
12
|
+
{% if s.template == "section" %}
|
|
13
|
+
<li><a href="#/{{ loop.index0 }}">{{ s.title }}</a></li>
|
|
14
|
+
{% endif %}
|
|
15
|
+
{% endfor %}
|
|
16
|
+
{% else %}
|
|
17
|
+
{% for item in slide.sections %}
|
|
9
18
|
<li><a href="#/{{ item.slide }}">{{ item.title }}</a></li>
|
|
10
|
-
|
|
19
|
+
{% endfor %}
|
|
20
|
+
{% endif %}
|
|
11
21
|
</ol>
|
|
12
22
|
</div>
|
|
23
|
+
{% if global_footer and not slide.hide_footer %}
|
|
13
24
|
{% set reference = slide.reference %}
|
|
14
25
|
{% set reference_link = slide.reference_link %}
|
|
15
26
|
{% set references = slide.references %}
|
|
16
27
|
{% include "slides/footer.njk" %}
|
|
28
|
+
{% endif %}
|
|
17
29
|
</section>
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
{% endif %}
|
|
10
10
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
11
11
|
</div>
|
|
12
|
+
{% if global_footer and not slide.hide_footer %}
|
|
12
13
|
{% set reference = slide.reference %}
|
|
13
14
|
{% set reference_link = slide.reference_link %}
|
|
14
15
|
{% set references = slide.references %}
|
|
15
16
|
{% include "slides/footer.njk" %}
|
|
17
|
+
{% endif %}
|
|
16
18
|
</section>
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
{% if slide.caption %}<p class="caption">{{ slide.caption }}</p>{% endif %}
|
|
9
9
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
10
10
|
</div>
|
|
11
|
+
{% if global_footer and not slide.hide_footer %}
|
|
11
12
|
{% set reference = slide.reference %}
|
|
12
13
|
{% set reference_link = slide.reference_link %}
|
|
13
14
|
{% set references = slide.references %}
|
|
14
15
|
{% include "slides/footer.njk" %}
|
|
16
|
+
{% endif %}
|
|
15
17
|
</section>
|
|
@@ -28,8 +28,10 @@
|
|
|
28
28
|
</div>
|
|
29
29
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
30
30
|
</div>
|
|
31
|
+
{% if global_footer and not slide.hide_footer %}
|
|
31
32
|
{% set reference = slide.reference %}
|
|
32
33
|
{% set reference_link = slide.reference_link %}
|
|
33
34
|
{% set references = slide.references %}
|
|
34
35
|
{% include "slides/footer.njk" %}
|
|
36
|
+
{% endif %}
|
|
35
37
|
</section>
|
|
@@ -22,8 +22,10 @@
|
|
|
22
22
|
</table>
|
|
23
23
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
24
24
|
</div>
|
|
25
|
+
{% if global_footer and not slide.hide_footer %}
|
|
25
26
|
{% set reference = slide.reference %}
|
|
26
27
|
{% set reference_link = slide.reference_link %}
|
|
27
28
|
{% set references = slide.references %}
|
|
28
29
|
{% include "slides/footer.njk" %}
|
|
30
|
+
{% endif %}
|
|
29
31
|
</section>
|
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
{% endif %}
|
|
16
16
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
17
17
|
</div>
|
|
18
|
+
{% if global_footer and not slide.hide_footer %}
|
|
18
19
|
{% set reference = slide.reference %}
|
|
19
20
|
{% set reference_link = slide.reference_link %}
|
|
20
21
|
{% set references = slide.references %}
|
|
21
22
|
{% include "slides/footer.njk" %}
|
|
23
|
+
{% endif %}
|
|
22
24
|
</section>
|
|
@@ -23,8 +23,10 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
25
25
|
</div>
|
|
26
|
+
{% if global_footer and not slide.hide_footer %}
|
|
26
27
|
{% set reference = slide.reference %}
|
|
27
28
|
{% set reference_link = slide.reference_link %}
|
|
28
29
|
{% set references = slide.references %}
|
|
29
30
|
{% include "slides/footer.njk" %}
|
|
31
|
+
{% endif %}
|
|
30
32
|
</section>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
{% endif %}
|
|
19
19
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
20
20
|
</div>
|
|
21
|
-
{% if
|
|
21
|
+
{% if global_footer and slide.show_footer %}
|
|
22
22
|
{% set reference = slide.reference %}
|
|
23
23
|
{% set reference_link = slide.reference_link %}
|
|
24
24
|
{% set references = slide.references %}
|
|
@@ -17,8 +17,10 @@
|
|
|
17
17
|
</div>
|
|
18
18
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
19
19
|
</div>
|
|
20
|
+
{% if global_footer and not slide.hide_footer %}
|
|
20
21
|
{% set reference = slide.reference %}
|
|
21
22
|
{% set reference_link = slide.reference_link %}
|
|
22
23
|
{% set references = slide.references %}
|
|
23
24
|
{% include "slides/footer.njk" %}
|
|
25
|
+
{% endif %}
|
|
24
26
|
</section>
|
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
22
22
|
</div>
|
|
23
|
+
{% if global_footer and not slide.hide_footer %}
|
|
23
24
|
{% set reference = slide.reference %}
|
|
24
25
|
{% set reference_link = slide.reference_link %}
|
|
25
26
|
{% set references = slide.references %}
|
|
26
27
|
{% include "slides/footer.njk" %}
|
|
28
|
+
{% endif %}
|
|
27
29
|
</section>
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
{% endif %}
|
|
11
11
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
12
12
|
</div>
|
|
13
|
+
{% if global_footer and not slide.hide_footer %}
|
|
13
14
|
{% set reference = slide.reference %}
|
|
14
15
|
{% set reference_link = slide.reference_link %}
|
|
15
16
|
{% set references = slide.references %}
|
|
16
17
|
{% include "slides/footer.njk" %}
|
|
18
|
+
{% endif %}
|
|
17
19
|
</section>
|
|
@@ -3,4 +3,10 @@
|
|
|
3
3
|
<h2>{{ slide.title }}</h2>
|
|
4
4
|
{% if slide.subtitle %}<p class="subtitle">{{ slide.subtitle }}</p>{% endif %}
|
|
5
5
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
6
|
+
{% if global_footer and slide.show_footer %}
|
|
7
|
+
{% set reference = slide.reference %}
|
|
8
|
+
{% set reference_link = slide.reference_link %}
|
|
9
|
+
{% set references = slide.references %}
|
|
10
|
+
{% include "slides/footer.njk" %}
|
|
11
|
+
{% endif %}
|
|
6
12
|
</section>
|
|
@@ -23,8 +23,10 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
|
+
{% if global_footer and not slide.hide_footer %}
|
|
26
27
|
{% set reference = slide.reference %}
|
|
27
28
|
{% set reference_link = slide.reference_link %}
|
|
28
29
|
{% set references = slide.references %}
|
|
29
30
|
{% include "slides/footer.njk" %}
|
|
31
|
+
{% endif %}
|
|
30
32
|
</section>
|
|
@@ -23,8 +23,10 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
|
+
{% if global_footer and not slide.hide_footer %}
|
|
26
27
|
{% set reference = slide.reference %}
|
|
27
28
|
{% set reference_link = slide.reference_link %}
|
|
28
29
|
{% set references = slide.references %}
|
|
29
30
|
{% include "slides/footer.njk" %}
|
|
31
|
+
{% endif %}
|
|
30
32
|
</section>
|
|
@@ -24,8 +24,10 @@
|
|
|
24
24
|
</table>
|
|
25
25
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
26
26
|
</div>
|
|
27
|
+
{% if global_footer and not slide.hide_footer %}
|
|
27
28
|
{% set reference = slide.reference %}
|
|
28
29
|
{% set reference_link = slide.reference_link %}
|
|
29
30
|
{% set references = slide.references %}
|
|
30
31
|
{% include "slides/footer.njk" %}
|
|
32
|
+
{% endif %}
|
|
31
33
|
</section>
|
|
@@ -23,8 +23,10 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
{% if slide.notes %}<aside class="notes">{{ slide.notes }}</aside>{% endif %}
|
|
25
25
|
</div>
|
|
26
|
+
{% if global_footer and not slide.hide_footer %}
|
|
26
27
|
{% set reference = slide.reference %}
|
|
27
28
|
{% set reference_link = slide.reference_link %}
|
|
28
29
|
{% set references = slide.references %}
|
|
29
30
|
{% include "slides/footer.njk" %}
|
|
31
|
+
{% endif %}
|
|
30
32
|
</section>
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
{% set slide_index = loop.index %}
|
|
44
44
|
{% set total_slides = slides | length %}
|
|
45
45
|
{% set presentation_title = title %}
|
|
46
|
+
{% set global_footer = show_footer if show_footer is defined else true %}
|
|
46
47
|
{% include "slides/" + slide.template + ".njk" %}
|
|
47
48
|
{% endfor %}
|
|
48
49
|
</div>
|
package/index.js
CHANGED
|
@@ -134,7 +134,7 @@ eleventyExcludeFromCollections: true
|
|
|
134
134
|
---
|
|
135
135
|
<!DOCTYPE html>
|
|
136
136
|
<html>
|
|
137
|
-
<head><meta http-equiv="refresh" content="0; url={{ '/presentations/
|
|
137
|
+
<head><meta http-equiv="refresh" content="0; url={{ '/presentations/' | url }}"></head>
|
|
138
138
|
<body></body>
|
|
139
139
|
</html>
|
|
140
140
|
`);
|
package/package.json
CHANGED
package/scaffold/CLAUDE.md
CHANGED
|
@@ -42,11 +42,12 @@ theme: default
|
|
|
42
42
|
transition: slide
|
|
43
43
|
progress: true
|
|
44
44
|
slideNumber: true
|
|
45
|
-
show_footer: true
|
|
45
|
+
show_footer: true # show footer on slides (default: true, set false to hide globally)
|
|
46
46
|
slides: # required — array of slide objects
|
|
47
47
|
- template: content # required on every slide
|
|
48
48
|
title: Slide Title
|
|
49
49
|
# ... template-specific fields
|
|
50
|
+
hide_footer: true # optional — hide footer on this slide (default: false)
|
|
50
51
|
notes: | # optional speaker notes (all templates)
|
|
51
52
|
What to say during this slide
|
|
52
53
|
---
|
|
@@ -67,6 +68,7 @@ Fields marked with `*` are required.
|
|
|
67
68
|
#### `section` — Chapter divider
|
|
68
69
|
- `title`* — section name
|
|
69
70
|
- `subtitle` — section description
|
|
71
|
+
- `show_footer` — show footer on this slide (default: hidden)
|
|
70
72
|
|
|
71
73
|
#### `content` — Standard bullets
|
|
72
74
|
- `title`* — slide title
|
|
@@ -92,7 +94,7 @@ Fields marked with `*` are required.
|
|
|
92
94
|
- `box_title` — overlay box heading
|
|
93
95
|
- `box_text` — overlay box content
|
|
94
96
|
- `box_items` — overlay box bullet list
|
|
95
|
-
- `
|
|
97
|
+
- `show_footer` — show footer on this slide (default: hidden)
|
|
96
98
|
|
|
97
99
|
#### `metrics` — Key statistics
|
|
98
100
|
- `title`* — slide title
|
|
@@ -182,9 +184,10 @@ Fields marked with `*` are required.
|
|
|
182
184
|
|
|
183
185
|
#### `agenda` — Clickable table of contents
|
|
184
186
|
- `title` — slide title (default: "Agenda")
|
|
185
|
-
- `
|
|
187
|
+
- `auto_generate` — build agenda automatically from `section` slides (default: false)
|
|
188
|
+
- `sections` — manual array of section objects (ignored when `auto_generate` is true):
|
|
186
189
|
- `title`* — section name
|
|
187
|
-
- `slide`* — slide
|
|
190
|
+
- `slide`* — 0-based slide index to link to
|
|
188
191
|
- `reference` / `reference_link` / `references`
|
|
189
192
|
|
|
190
193
|
## Common Patterns
|
|
@@ -269,6 +272,8 @@ Images in `center`, `split`, and `split-wide` templates automatically get lightb
|
|
|
269
272
|
| `/research-topic` | Research a topic for data-driven slides |
|
|
270
273
|
| `/create-outline` | Create a structured outline before generating YAML |
|
|
271
274
|
| `/refine-slides` | Review and improve an existing presentation |
|
|
275
|
+
| `/add-template` | Create a custom slide template |
|
|
276
|
+
| `/add-theme` | Create a custom CSS theme |
|
|
272
277
|
|
|
273
278
|
## Build Commands
|
|
274
279
|
|
package/scaffold/README.md
CHANGED
|
@@ -27,3 +27,4 @@ Add a new folder under `presentations/` with an `index.md` file containing your
|
|
|
27
27
|
|
|
28
28
|
- **Themes** — Drop CSS files into `themes/` to override the default theme
|
|
29
29
|
- **Styles** — Add custom CSS to `src/styles.css`
|
|
30
|
+
- **Templates** — Run `/add-template` in Claude Code to create custom slide templates
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Add Template
|
|
2
|
+
|
|
3
|
+
You are helping the user create a custom slide template for their LazySlides project.
|
|
4
|
+
|
|
5
|
+
## Step 1: Gather Requirements
|
|
6
|
+
|
|
7
|
+
Ask the user:
|
|
8
|
+
- What should the template do? (purpose, layout idea)
|
|
9
|
+
- What content fields does it need? (titles, text, images, lists, etc.)
|
|
10
|
+
- Any specific layout or styling requirements?
|
|
11
|
+
|
|
12
|
+
## Step 2: Choose a Name
|
|
13
|
+
|
|
14
|
+
Help the user pick a kebab-case name for the template (e.g. `icon-grid`, `two-images`, `photo-grid`). The name must not conflict with the 17 built-in templates: `title`, `section`, `content`, `center`, `hero`, `metrics`, `comparison`, `columns`, `quote`, `image-overlay`, `code`, `timeline`, `funnel`, `split`, `split-wide`, `table`, `agenda`.
|
|
15
|
+
|
|
16
|
+
## Step 3: Pick a Starting Point
|
|
17
|
+
|
|
18
|
+
Read the existing templates in `_includes/slides/` and suggest the closest built-in template as a base to adapt from. Show the user the docblock and structure of the suggested template. They can also choose to start from scratch.
|
|
19
|
+
|
|
20
|
+
## Step 4: Create the Template File
|
|
21
|
+
|
|
22
|
+
Generate `_includes/slides/<name>.njk` following the standard pattern:
|
|
23
|
+
|
|
24
|
+
```nunjucks
|
|
25
|
+
{#
|
|
26
|
+
TEMPLATE: <name> — <short description>
|
|
27
|
+
|
|
28
|
+
Fields:
|
|
29
|
+
- field_name* — description (required)
|
|
30
|
+
- field_name — description (optional)
|
|
31
|
+
|
|
32
|
+
Usage:
|
|
33
|
+
- template: <name>
|
|
34
|
+
field_name: "value"
|
|
35
|
+
#}
|
|
36
|
+
|
|
37
|
+
<section class="slide-<name>">
|
|
38
|
+
<div class="slide-body">
|
|
39
|
+
{% if slide.title %}
|
|
40
|
+
<div class="slide-header">
|
|
41
|
+
<h2>{{ slide.title }}</h2>
|
|
42
|
+
</div>
|
|
43
|
+
{% endif %}
|
|
44
|
+
|
|
45
|
+
<div class="slide-content">
|
|
46
|
+
{# Template-specific content here #}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
{% if slide.notes %}
|
|
51
|
+
<aside class="notes">{{ slide.notes }}</aside>
|
|
52
|
+
{% endif %}
|
|
53
|
+
|
|
54
|
+
{% include "slides/_footer.njk" %}
|
|
55
|
+
</section>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Key conventions to follow:
|
|
59
|
+
- Wrap everything in `<section class="slide-<name>">`
|
|
60
|
+
- Use `slide-body` > `slide-header` + `slide-content` structure
|
|
61
|
+
- Access slide data via `slide.fieldName`
|
|
62
|
+
- Include speaker notes block and footer include
|
|
63
|
+
- Use existing CSS utility classes from the design system where possible
|
|
64
|
+
|
|
65
|
+
## Step 5: Add CSS
|
|
66
|
+
|
|
67
|
+
If the template needs custom styles, add them to `src/styles.css`. Place them after the existing slide template styles. Use the `.slide-<name>` class as the scope. Follow the existing spacing, font, and color conventions from the design system.
|
|
68
|
+
|
|
69
|
+
## Step 6: Test It
|
|
70
|
+
|
|
71
|
+
1. Add a test slide to an existing presentation using `template: <name>` with sample data
|
|
72
|
+
2. Run `pnpm run validate` — the validator will warn about an unknown template name (this is expected for custom templates)
|
|
73
|
+
3. Run `pnpm run dev` to preview the result in the browser
|
|
74
|
+
4. Iterate on the template and styles until it looks right
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Add Theme
|
|
2
|
+
|
|
3
|
+
You are helping the user create a custom CSS theme for their LazySlides project.
|
|
4
|
+
|
|
5
|
+
## Step 1: Gather Brand Requirements
|
|
6
|
+
|
|
7
|
+
Ask the user:
|
|
8
|
+
- What brand or visual identity is this for?
|
|
9
|
+
- Primary accent color (hex code or description like "dark teal")
|
|
10
|
+
- Preferred fonts for headings and body text (or "keep defaults")
|
|
11
|
+
- Footer brand name and optional logo image
|
|
12
|
+
- Any other styling preferences (background gradient, etc.)
|
|
13
|
+
|
|
14
|
+
## Step 2: Choose a Theme Name
|
|
15
|
+
|
|
16
|
+
Help the user pick a kebab-case name (e.g. `acme-corp`, `dark-blue`, `conference-2026`). This becomes both the filename (`themes/<name>.css`) and the frontmatter value (`theme: <name>`).
|
|
17
|
+
|
|
18
|
+
## Step 3: Create the Theme File
|
|
19
|
+
|
|
20
|
+
Read `assets/css/themes/default.css` as the reference for all customizable properties. Create `themes/<name>.css` with the user's values. The theme can override any of these:
|
|
21
|
+
|
|
22
|
+
**Typography:**
|
|
23
|
+
- `--font-heading` — headings, quotes, metric values (default: Source Serif 4)
|
|
24
|
+
- `--font-body` — paragraphs, lists, labels, footer (default: Plus Jakarta Sans)
|
|
25
|
+
- Add `@import url(...)` at the top for Google Fonts if needed
|
|
26
|
+
|
|
27
|
+
**Primary color scale:**
|
|
28
|
+
- `--color-primary-50` through `--color-primary-700` — light tints to dark accents
|
|
29
|
+
- Generate a harmonious 7-step scale from the user's chosen color
|
|
30
|
+
|
|
31
|
+
**Footer branding:**
|
|
32
|
+
- `--footer-brand-name` — text shown in footer center
|
|
33
|
+
- `--footer-logo-url` — optional logo URL (e.g. `url('/assets/images/brands/logo.svg')`)
|
|
34
|
+
|
|
35
|
+
**Theater background:**
|
|
36
|
+
- `html, body { background: ... }` — gradient behind the slide cards
|
|
37
|
+
|
|
38
|
+
Only include properties the user wants to change — omitted properties inherit from `src/styles.css` defaults.
|
|
39
|
+
|
|
40
|
+
## Step 4: Apply the Theme
|
|
41
|
+
|
|
42
|
+
Update the target presentation's `index.md` frontmatter to use the new theme:
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
theme: <name>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Step 5: Preview
|
|
49
|
+
|
|
50
|
+
Run `pnpm run dev` and open the presentation in the browser to review. Iterate on colors, fonts, and spacing until the user is satisfied.
|
package/src/styles.css
CHANGED
|
@@ -171,6 +171,19 @@ html, body {
|
|
|
171
171
|
overflow: hidden;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
+
/* Overview mode (ESC key) — ensure all slides are visible as thumbnails.
|
|
175
|
+
Reveal.js sets the hidden attribute on non-present sections, and
|
|
176
|
+
Tailwind's @layer base includes [hidden] { display: none !important }.
|
|
177
|
+
With CSS layers, layered !important beats unlayered !important, so we
|
|
178
|
+
must place our override inside @layer base where specificity decides. */
|
|
179
|
+
@layer base {
|
|
180
|
+
.reveal.overview .slides > section {
|
|
181
|
+
display: flex !important;
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
opacity: 1 !important;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
174
187
|
/* ============================================
|
|
175
188
|
BASE TYPOGRAPHY
|
|
176
189
|
============================================ */
|
|
@@ -1555,7 +1568,8 @@ html, body {
|
|
|
1555
1568
|
}
|
|
1556
1569
|
|
|
1557
1570
|
/* Enlarge progress bar when hovering near bottom */
|
|
1558
|
-
.reveal:has(.section-progress-dots:hover) .progress
|
|
1571
|
+
.reveal:has(.section-progress-dots:hover) .progress,
|
|
1572
|
+
.reveal:has(.progress:hover) .progress {
|
|
1559
1573
|
height: 20px; /* 5x the original 4px */
|
|
1560
1574
|
}
|
|
1561
1575
|
|
|
@@ -2022,7 +2036,7 @@ html, body {
|
|
|
2022
2036
|
right: 0;
|
|
2023
2037
|
height: 40px; /* Large hover zone for easier mouse targeting */
|
|
2024
2038
|
z-index: 11; /* Above progress bar (z-index: 10) */
|
|
2025
|
-
pointer-events:
|
|
2039
|
+
pointer-events: none; /* Let clicks pass through to progress bar */
|
|
2026
2040
|
}
|
|
2027
2041
|
|
|
2028
2042
|
.section-progress-dots .section-dot {
|
|
@@ -2039,7 +2053,8 @@ html, body {
|
|
|
2039
2053
|
}
|
|
2040
2054
|
|
|
2041
2055
|
/* Enlarge dots when hovering near bottom */
|
|
2042
|
-
.section-progress-dots:hover .section-dot
|
|
2056
|
+
.section-progress-dots:hover .section-dot,
|
|
2057
|
+
.reveal:has(.progress:hover) .section-progress-dots .section-dot {
|
|
2043
2058
|
width: 20px;
|
|
2044
2059
|
height: 20px;
|
|
2045
2060
|
}
|