@celestia-island/hikari 0.55.28 → 0.55.30

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.28",
3
+ "version": "0.55.30",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Hikari Vue 3 component library — production-grade UI components based on shittim-chest design system",
@@ -107,6 +107,7 @@
107
107
  }
108
108
 
109
109
  .hk-icon-group-item {
110
+ position: relative;
110
111
  display: inline-flex;
111
112
  align-items: center;
112
113
  justify-content: center;
@@ -168,3 +169,29 @@
168
169
  font-weight: 600;
169
170
  line-height: 1;
170
171
  }
172
+
173
+ /* Status marker (HkIconButtonGroupOption.marker) — a small dot pinned to
174
+ * the item's bottom-right corner. "success" = the theme's success green
175
+ * with a surface-colored ring so it stays legible on top of the icon's
176
+ * corner and across active/muted tints. Purely decorative: the accessible
177
+ * meaning lives in the option's label/tooltip the host controls. */
178
+ .hk-icon-group-item-marker {
179
+ position: absolute;
180
+ right: calc(var(--space-1, 0.25rem) / 2);
181
+ bottom: calc(var(--space-1, 0.25rem) / 2);
182
+ width: 0.5rem;
183
+ height: 0.5rem;
184
+ border-radius: 999px;
185
+ pointer-events: none;
186
+ }
187
+
188
+ .hk-icon-group-item-marker-success {
189
+ background: rgb(var(--color-success, 14 184 64));
190
+ box-shadow: 0 0 0 0.125rem rgb(var(--color-surface, 240 244 248));
191
+ }
192
+
193
+ /* Slider items already establish position:relative for the thumb stack —
194
+ * keep the marker above the gliding pill, not under it. */
195
+ .hk-icon-group-slider .hk-icon-group-item .hk-icon-group-item-marker {
196
+ z-index: 1;
197
+ }
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { afterEach, describe, expect, it } from "vitest";
3
+ import { afterEach, describe, expect, it, vi } from "vitest";
4
4
  import { createApp, defineComponent, h, nextTick, ref } from "vue";
5
5
 
6
6
  import HkIconButtonGroup from "./HkIconButtonGroup";
@@ -303,3 +303,41 @@ describe("HkIconButtonGroup", () => {
303
303
  });
304
304
  });
305
305
  });
306
+ describe("option markers", () => {
307
+ const baseOpts = (marker?: "success", disabled?: boolean) => [
308
+ { key: "totp", label: "TOTP" },
309
+ { key: "password", label: "Password", marker, disabled },
310
+ ];
311
+
312
+ it("renders the success marker dot and data-marker attribute", () => {
313
+ const c = mountComp(() => h(HkIconButtonGroup, {
314
+ mode: "single",
315
+ variant: "slider",
316
+ options: baseOpts("success"),
317
+ modelValue: "totp",
318
+ }));
319
+ const item = c.querySelector('.hk-icon-group-item[data-key="password"]') as HTMLElement;
320
+ expect(item).toBeTruthy();
321
+ expect(item.getAttribute("data-marker")).toBe("success");
322
+ expect(item.querySelector(".hk-icon-group-item-marker-success")).toBeTruthy();
323
+ // The untouched sibling carries no marker.
324
+ const sibling = c.querySelector('.hk-icon-group-item[data-key="totp"]') as HTMLElement;
325
+ expect(sibling.getAttribute("data-marker")).toBeNull();
326
+ });
327
+
328
+ it("ignores activation of a disabled marked option", async () => {
329
+ const onSelect = vi.fn();
330
+ const c = mountComp(() => h(HkIconButtonGroup, {
331
+ mode: "single",
332
+ variant: "slider",
333
+ options: baseOpts("success", true),
334
+ modelValue: "totp",
335
+ onSelect,
336
+ }));
337
+ const item = c.querySelector('.hk-icon-group-item[data-key="password"]') as HTMLButtonElement;
338
+ expect(item.getAttribute("disabled")).not.toBeNull();
339
+ item.click();
340
+ await Promise.resolve();
341
+ expect(onSelect).not.toHaveBeenCalled();
342
+ });
343
+ });
@@ -17,6 +17,11 @@ export interface HkIconButtonGroupOption {
17
17
  * host's vue differs. Missing icons fall back to the label's initial. */
18
18
  icon?: unknown;
19
19
  disabled?: boolean;
20
+ /** Status dot pinned to the item's bottom-right corner. `"success"`
21
+ * draws a small green dot (step-proven factor, completed requirement);
22
+ * the dot is decorative — pair it with `disabled` and an updated
23
+ * tooltip when it means "this one is done". */
24
+ marker?: "success";
20
25
  /** Tooltip text override; an EMPTY string suppresses the tooltip. */
21
26
  tooltip?: string;
22
27
  }
