@livx.cc/bare-v3 0.1.0-alpha.46 → 0.1.0-alpha.47
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/manifest.json +2 -2
- package/dist/references/disclosure.md +1 -1
- package/dist/ui.js +50 -5
- package/package.json +1 -1
package/dist/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.0-alpha.
|
|
2
|
+
"version": "0.1.0-alpha.47",
|
|
3
3
|
"cssSha256": "4b198a96fb6998163311dad7e93b6bcbfe4e5553a3ef5d7d79c1a7dcd6e9ed39",
|
|
4
4
|
"classes": [
|
|
5
5
|
"b3-accordion",
|
|
@@ -295,7 +295,7 @@
|
|
|
295
295
|
"b3-dropdown-panel",
|
|
296
296
|
"b3-tree"
|
|
297
297
|
],
|
|
298
|
-
"guidance": "Accordion and dropdown use native details/summary. Dropdown is a disclosure containing ordinary links/buttons, not an ARIA menu. mount() adds outside-click and Escape dismissal. Tree is a nested list/details presentation, not a role=tree widget. Browser disclosure behavior supplies keyboard activation.",
|
|
298
|
+
"guidance": "Accordion and dropdown use native details/summary. Dropdown is a disclosure containing ordinary links/buttons, not an ARIA menu. mount() adds outside-click and Escape dismissal, shifts the dropdown within horizontal viewport bounds, and opens it on the roomier side with a scrollable height when space is limited. Authored height limits are respected; close and unmount restore inline placement styles. Placement follows viewport resize and ancestor scrolling; scrolling the panel itself preserves its position. A trigger scrolled fully outside the viewport closes its disclosure without moving focus. Tree is a nested list/details presentation, not a role=tree widget. Browser disclosure behavior supplies keyboard activation.",
|
|
299
299
|
"example": "<details class=\"b3-accordion\"><summary>More information</summary><p>Useful details.</p></details><details class=\"b3-dropdown\"><summary class=\"b3-button\">Actions</summary><div class=\"b3-dropdown-panel\"><a class=\"b3-nav-link\" href=\"#details\">View details</a></div></details>"
|
|
300
300
|
},
|
|
301
301
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Accordion, dropdown and hierarchy
|
|
2
2
|
|
|
3
|
-
Accordion and dropdown use native details/summary. Dropdown is a disclosure containing ordinary links/buttons, not an ARIA menu. mount() adds outside-click and Escape dismissal. Tree is a nested list/details presentation, not a role=tree widget. Browser disclosure behavior supplies keyboard activation.
|
|
3
|
+
Accordion and dropdown use native details/summary. Dropdown is a disclosure containing ordinary links/buttons, not an ARIA menu. mount() adds outside-click and Escape dismissal, shifts the dropdown within horizontal viewport bounds, and opens it on the roomier side with a scrollable height when space is limited. Authored height limits are respected; close and unmount restore inline placement styles. Placement follows viewport resize and ancestor scrolling; scrolling the panel itself preserves its position. A trigger scrolled fully outside the viewport closes its disclosure without moving focus. Tree is a nested list/details presentation, not a role=tree widget. Browser disclosure behavior supplies keyboard activation.
|
|
4
4
|
|
|
5
5
|
Classes: b3-accordion, b3-dropdown, b3-dropdown-panel, b3-tree
|
|
6
6
|
|
package/dist/ui.js
CHANGED
|
@@ -305,18 +305,55 @@ function reel({ root, document: document2, find, options }) {
|
|
|
305
305
|
|
|
306
306
|
// src/interactions/disclosures.js
|
|
307
307
|
function disclosures({ root, document: document2, options }) {
|
|
308
|
+
const placements = new Map;
|
|
309
|
+
const properties = ["transform", "inset-block-start", "inset-block-end", "max-block-size"];
|
|
310
|
+
function restore(panel) {
|
|
311
|
+
const original = placements.get(panel);
|
|
312
|
+
if (!original)
|
|
313
|
+
return;
|
|
314
|
+
for (const [property, value, priority] of original) {
|
|
315
|
+
if (value)
|
|
316
|
+
panel.style.setProperty(property, value, priority);
|
|
317
|
+
else
|
|
318
|
+
panel.style.removeProperty(property);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
options.signal.addEventListener("abort", () => {
|
|
322
|
+
for (const panel of placements.keys())
|
|
323
|
+
restore(panel);
|
|
324
|
+
placements.clear();
|
|
325
|
+
}, { once: true });
|
|
308
326
|
function placeDisclosure(disclosure) {
|
|
309
327
|
const panel = disclosure.querySelector(".b3-dropdown-panel");
|
|
310
|
-
if (!panel
|
|
328
|
+
if (!panel)
|
|
329
|
+
return;
|
|
330
|
+
restore(panel);
|
|
331
|
+
if (!disclosure.open) {
|
|
332
|
+
placements.delete(panel);
|
|
311
333
|
return;
|
|
312
|
-
|
|
313
|
-
panel
|
|
314
|
-
|
|
334
|
+
}
|
|
335
|
+
if (!placements.has(panel)) {
|
|
336
|
+
placements.set(panel, properties.map((property) => [
|
|
337
|
+
property,
|
|
338
|
+
panel.style.getPropertyValue(property),
|
|
339
|
+
panel.style.getPropertyPriority(property)
|
|
340
|
+
]));
|
|
341
|
+
}
|
|
315
342
|
const viewport = document2.defaultView;
|
|
316
343
|
const bounds = panel.getBoundingClientRect();
|
|
317
344
|
const shift = bounds.left < 8 ? 8 - bounds.left : bounds.right > viewport.innerWidth - 8 ? viewport.innerWidth - 8 - bounds.right : 0;
|
|
318
345
|
panel.style.transform = `translateX(${shift}px)`;
|
|
319
|
-
|
|
346
|
+
const trigger = disclosure.getBoundingClientRect();
|
|
347
|
+
if (trigger.bottom <= 0 || trigger.top >= viewport.innerHeight) {
|
|
348
|
+
disclosure.open = false;
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const gap = Math.max(0, bounds.top - trigger.bottom);
|
|
352
|
+
const below = Math.max(0, viewport.innerHeight - trigger.bottom - gap - 8);
|
|
353
|
+
const above = Math.max(0, trigger.top - gap - 8);
|
|
354
|
+
const opensAbove = bounds.height > below && above > below;
|
|
355
|
+
panel.style.maxBlockSize = `${Math.min(bounds.height, opensAbove ? above : below)}px`;
|
|
356
|
+
if (opensAbove) {
|
|
320
357
|
panel.style.insetBlockStart = "auto";
|
|
321
358
|
panel.style.insetBlockEnd = "calc(100% + .5rem)";
|
|
322
359
|
}
|
|
@@ -328,6 +365,14 @@ function disclosures({ root, document: document2, options }) {
|
|
|
328
365
|
document2.defaultView.addEventListener("resize", () => {
|
|
329
366
|
root.querySelectorAll("details.b3-dropdown[open]").forEach(placeDisclosure);
|
|
330
367
|
}, options);
|
|
368
|
+
document2.defaultView.addEventListener("scroll", (event) => {
|
|
369
|
+
for (const disclosure of root.querySelectorAll("details.b3-dropdown[open]")) {
|
|
370
|
+
const panel = disclosure.querySelector(".b3-dropdown-panel");
|
|
371
|
+
if (event.target?.nodeType && panel?.contains(event.target))
|
|
372
|
+
continue;
|
|
373
|
+
placeDisclosure(disclosure);
|
|
374
|
+
}
|
|
375
|
+
}, { ...options, capture: true, passive: true });
|
|
331
376
|
root.addEventListener("keydown", (event) => {
|
|
332
377
|
if (event.key === "Escape") {
|
|
333
378
|
const disclosure = event.target.closest?.("details.b3-dropdown[open]");
|