Compare commits

...

2 Commits

Author SHA1 Message Date
Nolann Biron d6be0d0a01 Replace the chat-open and sheet-open :has() variants with <html> attributes 2026-08-12 18:36:15 +02:00
Nolann Biron b9d7afea45 Bound the OpenAPI disclosure hover :has() selectors to the header 2026-08-12 18:36:11 +02:00
5 changed files with 32 additions and 7 deletions
@@ -202,6 +202,13 @@ const globalState = zustand.create<AIChatState>(() => {
};
});
// Mirrored onto <html> because CSS (the `chat-open` variant) can't read the store.
globalState.subscribe((state, prev) => {
if (state.opened !== prev.opened) {
document.documentElement.dataset.aiChatOpen = String(state.opened);
}
});
/**
* Get the current state of the AI chat.
*/
@@ -64,6 +64,13 @@ export function AIChat() {
[]
);
// AI chat can be disabled per space, so this view can go away while the store says opened.
React.useEffect(() => {
return () => {
delete document.documentElement.dataset.aiChatOpen;
};
}, []);
// Track the view of the AI chat
const trackEvent = useTrackEvent();
React.useEffect(() => {
@@ -798,11 +798,12 @@ button.openapi-mcp {
@apply border-tint-subtle transition-all border-b border-x overflow-auto rounded-corners:last:rounded-b-xl circular-corners:last:rounded-b-2xl straight-corners:last:rounded-b-xs rounded-corners:first:rounded-t-xl circular-corners:first:rounded-t-2xl straight-corners:first:rounded-t-xs first:border-t relative;
}
.openapi-disclosure-group:has(.openapi-disclosure-group-trigger:hover) {
.openapi-disclosure-group:has(> .openapi-disclosure-group-trigger:hover) {
@apply bg-tint-subtle;
}
.openapi-disclosure-group:has(.openapi-disclosure-group-trigger:hover):has(.openapi-select:hover) {
/* Selects also live in the panel, so only a header select may clear the highlight. */
.openapi-disclosure-group:has(> .openapi-disclosure-group-trigger .openapi-select:hover) {
@apply !bg-transparent;
}
@@ -143,6 +143,18 @@ export function SideSheet(
return () => observer.disconnect();
}, [toggleClass, openState, onOpenChange]);
React.useEffect(() => {
if (!isModal || !isOpen) {
return;
}
document.documentElement.setAttribute('data-sheet-open', '');
return () => {
document.documentElement.removeAttribute('data-sheet-open');
};
}, [isModal, isOpen]);
// Handle Escape key press to close the modal sheet
React.useEffect(() => {
if (!isModal || !isOpen) {
+3 -5
View File
@@ -674,11 +674,9 @@ const config: Config = {
* Variant when the Table of Content navigation is open.
*/
addVariant('navigation-open', 'body.navigation-open &');
addVariant('chat-open', 'body:has(.ai-chat[aria-expanded="true"]) &');
addVariant(
'sheet-open',
'html:has(.side-sheet[aria-modal="true"][aria-expanded="true"]) &, &:has(.side-sheet[aria-modal="true"][aria-expanded="true"])'
);
addVariant('chat-open', 'html[data-ai-chat-open="true"] &');
/* Second selector targets the elements carrying the attribute themselves (<html>). */
addVariant('sheet-open', ['html[data-sheet-open] &', '&[data-sheet-open]']);
/**
* Variant when a header is displayed.