@kjaniec-dev/ui 0.7.1 → 0.7.2

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/dist/index.js CHANGED
@@ -1344,23 +1344,39 @@ function DataTable({
1344
1344
  }[col.align || "left"];
1345
1345
  const isSortable = col.sortable && onSort && col.sortKey;
1346
1346
  const isSortedActive = sortBy && col.sortKey === sortBy;
1347
+ const ariaSort = isSortable ? isSortedActive ? sortDirection === "asc" ? "ascending" : "descending" : "none" : void 0;
1347
1348
  return /* @__PURE__ */ jsx(
1348
1349
  TableHead,
1349
1350
  {
1350
1351
  className: cn(
1351
1352
  alignClass,
1352
- isSortable && "cursor-pointer select-none hover:bg-muted/30 transition-colors",
1353
+ isSortable && "p-0 hover:bg-muted/30 transition-colors",
1353
1354
  col.className
1354
1355
  ),
1355
- onClick: () => {
1356
- if (!isSortable || !col.sortKey) return;
1357
- const nextDirection = isSortedActive && sortDirection === "asc" ? "desc" : "asc";
1358
- onSort(col.sortKey, nextDirection);
1359
- },
1360
- children: /* @__PURE__ */ jsxs("div", { className: cn("inline-flex items-center gap-1.5", alignClass === "text-right" && "justify-end w-full"), children: [
1361
- /* @__PURE__ */ jsx("span", { children: col.header }),
1362
- isSortable && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground shrink-0 select-none", children: isSortedActive ? sortDirection === "asc" ? "\u25B2" : "\u25BC" : "\u21C5" })
1363
- ] })
1356
+ "aria-sort": ariaSort,
1357
+ children: isSortable ? /* @__PURE__ */ jsxs(
1358
+ "button",
1359
+ {
1360
+ type: "button",
1361
+ onClick: () => {
1362
+ if (!col.sortKey) return;
1363
+ const nextDirection = isSortedActive && sortDirection === "asc" ? "desc" : "asc";
1364
+ onSort(col.sortKey, nextDirection);
1365
+ },
1366
+ className: cn(
1367
+ "w-full px-4 py-3 flex items-center gap-1.5 font-semibold text-[0.72rem] uppercase tracking-[0.05em] text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 transition-colors cursor-pointer",
1368
+ {
1369
+ "justify-start text-left": col.align === "left" || !col.align,
1370
+ "justify-center text-center": col.align === "center",
1371
+ "justify-end text-right": col.align === "right"
1372
+ }
1373
+ ),
1374
+ children: [
1375
+ /* @__PURE__ */ jsx("span", { children: col.header }),
1376
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground shrink-0 select-none", children: isSortedActive ? sortDirection === "asc" ? "\u25B2" : "\u25BC" : "\u21C5" })
1377
+ ]
1378
+ }
1379
+ ) : /* @__PURE__ */ jsx("div", { className: cn("inline-flex items-center gap-1.5", alignClass === "text-right" && "justify-end w-full"), children: col.header })
1364
1380
  },
1365
1381
  idx
1366
1382
  );
@@ -1873,7 +1889,7 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
1873
1889
  }, [open, filteredItems, activeIndex, onClose]);
