Skip to content

Commit e75ed65

Browse files
committed
feat: add multiple theme presets and enhance gallery functionality
1 parent b23721b commit e75ed65

20 files changed

Lines changed: 720 additions & 16 deletions

‎e2e/gallery.spec.ts‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,19 @@ test('on desktop every preview shows its whole matrix without scrolling', async
6363
test.skip((page.viewportSize()?.width ?? 0) < 1024, 'phones scroll previews inside their cards');
6464
await page.goto(GALLERY);
6565

66-
for (const preview of await page.locator('.preset-card .rdm-root').all()) {
67-
const { scrollWidth, clientWidth } = await preview.evaluate((root) => ({
68-
scrollWidth: root.scrollWidth,
69-
clientWidth: root.clientWidth,
70-
}));
71-
expect(scrollWidth, 'preview is clipped').toBeLessThanOrEqual(clientWidth);
66+
// Several widths: the column count changes with the window, and a narrower
67+
// column is what once clipped the widest designs.
68+
for (const width of [1280, 1600, 2400]) {
69+
await page.setViewportSize({ width, height: 900 });
70+
const clipped = await page.locator('.preset-card').evaluateAll((cards) =>
71+
cards
72+
.filter((card) => {
73+
const root = card.querySelector<HTMLElement>('.rdm-root')!;
74+
return root.scrollWidth > root.clientWidth;
75+
})
76+
.map((card) => card.querySelector('h2')?.textContent ?? '?')
77+
);
78+
expect(clipped, `clipped at ${width}px`).toEqual([]);
7279
}
7380
});
7481

