@fiestaboard/ui 6.1.0 → 6.1.1

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.
@@ -1,6 +1,15 @@
1
1
  export interface BoardOption {
2
2
  id: string;
3
3
  name?: string;
4
+ /**
5
+ * Per-board health, surfaced as a small destructive dot beside the name —
6
+ * and in the trigger while this board is the selected one. Presentational
7
+ * only: the wiring side decides what "error" means (a board whose client
8
+ * failed to initialize, say) and supplies the words for it as
9
+ * `BoardSelectorLabels.boardError`, which the option and the trigger are
10
+ * then DESCRIBED by (`aria-describedby`). Omit for a healthy board.
11
+ */
12
+ status?: "error";
4
13
  }
5
14
  export interface BoardSelectorLabels {
6
15
  /** aria-label for the trigger, e.g. "Select board". */
@@ -9,6 +18,17 @@ export interface BoardSelectorLabels {
9
18
  selectBoard: string;
10
19
  /** Fallback display name for unnamed boards. */
11
20
  unnamedBoard: string;
21
+ /**
22
+ * What `status: "error"` means, in words — e.g. "Unavailable". Rendered
23
+ * once as an sr-only description that every errored option, and the
24
+ * trigger while an errored board is selected, points at with
25
+ * `aria-describedby`; the dot itself stays decorative. That is what keeps
26
+ * the state off colour alone (WCAG 1.4.1) without folding the word into
27
+ * the option's NAME, so "Kitchen" is still announced as "Kitchen", then
28
+ * described. Only consulted when at least one board sets `status`, but
29
+ * provide it whenever you do: without it the dot is the only signal.
30
+ */
31
+ boardError?: string;
12
32
  }
13
33
  interface BoardSelectorProps {
14
34
  boards: BoardOption[];
@@ -1,37 +1,64 @@
1
1
  "use client";
2
2
  import { cn as e } from "../../lib/utils.js";
3
- import { Select as t, SelectContent as n, SelectItem as r, SelectTrigger as i, SelectValue as a } from "../forms/select.js";
4
- import { Tooltip as o, TooltipContent as s, TooltipTrigger as c } from "../overlays/tooltip.js";
5
- import { BoardIcon as l } from "./board-icon.js";
6
- import { memo as u, useMemo as d } from "react";
7
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
3
+ import { StatusDot as t } from "../feedback/status-dot.js";
4
+ import { Select as n, SelectContent as r, SelectItem as i, SelectTrigger as a, SelectValue as o } from "../forms/select.js";
5
+ import { Tooltip as s, TooltipContent as c, TooltipTrigger as l } from "../overlays/tooltip.js";
6
+ import { BoardIcon as u } from "./board-icon.js";
7
+ import { memo as d, useId as f, useMemo as p } from "react";
8
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
8
9
  //#region src/components/chrome/board-selector.tsx
9
- var m = u(function({ boards: u, value: m, onChange: h, labels: g, collapsed: _ = !1, variant: v = "sidebar" }) {
10
- let y = d(() => u.map((e) => /* @__PURE__ */ f(r, {
11
- value: e.id,
12
- children: e.name || g.unnamedBoard
13
- }, e.id)), [u, g.unnamedBoard]), b = /* @__PURE__ */ p(i, {
14
- "aria-label": g.boardSelector,
15
- className: e("gap-2 border-sidebar-border/70 bg-sidebar-accent/40 font-medium text-sidebar-foreground shadow-none transition-[width,padding] duration-fast hover:bg-sidebar-accent/70", v === "mobileHeader" && "h-9 w-auto min-w-0 max-w-[170px] px-2.5 max-[479px]:gap-1 max-[479px]:px-2", v === "sidebar" && (_ ? "h-9 w-full justify-center gap-0 px-0 [&>span:last-child]:hidden" : "h-10 w-full")),
16
- children: [/* @__PURE__ */ f(l, { className: "h-5 w-5 flex-shrink-0 text-sidebar-foreground/70" }), /* @__PURE__ */ f("span", {
17
- className: e("min-w-0 flex-1 overflow-hidden whitespace-nowrap text-left transition-opacity duration-fast", v === "sidebar" && _ ? "max-w-0 opacity-0" : "max-w-48 opacity-100 delay-150", v === "mobileHeader" && "max-[479px]:hidden!"),
18
- children: /* @__PURE__ */ f(a, { placeholder: g.selectBoard })
10
+ var g = d(function({ boards: d, value: g, onChange: _, labels: v, collapsed: y = !1, variant: b = "sidebar" }) {
11
+ let x = f(), S = v.boardError && d.some((e) => e.status === "error") ? x : void 0, C = d.find((e) => e.id === g), w = p(() => d.map((e) => {
12
+ let n = e.name || v.unnamedBoard, r = e.status === "error";
13
+ return /* @__PURE__ */ m(i, {
14
+ value: e.id,
15
+ "aria-describedby": r ? S : void 0,
16
+ children: r ? /* @__PURE__ */ h("span", {
17
+ className: "flex min-w-0 items-center gap-2",
18
+ children: [/* @__PURE__ */ m("span", {
19
+ className: "min-w-0 flex-1 truncate",
20
+ children: n
21
+ }), /* @__PURE__ */ m(t, {
22
+ status: "danger",
23
+ size: "sm"
24
+ })]
25
+ }) : n
26
+ }, e.id);
27
+ }), [
28
+ d,
29
+ v.unnamedBoard,
30
+ S
31
+ ]), T = /* @__PURE__ */ h(a, {
32
+ "aria-label": v.boardSelector,
33
+ "aria-describedby": C?.status === "error" ? S : void 0,
34
+ className: e("gap-2 border-sidebar-border/70 bg-sidebar-accent/40 font-medium text-sidebar-foreground shadow-none transition-[width,padding] duration-fast hover:bg-sidebar-accent/70", b === "mobileHeader" && "h-9 w-auto min-w-0 max-w-[170px] px-2.5 max-[479px]:gap-1 max-[479px]:px-2", b === "sidebar" && (y ? "h-9 w-full justify-center gap-0 px-0 [&>span:last-child]:hidden" : "h-10 w-full")),
35
+ children: [/* @__PURE__ */ m(u, { className: "h-5 w-5 flex-shrink-0 text-sidebar-foreground/70" }), /* @__PURE__ */ m("span", {
36
+ className: e("min-w-0 flex-1 overflow-hidden whitespace-nowrap text-left transition-opacity duration-fast", b === "sidebar" && y ? "max-w-0 opacity-0" : "max-w-48 opacity-100 delay-150", b === "mobileHeader" && "max-[479px]:hidden!"),
37
+ children: /* @__PURE__ */ m(o, { placeholder: v.selectBoard })
19
38
  })]
20
39
  });
21
- return /* @__PURE__ */ p(t, {
22
- value: m,
23
- onValueChange: h,
24
- children: [_ ? /* @__PURE__ */ p(o, { children: [/* @__PURE__ */ f(c, {
25
- asChild: !0,
26
- children: b
27
- }), /* @__PURE__ */ f(s, {
28
- side: "right",
29
- className: "font-medium",
30
- children: u.find((e) => e.id === m)?.name || g.unnamedBoard
31
- })] }) : b, /* @__PURE__ */ f(n, { children: y })]
40
+ return /* @__PURE__ */ h(n, {
41
+ value: g,
42
+ onValueChange: _,
43
+ children: [
44
+ y ? /* @__PURE__ */ h(s, { children: [/* @__PURE__ */ m(l, {
45
+ asChild: !0,
46
+ children: T
47
+ }), /* @__PURE__ */ m(c, {
48
+ side: "right",
49
+ className: "font-medium",
50
+ children: C?.name || v.unnamedBoard
51
+ })] }) : T,
52
+ S ? /* @__PURE__ */ m("span", {
53
+ id: S,
54
+ className: "sr-only",
55
+ children: v.boardError
56
+ }) : null,
57
+ /* @__PURE__ */ m(r, { children: w })
58
+ ]
32
59
  });
33
60
  });
34
61
  //#endregion
35
- export { m as BoardSelector };
62
+ export { g as BoardSelector };
36
63
 
37
64
  //# sourceMappingURL=board-selector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"board-selector.js","names":[],"sources":["../../../src/components/chrome/board-selector.tsx"],"mappings":";;;;;;;;AAwCA,IAAa,IAAgB,EAAK,SAAuB,EACvD,WACA,UACA,aACA,WACA,eAAY,IACZ,aAAU,aACW;CAIrB,IAAM,IAAQ,QAEV,EAAO,KAAK,MACV,kBAAC,GAAD;EAA2B,OAAO,EAAM;EACrC,UAAA,EAAM,QAAQ,EAAO;CACZ,GAFK,EAAM,EAEX,CACb,GACH,CAAC,GAAQ,EAAO,YAAY,CAC9B,GAEM,IACJ,kBAAC,GAAD;EACE,cAAY,EAAO;EACnB,WAAW,EACT,2KAGA,MAAY,kBAAkB,8EAC9B,MAAY,cACT,IAQG,oEACA,cACR;EAlBF,UAAA,CAoBE,kBAAC,GAAD,EAAW,WAAU,mDAAoD,CAAA,GACzE,kBAAC,QAAD;GACE,WAAW,EACT,+FACA,MAAY,aAAa,IAAY,sBAAsB,kCAG3D,MAAY,kBAAkB,qBAChC;GAEA,UAAA,kBAAC,GAAD,EAAa,aAAa,EAAO,YAAc,CAAA;EAC3C,CAAA,CACO;;CAGjB,OACE,kBAAC,GAAD;EAAe;EAAO,eAAe;EAArC,UAAA,CACG,IACC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAgB,SAAA;GAAS,UAAA;EAAwB,CAAA,GACjD,kBAAC,GAAD;GAAgB,MAAK;GAAQ,WAAU;GACpC,UAAA,EAAO,MAAM,MAAM,EAAE,OAAO,CAAK,CAAC,EAAE,QAAQ,EAAO;EACtC,CAAA,CACT,EAAA,CAAA,IAET,GAEF,kBAAC,GAAD,EAAA,UAAgB,EAAqB,CAAA,CAC/B;;AAEZ,CAAC"}
1
+ {"version":3,"file":"board-selector.js","names":[],"sources":["../../../src/components/chrome/board-selector.tsx"],"mappings":";;;;;;;;;AA6DA,IAAa,IAAgB,EAAK,SAAuB,EACvD,WACA,UACA,aACA,WACA,eAAY,IACZ,aAAU,aACW;CAOrB,IAAM,IAAsB,EAAM,GAC5B,IACJ,EAAO,cAAc,EAAO,MAAM,MAAU,EAAM,WAAW,OAAO,IAAI,IAAsB,KAAA,GAC1F,IAAgB,EAAO,MAAM,MAAU,EAAM,OAAO,CAAK,GAKzD,IAAQ,QAEV,EAAO,KAAK,MAAU;EACpB,IAAM,IAAO,EAAM,QAAQ,EAAO,cAC5B,IAAU,EAAM,WAAW;EACjC,OACE,kBAAC,GAAD;GAA2B,OAAO,EAAM;GAAI,oBAAkB,IAAU,IAAc,KAAA;GACnF,UAAA,IAIC,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CACE,kBAAC,QAAD;KAAM,WAAU;KAA2B,UAAA;IAAW,CAAA,GACtD,kBAAC,GAAD;KAAW,QAAO;KAAS,MAAK;IAAM,CAAA,CAClC;GAGN,CAAA,IAAA;EAEQ,GAbK,EAAM,EAaX;CAEhB,CAAC,GACH;EAAC;EAAQ,EAAO;EAAc;CAAW,CAC3C,GAEM,IACJ,kBAAC,GAAD;EACE,cAAY,EAAO;EACnB,oBAAkB,GAAe,WAAW,UAAU,IAAc,KAAA;EACpE,WAAW,EACT,2KAGA,MAAY,kBAAkB,8EAC9B,MAAY,cACT,IAQG,oEACA,cACR;EAnBF,UAAA,CAqBE,kBAAC,GAAD,EAAW,WAAU,mDAAoD,CAAA,GACzE,kBAAC,QAAD;GACE,WAAW,EACT,+FACA,MAAY,aAAa,IAAY,sBAAsB,kCAG3D,MAAY,kBAAkB,qBAChC;GAEA,UAAA,kBAAC,GAAD,EAAa,aAAa,EAAO,YAAc,CAAA;EAC3C,CAAA,CACO;;CAGjB,OACE,kBAAC,GAAD;EAAe;EAAO,eAAe;EAArC,UAAA;GACG,IACC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;IAAgB,SAAA;IAAS,UAAA;GAAwB,CAAA,GACjD,kBAAC,GAAD;IAAgB,MAAK;IAAQ,WAAU;IACpC,UAAA,GAAe,QAAQ,EAAO;GACjB,CAAA,CACT,EAAA,CAAA,IAET;GAED,IACC,kBAAC,QAAD;IAAM,IAAI;IAAa,WAAU;IAC9B,UAAA,EAAO;GACJ,CAAA,IACJ;GACJ,kBAAC,GAAD,EAAA,UAAgB,EAAqB,CAAA;EAC/B;;AAEZ,CAAC"}
@@ -42,8 +42,10 @@ export interface StatusDotProps extends Omit<React.ComponentProps<"span">, "chil
42
42
  * `role="status"` is a polite live region: the label is announced when it
43
43
  * changes, which is the right behaviour for a dot tracking a connection. For
44
44
  * a dot describing something static (a legend swatch, a row that never
45
- * updates in place) pass `role="img"` props spread over the computed
46
- * attributes, so the override lands.
45
+ * updates in place) pass `role="img"`. That role makes the dot's children
46
+ * presentational, so the label then goes out as `aria-label` instead of the
47
+ * sr-only span — an sr-only child inside `role="img"` is not a name, and axe
48
+ * fails it as `role-img-alt`.
47
49
  */
48
- declare function StatusDot({ className, status, size, pulse, glow, label, style, ...props }: StatusDotProps): React.JSX.Element;
50
+ declare function StatusDot({ className, status, size, pulse, glow, label, style, role, ...props }: StatusDotProps): React.JSX.Element;
49
51
  export { StatusDot, statusDotVariants };
@@ -28,14 +28,15 @@ var r = n("inline-block shrink-0 rounded-full align-middle transition-[backgroun
28
28
  pulse: !1
29
29
  }
30
30
  }), i = { boxShadow: "0 0 var(--status-dot-glow) color-mix(in oklch, var(--status-dot-color) 50%, transparent)" };
31
- function a({ className: n, status: a = "neutral", size: o = "md", pulse: s = !1, glow: c = !1, label: l = null, style: u, ...d }) {
32
- let f = l == null;
31
+ function a({ className: n, status: a = "neutral", size: o = "md", pulse: s = !1, glow: c = !1, label: l = null, style: u, role: d, ...f }) {
32
+ let p = l == null, m = d ?? (p ? void 0 : "status"), h = !p && m === "img";
33
33
  return /* @__PURE__ */ t("span", {
34
34
  "data-slot": "status-dot",
35
35
  "data-status": a,
36
36
  "data-size": o,
37
- role: f ? void 0 : "status",
38
- "aria-hidden": f || void 0,
37
+ role: m,
38
+ "aria-hidden": p || void 0,
39
+ "aria-label": h ? l : void 0,
39
40
  className: e(r({
40
41
  status: a,
41
42
  size: o,
@@ -45,8 +46,8 @@ function a({ className: n, status: a = "neutral", size: o = "md", pulse: s = !1,
45
46
  ...i,
46
47
  ...u
47
48
  } : u,
48
- ...d,
49
- children: f ? null : /* @__PURE__ */ t("span", {
49
+ ...f,
50
+ children: p || h ? null : /* @__PURE__ */ t("span", {
50
51
  className: "sr-only",
51
52
  children: l
52
53
  })
@@ -1 +1 @@
1
- {"version":3,"file":"status-dot.js","names":[],"sources":["../../../src/components/feedback/status-dot.tsx"],"mappings":";;;;;AAkBA,IAAM,IAAoB,EACxB,6GACA;CACE,UAAU;EACR,QAAQ;GACN,SAAS;GACT,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;EACX;EAIA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EAOA,OAAO;GACL,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,QAAQ;EACR,MAAM;EACN,OAAO;CACT;AACF,CACF,GAMM,IAAkC,EACtC,WAAW,2FACb;AA4CA,SAAS,EAAU,EACjB,cACA,YAAS,WACT,UAAO,MACP,WAAQ,IACR,UAAO,IACP,WAAQ,MACR,UACA,GAAG,KACc;CACjB,IAAM,IAAa,KAAS;CAC5B,OACE,kBAAC,QAAD;EACE,aAAU;EACV,eAAa;EACb,aAAW;EACX,MAAM,IAAa,KAAA,IAAY;EAC/B,eAAa,KAAc,KAAA;EAC3B,WAAW,EAAG,EAAkB;GAAE;GAAQ;GAAM;EAAM,CAAC,GAAG,CAAS;EAEnE,OAAO,IAAO;GAAE,GAAG;GAAY,GAAG;EAAM,IAAI;EAC5C,GAAI;EASH,UAAA,IAAa,OAAO,kBAAC,QAAD;GAAM,WAAU;GAAW,UAAA;EAAY,CAAA;CACxD,CAAA;AAEV"}
1
+ {"version":3,"file":"status-dot.js","names":[],"sources":["../../../src/components/feedback/status-dot.tsx"],"mappings":";;;;;AAkBA,IAAM,IAAoB,EACxB,6GACA;CACE,UAAU;EACR,QAAQ;GACN,SAAS;GACT,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;EACX;EAIA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EAOA,OAAO;GACL,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,QAAQ;EACR,MAAM;EACN,OAAO;CACT;AACF,CACF,GAMM,IAAkC,EACtC,WAAW,2FACb;AA8CA,SAAS,EAAU,EACjB,cACA,YAAS,WACT,UAAO,MACP,WAAQ,IACR,UAAO,IACP,WAAQ,MACR,UACA,SACA,GAAG,KACc;CACjB,IAAM,IAAa,KAAS,MACtB,IAAe,MAAS,IAAa,KAAA,IAAY,WAGjD,IAAmB,CAAC,KAAc,MAAiB;CACzD,OACE,kBAAC,QAAD;EACE,aAAU;EACV,eAAa;EACb,aAAW;EACX,MAAM;EACN,eAAa,KAAc,KAAA;EAC3B,cAAY,IAAmB,IAAQ,KAAA;EACvC,WAAW,EAAG,EAAkB;GAAE;GAAQ;GAAM;EAAM,CAAC,GAAG,CAAS;EAEnE,OAAO,IAAO;GAAE,GAAG;GAAY,GAAG;EAAM,IAAI;EAC5C,GAAI;EASH,UAAA,KAAc,IAAmB,OAAO,kBAAC,QAAD;GAAM,WAAU;GAAW,UAAA;EAAY,CAAA;CAC5E,CAAA;AAEV"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiestaboard/ui",
3
- "version": "6.1.0",
3
+ "version": "6.1.1",
4
4
  "description": "FiestaUI — the FiestaBoard design system. React components on Base UI with Tailwind v4 design tokens.",
5
5
  "license": "MIT",
6
6
  "repository": {