Studio
2

Notch

Installation

pnpm dlx @mielui/svelte add notch

Usage

The theme setting chrome.borders chooses "single" or "double" framing. Double is the default. Single removes the extra frame while preserving content padding, composition, and inset variants.

Bind open on Root. Content holds arbitrary children, stays centered on the chosen viewport edge, and animates as its content changes size. Header, Title, Description, Actions, Close, SideAction, and Accessory are optional. Close, swipe dismissal, and the automatic timer update the same open binding.

import * as Notch from '$lib/mielui/components/notch';

<Notch.Root bind:open side="top">
    <Notch.Content aria-label="Sync status">
        <Notch.Header>
            <Notch.Title>Everything is synced</Notch.Title>
            <Notch.Description>Your files are available on every device.</Notch.Description>
        </Notch.Header>
    </Notch.Content>
</Notch.Root>

Keep Root mounted during dismissal so Content can finish its exit. Use a width class on Content to change the panel width. Content keeps long panels within the viewport and scrolls their contents. The native manual popover places the panel above clipping ancestors while preserving inherited theme variables.

Triggered and peek modes

Triggered mode starts hidden. Set open to true to reveal it. It dismisses after five seconds; hover and keyboard focus pause the countdown. Set duration to 0 to keep it open until your application closes it.

Swipe toward the attached edge or press Escape while focus is inside to dismiss it. On touch screens, start the swipe on Header so the body can still scroll. Add Close when the panel needs a visible dismiss button. Reversing a swipe before release keeps the panel open.

Peek mode keeps a slim handle at the edge. Hover, focus, or tap the handle to expand it. It collapses after the pointer leaves and focus is outside. Place Notch.Peek beside Content to replace the handle's contents with a short, noninteractive indicator.

Examples

Detached controls

Place SideAction beside Content inside Root. For top and bottom notches, start and end mean left and right. For left and right notches, they mean above and below. SideAction accepts Button props and children; label icon-only actions.

The action rests as an arc beside the attached edge. Hover the panel, focus the action, or tap the panel to unfold the button. In this example, the button expands a file list and the panel resizes to fit.

Glass surface

Pass surface="glass" explicitly, or omit surface to follow the global glass setting from Studio. surface="solid" keeps this panel opaque.

Outside content

Place Notch.Accessory beside Content inside Root for a counter, hint, or custom controls. It floats below a top notch, above a bottom notch, or toward the page for a side notch. The export example uses it for a file count.

Accessory accepts normal div attributes and children. Hovering or focusing it pauses dismissal. Closing the notch hides the accessory too.

Focus and motion

Notch is nonmodal. Opening it does not move focus, lock scrolling, or make the page inert. Its controls remain keyboard accessible. Escape closes it when focus is inside. Use Dialog for a decision that must interrupt the current task.

Title defaults to h2; set level to match the surrounding outline. Content does not announce every update automatically. Put a role="status" message inside when an update needs a polite announcement, and keep interactive controls outside that message.

Entry, exit, and size changes use spring motion. Reduced motion and the theme's zero-duration motion preset settle the panel immediately. An interrupted exit reverses when open becomes true again.

Choose the right announcement

Use Accessory for a compact count or hint outside the panel, and Content for the task itself. Avoid repeating the same live announcement in both regions. These examples run in isolated viewports so their edge placement stays inside the preview.

API reference

Notch.Root

Prop Type Default
open Bindable boolean | undefined false
mode "triggered" | "peek" | undefined 'triggered'
duration number | undefined 5000
side "left" | "right" | "top" | "bottom" | undefined 'top'
surface "solid" | "glass" | undefined —
children Snippet<[]> | undefined —

Notch.Accessory

Notch.Actions

Notch.Close

Notch.Content

Notch.Description

Notch.Header

Notch.Peek

Prop Type Default
children Snippet<[]> | undefined —

Notch.SideAction

Prop Type Default
disabled boolean | undefined —
variant ButtonVariant | undefined 'panel'
size "sm" | "md" | "lg" | "icon" | undefined 'icon'
children Snippet<[]> | undefined —
element Bindable HTMLButtonElement | HTMLAnchorElement | undefined

Bindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site:

—
unstyled boolean | undefined

Skip the variant/size base classes and render with `class` alone.

—
status ButtonStatus | undefined

Controlled visual state. Loading remains focusable and refuses activation.

—
loading boolean | undefined

Convenience alias for `status="loading"`.

—
loadingLabel string | undefined —
successLabel string | undefined —
errorLabel string | undefined —
onclick ((event: MouseEvent) => void) | undefined —
onkeydown ((event: KeyboardEvent) => void) | undefined —
href string | undefined —
side "start" | "end" | undefined 'end'

Notch.Title

Prop Type Default
level HeadingLevel | undefined 2