@celestia-island/hikari 0.55.270 → 0.55.271
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
|
@@ -45,6 +45,22 @@ describe("HkDonutChart", () => {
|
|
|
45
45
|
]);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
it("gives the ring svg intrinsic dimensions from the size prop", () => {
|
|
49
|
+
// Without width/height attributes the svg has no intrinsic size and
|
|
50
|
+
// collapses to 0x0 inside the block-level ring-wrap (wowsp measured a
|
|
51
|
+
// 0x0 getBoundingClientRect on the consuming page before this fix).
|
|
52
|
+
const byDefault = mount(<HkDonutChart entries={ENTRIES} />);
|
|
53
|
+
const defaultSvg = byDefault.querySelector("svg.hk-donut__ring");
|
|
54
|
+
expect(defaultSvg?.getAttribute("width")).toBe("150");
|
|
55
|
+
expect(defaultSvg?.getAttribute("height")).toBe("150");
|
|
56
|
+
|
|
57
|
+
const custom = mount(<HkDonutChart entries={ENTRIES} size={96} />);
|
|
58
|
+
const customSvg = custom.querySelector("svg.hk-donut__ring");
|
|
59
|
+
expect(customSvg?.getAttribute("width")).toBe("96");
|
|
60
|
+
expect(customSvg?.getAttribute("height")).toBe("96");
|
|
61
|
+
expect(customSvg?.getAttribute("viewBox")).toBe("0 0 96 96");
|
|
62
|
+
});
|
|
63
|
+
|
|
48
64
|
it("defaults hints to label · value · percent", () => {
|
|
49
65
|
const el = mount(<HkDonutChart entries={ENTRIES} />);
|
|
50
66
|
const first = el.querySelector(".hk-donut__slice");
|
|
@@ -46,7 +46,7 @@ export default defineComponent({
|
|
|
46
46
|
props: {
|
|
47
47
|
/** The slices' source rows; pass count-desc for the wowsp look. */
|
|
48
48
|
entries: { type: Array as PropType<HkDonutEntry[]>, required: true },
|
|
49
|
-
/** Square ring size (px). */
|
|
49
|
+
/** Square ring size (px) — the SVG's intrinsic width/height and viewBox. */
|
|
50
50
|
size: { type: Number, default: 150 },
|
|
51
51
|
/** Legend rows per column. */
|
|
52
52
|
legendRows: { type: Number, default: LEGEND_ROWS_PER_COLUMN },
|
|
@@ -102,7 +102,12 @@ export default defineComponent({
|
|
|
102
102
|
return (
|
|
103
103
|
<div class="hk-donut" role="img" aria-label={aria.value}>
|
|
104
104
|
<div class="hk-donut__ring-wrap">
|
|
105
|
-
<svg
|
|
105
|
+
<svg
|
|
106
|
+
class="hk-donut__ring"
|
|
107
|
+
width={props.size}
|
|
108
|
+
height={props.size}
|
|
109
|
+
viewBox={`0 0 ${props.size} ${props.size}`}
|
|
110
|
+
>
|
|
106
111
|
{slices.value.map((s) => (
|
|
107
112
|
<path
|
|
108
113
|
key={s.key}
|
|
@@ -86,18 +86,23 @@
|
|
|
86
86
|
* half must be able to paint. Content clipping lives in
|
|
87
87
|
* .hk-sidebar-rail-clip (inside the panel). */
|
|
88
88
|
overflow: visible;
|
|
89
|
+
/* The sidebar z band (900 — above content, below floating panels),
|
|
90
|
+
* carried PERMANENTLY, not only while a peek is open (2026-11-02 user
|
|
91
|
+
* screenshot, wowsp): the straddling toggle hangs over the content
|
|
92
|
+
* column in every state, and its own z-index cannot save it — any
|
|
93
|
+
* stacking context the PANEL carries in a host (wowsp's glass
|
|
94
|
+
* backdrop-filter, a transform/opacity dress) demotes the toggle's
|
|
95
|
+
* local z into that panel, and the overhanging half then loses to
|
|
96
|
+
* plain positioned content painted later in tree order. The HOST is
|
|
97
|
+
* the elevation boundary: with the band here the whole rail subtree
|
|
98
|
+
* paints atomically above the content column no matter what contexts
|
|
99
|
+
* exist inside it, so a peek overlay, the pinned expand and the idle
|
|
100
|
+
* toggle all share one rule. */
|
|
101
|
+
z-index: var(--hk-z-sidebar, 900);
|
|
89
102
|
/* The layout animation the PIN window deliberately keeps. */
|
|
90
103
|
transition: width var(--duration-normal, 0.3s) ease;
|
|
91
104
|
}
|
|
92
105
|
|
|
93
|
-
/* A peek is an OVERLAY: the host rises to the sidebar z band (900 — above
|
|
94
|
-
* content, below floating panels) so the full-width panel paints over the
|
|
95
|
-
* content it temporarily covers. (The host no longer needs to toggle
|
|
96
|
-
* `overflow` here: it never clips.) */
|
|
97
|
-
.hk-sidebar-rail-host[data-peeking] {
|
|
98
|
-
z-index: var(--hk-z-sidebar, 900);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
106
|
.hk-sidebar-rail-panel {
|
|
102
107
|
position: absolute;
|
|
103
108
|
/* Logical: the panel docks the INLINE-START edge in either direction —
|
|
@@ -191,7 +196,11 @@
|
|
|
191
196
|
.hk-sidebar-rail-flight {
|
|
192
197
|
position: absolute;
|
|
193
198
|
inset: 0;
|
|
194
|
-
z-
|
|
199
|
+
/* Local bump (--hk-z-above band): the layer only has to outrank the
|
|
200
|
+
* z-auto dissolve items it substitutes for — during a flip those items
|
|
201
|
+
* hold opacity contexts, so everything inside them (scrollbar chrome
|
|
202
|
+
* included) is trapped below this layer. */
|
|
203
|
+
z-index: var(--hk-z-above, 1);
|
|
195
204
|
display: block;
|
|
196
205
|
pointer-events: none;
|
|
197
206
|
}
|
|
@@ -284,7 +293,14 @@
|
|
|
284
293
|
inset-inline-end: calc(var(--hk-sidebar-rail-toggle-size, 24px) / -2 - var(--hk-sidebar-rail-border-width, 1px) / 2);
|
|
285
294
|
inset-block-start: 50%;
|
|
286
295
|
translate: 0 -50%;
|
|
287
|
-
|
|
296
|
+
/* The fab band — a floating circular affordance above the panel's local
|
|
297
|
+
* chrome. The ranking threat inside the panel is the overlay-scrollbar
|
|
298
|
+
* TRACK (absolute, z-index: 10 — a stacking context that also contains
|
|
299
|
+
* the thumb's 2 and the markers' 1, attached beside the sidebar body):
|
|
300
|
+
* the old raw z-index: 2 ranked BELOW that track, so a scroll or a
|
|
301
|
+
* marker flash could paint its band over the circle's inner half. The
|
|
302
|
+
* fab band clears both the track and everything inside it. */
|
|
303
|
+
z-index: var(--hk-z-fab, 40);
|
|
288
304
|
opacity: 0;
|
|
289
305
|
pointer-events: none;
|
|
290
306
|
transition: opacity var(--duration-fast, 0.15s) ease;
|
|
@@ -34,7 +34,14 @@ import {
|
|
|
34
34
|
* 3. The toggle's center rides the border LINE: negative half-size inset
|
|
35
35
|
* (plus half the border), vertical centering, size token on the host.
|
|
36
36
|
* 4. The host stays the LAYOUT box (position relative, width transition)
|
|
37
|
-
* and
|
|
37
|
+
* and ALWAYS carries the sidebar z band — not only under [data-peeking]
|
|
38
|
+
* (2026-11-02 user screenshot, wowsp): the straddling toggle hangs over
|
|
39
|
+
* the content column in every state, and a host whose panel carries its
|
|
40
|
+
* own stacking context (wowsp's glass backdrop-filter) demotes the
|
|
41
|
+
* toggle's local z below plain positioned content, so the band must
|
|
42
|
+
* live on the host, the elevation boundary.
|
|
43
|
+
* 4b. No raw z-index numbers: the toggle rides the fab band, the flight
|
|
44
|
+
* layer the local-bump band — both through the scale tokens.
|
|
38
45
|
* 5. Pinning: [data-pinning] kills the panel's and any nested sidebar's
|
|
39
46
|
* width transitions (the expand must not replay the slide) while the
|
|
40
47
|
* HOST width transition stays — and the pinned panel keeps the peek
|
|
@@ -93,12 +100,19 @@ describe("HkSidebarRail geometry contract", () => {
|
|
|
93
100
|
expect(host, "the host width transition IS the intended motion").toContain("transition: width");
|
|
94
101
|
});
|
|
95
102
|
|
|
96
|
-
it("
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
|
|
103
|
+
it("the host carries the sidebar z band ALWAYS (the stacking-trap contract)", () => {
|
|
104
|
+
// The band lives on the host rule itself, not under [data-peeking]:
|
|
105
|
+
// the toggle's overhanging half must paint above the content column in
|
|
106
|
+
// every state, and a host whose panel carries its own stacking context
|
|
107
|
+
// (wowsp's glass backdrop-filter) demotes the toggle's local z below
|
|
108
|
+
// plain positioned content painted later in tree order. There is no
|
|
109
|
+
// bare peeking z rule left to tie the elevation to the peek state.
|
|
110
|
+
const host = ruleBody(css, ".hk-sidebar-rail-host {") ?? ruleBody(css, ".hk-sidebar-rail-host");
|
|
111
|
+
expect(host, "the host rule exists").not.toBeNull();
|
|
112
|
+
expect(host).toContain("z-index: var(--hk-z-sidebar, 900)");
|
|
113
|
+
expect(css).not.toContain(".hk-sidebar-rail-host[data-peeking] {");
|
|
114
|
+
// The peek shadow survives on the panel-scoped rules.
|
|
115
|
+
expect(css).toContain(".hk-sidebar-rail-host[data-peeking] .hk-sidebar-rail-panel");
|
|
102
116
|
});
|
|
103
117
|
|
|
104
118
|
it("the panel overlays from the inline-start edge, unclipped, and animates its width", () => {
|
|
@@ -186,8 +200,12 @@ describe("HkSidebarRail geometry contract", () => {
|
|
|
186
200
|
// Vertical centering on the edge.
|
|
187
201
|
expect(toggle).toContain("inset-block-start: 50%");
|
|
188
202
|
expect(toggle).toContain("translate: 0 -50%");
|
|
189
|
-
// Above the panel
|
|
190
|
-
|
|
203
|
+
// Above the panel's local chrome — through the FAB band token, never a
|
|
204
|
+
// raw number: the overlay-scrollbar thumb rides a raw 2 through
|
|
205
|
+
// uncontexted ancestors right up to this panel, so the toggle must
|
|
206
|
+
// strictly outrank it (a tie would be DOM-order roulette).
|
|
207
|
+
expect(toggle).toContain("z-index: var(--hk-z-fab, 40)");
|
|
208
|
+
expect(toggle).not.toMatch(/z-index:\s*\d/);
|
|
191
209
|
});
|
|
192
210
|
|
|
193
211
|
it("the peek casts its shadow toward the content side, mirrored in RTL", () => {
|
|
@@ -256,7 +274,9 @@ describe("HkSidebarRail geometry contract", () => {
|
|
|
256
274
|
expect(layer, "the flight layer rule exists").not.toBeNull();
|
|
257
275
|
expect(layer).toContain("position: absolute");
|
|
258
276
|
expect(layer).toContain("inset: 0");
|
|
259
|
-
|
|
277
|
+
// The local-bump band token, never a raw number (see 4b).
|
|
278
|
+
expect(layer).toContain("z-index: var(--hk-z-above, 1)");
|
|
279
|
+
expect(layer).not.toMatch(/z-index:\s*\d/);
|
|
260
280
|
expect(layer).toContain("pointer-events: none");
|
|
261
281
|
|
|
262
282
|
const clone = ruleBody(css, ".hk-sidebar-rail-flight-clone");
|