1874
1890
  React18.useEffect(() => {
1875
1891
  if (listRef.current) {
1876
- const activeEl = listRef.current.children[activeIndex];
1892
+ const activeEl = listRef.current.querySelector('[aria-selected="true"]');
1877
1893
  if (activeEl) {
1878
1894
  activeEl.scrollIntoView({ block: "nearest" });
1879
1895
  }
@@ -1896,6 +1912,9 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
1896
1912
  "div",
1897
1913
  {
1898
1914
  ref: containerRef,
1915
+ role: "dialog",
1916
+ "aria-modal": "true",
1917
+ "aria-label": "Command palette",
1899
1918
  className: "w-[95vw] max-w-lg bg-surface border border-border rounded-kj-xl shadow-kj-lg flex flex-col overflow-hidden max-h-[500px]",
1900
1919
  children: [
1901
1920
  /* @__PURE__ */ jsxs("div", { className: "p-4 border-b border-border flex items-center gap-2", children: [
@@ -1904,6 +1923,11 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
1904
1923
  "input",
1905
1924
  {
1906
1925
  type: "text",
1926
+ role: "combobox",
1927
+ "aria-expanded": open,
1928
+ "aria-autocomplete": "list",
1929
+ "aria-controls": "command-palette-listbox",
1930
+ "aria-activedescendant": filteredItems.length > 0 ? `cmd-item-${activeIndex}` : void 0,
1907
1931
  placeholder,
1908
1932
  value: search,
1909
1933
  onChange: (e) => setSearch(e.target.value),
@@ -1916,44 +1940,64 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
1916
1940
  'No results found for "',
1917
1941
  search,
1918
1942
  '"'
1919
- ] }) : /* @__PURE__ */ jsx("div", { ref: listRef, className: "space-y-4", children: Object.entries(groups).map(([cat, itemsInCat]) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1920
- /* @__PURE__ */ jsx("div", { className: "px-3 py-1 text-[0.65rem] font-bold uppercase tracking-wider text-muted-foreground", children: cat }),
1921
- itemsInCat.map((item) => {
1922
- const currentIdx = absoluteItemIndex++;
1923
- const isActive = currentIdx === activeIndex;
1924
- return /* @__PURE__ */ jsxs(
1925
- "div",
1926
- {
1927
- onClick: () => {
1928
- item.action();
1929
- onClose();
1930
- },
1931
- className: cn(
1932
- "flex items-center justify-between gap-3 px-3 py-2.5 rounded-kj-md cursor-pointer select-none transition-colors",
1933
- isActive ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
1934
- ),
1935
- children: [
1936
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
1937
- item.icon && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground [&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem]", children: item.icon }),
1938
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex flex-col", children: [
1939
- /* @__PURE__ */ jsx("span", { className: cn("text-[0.85rem] font-semibold", isActive ? "text-primary" : "text-foreground"), children: item.title }),
1940
- item.subtitle && /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] text-muted-foreground truncate", children: item.subtitle })
1941
- ] })
1942
- ] }),
1943
- item.shortcut && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: item.shortcut.map((sc, scIdx) => /* @__PURE__ */ jsx(
1944
- "kbd",
1945
- {
1946
- className: "px-1.5 py-0.5 rounded border border-border bg-subtle text-[10px] font-mono leading-none shadow-kj-xs text-muted-foreground",
1947
- children: sc
1943
+ ] }) : /* @__PURE__ */ jsx(
1944
+ "div",
1945
+ {
1946
+ ref: listRef,
1947
+ id: "command-palette-listbox",
1948
+ role: "listbox",
1949
+ "aria-label": "Commands",
1950
+ className: "space-y-4",
1951
+ children: Object.entries(groups).map(([cat, itemsInCat]) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": `cmd-cat-${cat}`, className: "space-y-1", children: [
1952
+ /* @__PURE__ */ jsx(
1953
+ "div",
1954
+ {
1955
+ id: `cmd-cat-${cat}`,
1956
+ className: "px-3 py-1 text-[0.65rem] font-bold uppercase tracking-wider text-muted-foreground",
1957
+ children: cat
1958
+ }
1959
+ ),
1960
+ itemsInCat.map((item) => {
1961
+ const currentIdx = absoluteItemIndex++;
1962
+ const isActive = currentIdx === activeIndex;
1963
+ return /* @__PURE__ */ jsxs(
1964
+ "div",
1965
+ {
1966
+ id: `cmd-item-${currentIdx}`,
1967
+ role: "option",
1968
+ "aria-selected": isActive,
1969
+ onClick: () => {
1970
+ item.action();
1971
+ onClose();
1948
1972
  },
1949
- scIdx
1950
- )) })
1951
- ]
1952
- },
1953
- item.id
1954
- );
1955
- })
1956
- ] }, cat)) }) }),
1973
+ className: cn(
1974
+ "flex items-center justify-between gap-3 px-3 py-2.5 rounded-kj-md cursor-pointer select-none transition-colors",
1975
+ isActive ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
1976
+ ),
1977
+ children: [
1978
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
1979
+ item.icon && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground [&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem]", children: item.icon }),
1980
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex flex-col", children: [
1981
+ /* @__PURE__ */ jsx("span", { className: cn("text-[0.85rem] font-semibold", isActive ? "text-primary" : "text-foreground"), children: item.title }),
1982
+ item.subtitle && /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] text-muted-foreground truncate", children: item.subtitle })
1983
+ ] })
1984
+ ] }),
1985
+ item.shortcut && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: item.shortcut.map((sc, scIdx) => /* @__PURE__ */ jsx(
1986
+ "kbd",
1987
+ {
1988
+ className: "px-1.5 py-0.5 rounded border border-border bg-subtle text-[10px] font-mono leading-none shadow-kj-xs text-muted-foreground",
1989
+ children: sc
1990
+ },
1991
+ scIdx
1992
+ )) })
1993
+ ]
1994
+ },
1995
+ item.id
1996
+ );
1997
+ })
1998
+ ] }, cat))
1999
+ }
2000
+ ) }),
1957
2001
  /* @__PURE__ */ jsxs("div", { className: "px-4 py-2.5 border-t border-border bg-subtle flex items-center justify-between text-[11px] text-muted-foreground font-medium", children: [
1958
2002
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1959
2003
  /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [