@quilltap/theme-storybook 1.0.66 → 1.0.68

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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to `@quilltap/theme-storybook` will be documented in this file.
4
4
 
5
+ ## [1.0.67] - 2026-08-30
6
+
7
+ ### Added
8
+ - `.qt-range` and its two tokens (`--qt-range-accent`, `--qt-range-focus-ring`), mirroring the app's new slider class, plus a "Range Sliders" section in the `Inputs` story so a theme can be previewed against an enabled and a disabled slider.
9
+
10
+ ### Notes
11
+ - Sliders stay natively rendered. `accent-color` is what paints the filled portion of the track *and* the thumb, so it is the whole default theming story; the class sets no disabled opacity, because browsers already drop the accent on a disabled range and app call sites nest sliders inside dimmed wrappers. A theme wanting a bespoke track can override `.qt-range` with `appearance: none`, at the cost of the filled bar in Chrome and Safari.
12
+
5
13
  ## [1.0.63] - 2026-08-25
6
14
 
7
15
  ### Added
@@ -848,6 +848,28 @@ var Inputs = () => {
848
848
  ] })
849
849
  ] })
850
850
  ] }),
851
+ /* @__PURE__ */ jsxs7("section", { style: { marginBottom: "2rem" }, children: [
852
+ /* @__PURE__ */ jsx7("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Range Sliders" }),
853
+ /* @__PURE__ */ jsxs7("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "24rem" }, children: [
854
+ /* @__PURE__ */ jsxs7("div", { children: [
855
+ /* @__PURE__ */ jsx7("label", { className: "qt-label", htmlFor: "range1", children: "Temperature" }),
856
+ /* @__PURE__ */ jsx7("input", { type: "range", id: "range1", className: "qt-range", style: { width: "100%" }, min: 0, max: 100, defaultValue: 65 })
857
+ ] }),
858
+ /* @__PURE__ */ jsxs7("div", { children: [
859
+ /* @__PURE__ */ jsx7("label", { className: "qt-label", htmlFor: "range2", style: { color: "var(--color-muted-foreground)" }, children: "Disabled slider" }),
860
+ /* @__PURE__ */ jsx7("input", { type: "range", id: "range2", className: "qt-range", style: { width: "100%" }, min: 0, max: 100, defaultValue: 35, disabled: true })
861
+ ] })
862
+ ] }),
863
+ /* @__PURE__ */ jsxs7("p", { style: { fontSize: "0.75rem", color: "var(--color-muted-foreground)", marginTop: "0.75rem", maxWidth: "32rem" }, children: [
864
+ "Sliders render natively; ",
865
+ /* @__PURE__ */ jsx7("code", { children: "--qt-range-accent" }),
866
+ " colours both the filled portion of the track and the thumb. Overriding ",
867
+ /* @__PURE__ */ jsx7("code", { children: ".qt-range" }),
868
+ " with",
869
+ /* @__PURE__ */ jsx7("code", { children: " appearance: none" }),
870
+ " gives a theme full control of the track, but drops the filled bar in Chrome and Safari."
871
+ ] })
872
+ ] }),
851
873
  /* @__PURE__ */ jsxs7("section", { style: { marginBottom: "2rem" }, children: [
852
874
  /* @__PURE__ */ jsx7("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Links" }),
853
875
  /* @__PURE__ */ jsxs7("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
package/dist/index.css CHANGED
@@ -230,6 +230,8 @@ body {
230
230
  --qt-radio-border: var(--color-border);
231
231
  --qt-radio-accent: var(--color-primary);
232
232
  --qt-radio-focus-ring: var(--color-ring);
233
+ --qt-range-accent: var(--color-primary);
234
+ --qt-range-focus-ring: var(--color-ring);
233
235
  --qt-navbar-height: 3.5rem;
234
236
  --qt-navbar-bg: var(--color-background);
235
237
  --qt-navbar-border: var(--color-border);
@@ -852,6 +854,17 @@ body {
852
854
  outline: none;
853
855
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--qt-radio-focus-ring) 35%, transparent);
854
856
  }
857
+ .qt-range {
858
+ cursor: pointer;
859
+ accent-color: var(--qt-range-accent);
860
+ }
861
+ .qt-range:focus-visible {
862
+ outline: none;
863
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--qt-range-focus-ring) 35%, transparent);
864
+ }
865
+ .qt-range:disabled {
866
+ cursor: not-allowed;
867
+ }
855
868
  .qt-badge {
856
869
  display: inline-flex;
857
870
  align-items: center;
@@ -933,6 +946,26 @@ body {
933
946
  color: var(--qt-status-info-fg);
934
947
  border: 1px solid var(--qt-status-info-border);
935
948
  }
949
+ .qt-danger-badge {
950
+ --qt-concierge-badge-color: var(--color-destructive, #dc2626);
951
+ display: inline-flex;
952
+ align-items: center;
953
+ gap: 0.25rem;
954
+ padding: 0.125rem 0.375rem;
955
+ border-radius: 0.25rem;
956
+ font-size: 0.75rem;
957
+ line-height: 1rem;
958
+ font-weight: 500;
959
+ background: color-mix(in srgb, var(--qt-concierge-badge-color) 15%, transparent);
960
+ color: var(--qt-concierge-badge-color);
961
+ border: 1px solid color-mix(in srgb, var(--qt-concierge-badge-color) 40%, transparent);
962
+ }
963
+ .qt-danger-badge-muted {
964
+ --qt-concierge-badge-color: var(--color-muted-foreground, #6b7280);
965
+ }
966
+ .qt-danger-badge-info {
967
+ --qt-concierge-badge-color: var(--color-info, #2563eb);
968
+ }
936
969
  .qt-badge-wardrobe-top,
937
970
  .qt-badge-wardrobe-bottom,
938
971
  .qt-badge-wardrobe-footwear,
package/dist/index.js CHANGED
@@ -958,6 +958,28 @@ var Inputs = () => {
958
958
  ] })
959
959
  ] })
