Skip to content

Flyout

Use the trigger slot and anchor sizing variables for a positioned flyout.

Order details
Express delivery

Package is in transit

Tracking number SV-2849-1038
  1. Order confirmed Monday, 9:32 AM
  2. Shipped from warehouse Tuesday, 4:18 PM
  3. In transit Arriving at your local facility
  4. Delivered Expected Thursday
Delivery address 14 Market Street, San Francisco

Code

The following example assumes that you have imported the component and set up the theme.

Flyout Basic
<div class="flyout-container">
<span class="label">Order details</span>
<sv-flyout class="shipping-flyout">
<!-- Flyout Trigger -->
<button type="button" class="trigger" slot="trigger">
10 collapsed lines
<span class="trigger-icon" aria-hidden="true">📦</span>
<span class="trigger-content">
<strong>Shipping information</strong>
<span>Arrives Thursday, March 14</span>
</span>
<svg class="trigger-arrow" aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path d="M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z"></path>
</svg>
</button>
<!-- Flyout Content -->
<article class="shipping-card">
84 collapsed lines
<header class="shipping-header">
<div>
<span class="eyebrow">Express delivery</span>
<h2>Package is in transit</h2>
</div>
</header>
<div class="tracking-code">
<span>Tracking number</span>
<strong>SV-2849-1038</strong>
</div>
<ol class="timeline">
<li class="timeline-item complete">
<span class="timeline-marker"></span>
<div>
<strong>Order confirmed</strong>
<span>Monday, 9:32 AM</span>
</div>
</li>
<li class="timeline-item complete">
<span class="timeline-marker"></span>
<div>
<strong>Shipped from warehouse</strong>
<span>Tuesday, 4:18 PM</span>
</div>
</li>
<li class="timeline-item current">
<span class="timeline-marker"></span>
<div>
<strong>In transit</strong>
<span>Arriving at your local facility</span>
</div>
</li>
<li class="timeline-item">
<span class="timeline-marker"></span>
<div>
<strong>Delivered</strong>
<span>Expected Thursday</span>
</div>
</li>
</ol>
<div class="destination">
<svg aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path
d="M480-80Q319-217 239.5-334.5T160-552q0-150 96.5-239T480-880q127 0 223.5 89T800-552q0 100-79.5 217.5T480-80Zm0-472q33 0 56.5-23.5T560-632q0-33-23.5-56.5T480-712q-33 0-56.5 23.5T400-632q0 33 23.5 56.5T480-552Z"
></path>
</svg>
<div>
<span>Delivery address</span>
<strong>14 Market Street, San Francisco</strong>
</div>
</div>
<footer class="shipping-footer">
<button type="button" class="secondary-action report-button">Report an issue</button>
<button type="button" class="primary-action track-button">Track package</button>
</footer>
</article>
</sv-flyout>
</div>
<script>
const flyout = document.querySelector(".shipping-flyout");
const reportButton = document.querySelector(".report-button");
const trackButton = document.querySelector(".track-button");
reportButton.addEventListener("click", () => {
flyout.close();
});
trackButton.addEventListener("click", () => {
flyout.close();
});
</script>
<style>
74 collapsed lines
.flyout-container {
display: flex;
flex-direction: column;
gap: 0.5em;
max-inline-size: 380px;
margin: auto;
.label {
font-size: 0.875rem;
font-weight: 600;
color: var(--sv-gray-2);
}
.trigger {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 0.75em;
align-items: center;
inline-size: 100%;
padding: 0.75em;
font-family: inherit;
color: var(--sv-gray-1);
text-align: start;
cursor: pointer;
background-color: var(--sv-gray-7);
border: solid var(--sv-bdr-sz-sm) var(--sv-gray-5);
border-radius: var(--sv-bdr-rad-lg);
transition:
border-color 200ms ease,
background-color 200ms ease;
.trigger-icon {
display: grid;
place-items: center;
inline-size: 2.5em;
block-size: 2.5em;
font-size: 1.1rem;
background-color: var(--sv-gray-6);
border-radius: var(--sv-bdr-rad-md);
}
.trigger-content {
display: flex;
flex-direction: column;
gap: 0.2em;
min-inline-size: 0;
strong {
font-size: 0.95rem;
}
span {
overflow: hidden;
text-overflow: ellipsis;
font-size: 0.8rem;
color: var(--sv-gray-3);
white-space: nowrap;
}
}
.trigger-arrow {
inline-size: 1.25em;
block-size: 1.25em;
fill: currentcolor;
transition: rotate 200ms ease;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: var(--sv-gray-6);
}
}
}
.shipping-flyout {
&::part(content) {
/* Match the flyout’s inline size to the anchor (trigger). */
inline-size: var(--sv-anchor-width);
/*
Prevent the flyout from shrinking below this size.
If a placement cannot satisfy it, try the next fallback.
*/
min-block-size: 200px;
/* Limit the flyout to the block space available for the current placement. */
max-block-size: var(--sv-anchor-available-height);
background-color: var(--sv-gray-7);
}
&:state(--open) {
.trigger {
border-color: var(--sv-accent);
.trigger-arrow {
rotate: 90deg;
}
}
}
}
182 collapsed lines
.shipping-card {
inline-size: min(360px, calc(100vw - 2rem));
padding: 1em;
color: var(--sv-gray-1);
.shipping-header {
display: flex;
gap: 1em;
align-items: flex-start;
justify-content: space-between;
.eyebrow {
font-size: 0.75rem;
font-weight: 700;
color: var(--sv-accent);
text-transform: uppercase;
letter-spacing: 0.08em;
}
h2 {
margin: 0.25em 0 0;
font-size: 1.1rem;
}
}
.tracking-code {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75em;
margin-block: 1em;
background-color: var(--sv-gray-6);
border-radius: var(--sv-bdr-rad-md);
span {
font-size: 0.8rem;
color: var(--sv-gray-3);
}
strong {
font-family: monospace;
font-size: 0.85rem;
letter-spacing: 0.04em;
}
}
.timeline {
display: flex;
flex-direction: column;
gap: 0;
padding: 0;
margin: 0;
list-style: none;
}
.timeline-item {
position: relative;
display: grid;
grid-template-columns: 1em 1fr;
gap: 0.75em;
min-block-size: 3.5em;
&::after {
position: absolute;
inset-block: 1em 0;
inset-inline-start: 0.3em;
inline-size: 2px;
content: "";
background-color: var(--sv-gray-5);
}
&:last-child::after {
display: none;
}
.timeline-marker {
position: relative;
z-index: 1;
inline-size: 0.8em;
block-size: 0.8em;
margin-block-start: 0.15em;
background-color: var(--sv-gray-5);
border: 2px solid var(--sv-gray-7);
border-radius: 50%;
box-shadow: 0 0 0 2px var(--sv-gray-5);
}
div {
display: flex;
flex-direction: column;
gap: 0.2em;
}
strong {
font-size: 0.875rem;
}
span {
font-size: 0.75rem;
color: var(--sv-gray-3);
}
&.complete {
&::after {
background-color: var(--sv-accent);
}
.timeline-marker {
background-color: var(--sv-accent);
box-shadow: 0 0 0 2px var(--sv-accent);
}
}
&.current {
.timeline-marker {
background-color: var(--sv-accent);
box-shadow:
0 0 0 2px var(--sv-accent),
0 0 0 6px color-mix(in srgb, var(--sv-accent) 20%, transparent);
}
strong {
color: var(--sv-accent);
}
}
}
.destination {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.75em;
align-items: center;
padding: 0.75em;
margin-block-start: 0.5em;
background-color: var(--sv-gray-6);
border-radius: var(--sv-bdr-rad-md);
svg {
inline-size: 1.5em;
block-size: 1.5em;
fill: var(--sv-accent);
}
div {
display: flex;
flex-direction: column;
gap: 0.2em;
}
span {
font-size: 0.75rem;
color: var(--sv-gray-3);
}
}
.shipping-footer {
display: flex;
gap: 0.5em;
justify-content: flex-end;
margin-block-start: 1em;
button {
padding: 0.6em 0.8em;
font-family: inherit;
font-weight: 600;
cursor: pointer;
border-radius: var(--sv-bdr-rad-md);
}
.secondary-action {
color: var(--sv-gray-2);
background-color: transparent;
border: solid var(--sv-bdr-sz-sm) var(--sv-gray-5);
}
.primary-action {
color: var(--sv-accent-content);
background-color: var(--sv-accent);
border: solid var(--sv-bdr-sz-sm) var(--sv-accent);
}
}
}
}
</style>