Documentation
API guide forinlet
Installation
npm install inlet-ui
Works with Electron 28+ and React 18+. A prebuilt universal helper reads the exact notch size and plays haptics, so there is nothing to compile.
Setup
API
<Notch />
| Name | Type | Default | Description |
|---|---|---|---|
| trigger | 'hover' | 'click' | 'press' | 'manual' | 'hover' | How the notch expands. 'press' is a long press. |
| openDelay | number | 120 | Milliseconds the pointer rests on the notch before it opens. |
| pressDuration | number | 450 | Milliseconds to hold for trigger='press'. |
| swipeToDismiss | boolean | true | Flick up (trackpad or drag) to send it back in. |
| open / defaultOpen | boolean | — | Controlled or uncontrolled open state. |
| onOpenChange | (open, { reason }) => void | — | reason is 'hover', 'click', 'press', 'keyboard', 'swipe', 'outside', 'escape', 'blur' or 'api'. |
| collapseDelay | number | 150 | Milliseconds after the pointer leaves. |
| notchSize | { width, height } | measured | Measured from the display in Electron; 185 × 32 in a browser. |
| menuBar | 'avoid' | 'overlay' | 'avoid' | avoid drops a compact side that would cover a menu bar item. On the web, data-notch-menu-item elements count. |
| background | string | '#000' | Any CSS background: a colour or a gradient. The camera band stays black, like the hardware. |
| accent | string | '#fff' | Peek icons, the loading spinner and the keyboard focus ring. |
| onDrop / dropLabel | (drop: NotchDrop) => void / string | — / 'Drop here' | Take drops when no activity does. |
| label | string | 'Notch' | Screen reader name for the notch's keyboard handle. Defaults to the activity's label. |
| split | boolean | false | Show a second activity in a bubble beside the notch. Click it to swap; swipe sideways to cycle. |
| className / style | — | Applied to the full-window stage. |
<NotchActivity />
| Name | Type | Default | Description |
|---|---|---|---|
| leading / trailing | ReactNode | — | Beside the camera. About 20px tall. |
| expanded | ReactNode | — | Shown when the notch opens. |
| priority | number | 0 | Higher wins. Ties go to the most recently mounted. |
| width / height | number | fit content | Expanded size in px. Height includes the camera row. |
| radius | number | 26 | Bottom corner radius when expanded. |
| onDrop | (drop: NotchDrop) => void | — | Accept files, links and text dragged onto the notch. NotchDrop has files, paths (Electron), urls and text. |
| dropLabel | string | 'Drop here' | What the drop target says while something is over it. |
| label | string | — | A name for screen readers, like "Now Playing". |
| id | string | useId() | Stable identity if you render it from different places. |
notch
| Name | Type | Default | Description |
|---|---|---|---|
| notch.peek(content, options?) | => id | 2600 ms | A string or any element. Options: type, description, icon, duration, id, action, reply, level. |
| action | { label, onClick } | 5000 ms | A button in the peek, like Undo. Clicking it runs onClick and closes the peek. |
| reply | { placeholder?, onSend } | 8000 ms | A text field. Enter calls onSend(text) and closes the peek. |
| level | number | — | A bar from 0 to 1. Peek again with the same id and it moves in place. |
| notch.peek.promise(promise, messages) | => Promise | — | { loading, success, error }. success and error can be functions. |
| notch.dismiss(id?) | void | — | Hide the current peek. |
| notch.expand({ duration? }) | void | — | Open; with duration, close again after it unless hovered. |
| notch.collapse() / toggle() | void | — | Change state from anywhere. |
| notch.show(id) / notch.cycle(dir?) | void | — | Put an activity first, or move to the next (1) or previous (-1). |
<NotchAvoid /> and useNotchFrame()
| Name | Type | Default | Description |
|---|---|---|---|
| <NotchAvoid gap? boundary?> | component | gap 12, window | Slides its children out of the notch; fades them if that would push them past the boundary. |
| useNotchFrame() | => NotchFrame | null | — | The notch's target rect in viewport coordinates. |
useNotch()
| Name | Type | Default | Description |
|---|---|---|---|
| presentation | 'rest' | 'compact' | 'peek' | 'expanded' | 'drop' | 'rest' | The current state. 'drop' while something is dragged over it. |
| activity | string | undefined | — | The id of the activity being shown. |
| open / hovering | boolean | false | Whether the notch is expanded, and whether the pointer is over it. |
| expand, collapse, toggle, peek, dismiss | — | The same functions as notch. |
createNotch(options) · main process
| Name | Type | Default | Description |
|---|---|---|---|
| entry | string | — | Dev server URL, or an absolute path to the HTML that renders <Notch>. |
| display | 'automatic' | 'primary' | Display | 'automatic' | The built-in notched display first. |
| canvas | { width, height } | 760 × 380 | The transparent window the notch can grow into. |
| preload | string | bundled | Your own preload. It must import 'inlet-ui/preload'. |
| haptics | boolean | true | A trackpad tick when the pointer opens the notch, through the native helper. Opening from code stays silent. |
| requestMenuBarAccess() | => boolean | — | Prompts for Accessibility so app menus are avoided too. |
NotchHandle
| Name | Type | Default | Description |
|---|---|---|---|
| peek(title, options?) | => id | — | Options: type, description, icon (emoji or text), duration, id, action (a label), reply ({ placeholder }), level. |
| expand() / collapse() / toggle() / dismiss() | void | — | Forwarded to the renderer. |
| on(event, listener) | => unsubscribe | — | 'hover', 'presentation', 'expand', 'collapse', 'drop' (paths, urls, text), 'action' (peek id) and 'reply' (peek id, text). |
| window / screen | BrowserWindow / NotchScreenInfo | — | The panel window and the measured housing. |
| destroy() | void | — | Close the window and stop tracking the cursor. |
From the main process
createNotch() returns a handle, so tray menus, background jobs and system events can peek without going through your renderer.
Drag and drop
Give an activity onDrop and dragging files, links or text over the notch opens it into a drop target that says dropLabel. The highest-priority activity that takes drops gets them. With no activity taking drops, onDrop on the notch itself does.
Styling
background fills the notch below the camera band, which stays black like the hardware. accent colours peek icons, the spinner and the keyboard focus ring.
Accessibility
Peeks are announced as they appear: through a live region on the web, and VoiceOver in SwiftUI. Name activities with label. On the web the notch has a keyboard handle: Tab to it, Enter opens it and moves focus inside, Escape closes it and returns focus. In SwiftUI, call expand(focus: true) from a shortcut to give the notch the keyboard; Escape closes it. Reduced motion swaps the springs for ones that don't bounce.
Design tokens
Shape and motion are defined once in design/tokens.json and generated into Swift and TypeScript. The React renderer runs the same spring as SwiftUI's .spring(response:dampingFraction:), so both platforms move the same way, even mid-animation.
{
"spring": {
"open": { "response": 0.38, "dampingFraction": 0.8 },
"close": { "response": 0.3, "dampingFraction": 1.0 }
},
"radius": {
"rest": { "top": 6, "bottom": 10 },
"toast": { "top": 8, "bottom": 18 },
"expanded": { "top": 12, "bottom": 26 }
}
}
How the Electron version works
The notch is a transparent, non-activating panel above the menu bar, on every Space and over full-screen apps. It ignores the mouse until the pointer is over the notch's current shape, so clicking it never takes focus from the app you were using. The housing is measured with NSScreen.auxiliaryTopLeftArea through a small N-API helper.
For agents
Plain-text setup instructions for coding agents live at /llms.txt.