@@ -168,6 +173,7 @@ export default defineComponent({
168
173
  class="hk-icon-group-item"
169
174
  data-key={option.key}
170
175
  data-active={active || undefined}
176
+ data-marker={option.marker || undefined}
171
177
  role={props.mode === "single" ? "radio" : undefined}
172
178
  aria-checked={props.mode === "single" ? active : undefined}
173
179
  aria-pressed={props.mode === "multiple" ? active : undefined}
@@ -185,6 +191,12 @@ export default defineComponent({
185
191
  </span>
186
192
  )}
187
193
  </span>
194
+ {option.marker && (
195
+ <span
196
+ class={`hk-icon-group-item-marker hk-icon-group-item-marker-${option.marker}`}
197
+ aria-hidden="true"
198
+ />
199
+ )}
188
200
  </button>
189
201
  );
190
202
  // An empty tooltip override suppresses the wrapper entirely.
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "إزالة",
218
218
  "hikari::tagInput.addCustom": "استخدام \"{q}\"",
219
219
  "hikari::tagInput.reorder": "إعادة الترتيب — {label}",
220
- "hikari::modal.hiddenLayers": "الطبقات المخفية"
220
+ "hikari::modal.hiddenLayers": "الطبقات المخفية",
221
+ "hikari::theme.modeTabHint": "هذه التبويبات تختار لوحة الألوان التي تحرّرها؛ لتبديل الوضع الفاتح/الداكن للتطبيق كله استخدم شريط الأوضاع أعلى نافذة السمة."
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "Entfernen",
218
218
  "hikari::tagInput.addCustom": "„{q}“ verwenden",
219
219
  "hikari::tagInput.reorder": "Neu anordnen — {label}",
220
- "hikari::modal.hiddenLayers": "Verdeckte Ebenen"
220
+ "hikari::modal.hiddenLayers": "Verdeckte Ebenen",
221
+ "hikari::theme.modeTabHint": "Diese Reiter wählen die zu bearbeitende Palette; die appweite Hell/Dunkel-Umschaltung liegt im Modusstreifen des Themen-Popups."
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "Remove",
218
218
  "hikari::tagInput.addCustom": "Use “{q}”",
219
219
  "hikari::tagInput.reorder": "Reorder {label}",
220
- "hikari::modal.hiddenLayers": "Hidden layers"
220
+ "hikari::modal.hiddenLayers": "Hidden layers",
221
+ "hikari::theme.modeTabHint": "These tabs pick which palette you are EDITING; to switch the app-wide light/dark, use the mode strip at the top of the theme popup."
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "Quitar",
218
218
  "hikari::tagInput.addCustom": "Usar «{q}»",
219
219
  "hikari::tagInput.reorder": "Reordenar — {label}",
220
- "hikari::modal.hiddenLayers": "Capas ocultas"
220
+ "hikari::modal.hiddenLayers": "Capas ocultas",
221
+ "hikari::theme.modeTabHint": "Estas pestañas eligen la paleta que estás EDITANDO; para cambiar el modo claro/oscuro de toda la app, usa la franja de modos de la parte superior del panel de temas."
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "Retirer",
218
218
  "hikari::tagInput.addCustom": "Utiliser « {q} »",
219
219
  "hikari::tagInput.reorder": "Réorganiser — {label}",
220
- "hikari::modal.hiddenLayers": "Couches masquées"
220
+ "hikari::modal.hiddenLayers": "Couches masquées",
221
+ "hikari::theme.modeTabHint": "Ces onglets choisissent la palette éditée ; pour basculer clair/sombre dans toute l’app, utilisez la barre de mode du menu de thème."
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "削除",
218
218
  "hikari::tagInput.addCustom": "「{q}」を使用",
219
219
  "hikari::tagInput.reorder": "並べ替え — {label}",
220
- "hikari::modal.hiddenLayers": "非表示の階層"
220
+ "hikari::modal.hiddenLayers": "非表示の階層",
221
+ "hikari::theme.modeTabHint": "このタブは編集対象のパレットを選ぶだけです。アプリ全体の明/暗はテーマポップアップ上部のモードストリップで切り替えてください。"
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "제거",
218
218
  "hikari::tagInput.addCustom": "\"{q}\" 사용",
219
219
  "hikari::tagInput.reorder": "순서 변경 — {label}",
220
- "hikari::modal.hiddenLayers": "숨겨진 레이어"
220
+ "hikari::modal.hiddenLayers": "숨겨진 레이어",
221
+ "hikari::theme.modeTabHint": "이 탭은 편집할 팔레트를 고를 뿐입니다. 앱 전체 밝기/어둠은 테마 팝업 상단의 모드 스트립에서 바꾸세요."
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "Remover",
218
218
  "hikari::tagInput.addCustom": "Usar \"{q}\"",
219
219
  "hikari::tagInput.reorder": "Reordenar — {label}",
220
- "hikari::modal.hiddenLayers": "Camadas ocultas"
220
+ "hikari::modal.hiddenLayers": "Camadas ocultas",
221
+ "hikari::theme.modeTabHint": "Estas abas escolhem a paleta que você está EDITANDO; para alternar o claro/escuro do app inteiro, use a faixa de modos no topo do painel de temas."
221
222
  }
