Revamped the select docs

This commit is contained in:
Ronan Berder
2025-06-13 14:14:38 +08:00
parent 056c025628
commit 7e3773276c
22 changed files with 321 additions and 492 deletions
+2 -2
View File
@@ -731,12 +731,12 @@
@apply bg-popover text-popover-foreground;
}
}
div.select {
*:not(select).select {
[popover].popover {
@apply p-1 min-w-[anchor-size(width)];
[role='option'] {
@apply aria-hidden:hidden [&_svg]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none [&_svg]:shrink-0 [&_svg]:size-4 aria-disabled:opacity-50 aria-disabled:pointer-events-none disabled:opacity-50 disabled:pointer-events-none w-full truncate;
@apply aria-hidden:hidden [&_svg]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm pl-2 py-1.5 pr-7.5 text-sm outline-hidden select-none [&_svg]:shrink-0 [&_svg]:size-4 aria-disabled:opacity-50 aria-disabled:pointer-events-none disabled:opacity-50 disabled:pointer-events-none w-full truncate;
&[aria-selected='true'] {
@apply bg-[image:var(--check-icon)] bg-no-repeat bg-position-[center_right_0.5rem] bg-size-[0.875rem];
+45 -3
View File
@@ -1,4 +1,21 @@
(() => {
// Monkey patching the history API to detect client-side navigation
if (!window.history.__basecoatPatched) {
const originalPushState = window.history.pushState;
window.history.pushState = function(...args) {
originalPushState.apply(this, args);
window.dispatchEvent(new Event('basecoat:locationchange'));
};
const originalReplaceState = window.history.replaceState;
window.history.replaceState = function(...args) {
originalReplaceState.apply(this, args);
window.dispatchEvent(new Event('basecoat:locationchange'));
};
window.history.__basecoatPatched = true;
}
const initSidebar = (sidebarComponent) => {
const initialOpen = sidebarComponent.dataset.initialOpen !== 'false';
const initialMobileOpen = sidebarComponent.dataset.initialMobileOpen === 'true';
@@ -8,6 +25,20 @@
? (window.innerWidth >= breakpoint ? initialOpen : initialMobileOpen)
: initialOpen;
const updateCurrentPageLinks = () => {
const currentPath = window.location.pathname.replace(/\/$/, '');
sidebarComponent.querySelectorAll('a').forEach(link => {
if (link.hasAttribute('data-ignore-current')) return;
const linkPath = new URL(link.href).pathname.replace(/\/$/, '');
if (linkPath === currentPath) {
link.setAttribute('aria-current', 'page');
} else {
link.removeAttribute('aria-current');
}
});
};
const updateState = () => {
sidebarComponent.setAttribute('aria-hidden', !open);
if (open) {
@@ -35,17 +66,28 @@
});
sidebarComponent.addEventListener('click', (e) => {
const target = e.target;
const nav = sidebarComponent.querySelector('nav');
const closeTarget = e.target.closest('[data-sidebar-close-on-mobile]');
if (closeTarget && window.innerWidth < breakpoint) {
const isMobile = window.innerWidth < breakpoint;
if (isMobile && (target.closest('[data-close-mobile-sidebar]') || (target.closest('a, button') && !target.closest('[data-keep-mobile-sidebar-open]')))) {
if (document.activeElement) document.activeElement.blur();
setState(false);
} else if (e.target === sidebarComponent || (nav && !nav.contains(e.target))) {
return;
}
if (target === sidebarComponent || (nav && !nav.contains(target))) {
if (document.activeElement) document.activeElement.blur();
setState(false);
}
});
window.addEventListener('popstate', updateCurrentPageLinks);
window.addEventListener('basecoat:locationchange', updateCurrentPageLinks);
updateState();
updateCurrentPageLinks();
sidebarComponent.dataset.sidebarInitialized = true;
};
+14 -13
View File
@@ -22,12 +22,11 @@
title=None,
description=None,
footer=None,
main_attrs={},
dialog_attrs={},
trigger_attrs={},
content_attrs={},
content_header_attrs={},
content_body_attrs={},
content_footer_attrs={},
header_attrs={},
body_attrs={},
footer_attrs={},
open=false,
close_button=true,
close_on_overlay_click=true
@@ -47,25 +46,27 @@
<dialog
id="{{ id }}"
class="dialog"
onClick="this.close()"
{% for key, value in main_attrs %}
aria-labelledby="{{ id }}-title"
{% if description %}aria-describedby="{{ id }}-description"{% endif %}
{% if close_on_overlay_click %}onClick="this.close()"{% endif %}
{% for key, value in dialog_attrs %}
{{ key }}="{{ value }}"
{% endfor %}
>
<article onClick="event.stopPropagation()">
<article {% if close_on_overlay_click %}onClick="event.stopPropagation()"{% endif %}>
{% if title or description %}
<header
{% for key, value in content_header_attrs %}
{% for key, value in header_attrs %}
{{ key }}="{{ value }}"
{% endfor %}
>
<h2 id="{{ id }}-title">{{ title | safe }}</h2>
{% if description %}<p>{{ description | safe }}</p>{% endif %}
{% if description %}<p id="{{ id }}-description">{{ description | safe }}</p>{% endif %}
</header>
{% endif %}
{% if caller %}
<section
{% for key, value in content_body_attrs %}
{% for key, value in body_attrs %}
{{ key }}="{{ value }}"
{% endfor %}
>
@@ -74,7 +75,7 @@
{% endif %}
{% if footer %}
<footer
{% for key, value in content_footer_attrs %}
{% for key, value in footer_attrs %}
{{ key }}="{{ value }}"
{% endfor %}
>
@@ -85,7 +86,7 @@
<form method="dialog">
<button aria-label="Close dialog">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
</button>
</button>
</form>
{% endif %}
</article>