@celestia-island/hikari 0.55.221 → 0.55.222

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.221",
3
+ "version": "0.55.222",
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",
@@ -193,6 +193,21 @@ describe("HkAdminHeader", () => {
193
193
  expect(c.textContent).not.toContain("alice");
194
194
  });
195
195
 
196
+ it("reserves the workspace-switcher slot in drawer mode only", () => {
197
+ // 2026-10-29 user direction: the frontend header's left wing is
198
+ // avatar + ws-trigger; the console drawer face keeps the SLOT as a
199
+ // deliberate blank so the centre strip can never slide into the
200
+ // space — menu mode carries the page title in that position instead.
201
+ const drawer = mount(headerNode({ avatarAction: "drawer", userEmail: "alice@example.com" }));
202
+ const slot = drawer.querySelector(".s-admin-header-ws-slot");
203
+ expect(slot, "drawer face must render the reserved ws slot").toBeTruthy();
204
+ expect(slot?.getAttribute("aria-hidden")).toBe("true");
205
+
206
+ const menu = mount(headerNode({ title: "Providers", logoutLabel: "Log out" }));
207
+ expect(menu.querySelector(".s-admin-header-ws-slot")).toBeNull();
208
+ expect(menu.querySelector(".s-admin-header-title")).toBeTruthy();
209
+ });
210
+
196
211
  it("renders the signing-in placeholder with the force-sign-out escape when the identity is empty", async () => {
197
212
  const onForceSignOut = vi.fn();
198
213
  const c = mount(headerNode({
@@ -249,6 +249,20 @@ export const HkAdminHeader = defineComponent({
249
249
  )}
250
250
  </button>
251
251
  )}
252
+ {/* The reserved workspace-switcher slot (drawer face only).
253
+ The chat header's left wing is avatar + ws-trigger button,
254
+ and that wing's min-content floor is what keeps the
255
+ header-centre strip off the space on a phone. The console
256
+ has no workspace concept, but the drawer face hides the
257
+ title too — without a stand-in the wing's floor is just
258
+ the 28px avatar and a wide centre strip slides left into
259
+ the slot and reads as hugging the avatar (2026-10-29 user
260
+ direction: 头像右侧留白,前后台布局统一). An aria-hidden
261
+ blank of the trigger's own footprint keeps both faces'
262
+ left wings at the same floor. */}
263
+ {props.avatarAction === "drawer" && (
264
+ <span class="s-admin-header-ws-slot" aria-hidden="true" />
265
+ )}
252
266
  {/* WHERE am I — the open view's title, not the nickname. The
253
267
  1.5 line-height (in the class) keeps descenders (g, y, p)
254
268
  inside the truncate clip box: the default text-sm box is
@@ -95,6 +95,20 @@ describe("admin header chrome geometry (the two user-requested fixes)", () => {
95
95
  expect(rule).toContainEqual(["gap", "var(--space-16)"]);
96
96
  });
97
97
 
98
+ it("reserves the drawer face's workspace-switcher slot at the trigger's own footprint", () => {
99
+ // 2026-10-29 user direction: the chat header's left wing is avatar +
100
+ // ws-trigger, and that wing's min-content floor is what stops the
101
+ // balanced grid's centre strip from sliding into the space on a
102
+ // phone. The console drawer face (no title, no workspace concept)
103
+ // must keep the slot as a blank of the trigger's own 28px box —
104
+ // dropping the rule would drop the floor and the strip would hug
105
+ // the avatar again.
106
+ const rule = ruleDeclarations(adminTokens, ".s-admin-header-ws-slot");
107
+ expect(rule, ".s-admin-header-ws-slot must be declared").not.toBeNull();
108
+ expect(rule).toContainEqual(["width", "var(--space-28)"]);
109
+ expect(rule).toContainEqual(["flex-shrink", "0"]);
110
+ });
111
+
98
112
  it("hangs the shared balanced-header grid contract (the ONE header layout)", () => {
99
113
  // User report 2026-10-15: the console's header-centre tab strip sat
100
114
  // LEFT of centre on phones (drawer mode hides the title, so the left
@@ -597,6 +597,23 @@
597
597
  object-fit: cover;
598
598
  }
599
599
 
600
+ /* The reserved workspace-switcher slot (HkAdminHeader, drawer face).
601
+ * The chat header's left wing is avatar + ws-trigger (8px flex gap +
602
+ * 28px button box), and that wing's min-content floor is what keeps the
603
+ * balanced grid's centre strip off the space on a phone: the strip can
604
+ * only shrink into its own column, never into a wing. The console's
605
+ * drawer face hides both the title and the workspace concept, so
606
+ * without a stand-in the wing's floor is just the 28px avatar — a wide
607
+ * strip (the firewall page's three sections on a 412px phone) slides
608
+ * left until it hugs the avatar (2026-10-29 user report). The blank
609
+ * span carries the trigger's 28px box; the wing's 16px gap already
610
+ * covers the button's 8px inline padding (the 2026-09-28 title-distance
611
+ * pin), so the floor lands within one padding-step of the frontend's. */
612
+ .s-admin-header-ws-slot {
613
+ width: var(--space-28);
614
+ flex-shrink: 0;
615
+ }
616
+
600
617
  /* The old hover camera veil ("change avatar" affordance) is gone: the
601
618
  * avatar trigger opens the account MENU — the avatar edit is the Camera
602
619
  * item inside it — so the veil promised an action the click never