@kadal/theme-swiss 0.0.0-stage → 0.4.3

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.
Files changed (5) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +70 -2
  3. package/index.tsx +114 -0
  4. package/package.json +101 -4
  5. package/style.css +723 -0
package/README.md CHANGED
@@ -1,3 +1,71 @@
1
- # Temporary Holding Version
1
+ # @kadal/theme-swiss
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Swiss**, a theme for [Kadal Deck](https://deck.kadal.cc). The International Typographic Style for design talks. Huge Inter Tight headings set tight and flush left on a twelve-column grid, heavy black rules, and one signal colour used sparingly. Facts, statements and quotes sit flush left, not centred; a section is the signal colour edge to edge; a running header carries the deck's title, the current section and the page.
4
+
5
+ <p>
6
+ <img src="https://deck.kadal.cc/themes/swiss-light-1.webp" alt="Swiss: the cover, light" width="49%">
7
+ <img src="https://deck.kadal.cc/themes/swiss-dark-2.webp" alt="Swiss: a content slide, dark" width="49%">
8
+ </p>
9
+
10
+ [All 16 themes](https://deck.kadal.cc/themes/) · [Themes and backgrounds](https://deck.kadal.cc/docs/themes-and-backgrounds/) · [Writing a theme](https://deck.kadal.cc/docs/writing-a-theme/) · [Source](https://github.com/kadalcc/deck/tree/main/packages/theme-swiss)
11
+
12
+ ## Use it
13
+
14
+ ```bash
15
+ npm install @kadal/theme-swiss
16
+ ```
17
+
18
+ ```yaml
19
+ ---
20
+ theme: swiss
21
+ themeConfig: # all optional
22
+ header: true
23
+ signal: "#d70017"
24
+ signalDark: "#ff3b2f"
25
+ ---
26
+ ```
27
+
28
+ The deck plugin brings the stylesheet and the module in; nothing to import. The prebuilt shell (the hosted builder, published decks) bundles this theme already. Schemes: light and dark. Fonts: Inter Tight (headings), Inter (text), JetBrains Mono (code), loaded through the theme's `config.fonts`. Code colours: Shiki's min-light / vesper. To show it beside other themes in the theme menu (<kbd>T</kbd>), list it: `themes: [swiss, minimal]`.
29
+
30
+ ## themeConfig
31
+
32
+ Every key arrives on the deck root as a CSS variable (`accentDark` → `--theme-accent-dark`); the theme reads them with fallbacks, so set only what you change.
33
+
34
+ | key | type | default | what it does |
35
+ | --- | --- | --- | --- |
36
+ | `header` | boolean | `true` | The running header on content slides. `false` turns it off; `header: false` in a slide's frontmatter hides it on that slide. |
37
+ | `signal` | colour | `#d70017` | The one colour (light scheme), and the section slides' ground. |
38
+ | `signalDark` | colour | `#ff3b2f` | The signal on the dark page. Without it, a set `signal` is lifted towards white. |
39
+
40
+ ## Layouts
41
+
42
+ Every built-in layout is styled (`default`, `center`, `cover`, `intro`, `section`, `end`, `fact`, `quote`, `statement`, `full`, `two-cols`, `two-cols-header`, `image`, `image-left`, `image-right`, `iframe`, `iframe-left`, `iframe-right`), and the theme adds:
43
+
44
+ | layout | what |
45
+ | --- | --- |
46
+ | `poster` | One word or number as large as the slide allows (`size: 15em`, `signal: true` for the signal colour); `::meta::` is small print in the top right. |
47
+ | `index` | The slide's list as a grid of numbered cells (`columns:`, default 3). A **bold** opening is the cell's title. |
48
+ | `grid` | A header across, then each named slot a column under a heavy rule; the columns follow the number of slots (2 to 5), or `columns:`. |
49
+
50
+ ## Components
51
+
52
+ | component | what |
53
+ | --- | --- |
54
+ | `<Rule label right signal />` | A heavy rule with a label on the left and one on the right; `signal` colours it. |
55
+
56
+ ## Preview
57
+
58
+ `preview/deck.mdx` walks through every layout and component (`theme: ../`). In this repository:
59
+
60
+ ```bash
61
+ bun run --filter @kadal/theme-swiss dev # the preview deck, live
62
+ node tools/theme-shots.mjs swiss # screenshots in light and dark, contrast and overflow checks
63
+ ```
64
+
65
+ ## Accessibility and print
66
+
67
+ Body and muted text meet WCAG AA (4.5:1) on the page and on cards in every scheme the theme draws (checked by `tools/theme-shots.mjs`). Anything that moves stands still under `prefers-reduced-motion` and on a still copy; printed pages and exports drop shadows and glows.
68
+
69
+ ## Licence
70
+
71
+ AGPL-3.0-or-later, like the engine (see LICENSE); a commercial licence is available — see [LICENSING](https://github.com/kadalcc/deck/blob/main/LICENSING.md).
package/index.tsx ADDED
@@ -0,0 +1,114 @@
1
+ import type { CSSProperties } from "react";
2
+
3
+ import { type LayerProps, type LayoutProps, useDeck } from "@kadal/deck";
4
+
5
+ /**
6
+ * ─────────────────────────────────────────────────────────────────────────────
7
+ * Swiss's module: a running header, three grid layouts and a rule.
8
+ *
9
+ * the header a slide-top layer on content slides: the deck's title, the current
10
+ * section (the last `layout: section` slide's heading) and the page, under a
11
+ * heavy rule. `themeConfig.header: false` turns it off; `header: false` in a
12
+ * slide's frontmatter hides it there.
13
+ * layout: poster one word or number as large as the slide allows (`size: 15em`,
14
+ * `signal: true` for the signal colour); `::meta::` is small print top right
15
+ * layout: index the slide's list as a grid of numbered cells (`columns: 3`)
16
+ * layout: grid a header across, then each `::slot::` a column under a heavy rule
17
+ * (`columns:` defaults to the number of slots)
18
+ * <Rule> a heavy rule with a label on the left and one on the right
19
+ * ─────────────────────────────────────────────────────────────────────────────
20
+ */
21
+
22
+ const HEADER_LAYOUTS = new Set([
23
+ "default",
24
+ "center",
25
+ "two-cols",
26
+ "two-cols-header",
27
+ "index",
28
+ "grid",
29
+ ]);
30
+
31
+ function Header({ slide, page, total, layout, frontmatter }: LayerProps) {
32
+ const deck = useDeck();
33
+ if (deck.config.themeConfig.header === false || frontmatter.header === false) return null;
34
+ if (!HEADER_LAYOUTS.has(layout)) return null;
35
+ const index = slide?.index ?? 0;
36
+ const section = [...deck.manifest.slides]
37
+ .reverse()
38
+ .find((s) => s.index <= index && s.frontmatter.layout === "section");
39
+ const pad = (n: number) => String(n).padStart(2, "0");
40
+ return (
41
+ <div className="swiss-header" aria-hidden="true">
42
+ <span className="swiss-header-title">{deck.config.title}</span>
43
+ <span className="swiss-header-section">{section?.title ?? ""}</span>
44
+ <span className="swiss-header-page">
45
+ <b>{pad(page)}</b> / {pad(total)}
46
+ </span>
47
+ </div>
48
+ );
49
+ }
50
+
51
+ const num = (v: unknown) =>
52
+ typeof v === "number" ? v : typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : null;
53
+ const str = (v: unknown) => (typeof v === "string" && v.trim() ? v.trim() : null);
54
+
55
+ function Poster({ children, frontmatter }: LayoutProps) {
56
+ const size =
57
+ str(frontmatter.size) ?? (num(frontmatter.size) ? `${num(frontmatter.size)}em` : null);
58
+ return (
59
+ <div
60
+ className={`deck-layout deck-layout-poster${frontmatter.signal ? " is-signal" : ""}`}
61
+ style={size ? ({ "--swiss-poster-size": size } as CSSProperties) : undefined}
62
+ >
63
+ {children}
64
+ </div>
65
+ );
66
+ }
67
+
68
+ function Index({ children, frontmatter }: LayoutProps) {
69
+ const cols = num(frontmatter.columns);
70
+ return (
71
+ <div
72
+ className="deck-layout deck-layout-index"
73
+ style={cols ? ({ "--swiss-index-cols": cols } as CSSProperties) : undefined}
74
+ >
75
+ {children}
76
+ </div>
77
+ );
78
+ }
79
+
80
+ function Grid({ children, frontmatter }: LayoutProps) {
81
+ // Without `columns:`, style.css counts the slots (two to five) with :has().
82
+ const cols = num(frontmatter.columns);
83
+ return (
84
+ <div
85
+ className="deck-layout deck-layout-grid"
86
+ style={cols ? ({ "--swiss-grid-cols": cols } as CSSProperties) : undefined}
87
+ >
88
+ {children}
89
+ </div>
90
+ );
91
+ }
92
+
93
+ function Rule({
94
+ label,
95
+ right,
96
+ signal = false,
97
+ }: {
98
+ label?: string;
99
+ right?: string;
100
+ signal?: boolean;
101
+ }) {
102
+ return (
103
+ <div className={`swiss-rule${signal ? " is-signal" : ""}`} role="separator">
104
+ {label ? <span>{label}</span> : null}
105
+ {right ? <span>{right}</span> : null}
106
+ </div>
107
+ );
108
+ }
109
+
110
+ export default {
111
+ layouts: { poster: Poster, index: Index, grid: Grid },
112
+ components: { Rule },
113
+ layers: { "slide-top": Header },
114
+ };
package/package.json CHANGED
@@ -1,6 +1,103 @@
1
1
  {
2
2
  "name": "@kadal/theme-swiss",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.4.3",
4
+ "description": "Swiss, a theme for Kadal Deck (@kadal/deck). A bold International-style theme for design talks: huge grotesk headings on a strict twelve-column grid, one signal colour.",
5
+ "keywords": [
6
+ "kadal-theme",
7
+ "kadal-deck",
8
+ "presentation",
9
+ "slides",
10
+ "theme",
11
+ "swiss",
12
+ "grid",
13
+ "design",
14
+ "grotesk"
15
+ ],
16
+ "homepage": "https://deck.kadal.cc/themes/",
17
+ "funding": {
18
+ "type": "github",
19
+ "url": "https://github.com/sponsors/pmithunish"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/kadalcc/deck.git",
24
+ "directory": "packages/theme-swiss"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/kadalcc/deck/issues"
28
+ },
29
+ "license": "AGPL-3.0-or-later",
30
+ "author": "Kadal <hello@kadal.cc> (https://kadal.cc)",
31
+ "type": "module",
32
+ "sideEffects": [
33
+ "*.css"
34
+ ],
35
+ "files": [
36
+ "style.css",
37
+ "index.tsx",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "exports": {
42
+ ".": "./index.tsx",
43
+ "./style.css": "./style.css",
44
+ "./package.json": "./package.json"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public",
48
+ "provenance": true
49
+ },
50
+ "kadal": {
51
+ "theme": {
52
+ "name": "swiss",
53
+ "title": "Swiss",
54
+ "description": "A bold International-style theme for design talks: huge grotesk headings on a strict twelve-column grid, one signal colour.",
55
+ "colorScheme": "both",
56
+ "config": {
57
+ "transition": "fade",
58
+ "fonts": {
59
+ "heading": "Inter Tight",
60
+ "sans": "Inter",
61
+ "mono": "JetBrains Mono",
62
+ "weights": "400,500,700,800"
63
+ }
64
+ },
65
+ "themeConfig": {
66
+ "header": true
67
+ },
68
+ "shiki": {
69
+ "light": "min-light",
70
+ "dark": "vesper"
71
+ },
72
+ "defaults": {},
73
+ "layouts": [
74
+ "poster",
75
+ "index",
76
+ "grid"
77
+ ],
78
+ "components": [
79
+ "Rule"
80
+ ]
81
+ }
82
+ },
83
+ "scripts": {
84
+ "dev": "kadal-deck dev -C preview",
85
+ "check": "kadal-deck check -C preview",
86
+ "typecheck": "tsc --noEmit",
87
+ "test": "bun test"
88
+ },
89
+ "peerDependencies": {
90
+ "@kadal/deck": "^0.4.3",
91
+ "react": "^19.2.0"
92
+ },
93
+ "devDependencies": {
94
+ "@kadal/deck": "workspace:*",
95
+ "@types/react": "^19.2.0",
96
+ "@types/react-dom": "^19.2.0",
97
+ "@vitejs/plugin-react": "^6.0.2",
98
+ "react": "^19.2.7",
99
+ "react-dom": "^19.2.7",
100
+ "typescript": "^6.0.3",
101
+ "vite": "^8.0.16"
102
+ }
103
+ }