@kadal/theme-ocean 0.0.0-stage → 0.4.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/LICENSE +661 -0
- package/README.md +64 -2
- package/index.tsx +113 -0
- package/package.json +99 -4
- package/style.css +754 -0
package/README.md
CHANGED
|
@@ -1,3 +1,65 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @kadal/theme-ocean
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Ocean**, a theme for [Kadal Deck](https://deck.kadal.cc). Kadal's own theme. *Kadal* is Tamil for the sea, and the palette is the one [kadal.cc](https://kadal.cc) dives through: sunlit shallows in the light scheme (foam, sky and deep-sea ink), midnight water in the dark one (twilight blue, bioluminescent cyan, lure amber). Calm gradients for the page, Catamaran for type, Night Owl for code. Made to be a good default for a new deck.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Use it
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @kadal/theme-ocean
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
---
|
|
15
|
+
theme: ocean
|
|
16
|
+
themeConfig: # all optional
|
|
17
|
+
accent: "#1d63a8"
|
|
18
|
+
accentDark: "#5ff7ff"
|
|
19
|
+
waves: true
|
|
20
|
+
---
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
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: Catamaran (text and headings), JetBrains Mono (code), loaded through the theme's `config.fonts`. Code colours: Shiki's night-owl-light / night-owl. To show it beside other themes in the theme menu (<kbd>T</kbd>), list it: `themes: [ocean, minimal]`.
|
|
24
|
+
|
|
25
|
+
## themeConfig
|
|
26
|
+
|
|
27
|
+
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.
|
|
28
|
+
|
|
29
|
+
| key | type | default | what it does |
|
|
30
|
+
| --- | --- | --- | --- |
|
|
31
|
+
| `accent` | colour | `#1d63a8` | The accent in the light scheme (links, bullets, the progress bar). |
|
|
32
|
+
| `accentDark` | colour | `#5ff7ff` | The accent in the dark scheme. Without it, a set `accent` is lifted towards white. |
|
|
33
|
+
| `waves` | boolean | `true` | `false` hides the swells along the cover's foot. |
|
|
34
|
+
|
|
35
|
+
## Layouts
|
|
36
|
+
|
|
37
|
+
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:
|
|
38
|
+
|
|
39
|
+
| layout | what |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `waves` | A cover with the sea moving along the bottom edge. `align: center` centres it. The swells stand still under `prefers-reduced-motion` and in print. |
|
|
42
|
+
| `depth` | A section opener: its number (counted, or `n:`), a label (`depth: "200 m · twilight"`) and a sounding line down the side marking how far into the deck it is. |
|
|
43
|
+
|
|
44
|
+
## Components
|
|
45
|
+
|
|
46
|
+
| component | what |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `<Wave />` | A single swell as a divider, in the accent colour; `flip` turns it over. |
|
|
49
|
+
|
|
50
|
+
## Preview
|
|
51
|
+
|
|
52
|
+
`preview/deck.mdx` walks through every layout and component (`theme: ../`). In this repository:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
bun run --filter @kadal/theme-ocean dev # the preview deck, live
|
|
56
|
+
node tools/theme-shots.mjs ocean # screenshots in light and dark, contrast and overflow checks
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Accessibility and print
|
|
60
|
+
|
|
61
|
+
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.
|
|
62
|
+
|
|
63
|
+
## Licence
|
|
64
|
+
|
|
65
|
+
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,113 @@
|
|
|
1
|
+
import { type LayoutProps, useDeck, useSlideOptional } from "@kadal/deck";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
* Ocean's module: two layouts and a divider. The stylesheet (style.css) styles every built-in
|
|
6
|
+
* layout; these add what a sea-themed deck reaches for.
|
|
7
|
+
*
|
|
8
|
+
* layout: waves a cover with the sea moving along the bottom edge (`align: center` centres
|
|
9
|
+
* it); the swells stand still under prefers-reduced-motion and in print
|
|
10
|
+
* layout: depth a section opener: its number, a label (`depth: "200 m · twilight"`), and a
|
|
11
|
+
* sounding line down the side marking how far into the deck it is
|
|
12
|
+
* <Wave /> a single swell as a divider, in the accent colour
|
|
13
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const str = (v: unknown) => (typeof v === "string" && v.trim() ? v.trim() : null);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A swell as an SVG path: `periods` crests across 2880 units (twice the visible width, so a
|
|
20
|
+
* -50% drift loops without a seam), `amp` high, its mean line at `base` from the top of 320.
|
|
21
|
+
*/
|
|
22
|
+
function swell(periods: number, amp: number, base: number, phase = 0): string {
|
|
23
|
+
const w = 2880;
|
|
24
|
+
const step = w / (periods * 2);
|
|
25
|
+
let d = `M0 ${base + Math.sin(phase) * amp}`;
|
|
26
|
+
for (let i = 0; i < periods * 2; i++) {
|
|
27
|
+
const x0 = i * step;
|
|
28
|
+
const crest = i % 2 === 0 ? -amp : amp;
|
|
29
|
+
d += ` Q${x0 + step / 2} ${base + crest * 1.6 + Math.sin(phase) * amp * 0.2} ${x0 + step} ${base}`;
|
|
30
|
+
}
|
|
31
|
+
return `${d} L${w} 320 L0 320 Z`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const SWELLS = [swell(4, 22, 120, 0.4), swell(6, 16, 175, 1.2), swell(8, 12, 235, 2.1)];
|
|
35
|
+
|
|
36
|
+
function Waves({ children, frontmatter }: LayoutProps) {
|
|
37
|
+
const center = str(frontmatter.align) === "center";
|
|
38
|
+
return (
|
|
39
|
+
<div className={`deck-layout deck-layout-waves${center ? " is-center" : ""}`}>
|
|
40
|
+
<div className="ocean-waves-body">{children}</div>
|
|
41
|
+
{/* placed, not flowed (deck-absolute): the auto-fit does not count the swells as overflow */}
|
|
42
|
+
<div className="ocean-waves deck-absolute" aria-hidden="true">
|
|
43
|
+
<svg viewBox="0 0 2880 320" preserveAspectRatio="none">
|
|
44
|
+
{SWELLS.map((d, i) => (
|
|
45
|
+
<path key={i} className={`ocean-swell-${i + 1}`} d={d} />
|
|
46
|
+
))}
|
|
47
|
+
</svg>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Which depth opener this is (1-based), counting only `layout: depth` slides before it. */
|
|
54
|
+
function useDepthNumber(): { n: number; at: number } {
|
|
55
|
+
const deck = useDeck();
|
|
56
|
+
const slide = useSlideOptional();
|
|
57
|
+
const index = slide?.meta.index ?? 0;
|
|
58
|
+
const slides = deck.manifest.slides;
|
|
59
|
+
const n = slides.filter((s) => s.index <= index && s.frontmatter.layout === "depth").length;
|
|
60
|
+
return { n: Math.max(1, n), at: slides.length > 1 ? index / (slides.length - 1) : 0 };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const TICKS = 21;
|
|
64
|
+
|
|
65
|
+
function Depth({ children, frontmatter }: LayoutProps) {
|
|
66
|
+
const { n, at } = useDepthNumber();
|
|
67
|
+
const label = str(frontmatter.depth);
|
|
68
|
+
const given = frontmatter.n == null ? "" : String(frontmatter.n).trim();
|
|
69
|
+
const number = given || String(n).padStart(2, "0");
|
|
70
|
+
const here = Math.round(at * (TICKS - 1));
|
|
71
|
+
return (
|
|
72
|
+
<div className="deck-layout deck-layout-depth">
|
|
73
|
+
<div className="ocean-depth-number" aria-hidden="true">
|
|
74
|
+
{number}
|
|
75
|
+
</div>
|
|
76
|
+
<div className="ocean-depth-body">
|
|
77
|
+
{label ? <span className="ocean-depth-meta">{label}</span> : null}
|
|
78
|
+
{children}
|
|
79
|
+
</div>
|
|
80
|
+
<div className="ocean-depth-gauge" aria-hidden="true">
|
|
81
|
+
{Array.from({ length: TICKS }, (_, i) => (
|
|
82
|
+
<span key={i} className={i === here ? "is-here" : undefined} />
|
|
83
|
+
))}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** A divider: one swell across the column, in the accent colour (`flip` turns it over). */
|
|
90
|
+
function Wave({ flip = false, className }: { flip?: boolean; className?: string }) {
|
|
91
|
+
return (
|
|
92
|
+
<svg
|
|
93
|
+
className={["ocean-wave", className].filter(Boolean).join(" ")}
|
|
94
|
+
viewBox="0 0 240 14"
|
|
95
|
+
preserveAspectRatio="none"
|
|
96
|
+
aria-hidden="true"
|
|
97
|
+
style={flip ? { transform: "scaleY(-1)" } : undefined}
|
|
98
|
+
>
|
|
99
|
+
<path
|
|
100
|
+
d="M2 7 Q 17 -1 32 7 T 62 7 T 92 7 T 122 7 T 152 7 T 182 7 T 212 7 T 238 7"
|
|
101
|
+
fill="none"
|
|
102
|
+
strokeWidth="2.4"
|
|
103
|
+
strokeLinecap="round"
|
|
104
|
+
vectorEffect="non-scaling-stroke"
|
|
105
|
+
/>
|
|
106
|
+
</svg>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export default {
|
|
111
|
+
layouts: { waves: Waves, depth: Depth },
|
|
112
|
+
components: { Wave },
|
|
113
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,101 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kadal/theme-ocean",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Ocean, a theme for Kadal Deck (@kadal/deck). Kadal's own theme: the sea's palette from sunlit shallows to midnight water, calm gradients and polished type.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"kadal-theme",
|
|
7
|
+
"kadal-deck",
|
|
8
|
+
"presentation",
|
|
9
|
+
"slides",
|
|
10
|
+
"theme",
|
|
11
|
+
"ocean",
|
|
12
|
+
"sea",
|
|
13
|
+
"kadal",
|
|
14
|
+
"gradient"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://deck.kadal.cc/docs/",
|
|
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-ocean"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/kadalcc/deck/issues"
|
|
28
|
+
},
|
|
29
|
+
"license": "AGPL-3.0-or-later",
|
|
30
|
+
"author": "Mithunish Prabhakaran <pmithunish@gmail.com>",
|
|
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": "ocean",
|
|
53
|
+
"title": "Ocean",
|
|
54
|
+
"description": "Kadal's own theme: the sea's palette from sunlit shallows to midnight water, calm gradients and polished type.",
|
|
55
|
+
"colorScheme": "both",
|
|
56
|
+
"config": {
|
|
57
|
+
"transition": "fade",
|
|
58
|
+
"fonts": {
|
|
59
|
+
"sans": "Catamaran",
|
|
60
|
+
"mono": "JetBrains Mono",
|
|
61
|
+
"weights": "400,500,600,700,800"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"themeConfig": {
|
|
65
|
+
"waves": true
|
|
66
|
+
},
|
|
67
|
+
"shiki": {
|
|
68
|
+
"light": "night-owl-light",
|
|
69
|
+
"dark": "night-owl"
|
|
70
|
+
},
|
|
71
|
+
"defaults": {},
|
|
72
|
+
"layouts": [
|
|
73
|
+
"waves",
|
|
74
|
+
"depth"
|
|
75
|
+
],
|
|
76
|
+
"components": [
|
|
77
|
+
"Wave"
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"scripts": {
|
|
82
|
+
"dev": "kadal-deck dev -C preview",
|
|
83
|
+
"check": "kadal-deck check -C preview",
|
|
84
|
+
"typecheck": "tsc --noEmit",
|
|
85
|
+
"test": "bun test"
|
|
86
|
+
},
|
|
87
|
+
"peerDependencies": {
|
|
88
|
+
"@kadal/deck": "^0.4.0",
|
|
89
|
+
"react": "^19.2.0"
|
|
90
|
+
},
|
|
91
|
+
"devDependencies": {
|
|
92
|
+
"@kadal/deck": "workspace:*",
|
|
93
|
+
"@types/react": "^19.2.0",
|
|
94
|
+
"@types/react-dom": "^19.2.0",
|
|
95
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
96
|
+
"react": "^19.2.7",
|
|
97
|
+
"react-dom": "^19.2.7",
|
|
98
|
+
"typescript": "^6.0.3",
|
|
99
|
+
"vite": "^8.0.16"
|
|
100
|
+
}
|
|
101
|
+
}
|