@open-mercato/ui 0.7.1-develop.7137.1.26575786c0 → 0.7.1-develop.7149.1.7efa6e1612

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.
@@ -28,51 +28,59 @@ function ViewChip({
28
28
  const t = useT();
29
29
  if (isRenaming) {
30
30
  const renameTrimmed = renameValue.trim();
31
- return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 rounded-md border border-primary bg-primary/5 px-3 h-8", children: [
32
- /* @__PURE__ */ jsx(
33
- "input",
34
- {
35
- value: renameValue,
36
- onChange: (e) => onRenameValueChange(e.target.value),
37
- className: "w-24 bg-transparent text-sm outline-none",
38
- autoFocus: true,
39
- onKeyDown: (e) => {
40
- if (e.key === "Enter") onRenameConfirm();
41
- if (e.key === "Escape") onRenameCancel();
42
- }
43
- }
44
- ),
45
- /* @__PURE__ */ jsx(
46
- IconButton,
47
- {
48
- type: "button",
49
- variant: "ghost",
50
- size: "xs",
51
- className: "h-auto",
52
- onClick: onRenameConfirm,
53
- disabled: !renameTrimmed,
54
- "aria-label": t("ui.perspectives.rename.confirm", "Confirm rename"),
55
- children: /* @__PURE__ */ jsx(Check, { className: `size-4 ${renameTrimmed ? "text-brand-violet" : "text-muted-foreground opacity-50"}` })
56
- }
57
- ),
58
- /* @__PURE__ */ jsx(
59
- IconButton,
60
- {
61
- type: "button",
62
- variant: "ghost",
63
- size: "xs",
64
- className: "h-auto",
65
- onClick: onRenameCancel,
66
- "aria-label": t("ui.perspectives.rename.cancel", "Cancel rename"),
67
- children: /* @__PURE__ */ jsx(X, { className: "size-4 text-muted-foreground hover:text-destructive" })
68
- }
69
- )
70
- ] });
31
+ return /* @__PURE__ */ jsxs(
32
+ "div",
33
+ {
34
+ "data-active": isActive ? "true" : "false",
35
+ className: "inline-flex items-center gap-1 rounded-md border border-primary bg-primary/5 px-3 h-8",
36
+ children: [
37
+ /* @__PURE__ */ jsx(
38
+ "input",
39
+ {
40
+ value: renameValue,
41
+ onChange: (e) => onRenameValueChange(e.target.value),
42
+ className: "w-24 bg-transparent text-sm outline-none",
43
+ autoFocus: true,
44
+ onKeyDown: (e) => {
45
+ if (e.key === "Enter") onRenameConfirm();
46
+ if (e.key === "Escape") onRenameCancel();
47
+ }
48
+ }
49
+ ),
50
+ /* @__PURE__ */ jsx(
51
+ IconButton,
52
+ {
53
+ type: "button",
54
+ variant: "ghost",
55
+ size: "xs",
56
+ className: "h-auto",
57
+ onClick: onRenameConfirm,
58
+ disabled: !renameTrimmed,
59
+ "aria-label": t("ui.perspectives.rename.confirm", "Confirm rename"),
60
+ children: /* @__PURE__ */ jsx(Check, { className: `size-4 ${renameTrimmed ? "text-brand-violet" : "text-muted-foreground opacity-50"}` })
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsx(
64
+ IconButton,
65
+ {
66
+ type: "button",
67
+ variant: "ghost",
68
+ size: "xs",
69
+ className: "h-auto",
70
+ onClick: onRenameCancel,
71
+ "aria-label": t("ui.perspectives.rename.cancel", "Cancel rename"),
72
+ children: /* @__PURE__ */ jsx(X, { className: "size-4 text-muted-foreground hover:text-destructive" })
73
+ }
74
+ )
75
+ ]
76
+ }
77
+ );
71
78
  }
72
79
  const showUsersIcon = kind === "role" || isShared;
73
80
  return /* @__PURE__ */ jsxs(
74
81
  "div",
75
82
  {
83
+ "data-active": isActive ? "true" : "false",
76
84
  className: `inline-flex items-center gap-0.5 rounded-md border h-8 text-sm ${isActive ? "bg-brand-violet/10 border-brand-violet/30 font-medium text-brand-violet" : "border-border"}`,
77
85
  children: [
78
86
  /* @__PURE__ */ jsxs(
@@ -84,6 +92,7 @@ function ViewChip({
84
92
  className: "h-auto px-3 py-0 text-sm hover:bg-transparent",
85
93
  onClick: onActivate,
86
94
  disabled,
95
+ "aria-current": isActive ? "true" : void 0,
87
96
  children: [
88
97
  showUsersIcon ? /* @__PURE__ */ jsx(Users, { className: "size-3 mr-1 opacity-50" }) : null,
89
98
  label
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/backend/views/ViewChip.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { Check, X, Users } from 'lucide-react'\nimport { Button } from '../../primitives/button'\nimport { IconButton } from '../../primitives/icon-button'\nimport { ViewChipMenu } from './ViewChipMenu'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype Props = {\n id: string\n label: string\n kind: 'personal' | 'role'\n isActive: boolean\n disabled: boolean\n isShared: boolean\n isRenaming: boolean\n renameValue: string\n canApplyToRoles: boolean\n deleting: boolean\n onActivate: () => void\n onRenameValueChange: (value: string) => void\n onRenameConfirm: () => void\n onRenameCancel: () => void\n onRenameStart?: () => void\n onClone: () => void\n onShareStart?: () => void\n onDelete: () => void\n}\n\nexport function ViewChip({\n id,\n label,\n kind,\n isActive,\n disabled,\n isShared,\n isRenaming,\n renameValue,\n canApplyToRoles,\n deleting,\n onActivate,\n onRenameValueChange,\n onRenameConfirm,\n onRenameCancel,\n onRenameStart,\n onClone,\n onShareStart,\n onDelete,\n}: Props) {\n const t = useT()\n\n if (isRenaming) {\n const renameTrimmed = renameValue.trim()\n return (\n <div className=\"inline-flex items-center gap-1 rounded-md border border-primary bg-primary/5 px-3 h-8\">\n <input\n value={renameValue}\n onChange={(e) => onRenameValueChange(e.target.value)}\n className=\"w-24 bg-transparent text-sm outline-none\"\n autoFocus\n onKeyDown={(e) => {\n if (e.key === 'Enter') onRenameConfirm()\n if (e.key === 'Escape') onRenameCancel()\n }}\n />\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n className=\"h-auto\"\n onClick={onRenameConfirm}\n disabled={!renameTrimmed}\n aria-label={t('ui.perspectives.rename.confirm', 'Confirm rename')}\n >\n <Check className={`size-4 ${renameTrimmed ? 'text-brand-violet' : 'text-muted-foreground opacity-50'}`} />\n </IconButton>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n className=\"h-auto\"\n onClick={onRenameCancel}\n aria-label={t('ui.perspectives.rename.cancel', 'Cancel rename')}\n >\n <X className=\"size-4 text-muted-foreground hover:text-destructive\" />\n </IconButton>\n </div>\n )\n }\n\n const showUsersIcon = kind === 'role' || isShared\n\n return (\n <div\n className={`inline-flex items-center gap-0.5 rounded-md border h-8 text-sm ${\n isActive\n ? 'bg-brand-violet/10 border-brand-violet/30 font-medium text-brand-violet'\n : 'border-border'\n }`}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto px-3 py-0 text-sm hover:bg-transparent\"\n onClick={onActivate}\n disabled={disabled}\n >\n {showUsersIcon ? <Users className=\"size-3 mr-1 opacity-50\" /> : null}\n {label}\n </Button>\n <ViewChipMenu\n kind={kind}\n canApplyToRoles={canApplyToRoles}\n deleting={deleting}\n onRenameStart={onRenameStart}\n onClone={onClone}\n onShareStart={onShareStart}\n onDelete={onDelete}\n />\n </div>\n )\n}\n"],
5
- "mappings": ";AAsDM,SACE,KADF;AApDN,SAAS,OAAO,GAAG,aAAa;AAChC,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AAuBd,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAU;AACR,QAAM,IAAI,KAAK;AAEf,MAAI,YAAY;AACd,UAAM,gBAAgB,YAAY,KAAK;AACvC,WACE,qBAAC,SAAI,WAAU,yFACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,oBAAoB,EAAE,OAAO,KAAK;AAAA,UACnD,WAAU;AAAA,UACV,WAAS;AAAA,UACT,WAAW,CAAC,MAAM;AAChB,gBAAI,EAAE,QAAQ,QAAS,iBAAgB;AACvC,gBAAI,EAAE,QAAQ,SAAU,gBAAe;AAAA,UACzC;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS;AAAA,UACT,UAAU,CAAC;AAAA,UACX,cAAY,EAAE,kCAAkC,gBAAgB;AAAA,UAEhE,8BAAC,SAAM,WAAW,UAAU,gBAAgB,sBAAsB,kCAAkC,IAAI;AAAA;AAAA,MAC1G;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS;AAAA,UACT,cAAY,EAAE,iCAAiC,eAAe;AAAA,UAE9D,8BAAC,KAAE,WAAU,uDAAsD;AAAA;AAAA,MACrE;AAAA,OACF;AAAA,EAEJ;AAEA,QAAM,gBAAgB,SAAS,UAAU;AAEzC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,kEACT,WACI,4EACA,eACN;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS;AAAA,YACT;AAAA,YAEC;AAAA,8BAAgB,oBAAC,SAAM,WAAU,0BAAyB,IAAK;AAAA,cAC/D;AAAA;AAAA;AAAA,QACH;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { Check, X, Users } from 'lucide-react'\nimport { Button } from '../../primitives/button'\nimport { IconButton } from '../../primitives/icon-button'\nimport { ViewChipMenu } from './ViewChipMenu'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype Props = {\n id: string\n label: string\n kind: 'personal' | 'role'\n isActive: boolean\n disabled: boolean\n isShared: boolean\n isRenaming: boolean\n renameValue: string\n canApplyToRoles: boolean\n deleting: boolean\n onActivate: () => void\n onRenameValueChange: (value: string) => void\n onRenameConfirm: () => void\n onRenameCancel: () => void\n onRenameStart?: () => void\n onClone: () => void\n onShareStart?: () => void\n onDelete: () => void\n}\n\nexport function ViewChip({\n id,\n label,\n kind,\n isActive,\n disabled,\n isShared,\n isRenaming,\n renameValue,\n canApplyToRoles,\n deleting,\n onActivate,\n onRenameValueChange,\n onRenameConfirm,\n onRenameCancel,\n onRenameStart,\n onClone,\n onShareStart,\n onDelete,\n}: Props) {\n const t = useT()\n\n if (isRenaming) {\n const renameTrimmed = renameValue.trim()\n return (\n <div\n data-active={isActive ? 'true' : 'false'}\n className=\"inline-flex items-center gap-1 rounded-md border border-primary bg-primary/5 px-3 h-8\"\n >\n <input\n value={renameValue}\n onChange={(e) => onRenameValueChange(e.target.value)}\n className=\"w-24 bg-transparent text-sm outline-none\"\n autoFocus\n onKeyDown={(e) => {\n if (e.key === 'Enter') onRenameConfirm()\n if (e.key === 'Escape') onRenameCancel()\n }}\n />\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n className=\"h-auto\"\n onClick={onRenameConfirm}\n disabled={!renameTrimmed}\n aria-label={t('ui.perspectives.rename.confirm', 'Confirm rename')}\n >\n <Check className={`size-4 ${renameTrimmed ? 'text-brand-violet' : 'text-muted-foreground opacity-50'}`} />\n </IconButton>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n className=\"h-auto\"\n onClick={onRenameCancel}\n aria-label={t('ui.perspectives.rename.cancel', 'Cancel rename')}\n >\n <X className=\"size-4 text-muted-foreground hover:text-destructive\" />\n </IconButton>\n </div>\n )\n }\n\n const showUsersIcon = kind === 'role' || isShared\n\n return (\n <div\n data-active={isActive ? 'true' : 'false'}\n className={`inline-flex items-center gap-0.5 rounded-md border h-8 text-sm ${\n isActive\n ? 'bg-brand-violet/10 border-brand-violet/30 font-medium text-brand-violet'\n : 'border-border'\n }`}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto px-3 py-0 text-sm hover:bg-transparent\"\n onClick={onActivate}\n disabled={disabled}\n aria-current={isActive ? 'true' : undefined}\n >\n {showUsersIcon ? <Users className=\"size-3 mr-1 opacity-50\" /> : null}\n {label}\n </Button>\n <ViewChipMenu\n kind={kind}\n canApplyToRoles={canApplyToRoles}\n deleting={deleting}\n onRenameStart={onRenameStart}\n onClone={onClone}\n onShareStart={onShareStart}\n onDelete={onDelete}\n />\n </div>\n )\n}\n"],
5
+ "mappings": ";AAsDM,SAIE,KAJF;AApDN,SAAS,OAAO,GAAG,aAAa;AAChC,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AAuBd,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAU;AACR,QAAM,IAAI,KAAK;AAEf,MAAI,YAAY;AACd,UAAM,gBAAgB,YAAY,KAAK;AACvC,WACE;AAAA,MAAC;AAAA;AAAA,QACC,eAAa,WAAW,SAAS;AAAA,QACjC,WAAU;AAAA,QAEV;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,oBAAoB,EAAE,OAAO,KAAK;AAAA,cACnD,WAAU;AAAA,cACV,WAAS;AAAA,cACT,WAAW,CAAC,MAAM;AAChB,oBAAI,EAAE,QAAQ,QAAS,iBAAgB;AACvC,oBAAI,EAAE,QAAQ,SAAU,gBAAe;AAAA,cACzC;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cACT,UAAU,CAAC;AAAA,cACX,cAAY,EAAE,kCAAkC,gBAAgB;AAAA,cAEhE,8BAAC,SAAM,WAAW,UAAU,gBAAgB,sBAAsB,kCAAkC,IAAI;AAAA;AAAA,UAC1G;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cACT,cAAY,EAAE,iCAAiC,eAAe;AAAA,cAE9D,8BAAC,KAAE,WAAU,uDAAsD;AAAA;AAAA,UACrE;AAAA;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,gBAAgB,SAAS,UAAU;AAEzC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAa,WAAW,SAAS;AAAA,MACjC,WAAW,kEACT,WACI,4EACA,eACN;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS;AAAA,YACT;AAAA,YACA,gBAAc,WAAW,SAAS;AAAA,YAEjC;AAAA,8BAAgB,oBAAC,SAAM,WAAU,0BAAyB,IAAK;AAAA,cAC/D;AAAA;AAAA;AAAA,QACH;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/ui",
3
- "version": "0.7.1-develop.7137.1.26575786c0",
3
+ "version": "0.7.1-develop.7149.1.7efa6e1612",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -155,14 +155,14 @@
155
155
  "remark-gfm": "^4.0.1"
156
156
  },
157
157
  "peerDependencies": {
158
- "@open-mercato/shared": "0.7.1-develop.7137.1.26575786c0",
158
+ "@open-mercato/shared": "0.7.1-develop.7149.1.7efa6e1612",
159
159
  "react": ">=18.0.0",
160
160
  "react-dom": ">=18.0.0",
161
161
  "react-is": ">=18.0.0"
162
162
  },
163
163
  "devDependencies": {
164
164
  "@figma/code-connect": "^1.3.4",
165
- "@open-mercato/shared": "0.7.1-develop.7137.1.26575786c0",
165
+ "@open-mercato/shared": "0.7.1-develop.7149.1.7efa6e1612",
166
166
  "@testing-library/dom": "^10.4.1",
167
167
  "@testing-library/jest-dom": "^7.0.0",
168
168
  "@testing-library/react": "^16.3.1",
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+
5
+ import * as React from 'react'
6
+ import { screen } from '@testing-library/react'
7
+ import { ViewChip } from '../views/ViewChip'
8
+ import { renderWithProviders } from '@open-mercato/shared/lib/testing/renderWithProviders'
9
+
10
+ // Coverage for issue #5846: the chip's "this view is active" state used to live
11
+ // only in its Tailwind classes (`bg-brand-violet/10 border-brand-violet/30 ...`),
12
+ // so the only way to assert it was to string-match `className` on `.parentElement`.
13
+ // That broke on any restyle and left the state invisible to assistive technology.
14
+ // The chip now carries `data-active` on its root and `aria-current` on the button
15
+ // the user actually activates, mirroring how `pagination.tsx` marks the current page.
16
+
17
+ type ChipProps = React.ComponentProps<typeof ViewChip>
18
+
19
+ function renderChip(overrides: Partial<ChipProps> = {}) {
20
+ const props: ChipProps = {
21
+ id: 'view-1',
22
+ label: 'My view',
23
+ kind: 'personal',
24
+ isActive: false,
25
+ disabled: false,
26
+ isShared: false,
27
+ isRenaming: false,
28
+ renameValue: '',
29
+ canApplyToRoles: false,
30
+ deleting: false,
31
+ onActivate: jest.fn(),
32
+ onRenameValueChange: jest.fn(),
33
+ onRenameConfirm: jest.fn(),
34
+ onRenameCancel: jest.fn(),
35
+ onClone: jest.fn(),
36
+ onDelete: jest.fn(),
37
+ ...overrides,
38
+ }
39
+ return renderWithProviders(<ViewChip {...props} />, { dict: {} })
40
+ }
41
+
42
+ describe('ViewChip active-state hook', () => {
43
+ it('marks the active chip with data-active="true" and aria-current on its activate button', () => {
44
+ const { container } = renderChip({ isActive: true, label: 'Active view' })
45
+
46
+ expect(container.querySelector('[data-active="true"]')).toBeInTheDocument()
47
+ expect(screen.getByRole('button', { name: 'Active view' })).toHaveAttribute('aria-current', 'true')
48
+ })
49
+
50
+ it('marks an inactive chip with data-active="false" and omits aria-current entirely', () => {
51
+ const { container } = renderChip({ isActive: false, label: 'Inactive view' })
52
+
53
+ expect(container.querySelector('[data-active="false"]')).toBeInTheDocument()
54
+ expect(container.querySelector('[data-active="true"]')).toBeNull()
55
+ expect(screen.getByRole('button', { name: 'Inactive view' })).not.toHaveAttribute('aria-current')
56
+ })
57
+
58
+ it('exposes the active state without depending on the chip styling', () => {
59
+ const { container } = renderChip({ isActive: true, label: 'Styled view' })
60
+
61
+ const chip = container.querySelector('[data-active]') as HTMLElement
62
+ expect(chip).toBeInTheDocument()
63
+
64
+ // Strip every class off the chip: the semantic hook must survive a restyle
65
+ // that drops or renames the `border-brand-violet/30` marker the old assertion read.
66
+ chip.className = ''
67
+ expect(chip.getAttribute('data-active')).toBe('true')
68
+ expect(screen.getByRole('button', { name: 'Styled view' })).toHaveAttribute('aria-current', 'true')
69
+ })
70
+
71
+ it('keeps the hook on the chip root while the view is being renamed', () => {
72
+ const { container } = renderChip({ isActive: true, isRenaming: true, renameValue: 'Draft name' })
73
+
74
+ expect(container.querySelector('[data-active="true"]')).toBeInTheDocument()
75
+ })
76
+ })
@@ -52,7 +52,10 @@ export function ViewChip({
52
52
  if (isRenaming) {
53
53
  const renameTrimmed = renameValue.trim()
54
54
  return (
55
- <div className="inline-flex items-center gap-1 rounded-md border border-primary bg-primary/5 px-3 h-8">
55
+ <div
56
+ data-active={isActive ? 'true' : 'false'}
57
+ className="inline-flex items-center gap-1 rounded-md border border-primary bg-primary/5 px-3 h-8"
58
+ >
56
59
  <input
57
60
  value={renameValue}
58
61
  onChange={(e) => onRenameValueChange(e.target.value)}
@@ -92,6 +95,7 @@ export function ViewChip({
92
95
 
93
96
  return (
94
97
  <div
98
+ data-active={isActive ? 'true' : 'false'}
95
99
  className={`inline-flex items-center gap-0.5 rounded-md border h-8 text-sm ${
96
100
  isActive
97
101
  ? 'bg-brand-violet/10 border-brand-violet/30 font-medium text-brand-violet'
@@ -105,6 +109,7 @@ export function ViewChip({
105
109
  className="h-auto px-3 py-0 text-sm hover:bg-transparent"
106
110
  onClick={onActivate}
107
111
  disabled={disabled}
112
+ aria-current={isActive ? 'true' : undefined}
108
113
  >
109
114
  {showUsersIcon ? <Users className="size-3 mr-1 opacity-50" /> : null}
110
115
  {label}