960
960
  ] }),
961
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
962
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Range Sliders" }),
963
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "24rem" }, children: [
964
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
965
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "qt-label", htmlFor: "range1", children: "Temperature" }),
966
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "range", id: "range1", className: "qt-range", style: { width: "100%" }, min: 0, max: 100, defaultValue: 65 })
967
+ ] }),
968
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
969
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "qt-label", htmlFor: "range2", style: { color: "var(--color-muted-foreground)" }, children: "Disabled slider" }),
970
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "range", id: "range2", className: "qt-range", style: { width: "100%" }, min: 0, max: 100, defaultValue: 35, disabled: true })
971
+ ] })
972
+ ] }),
973
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { style: { fontSize: "0.75rem", color: "var(--color-muted-foreground)", marginTop: "0.75rem", maxWidth: "32rem" }, children: [
974
+ "Sliders render natively; ",
975
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { children: "--qt-range-accent" }),
976
+ " colours both the filled portion of the track and the thumb. Overriding ",
977
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { children: ".qt-range" }),
978
+ " with",
979
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { children: " appearance: none" }),
980
+ " gives a theme full control of the track, but drops the filled bar in Chrome and Safari."
981
+ ] })
982
+ ] }),
961
983
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
962
984
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Links" }),
963
985
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
package/dist/index.mjs CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  ThemeComparison,
22
22
  Typography,
23
23
  Workspace
24
- } from "./chunk-PCPCAOQ7.mjs";
24
+ } from "./chunk-IAVNW2EO.mjs";
25
25
  import "./chunk-WUKYLWAZ.mjs";
26
26
 
27
27
  // src/preview.tsx
@@ -895,6 +895,28 @@ var Inputs = () => {
895
895
  ] })
896
896
  ] })
897
897
  ] }),
898
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
899
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Range Sliders" }),
900
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "24rem" }, children: [
901
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
902
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "qt-label", htmlFor: "range1", children: "Temperature" }),
903
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "range", id: "range1", className: "qt-range", style: { width: "100%" }, min: 0, max: 100, defaultValue: 65 })
904
+ ] }),
905
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
906
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "qt-label", htmlFor: "range2", style: { color: "var(--color-muted-foreground)" }, children: "Disabled slider" }),
907
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "range", id: "range2", className: "qt-range", style: { width: "100%" }, min: 0, max: 100, defaultValue: 35, disabled: true })
908
+ ] })
909
+ ] }),
910
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { style: { fontSize: "0.75rem", color: "var(--color-muted-foreground)", marginTop: "0.75rem", maxWidth: "32rem" }, children: [
911
+ "Sliders render natively; ",
912
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { children: "--qt-range-accent" }),
913
+ " colours both the filled portion of the track and the thumb. Overriding ",
914
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { children: ".qt-range" }),
915
+ " with",
916
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { children: " appearance: none" }),
917
+ " gives a theme full control of the track, but drops the filled bar in Chrome and Safari."
918
+ ] })
919
+ ] }),
898
920
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
899
921
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Links" }),
900
922
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
@@ -21,7 +21,7 @@ import {
21
21
  ThemeComparison,
22
22
  Typography,
23
23
  Workspace
24
- } from "../chunk-PCPCAOQ7.mjs";
24
+ } from "../chunk-IAVNW2EO.mjs";
25
25
  import "../chunk-WUKYLWAZ.mjs";
26
26
  export {
27
27
  Avatars,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quilltap/theme-storybook",
3
- "version": "1.0.66",
3
+ "version": "1.0.68",
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",
@@ -83,6 +83,12 @@
83
83
  --qt-radio-accent: var(--color-primary);
84
84
  --qt-radio-focus-ring: var(--color-ring);
85
85
 
86
+ /* Range slider variables. Sliders stay natively rendered: accent-color paints
87
+ the filled track and the thumb, which `appearance: none` would discard in
88
+ Chrome and Safari. */
89
+ --qt-range-accent: var(--color-primary);
90
+ --qt-range-focus-ring: var(--color-ring);
91
+
86
92
  /* Navbar variables */
87
93
  --qt-navbar-height: 3.5rem;
88
94
  --qt-navbar-bg: var(--color-background);
@@ -873,6 +879,31 @@
873
879
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--qt-radio-focus-ring) 35%, transparent);
874
880
  }