@@ -217,5 +217,6 @@
217
217
  "hikari::tagInput.remove": "Удалить",
218
218
  "hikari::tagInput.addCustom": "Использовать «{q}»",
219
219
  "hikari::tagInput.reorder": "Изменить порядок — {label}",
220
- "hikari::modal.hiddenLayers": "Скрытые слои"
220
+ "hikari::modal.hiddenLayers": "Скрытые слои",
221
+ "hikari::theme.modeTabHint": "Вкладки выбирают редактируемую палитру; общесистемное переключение светлой/тёмной — в полосе режимов вверху меню темы."
221
222
  }
@@ -221,5 +221,6 @@
221
221
  "hikari::tagInput.remove": "移除",
222
222
  "hikari::tagInput.addCustom": "使用「{q}」",
223
223
  "hikari::tagInput.reorder": "拖动排序 — {label}",
224
- "hikari::modal.hiddenLayers": "隐藏层级"
224
+ "hikari::modal.hiddenLayers": "隐藏层级",
225
+ "hikari::theme.modeTabHint": "切换这里编辑的是对应模式的调色板;要切换应用整体深/浅,请用主题弹窗顶部的模式条。"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "hikari::tagInput.remove": "移除",
222
222
  "hikari::tagInput.addCustom": "使用「{q}」",
223
223
  "hikari::tagInput.reorder": "拖曳排序 — {label}",
224
- "hikari::modal.hiddenLayers": "隱藏層級"
224
+ "hikari::modal.hiddenLayers": "隱藏層級",
225
+ "hikari::theme.modeTabHint": "切換這裡編輯的是對應模式的調色盤;要切換應用整體深/淺,請用主題彈窗頂部的模式條。"
225
226
  }