fix: add popover and tooltip safe areas (#951)

This commit is contained in:
Sam Potts
2026-03-14 19:34:33 +11:00
committed by GitHub
parent dbf717f1a7
commit c39b1f8809
6 changed files with 135 additions and 6 deletions
@@ -34,10 +34,50 @@
&[data-side="right"] { &[data-side="right"] {
transform-origin: left; transform-origin: left;
} }
/* Safe area between trigger and popup */
&::before {
content: "";
position: absolute;
pointer-events: inherit;
}
&[data-side="top"]::before,
&[data-side="bottom"]::before {
width: 100%;
inset-inline: 0;
}
&[data-side="top"]::before {
top: 100%;
}
&[data-side="bottom"]::before {
bottom: 100%;
}
&[data-side="left"]::before,
&[data-side="right"]::before {
height: 100%;
inset-block: 0;
}
&[data-side="left"]::before {
left: 100%;
}
&[data-side="right"]::before {
right: 100%;
}
} }
.media-default-skin .media-popover { .media-default-skin .media-popover {
--media-popover-side-offset: 0.5rem; --media-popover-side-offset: 0.5rem;
&[data-side="top"]::before,
&[data-side="bottom"]::before {
height: var(--media-popover-side-offset);
}
&[data-side="left"]::before,
&[data-side="right"]::before {
width: var(--media-popover-side-offset);
}
} }
.media-default-skin .media-popover--volume { .media-default-skin .media-popover--volume {
padding: 0.625rem 0.25rem; padding: 0.625rem 0.25rem;
@@ -50,4 +90,13 @@
font-size: 0.75rem; font-size: 0.75rem;
white-space: nowrap; white-space: nowrap;
--media-tooltip-side-offset: 0.75rem; --media-tooltip-side-offset: 0.75rem;
&[data-side="top"]::before,
&[data-side="bottom"]::before {
height: var(--media-tooltip-side-offset);
}
&[data-side="left"]::before,
&[data-side="right"]::before {
width: var(--media-tooltip-side-offset);
}
} }
@@ -9,15 +9,28 @@ const base = cn(
'data-ending-style:opacity-0 data-ending-style:scale-50 data-ending-style:blur-sm', 'data-ending-style:opacity-0 data-ending-style:scale-50 data-ending-style:blur-sm',
'data-instant:duration-0', 'data-instant:duration-0',
// Ensure we animate from the correct origin based on the side the popover is on // Ensure we animate from the correct origin based on the side the popover is on
'data-[side=top]:origin-bottom data-[side=bottom]:origin-top data-[side=left]:origin-right data-[side=right]:origin-left' 'data-[side=top]:origin-bottom data-[side=bottom]:origin-top data-[side=left]:origin-right data-[side=right]:origin-left',
// Safe area between trigger and popup
'before:absolute before:pointer-events-[inherit]',
'data-[side=top]:before:left-0 data-[side=top]:before:right-0 data-[side=top]:before:top-full',
'data-[side=bottom]:before:left-0 data-[side=bottom]:before:right-0 data-[side=bottom]:before:bottom-full',
'data-[side=left]:before:top-0 data-[side=left]:before:bottom-0 data-[side=left]:before:left-full',
'data-[side=right]:before:top-0 data-[side=right]:before:bottom-0 data-[side=right]:before:right-full'
); );
export const popup = { export const popup = {
popover: cn(base, '[--media-popover-side-offset:0.5rem]'), popover: cn(
base,
'[--media-popover-side-offset:0.5rem]',
'data-[side=top]:before:h-(--media-popover-side-offset) data-[side=bottom]:before:h-(--media-popover-side-offset)',
'data-[side=left]:before:w-(--media-popover-side-offset) data-[side=right]:before:w-(--media-popover-side-offset)'
),
tooltip: cn( tooltip: cn(
base, base,
'py-1 px-2.5 rounded-full text-[0.75rem] whitespace-nowrap', 'py-1 px-2.5 rounded-full text-[0.75rem] whitespace-nowrap',
'[--media-tooltip-side-offset:0.75rem]' '[--media-tooltip-side-offset:0.75rem]',
'data-[side=top]:before:h-(--media-tooltip-side-offset) data-[side=bottom]:before:h-(--media-tooltip-side-offset)',
'data-[side=left]:before:w-(--media-tooltip-side-offset) data-[side=right]:before:w-(--media-tooltip-side-offset)'
), ),
volume: 'py-2.5 px-1 rounded-full', volume: 'py-2.5 px-1 rounded-full',
}; };
@@ -34,6 +34,48 @@
&[data-side="right"] { &[data-side="right"] {
transform-origin: left; transform-origin: left;
} }
/* Safe area between trigger and popup */
&::before {
content: "";
position: absolute;
pointer-events: inherit;
}
&[data-side="top"]::before,
&[data-side="bottom"]::before {
width: 100%;
inset-inline: 0;
}
&[data-side="top"]::before {
top: 100%;
}
&[data-side="bottom"]::before {
bottom: 100%;
}
&[data-side="left"]::before,
&[data-side="right"]::before {
height: 100%;
inset-block: 0;
}
&[data-side="left"]::before {
left: 100%;
}
&[data-side="right"]::before {
right: 100%;
}
}
.media-minimal-skin .media-popover {
&[data-side="top"]::before,
&[data-side="bottom"]::before {
height: var(--media-popover-side-offset);
}
&[data-side="left"]::before,
&[data-side="right"]::before {
width: var(--media-popover-side-offset);
}
} }
.media-minimal-skin .media-tooltip { .media-minimal-skin .media-tooltip {
@@ -48,6 +90,15 @@
white-space: nowrap; white-space: nowrap;
--media-tooltip-side-offset: 0.75rem; --media-tooltip-side-offset: 0.75rem;
&[data-side="top"]::before,
&[data-side="bottom"]::before {
height: var(--media-tooltip-side-offset);
}
&[data-side="left"]::before,
&[data-side="right"]::before {
width: var(--media-tooltip-side-offset);
}
@media (prefers-reduced-transparency: reduce) { @media (prefers-reduced-transparency: reduce) {
background-color: oklch(0 0 0 / 0.7); background-color: oklch(0 0 0 / 0.7);
} }
@@ -42,6 +42,7 @@ export const controls = cn(
export const popup = { export const popup = {
...basePopup, ...basePopup,
volume: cn( volume: cn(
basePopup.popover,
'py-2 pr-0 pl-16', 'py-2 pr-0 pl-16',
'bg-transparent bg-gradient-to-l from-(--media-controls-background-color) from-80% to-transparent', 'bg-transparent bg-gradient-to-l from-(--media-controls-background-color) from-80% to-transparent',
'[--media-popover-side-offset:0.75rem]' '[--media-popover-side-offset:0.75rem]'
@@ -9,14 +9,29 @@ const base = cn(
'data-ending-style:opacity-0 data-ending-style:scale-50 data-ending-style:blur-sm', 'data-ending-style:opacity-0 data-ending-style:scale-50 data-ending-style:blur-sm',
'data-instant:duration-0', 'data-instant:duration-0',
// Ensure we animate from the correct origin based on the side the popover is on // Ensure we animate from the correct origin based on the side the popover is on
'data-[side=top]:origin-bottom data-[side=bottom]:origin-top data-[side=left]:origin-right data-[side=right]:origin-left' 'data-[side=top]:origin-bottom data-[side=bottom]:origin-top data-[side=left]:origin-right data-[side=right]:origin-left',
// Safe area between trigger and popup
'before:absolute before:pointer-events-[inherit]',
'data-[side=top]:before:left-0 data-[side=top]:before:right-0 data-[side=top]:before:top-full',
'data-[side=bottom]:before:left-0 data-[side=bottom]:before:right-0 data-[side=bottom]:before:bottom-full',
'data-[side=left]:before:top-0 data-[side=left]:before:bottom-0 data-[side=left]:before:left-full',
'data-[side=right]:before:top-0 data-[side=right]:before:bottom-0 data-[side=right]:before:right-full'
); );
export const popup = { export const popup = {
base, base,
popover: cn(
base,
'data-[side=top]:before:h-(--media-popover-side-offset) data-[side=bottom]:before:h-(--media-popover-side-offset)',
'data-[side=left]:before:w-(--media-popover-side-offset) data-[side=right]:before:w-(--media-popover-side-offset)'
),
tooltip: cn( tooltip: cn(
base, base,
'px-2 py-1 rounded-sm shadow-md shadow-black/10 bg-white/10 backdrop-blur-lg backdrop-saturate-150 text-[0.75rem] whitespace-nowrap', 'px-2 py-1 rounded-sm shadow-md shadow-black/10 bg-white/10 backdrop-blur-lg backdrop-saturate-150 text-[0.75rem] whitespace-nowrap',
'[--media-tooltip-side-offset:0.75rem]' '[--media-tooltip-side-offset:0.75rem]',
'data-[side=top]:before:h-(--media-tooltip-side-offset) data-[side=bottom]:before:h-(--media-tooltip-side-offset)',
'data-[side=left]:before:w-(--media-tooltip-side-offset) data-[side=right]:before:w-(--media-tooltip-side-offset)',
'[@media(prefers-reduced-transparency:reduce)]:bg-black/70',
'contrast-more:bg-black/90'
), ),
}; };
@@ -124,7 +124,7 @@ export const slider = {
export const popup = { export const popup = {
...basePopup, ...basePopup,
volume: cn(basePopup.base, '[--media-popover-side-offset:0.5rem] p-1 bg-transparent'), volume: cn(basePopup.popover, '[--media-popover-side-offset:0.5rem] p-1 bg-transparent'),
}; };
/* ========================================================================== /* ==========================================================================