875
881
 
882
+ /* ==========================================================================
883
+ RANGE (SLIDER) COMPONENT
884
+ Natively rendered on purpose — accent-color paints the filled portion of the
885
+ track and the thumb. Do not reimplement with appearance:none plus custom
886
+ ::-webkit-slider-thumb / ::-moz-range-thumb rules: that discards the filled
887
+ bar in Chrome and Safari. Call sites own width/layout.
888
+ ========================================================================== */
889
+
890
+ .qt-range {
891
+ cursor: pointer;
892
+ accent-color: var(--qt-range-accent);
893
+ }
894
+
895
+ .qt-range:focus-visible {
896
+ outline: none;
897
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--qt-range-focus-ring) 35%, transparent);
898
+ }
899
+
900
+ /* No disabled opacity on purpose: browsers already drop the accent on a
901
+ disabled range, and app call sites nest these inside dimmed wrappers where a
902
+ second 50% would compound to 25%. */
903
+ .qt-range:disabled {
904
+ cursor: not-allowed;
905
+ }
906
+
876
907
  /* ==========================================================================
877
908
  BADGE COMPONENTS
878
909
  ========================================================================== */
@@ -1001,6 +1032,41 @@
1001
1032
  border: 1px solid var(--qt-status-info-border);
1002
1033
  }
1003
1034
 
1035
+ /* ==========================================================================
1036
+ CONCIERGE BADGE (Salon breadcrumb header)
1037
+ ========================================================================== */
1038
+
1039
+ /**
1040
+ * Concierge badge for the Salon breadcrumb header. Parameterized over one
1041
+ * CSS var so the four-state family is a recolor, not four rules: the base
1042
+ * is the red Flagged pill; the modifiers below recolor it for the two
1043
+ * operator states (Monitored renders no badge at all).
1044
+ */
1045
+ .qt-danger-badge {
1046
+ --qt-concierge-badge-color: var(--color-destructive, #dc2626);
1047
+ display: inline-flex;
1048
+ align-items: center;
1049
+ gap: 0.25rem;
1050
+ padding: 0.125rem 0.375rem;
1051
+ border-radius: 0.25rem;
1052
+ font-size: 0.75rem;
1053
+ line-height: 1rem;
1054
+ font-weight: 500;
1055
+ background: color-mix(in srgb, var(--qt-concierge-badge-color) 15%, transparent);
1056
+ color: var(--qt-concierge-badge-color);
1057
+ border: 1px solid color-mix(in srgb, var(--qt-concierge-badge-color) 40%, transparent);
1058
+ }
1059
+
1060
+ /* Vouched Safe — no colour: the Concierge isn't in the room. */
1061
+ .qt-danger-badge-muted {
1062
+ --qt-concierge-badge-color: var(--color-muted-foreground, #6b7280);
1063
+ }
1064
+
1065
+ /* Uncensored — the eye you closed yourself. */
1066
+ .qt-danger-badge-info {
1067
+ --qt-concierge-badge-color: var(--color-info, #2563eb);
1068
+ }
1069
+
1004
1070
  /* ==========================================================================
1005
1071
  WARDROBE SLOT BADGES
1006
1072
  ========================================================================== */
@@ -102,6 +102,29 @@ export const Inputs: React.FC = () => {
102
102
  </div>
103
103
  </section>
104
104
 
105
+ {/* Range sliders */}
106
+ <section style={{ marginBottom: '2rem' }}>
107
+ <h3 style={{ fontSize: '1.125rem', fontWeight: 700, marginBottom: '1rem', borderBottom: '1px solid var(--color-border)', paddingBottom: '0.5rem' }}>
108
+ Range Sliders
109
+ </h3>
110
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '24rem' }}>
111
+ <div>
112
+ <label className="qt-label" htmlFor="range1">Temperature</label>
113
+ <input type="range" id="range1" className="qt-range" style={{ width: '100%' }} min={0} max={100} defaultValue={65} />
114
+ </div>
115
+ <div>
116
+ <label className="qt-label" htmlFor="range2" style={{ color: 'var(--color-muted-foreground)' }}>Disabled slider</label>
117
+ <input type="range" id="range2" className="qt-range" style={{ width: '100%' }} min={0} max={100} defaultValue={35} disabled />
118
+ </div>
119
+ </div>
120
+ <p style={{ fontSize: '0.75rem', color: 'var(--color-muted-foreground)', marginTop: '0.75rem', maxWidth: '32rem' }}>
121
+ Sliders render natively; <code>--qt-range-accent</code> colours both the filled
122
+ portion of the track and the thumb. Overriding <code>.qt-range</code> with
123
+ <code> appearance: none</code> gives a theme full control of the track, but drops
124
+ the filled bar in Chrome and Safari.
125
+ </p>
126
+ </section>
127
+
105
128
  {/* Links */}
106
129
  <section style={{ marginBottom: '2rem' }}>
107
130
  <h3 style={{ fontSize: '1.125rem', fontWeight: 700, marginBottom: '1rem', borderBottom: '1px solid var(--color-border)', paddingBottom: '0.5rem' }}>