‎lib/index.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const ReactMatrix = ({
118118
};
119119

120120
export default ReactMatrix;
121-
export { original, presets, type PresetName } from './theme/presets/index.js';
121+
export * from './theme/presets/index.js';
122122
export type {
123123
CellClickContext,
124124
MatrixData,

‎lib/theme/presets/aurora.ts‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// Northern lights over a night sky: deep indigo with a faint aurora wash,
4+
// luminous teal → violet → magenta cells and a soft glow.
5+
export const aurora: MatrixTheme = {
6+
name: 'Aurora',
7+
scheme: 'dark',
8+
font: "'Avenir Next', 'Segoe UI Variable', system-ui, sans-serif",
9+
fontSize: '0.9375rem',
10+
surface: '#0b1026',
11+
backdrop:
12+
'radial-gradient(120% 80% at 10% 0%, rgba(45, 212, 191, 0.16), transparent 60%), radial-gradient(90% 70% at 90% 10%, rgba(168, 85, 247, 0.18), transparent 60%)',
13+
text: '#e6ecff',
14+
mutedText: '#a9b4d6',
15+
headerSurface: '#141b3a',
16+
headerText: '#e6ecff',
17+
line: '#2a3470',
18+
lineWidth: '0',
19+
lineStyle: 'solid',
20+
radius: '14px',
21+
gap: '6px',
22+
cellPadding: '0.5rem',
23+
cellShadow: '0 0 14px rgba(94, 234, 212, 0.25)',
24+
cellVariant: 'fill',
25+
emphasis: 'label',
26+
align: 'center',
27+
axisCase: 'upper',
28+
palette: [
29+
{ bg: '#5eead4', fg: '#04201c' },
30+
{ bg: '#818cf8', fg: '#0b1026' },
31+
{ bg: '#c084fc', fg: '#1a0b2e' },
32+
{ bg: '#e879f9', fg: '#1a0b2e' },
33+
{ bg: '#be185d', fg: '#ffffff' },
34+
],
35+
scale: 'tier',
36+
focus: '#5eead4',
37+
};

‎lib/theme/presets/blueprint.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// A technical drawing: blueprint blue, dashed white construction lines and
4+
// monospace labels, with cells outlined in light severity colours.
5+
export const blueprint: MatrixTheme = {
6+
name: 'Blueprint',
7+
scheme: 'dark',
8+
font: "ui-monospace, 'SF Mono', Menlo, Consolas, monospace",
9+
fontSize: '0.875rem',
10+
surface: '#0b3d91',
11+
text: '#ffffff',
12+
mutedText: '#cfe0ff',
13+
headerSurface: '#0d47a1',
14+
headerText: '#ffffff',
15+
line: '#e3eeff',
16+
lineWidth: '1px',
17+
lineStyle: 'dashed',
18+
radius: '0',
19+
gap: '0',
20+
cellPadding: '0.4rem',
21+
cellShadow: 'none',
22+
cellVariant: 'outline',
23+
emphasis: 'label',
24+
align: 'center',
25+
axisCase: 'upper',
26+
palette: [
27+
{ bg: '#b9f6ca', fg: '#051d4a' },
28+
{ bg: '#fff59d', fg: '#051d4a' },
29+
{ bg: '#ffcc80', fg: '#051d4a' },
30+
{ bg: '#ff8a80', fg: '#051d4a' },
31+
],
32+
scale: 'tier',
33+
focus: '#ffeb3b',
34+
};

‎lib/theme/presets/boardroom.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// A board report: a navy header band, slate hairlines, left-aligned text and a
4+
// conservative teal → amber → orange → crimson ramp.
5+
export const boardroom: MatrixTheme = {
6+
name: 'Boardroom',
7+
scheme: 'light',
8+
font: "'Segoe UI', 'Helvetica Neue', system-ui, sans-serif",
9+
fontSize: '0.9375rem',
10+
surface: '#f4f6f9',
11+
text: '#1b2a41',
12+
mutedText: '#c9d4e5',
13+
headerSurface: '#1b2a41',
14+
headerText: '#ffffff',
15+
line: '#9aa7b8',
16+
lineWidth: '1px',
17+
lineStyle: 'solid',
18+
radius: '4px',
19+
gap: '2px',
20+
cellPadding: '0.4rem 0.6rem',
21+
cellShadow: 'none',
22+
cellVariant: 'fill',
23+
emphasis: 'label',
24+
align: 'start',
25+
axisCase: 'upper',
26+
palette: [
27+
{ bg: '#0f766e', fg: '#ffffff' },
28+
{ bg: '#f59e0b', fg: '#1b2a41' },
29+
{ bg: '#c2410c', fg: '#ffffff' },
30+
{ bg: '#991b1b', fg: '#ffffff' },
31+
],
32+
scale: 'tier',
33+
focus: '#0b5fff',
34+
};

‎lib/theme/presets/broadsheet.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// A newspaper's financial pages: newsprint, serif type, hairline rules, no
4+
// gaps, left-aligned figures with large scores and a muted ink ramp.
5+
export const broadsheet: MatrixTheme = {
6+
name: 'Broadsheet',
7+
scheme: 'light',
8+
font: "ui-serif, Charter, 'Bitstream Charter', Cambria, Georgia, serif",
9+
fontSize: '1rem',
10+
surface: '#f7f3e8',
11+
text: '#1c1b17',
12+
mutedText: '#4d4a42',
13+
headerSurface: '#efe9d8',
14+
headerText: '#1c1b17',
15+
line: '#2b2a26',
16+
lineWidth: '1px',
17+
lineStyle: 'solid',
18+
radius: '0',
19+
gap: '0',
20+
cellPadding: '0.35rem 0.5rem',
21+
cellShadow: 'none',
22+
cellVariant: 'fill',
23+
emphasis: 'score',
24+
align: 'start',
25+
axisCase: 'upper',
26+
palette: [
27+
{ bg: '#c9d6c0', fg: '#1c1b17' },
28+
{ bg: '#e0c27a', fg: '#1c1b17' },
29+
{ bg: '#c77b4e', fg: '#1c1b17' },
30+
{ bg: '#8c2f1c', fg: '#f7f3e8' },
31+
],
32+
scale: 'tier',
33+
focus: '#8c2f1c',
34+
};

‎lib/theme/presets/brutal.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// Neo-brutalist: separate blocks with thick black borders, hard offset
4+
// shadows, flat primary colours and a plain grotesk.
5+
export const brutal: MatrixTheme = {
6+
name: 'Brutal',
7+
scheme: 'light',
8+
font: "'Helvetica Neue', Arial, system-ui, sans-serif",
9+
fontSize: '1rem',
10+
surface: '#fffdf5',
11+
text: '#000000',
12+
mutedText: '#1a1a1a',
13+
headerSurface: '#ffffff',
14+
headerText: '#000000',
15+
line: '#000000',
16+
lineWidth: '3px',
17+
lineStyle: 'solid',
18+
radius: '0',
19+
gap: '6px',
20+
cellPadding: '0.5rem',
21+
cellShadow: '4px 4px 0 #000000',
22+
cellVariant: 'fill',
23+
emphasis: 'label',
24+
align: 'center',
25+
axisCase: 'upper',
26+
palette: [
27+
{ bg: '#a3e635', fg: '#000000' },
28+
{ bg: '#facc15', fg: '#000000' },
29+
{ bg: '#fb923c', fg: '#000000' },
30+
{ bg: '#ef4444', fg: '#000000' },
31+
],
32+
scale: 'tier',
33+
focus: '#0000ff',
34+
};

‎lib/theme/presets/clay.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// Neumorphic: monochrome tiles pressed out of a soft grey surface with paired
4+
// light and dark shadows, and a saturated dot marking each severity.
5+
export const clay: MatrixTheme = {
6+
name: 'Clay',
7+
scheme: 'light',
8+
font: "ui-rounded, 'SF Pro Rounded', Nunito, system-ui, sans-serif",
9+
fontSize: '0.9375rem',
10+
surface: '#e6e9ef',
11+
text: '#2d3142',
12+
mutedText: '#4f5569',
13+
headerSurface: '#e6e9ef',
14+
headerText: '#2d3142',
15+
line: '#d1d5de',
16+
lineWidth: '0',
17+
lineStyle: 'solid',
18+
radius: '18px',
19+
gap: '10px',
20+
cellPadding: '0.5rem',
21+
cellShadow: '6px 6px 12px #c3c7d0, -6px -6px 12px #ffffff',
22+
cellVariant: 'dot',
23+
emphasis: 'label',
24+
align: 'center',
25+
axisCase: 'upper',
26+
palette: [
27+
{ bg: '#067647', fg: '#ffffff' },
28+
{ bg: '#9a6700', fg: '#ffffff' },
29+
{ bg: '#c4320a', fg: '#ffffff' },
30+
{ bg: '#9f1d2c', fg: '#ffffff' },
31+
],
32+
scale: 'tier',
33+
focus: '#5b5bd6',
34+
};

‎lib/theme/presets/glasshouse.ts‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// Bright and airy: a vivid pastel gradient behind white, rounded cells with
4+
// hairline white edges and soft lift shadows.
5+
export const glasshouse: MatrixTheme = {
6+
name: 'Glasshouse',
7+
scheme: 'light',
8+
font: 'system-ui, sans-serif',
9+
fontSize: '0.9375rem',
10+
surface: '#f5f3ff',
11+
backdrop: 'linear-gradient(135deg, #cffafe 0%, #ede9fe 50%, #fce7f3 100%)',
12+
text: '#1e1b4b',
13+
mutedText: '#4c4a6b',
14+
headerSurface: '#ffffff',
15+
headerText: '#1e1b4b',
16+
line: '#ffffff',
17+
lineWidth: '1px',
18+
lineStyle: 'solid',
19+
radius: '16px',
20+
gap: '8px',
21+
cellPadding: '0.5rem',
22+
cellShadow: '0 8px 24px rgba(30, 27, 75, 0.12)',
23+
cellVariant: 'fill',
24+
emphasis: 'label',
25+
align: 'center',
26+
axisCase: 'upper',
27+
palette: [
28+
{ bg: '#99f6e4', fg: '#1e1b4b' },
29+
{ bg: '#fde68a', fg: '#1e1b4b' },
30+
{ bg: '#fdba74', fg: '#1e1b4b' },
31+
{ bg: '#be123c', fg: '#ffffff' },
32+
],
33+
scale: 'tier',
34+
focus: '#4f46e5',
35+
};

‎lib/theme/presets/graphite.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { MatrixTheme } from '../types.js';
2+
3+
// Greyscale only, so it survives printing and photocopying: severity is carried
4+
// by lightness and a bold, left-aligned score.
5+
export const graphite: MatrixTheme = {
6+
name: 'Graphite',
7+
scheme: 'light',
8+
font: 'system-ui, sans-serif',
9+
fontSize: '0.9375rem',
10+
surface: '#fafafa',
11+
text: '#1f1f1f',
12+
mutedText: '#555555',
13+
headerSurface: '#ececec',
14+
headerText: '#1f1f1f',
15+
line: '#8a8a8a',
16+
lineWidth: '1px',
17+
lineStyle: 'solid',
18+
radius: '2px',
19+
gap: '2px',
20+
cellPadding: '0.35rem 0.5rem',
21+
cellShadow: 'none',
22+
cellVariant: 'fill',
23+
emphasis: 'score',
24+
align: 'start',
25+
axisCase: 'upper',
26+
palette: [
27+
{ bg: '#e5e5e5', fg: '#111111' },
28+
{ bg: '#b3b3b3', fg: '#111111' },
29+
{ bg: '#6b6b6b', fg: '#ffffff' },
30+
{ bg: '#262626', fg: '#ffffff' },
31+
],
32+
scale: 'tier',
33+
focus: '#000000',
34+
};

0 commit comments

Comments
 (0)