Menu bar & Dock
The menu bar displays the top-level menus of your app. The dock holds app icons for launching and switching. Together they frame an app-like layout; both are chrome, not content.
Preview
Move the pointer along the dock to magnify. Click an icon for the launch bounce. Click a menu bar item, then slide across its neighbors.
Anatomy: menu bar
The bar is 37px tall and fully transparent; the text sits on whatever is behind it. Items are 13px at weight 590 (the app name is heavy, weight 860, and the Apple slot is 16.3px) inside 25px capsule slots with a 12.5px radius and 13px side padding. Status items align right at a 38px minimum width, ending with the clock.
Because pages rarely have a wallpaper, two helpers set the ink explicitly: .p-menubar-on-dark for white text over dark imagery and .p-menubar-on-light for black text over light imagery. Without them the bar follows the page theme. Add .p-menubar-material for a translucent glass backing when the backdrop is busy; over variable imagery the material is the accessible choice, since bare text can drop below 4.5:1 contrast.
| Class | Role |
|---|---|
.p-menubar | The 37px transparent bar. |
.p-menubar-item | Capsule slot, 25px tall, radius 12.5px. |
.p-menubar-app / .p-menubar-apple | Heavy (860) app name / 16.3px Apple slot. |
.p-menubar-status | Right-aligned status group with the clock. |
.p-menubar-material | Optional glass backing. |
Behavior: menu bar
Items highlight only while their menu is open, never on plain hover. The open capsule fills rgba(0, 0, 0, 0.08) on light backdrops and rgba(255, 255, 255, 0.08) on dark ones, and blurs what is behind it by 30px so the label stays legible over busy imagery. With reduced transparency the blur is dropped and only the fill remains.
Menus are ordinary menu surfaces: point each item at one with data-p-menu="#id" and include menus.js. Adding menubar.js turns the bar into a session: while one menu is open, hovering another item switches to it, and Left and Right arrows walk the bar. Escape or an outside click ends the session.
Anatomy: dock
The platter is 55px tall with a 15px radius: 8px above the icons, 11px below, and 8px at each end. Its glass fill darkens the wallpaper slightly in light mode (rgba(0, 0, 0, 0.17) over a 20px blur) and lifts it slightly in dark (rgba(255, 255, 255, 0.07)), without a saturation boost so the wallpaper keeps its own color. The edge is a 0.5px dark outline, a strong 1px bright rim along the top and bottom with a soft glow that fades over about 12px, and no rim on the sides. There is no drop shadow. Icons are 36px in 9px gaps. The separator is a 1×36px light line (35% white) with 14px of clear space on each side. Running apps show a 4px dot 3px above the platter’s bottom edge. Pinned with .p-dock-fixed, the platter sits 4px above the bottom of the viewport.
| Class | Role |
|---|---|
.p-dock | The platter. 55px tall, bottom-aligned flex, radius 15px. |
.p-dock-fixed | Pins the platter 4px above the bottom center of the viewport. |
.p-dock-item | 36px icon button. |
.p-running | Adds the indicator dot. |
.p-dock-separator | 1×36px light divider with 14px clear space on each side. |
data-p-dock-magnify | Opts the platter into magnification. |
Behavior: dock
Magnification is off by default, matching the system. With data-p-dock-magnify and dock.js, icons scale with a parabolic falloff of the distance to the pointer: 36px at rest, 72px under the cursor, fading over one zoomed-icon width. Growth is real box size, so icons repaint sharp at every step, neighbors get pushed apart, and the platter stretches, all of it rising from the platter baseline. Entering the dock ramps the effect in over 150ms and leaving ramps it out, so nothing snaps. Give icon images sources of at least 144px so they stay sharp at full magnification.
Clicking an icon plays the launch bounce: two decaying hops (22px, then 10px) over 0.9s. With prefers-reduced-motion, both magnification and bounce are disabled and icons stay at 36px.
Dark mode
The menu bar stays transparent and flips its ink to white; the material backing becomes rgba(40, 40, 44, 0.72). The dock platter uses the dark fill above with a darker 80% outline and a softer rim, the separator stays a light line at 30% white, and the indicator dot brightens to rgba(255, 255, 255, 0.65). Both .p-dark-mode and .p-auto-dark-mode are supported.
Code
<div class="p-menubar p-menubar-material">
<button class="p-menubar-item p-menubar-apple" data-p-menu="#apple-menu"
aria-expanded="false" aria-haspopup="menu"></button>
<button class="p-menubar-item p-menubar-app" data-p-menu="#app-menu"
aria-expanded="false" aria-haspopup="menu">Mail</button>
<button class="p-menubar-item" data-p-menu="#file-menu"
aria-expanded="false" aria-haspopup="menu">File</button>
<div class="p-menubar-status">
<span class="p-menubar-item p-menubar-clock">Mon Jun 10 9:41 AM</span>
</div>
</div>
<div class="p-dock p-dock-fixed" data-p-dock-magnify>
<button class="p-dock-item p-running" aria-label="Open Mail" data-p-tooltip="Mail">
<img src="mail.png" alt="" />
</button>
<div class="p-dock-separator" role="separator"></div>
<button class="p-dock-item" aria-label="Open Trash"><img src="trash.png" alt="" /></button>
</div>
Dock items are buttons; give each an aria-label since the icon is the only content. With dock.js present, hovering an item shows its app-name label automatically from that same aria-label: a 24px dark capsule with a pointer tail, 13px white text, floating 19px above the fully magnified icon. The label is dark in both appearance modes, matching the system, and it is not a tooltip: it appears with no delay and rides the magnified icon.