Popover
Non-modal floating surface on the native Popover API — any trigger plus panel, anchored with side/align/offset and viewport flipping.
INSTALL
1pnpm dlx @sayagodev/mo add popoverOr import the files from the package (no copy):
1import "@sayagodev/mo/css/popover.css";EXAMPLES
Basic
Dimensions
Set the dimensions for the layer.
1<button type="button" class="outline" popovertarget="ex-pop-basic">Open popover</button>2 3<div popover id="ex-pop-basic" class="popover" data-align="start">4 <div class="vstack gap-1">5 <div data-title>Dimensions</div>6 <p data-description>Set the dimensions for the layer.</p>7 </div>8</div>
Grid form
Dimensions
Set the dimensions for the layer.
1<button type="button" class="outline" popovertarget="ex-popover">Open popover</button>2 3<div popover id="ex-popover" class="popover">4 <div class="vstack gap-4">5 <div class="vstack gap-1">6 <div data-title>Dimensions</div>7 <p data-description>Set the dimensions for the layer.</p>8 </div>9 <div class="vstack gap-2">10 <div class="row gap-2 items-center">11 <label class="col-4" for="ex-pop-width">Width</label>12 <input id="ex-pop-width" class="col-8" value="100%" />13 </div>14 <div class="row gap-2 items-center">15 <label class="col-4" for="ex-pop-max-width">Max. width</label>16 <input id="ex-pop-max-width" class="col-8" value="300px" />17 </div>18 <div class="row gap-2 items-center">19 <label class="col-4" for="ex-pop-height">Height</label>20 <input id="ex-pop-height" class="col-8" value="25px" />21 </div>22 <div class="row gap-2 items-center">23 <label class="col-4" for="ex-pop-max-height">Max. height</label>24 <input id="ex-pop-max-height" class="col-8" value="none" />25 </div>26 </div>27 </div>28</div>29
Alignments
Aligned to start
Aligned to center
Aligned to end
1<div class="hstack">2 <button type="button" class="outline" popovertarget="ex-pop-start">Start</button>3 <button type="button" class="outline" popovertarget="ex-pop-center">Center</button>4 <button type="button" class="outline" popovertarget="ex-pop-end">End</button>5</div>6 7<!-- Alignment is manual by author: size/position each surface with your own8 CSS (e.g. anchor positioning or top/left overrides). -->9<div popover id="ex-pop-start" class="popover" data-align="start">Aligned to start</div>10<div popover id="ex-pop-center" class="popover" data-align="center">Aligned to center</div>11<div popover id="ex-pop-end" class="popover" data-align="end">Aligned to end</div>12
With form
Dimensions
Set the dimensions for the layer.
1<button type="button" class="outline" popovertarget="ex-pop-form">Open popover</button>2 3<div popover id="ex-pop-form" class="popover" style="inline-size: 16rem">4 <div class="vstack gap-4">5 <div class="vstack gap-1">6 <div data-title>Dimensions</div>7 <p data-description>Set the dimensions for the layer.</p>8 </div>9 <label class="vstack gap-2" for="ex-pop-form-width">10 Width11 <input id="ex-pop-form-width" value="100%" />12 </label>13 <label class="vstack gap-2" for="ex-pop-form-height">14 Height15 <input id="ex-pop-form-height" value="25px" />16 </label>17 <button type="button" class="small">Update</button>18 </div>19</div>20
USAGE
1<button popovertarget="p1">Open popover</button>2 3<div popover id="p1" class="popover" data-side="bottom" data-align="center">4 <div data-title>Dimensions</div>5 <p data-description>Set the dimensions for the layer.</p>6</div>7 8<!-- placement: data-side="top|right|bottom|left" (default bottom),9 data-align="start|center|end" (default center), data-offset (default 4) -->
API
NAMEKINDDESCRIPTION
.popoverclassSurface: w-72, bg-popover, p-4, shadow-md, enter transition
popovertargetattributeDeclarative trigger; the popover anchors to its invoker automatically
data-sideattributebottom (default) · top · right · left; flips on viewport overflow
data-alignattributecenter (default) · start · end
data-offsetattributeGap from the trigger, default 4 (Radix sideOffset)
[data-title] / [data-description]attributeHeader anatomy
--mo-popover-width / --mo-popover-radiustokenWidth and radius hooks
FILES
src/css/popover.cssInstall:
mo add popoverTHEMING · PLAYGROUND
This is the exact component from the examples above, wearing a completely different theme. Edit the tokens and --mo-* hooks in the editor — autocomplete knows them all — and the preview obeys in real time. Your CSS always wins.
Global tokens
--foreground--muted-foreground--popover--popover-foreground--radiusComponent hooks
--mo-popover-radius--mo-popover-widthPreview
Your CSS
Try it: type --mo- for the component hooks, or edit any value — the preview obeys in real time.