@celestia-island/hikari 0.55.329 → 0.55.330

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celestia-island/hikari",
3
- "version": "0.55.329",
3
+ "version": "0.55.330",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Hikari UI library, Vue 3 runtime — one design system for Vue 3 and Rust/WASM applications",
@@ -84,7 +84,7 @@
84
84
  // Padding
85
85
  padding: var(--space-4) var(--space-8);
86
86
  margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-8));
87
- border-radius: vars.$hikari-radius-fine-sm;
87
+ border-radius: var(--radius-sm, 4px);
88
88
 
89
89
  // Display
90
90
  display: inline-flex;
@@ -216,7 +216,7 @@
216
216
  z-index: var(--hk-z-header);
217
217
 
218
218
  // Appearance
219
- border-radius: vars.$hikari-radius-fine-md;
219
+ border-radius: var(--radius-lg, 12px);
220
220
  border: 1px solid var(--hi-color-border);
221
221
  background: var(--hi-surface);
222
222
  @include backdrop-filter(blur(4px));
@@ -321,7 +321,7 @@
321
321
  .hk-breadcrumb-item {
322
322
  background: var(--hi-card-bg);
323
323
  padding: 0.375rem 0.75rem;
324
- border-radius: vars.$hikari-radius-fine-sm;
324
+ border-radius: var(--radius-sm, 4px);
325
325
 
326
326
  &:not(:last-child):hover {
327
327
  background: var(--hi-primary);
@@ -270,6 +270,31 @@ describe("HkTable sections", () => {
270
270
  expect(empty!.getAttribute("colspan")).toBe(String(COLS.length));
271
271
  });
272
272
 
273
+ it("names an empty-title header cell via headerLabel without rendering text", async () => {
274
+ // Utility columns (row actions) intentionally carry `title: ""` —
275
+ // but an empty `<th>` is an UNNAMED one for assistive tech. The
276
+ // headerLabel contract: aria-label published on the th, visible
277
+ // header stays empty, and columns without the label render no
278
+ // aria-label at all (no behavior change for existing tables).
279
+ const columns = [
280
+ { key: "name", title: "Name" },
281
+ { key: "actions", title: "", headerLabel: "Actions", align: "right" as const },
282
+ ];
283
+ const sections: HkTableSection[] = [
284
+ { key: "panel-a", label: "Panel A", rows: [{ name: "alpha", actions: "…" }] },
285
+ ];
286
+ const c = mount(h(HTable, { columns, sections }));
287
+
288
+ const heads = Array.from(c.querySelectorAll("thead th"));
289
+ const named = heads.find((th) => th.getAttribute("aria-label") === "Actions");
290
+ expect(named, "the actions th carries the accessible name").toBeTruthy();
291
+ const plain = heads.find((th) => th.getAttribute("aria-label") === null) as HTMLElement;
292
+ expect(plain.textContent).toContain("Name");
293
+ // visible header of the named column stays EMPTY — the label is
294
+ // assistive-only
295
+ expect(named!.textContent!.trim()).toBe("");
296
+ });
297
+
273
298
  it("sorts inside each section and keeps the section order", async () => {
274
299
  const columns = [{ key: "name", title: "Name", sortable: true }];
275
300
  const sections: HkTableSection[] = [
@@ -18,6 +18,13 @@ import "./HkTable.scss";
18
18
  interface Column {
19
19
  key: string;
20
20
  title: string;
21
+ /** Accessible name for the header cell, WITHOUT visible text. Utility
22
+ * columns (row actions, ⋯ menus) intentionally render an empty
23
+ * `title` — but an empty `<th>` is also an unnamed one for screen
24
+ * readers. Set `headerLabel` to publish `aria-label` on that `<th>`
25
+ * while the visible header stays empty; it never renders text and
26
+ * never participates in sorting. */
27
+ headerLabel?: string;
21
28
  width?: string;
22
29
  sortable?: boolean;
23
30
  align?: "left" | "center" | "right";
@@ -1161,6 +1168,7 @@ export default defineComponent({
1161
1168
  return (
1162
1169
  <th
1163
1170
  key={col.key}
1171
+ aria-label={col.headerLabel}
1164
1172
  class={[
1165
1173
  "hk-table-header-cell",
1166
1174
  col.align ? `hk-text-${col.align}` : "",
@@ -4,3 +4,4 @@ $hikari-font-family-mono: ui-monospace, 'SF Mono', Menlo, Consolas, 'DejaVu Sans
4
4
  $hikari-font-size-sm: 0.875rem;
5
5
  $hikari-radius-fine-sm: 4px;
6
6
  $hikari-radius-fine-md: 6px;
7
+ $hikari-radius-fine-lg: 8px;
@@ -171,6 +171,38 @@ describe("theme token inventory", () => {
171
171
  expect(unexpected, "new multi-defined scale tokens").toEqual([]);
172
172
  });
173
173
 
174
+ it("scale seed defines the full radius ladder with canonical values", () => {
175
+ // Existence + value pin for the runtime radius scale. Before the
176
+ // 2026-11 radius wave, deleting a `--radius-*` definition stayed
177
+ // green everywhere (no read face checked for presence); this test is
178
+ // that read face. Values mirror hikari scale.scss — the same ladder
179
+ // chest mirrors into its own `:root`, so a value change here is a
180
+ // cross-repo contract change and must ride a dedicated wave.
181
+ const defs = harvestDefinitions(seedFiles);
182
+ const ladder: Array<[string, string]> = [
183
+ ["--radius-xs", "2px"],
184
+ ["--radius-sm", "4px"],
185
+ ["--radius-md", "8px"],
186
+ ["--radius-lg", "12px"],
187
+ ["--radius-xl", "16px"],
188
+ ["--radius-full", "9999px"],
189
+ ];
190
+ for (const [name, value] of ladder) {
191
+ const sites = defs.get(name);
192
+ expect(sites, `${name} missing from theme/scale.scss`).toBeDefined();
193
+ // Every site must carry the canonical value — not just the first.
194
+ // A same-file duplicate would slip past the multi-file guard above
195
+ // (files.size stays 1) and win the CSS cascade as the LAST
196
+ // definition; iterating all sites closes that bypass.
197
+ for (const site of sites!) {
198
+ expect(
199
+ site.value,
200
+ `${name} non-canonical site in ${site.file}`,
201
+ ).toBe(value);
202
+ }
203
+ }
204
+ });
205
+
174
206
  it("component --hi-color-* fallbacks stay on the canonical literals", () => {
175
207
  // The standalone-render contract: when a host loads nothing, a
176
208
  // component renders through these literals. They are DERIVED FROM THE