Popover
Popover Panel
import { component$, useStyles$ } from "@builder.io/qwik";
import { Popover } from "@kunai-consulting/qwik";
import styles from "./popover.css?inline";
export default component$(() => {
useStyles$(styles);
return (
<Popover.Root>
<Popover.Anchor class="popover-anchor">Open Popover</Popover.Anchor>
<Popover.Content class="popover-content">Popover Panel</Popover.Content>
</Popover.Root>
);
});
Animations
Entry and exit animations
Popover
import { component$, useStyles$ } from "@builder.io/qwik";
import { Popover } from "@kunai-consulting/qwik";
export default component$(() => {
useStyles$(styles);
return (
<Popover.Root>
<Popover.Anchor class="popover-anchor">Open Popover</Popover.Anchor>
<Popover.Content class="popover-content popover-transition">
Popover
</Popover.Content>
</Popover.Root>
);
});
// internal styles
import styles from "./transition.css?inline";
Value based state
Is open: false
Popover Panel
import { component$, useSignal } from "@builder.io/qwik";
import { Popover } from "@kunai-consulting/qwik";
export default component$(() => {
const isOpen = useSignal(false);
return (
<>
<p>Is open: {isOpen.value ? "true" : "false"}</p>
<Popover.Root
open={isOpen.value}
onChange$={(open: boolean) => {
console.log("hey", open);
isOpen.value = open;
}}
>
<Popover.Anchor class="popover-anchor">Open Popover</Popover.Anchor>
<Popover.Content class="popover-content">Popover Panel</Popover.Content>
</Popover.Root>
</>
);
});
Signal based state
Is open: false
Popover Panel
import { component$, useSignal } from "@builder.io/qwik";
import { Popover } from "@kunai-consulting/qwik";
export default component$(() => {
const isOpen = useSignal(false);
return (
<>
<p>Is open: {isOpen.value ? "true" : "false"}</p>
<button type="button" onClick$={() => (isOpen.value = !isOpen.value)}>
Toggle popover
</button>
<Popover.Root bind:open={isOpen}>
<Popover.Anchor class="popover-anchor">Open Popover</Popover.Anchor>
<Popover.Content class="popover-content">Popover Panel</Popover.Content>
</Popover.Root>
</>
);
});
Relevant CSS:
.popover-transition {
opacity: 0;
transition: opacity 0.3s, overlay 0.3s, display 0.3s;
transition-behavior: allow-discrete;
}
.popover-transition:popover-open {
opacity: 1;
}
/* @starting-style needs to be after the previous [popover]:popover-open rule
to take effect, as the specificity is the same */
@starting-style {
.popover-transition:popover-open {
opacity: 0;
}
}
Why no keyframe examples?
Transitions can be interrupted mid-animation. When users interact quickly (opening then immediately closing a popover), transitions smoothly reverse while keyframes must complete their full animation cycle.