@quilltap/theme-storybook 1.0.40 → 1.0.43

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.
@@ -15,11 +15,12 @@ import {
15
15
  Loading,
16
16
  Participant,
17
17
  Spacing,
18
+ Surfaces,
18
19
  Tabs,
19
20
  Terminal,
20
21
  ThemeComparison,
21
22
  Typography
22
- } from "../chunk-GXTUADEJ.mjs";
23
+ } from "../chunk-MKFVWQPL.mjs";
23
24
  import "../chunk-WUKYLWAZ.mjs";
24
25
  export {
25
26
  Avatars,
@@ -38,6 +39,7 @@ export {
38
39
  Loading,
39
40
  Participant,
40
41
  Spacing,
42
+ Surfaces,
41
43
  Tabs,
42
44
  Terminal,
43
45
  ThemeComparison,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quilltap/theme-storybook",
3
- "version": "1.0.40",
3
+ "version": "1.0.43",
4
4
  "description": "Storybook preset and stories for developing Quilltap theme plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1546,6 +1546,26 @@
1546
1546
  color: var(--color-accent-foreground);
1547
1547
  }
1548
1548
 
1549
+ /* Hoverable accent surface — list rows, menu items, and option cards that
1550
+ should highlight on hover. On hover it paints the accent background AND
1551
+ forces the accent foreground onto the row and every descendant, so the whole
1552
+ row stays legible even on themes where --color-accent is a bold colour (e.g.
1553
+ Madman's Box amber). Without the descendant flip, children carrying their own
1554
+ colour (qt-text-secondary, qt-text-primary, …) would wash out — or, when their
1555
+ colour matches the accent, vanish entirely. The descendant selector is wrapped
1556
+ in :where() so it adds no specificity to the resting state (children own their
1557
+ colour as usual); the :hover rules still win via the hover pseudo-class. */
1558
+ .qt-hover-accent {
1559
+ transition: background-color 0.15s ease, color 0.15s ease;
1560
+ }
1561
+ .qt-hover-accent:hover {
1562
+ background-color: var(--color-accent);
1563
+ color: var(--color-accent-foreground);
1564
+ }
1565
+ .qt-hover-accent:hover :where(*) {
1566
+ color: var(--color-accent-foreground);
1567
+ }
1568
+
1549
1569
  /* ==========================================================================
1550
1570
  STATUS COLOR UTILITIES (with opacity variants)
1551
1571
  ========================================================================== */
@@ -23,15 +23,15 @@ const ICON_GROUPS: IconGroup[] = [
23
23
  category: 'General UI',
24
24
  names: [
25
25
  'close', 'pencil', 'refresh', 'check', 'check-circle', 'chat', 'info', 'trash',
26
- 'copy', 'plus', 'search', 'download', 'upload', 'cloud-upload', 'external-link',
27
- 'link', 'send', 'paperclip', 'eye', 'eye-off', 'star', 'bookmark', 'expand', 'compress',
26
+ 'copy', 'plus', 'minus', 'search', 'download', 'upload', 'cloud-upload', 'external-link',
27
+ 'link', 'send', 'paperclip', 'eye', 'eye-off', 'star', 'bookmark', 'tag', 'expand', 'compress',
28
28
  ],
29
29
  },
30
30
  {
31
31
  category: 'Navigation arrows',
32
32
  names: [
33
33
  'chevron-down', 'chevron-right', 'chevron-left',
34
- 'arrow-left', 'arrow-right', 'arrow-up', 'arrow-down',
34
+ 'arrow-left', 'arrow-right', 'arrow-up', 'arrow-down', 'sort',
35
35
  ],
36
36
  },
37
37
  {
@@ -131,7 +131,9 @@ export const Icons: React.FC = () => {
131
131
  full color — best for textured or multi-color marks.
132
132
  </li>
133
133
  <li>
134
- The <code>brand</code> mark is always drawn in full color, even when overridden with an SVG.
134
+ The <code>brand</code> mark follows the same rule: an <code>.svg</code> override is
135
+ tinted like any other icon, so ship it as <code>.webp</code> if it should keep its own
136
+ colors.
135
137
  </li>
136
138
  <li>
137
139
  Names must match the built-in names below; unknown names are ignored. Run{' '}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Surfaces Story Component
3
+ *
4
+ * Demonstrates the accent-surface contract for theme authors. The app uses
5
+ * `accent` as a quiet hover/selected/surface tint, but a theme is free to map
6
+ * `accent` to a bold colour (e.g. Madman's Box amber). These patterns stay
7
+ * legible either way, because they pair the accent background with the theme's
8
+ * own `accentForeground`, or use the quiet `muted` / faint-`primary` surfaces.
9
+ */
10
+
11
+ import React from 'react';
12
+
13
+ const sectionHeading: React.CSSProperties = {
14
+ fontSize: '1.125rem',
15
+ fontWeight: 700,
16
+ marginBottom: '1rem',
17
+ borderBottom: '1px solid var(--color-border)',
18
+ paddingBottom: '0.5rem',
19
+ };
20
+
21
+ const note: React.CSSProperties = {
22
+ color: 'var(--color-muted-foreground)',
23
+ marginBottom: '1rem',
24
+ fontSize: '0.875rem',
25
+ };
26
+
27
+ export const Surfaces: React.FC = () => {
28
+ return (
29
+ <div style={{ padding: '1.5rem' }}>
30
+ <h2 style={{ fontSize: '1.5rem', fontWeight: 700, marginBottom: '0.5rem' }}>Surfaces</h2>
31
+ <p style={{ ...note, maxWidth: '44rem' }}>
32
+ How accent-coloured surfaces stay legible no matter how bold a theme makes
33
+ its <code>accent</code> token. Filled surfaces pair the background with{' '}
34
+ <code>qt-text-on-accent</code>; hover rows use <code>qt-hover-accent</code>;
35
+ quiet selected/panel surfaces lean on <code>muted</code> and faint{' '}
36
+ <code>primary</code> instead of the accent.
37
+ </p>
38
+
39
+ {/* Filled accent surfaces */}
40
+ <section style={{ marginBottom: '2rem' }}>
41
+ <h3 style={sectionHeading}>Filled accent surfaces</h3>
42
+ <p style={note}>
43
+ A solid <code>qt-bg-accent</code> fill <strong>must</strong> be paired with{' '}
44
+ <code>qt-text-on-accent</code> (the theme&apos;s <code>accentForeground</code>).
45
+ A fill without it falls back to the page foreground and washes out on bold accents.
46
+ </p>
47
+ <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem', alignItems: 'center' }}>
48
+ <span className="qt-bg-accent qt-text-on-accent" style={{ padding: '0.125rem 0.5rem', borderRadius: '0.25rem', fontSize: '0.75rem' }}>
49
+ keyword
50
+ </span>
51
+ <span className="qt-bg-accent qt-text-on-accent" style={{ padding: '0.125rem 0.5rem', borderRadius: '0.25rem', fontSize: '0.75rem' }}>
52
+ another keyword
53
+ </span>
54
+ <kbd className="qt-bg-accent qt-text-on-accent" style={{ padding: '0.125rem 0.375rem', borderRadius: '0.25rem', fontSize: '0.75rem' }}>
55
+
56
+ </kbd>
57
+ </div>
58
+ </section>
59
+
60
+ {/* Hover-highlight rows */}
61
+ <section style={{ marginBottom: '2rem' }}>
62
+ <h3 style={sectionHeading}>Hover-highlight rows — <code>qt-hover-accent</code></h3>
63
+ <p style={note}>
64
+ For list rows, menu items, and option cards. On hover it paints the accent
65
+ background and forces the accent foreground onto the row <em>and every
66
+ descendant</em> — so children that carry their own colour (the title and the
67
+ muted subtitle below) flip too, instead of washing out (or, when their colour
68
+ matches the accent, vanishing). Hover the rows to see it.
69
+ </p>
70
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.25rem', maxWidth: '24rem', border: '1px solid var(--color-border)', borderRadius: '0.5rem', padding: '0.375rem' }}>
71
+ <div className="qt-hover-accent" style={{ display: 'flex', flexDirection: 'column', padding: '0.5rem 0.75rem', borderRadius: '0.375rem', cursor: 'pointer' }}>
72
+ <span className="qt-text-primary">Compose a reply</span>
73
+ <span className="qt-text-secondary" style={{ fontSize: '0.8125rem' }}>Draft a response in this thread</span>
74
+ </div>
75
+ <div className="qt-hover-accent" style={{ display: 'flex', flexDirection: 'column', padding: '0.5rem 0.75rem', borderRadius: '0.375rem', cursor: 'pointer' }}>
76
+ <span className="qt-text-primary">Mark as resolved</span>
77
+ <span className="qt-text-secondary" style={{ fontSize: '0.8125rem' }}>Close and archive this item</span>
78
+ </div>
79
+ <div className="qt-hover-accent" style={{ display: 'flex', flexDirection: 'column', padding: '0.5rem 0.75rem', borderRadius: '0.375rem', cursor: 'pointer' }}>
80
+ <span className="qt-text-primary">Delete</span>
81
+ <span className="qt-text-secondary" style={{ fontSize: '0.8125rem' }}>Remove permanently</span>
82
+ </div>
83
+ </div>
84
+ </section>
85
+
86
+ {/* Quiet selected / panel surfaces */}
87
+ <section>
88
+ <h3 style={sectionHeading}>Quiet selected &amp; panel surfaces</h3>
89
+ <p style={note}>
90
+ Persistent surfaces (selected cards, informational panels) deliberately avoid
91
+ the bold accent. Selected states use a faint <code>qt-bg-primary/10</code> tint;
92
+ informational panels use the neutral <code>qt-bg-muted</code> surface.
93
+ </p>
94
+ <div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem' }}>
95
+ <div className="qt-bg-primary/10" style={{ padding: '0.75rem 1rem', borderRadius: '0.5rem', border: '1px solid var(--color-primary)', maxWidth: '16rem' }}>
96
+ <div className="qt-text-primary" style={{ fontWeight: 600 }}>Selected option</div>
97
+ <div className="qt-text-secondary" style={{ fontSize: '0.8125rem' }}>Faint primary tint marks the choice.</div>
98
+ </div>
99
+ <div className="qt-bg-muted" style={{ padding: '0.75rem 1rem', borderRadius: '0.5rem', border: '1px solid var(--color-border)', maxWidth: '16rem' }}>
100
+ <div style={{ fontWeight: 600 }}>Informational panel</div>
101
+ <div className="qt-text-secondary" style={{ fontSize: '0.8125rem' }}>Neutral muted surface, never the accent.</div>
102
+ </div>
103
+ </div>
104
+ </section>
105
+ </div>
106
+ );
107
+ };
@@ -14,6 +14,7 @@ export * from './components/Buttons';
14
14
  export * from './components/Cards';
15
15
  export * from './components/Inputs';
16
16
  export * from './components/Badges';
17
+ export * from './components/Surfaces';
17
18
  export * from './components/Avatars';
18
19
  export * from './components/Dialogs';
19
20
  export * from './components/Tabs';