Skyline_popover_v2SourceA Skyline-styled anchored popover. Popovers are stateful components that can be opened and closed.
This component provides positioning controls (position and alignment), focus management on open (focus_on_show), autoclose behavior on outside click/right-click (close_on_click_outside) and on Escape (always enabled), and sizing options (width via Content/Fixed/Max). Two APIs are available: component wraps content in a Skyline card surface, while component' leaves content unwrapped so it can appear to "float".
Common use cases include contextual menus, dropdowns, pickers, small inline forms, and detail popovers that should not disturb surrounding layout.
Layout behavior
This is an overlay element that sizes to its contents and renders in the browser top layer.
Example
Skyline_popover_v2.component
(fun ~hide:_ (Bonsai.local_ _graph) ->
Bonsai.return
%{%html|
<div style="text-align: center">
<h1>Hello world!</h1>
<p>Some interactive content here.</p>
</div>
|})
graphval attr :
?position:Position.t ->
?alignment:Alignment.t ->
?match_anchor_side_length:Match_anchor_side.t ->
?focus_on_show:bool ->
controller:Controller.t ->
Bonsai_web.Vdom.Node.t ->
Bonsai_web.Vdom.Attr.tattr is the stateless core of this module: it builds the popover anchor attr from a controller and plain values, with no graph involved, so it can be called from view code (e.g. inside a let%arr, or from a Skyline_field_v2.Content.t producer). Attach the result to the popover's anchor element. The popover is shown whenever Controller.is_open is true (when false, attr returns Vdom.Attr.empty).
The final argument is the popover contents. Unlike component, the contents are not wrapped in a Skyline_card_v2.view; since they are plain vdom, callers can wrap them in a card themselves (this matches component''s behavior).
Tradeoffs vs. component / component':
on_activate / on_deactivate lifecycle hooks; any state must be created by the caller at graph time and rendered into the contents. The contents are also computed even while the popover is closed, unless the caller branches on Controller.is_open themselves.Optional arguments have the same meaning and defaults as on component.
type t = private {anchor : Bonsai_web.Vdom.Attr.t;is_open : bool;set_is_open : bool -> unit Bonsai_web.Effect.t;}t is the runtime handle for a popover returned by component or component'.
anchor An attribute to attach to the popover's anchor element. When attached, the popover content (rendered in the browser top layer) is positioned relative to that element and outside-click handling is enabled according to the component's configuration.is_open Whether the popover is currently shown. This reflects the state supplied via ?state or the internally managed state.set_is_open Effect to open/close the popover. Typical usage is to call set_is_open true from the anchor's on-click handler, and set_is_open false from a dismiss control in the content or in response to outside clicks.val component :
?position:Position.t Bonsai_web.Bonsai.t ->
?alignment:Alignment.t Bonsai_web.Bonsai.t ->
?match_anchor_side_length:Match_anchor_side.t Bonsai_web.Bonsai.t ->
?focus_on_show:bool Bonsai_web.Bonsai.t ->
?close_on_click_outside:bool Bonsai_web.Bonsai.t ->
?state:
(bool Bonsai_web.Bonsai.t
* (bool -> unit Bonsai_web.Effect.t) Bonsai_web.Bonsai.t) ->
(hide:unit Bonsai_web.Effect.t Bonsai_web.Bonsai.t ->
Bonsai_web.Bonsai.graph @ local ->
Bonsai_web.Vdom.Node.t Bonsai_web.Bonsai.t) ->
Bonsai_web.Bonsai.graph @ local ->
t Bonsai_web.Bonsai.tA Skyline-styled popover that wraps your contents in a Skyline_card_v2.view. Attach the returned t.anchor to your anchor element; when t.is_open is true, the content is shown in the browser top layer and positioned relative to that anchor.
Content:
contents A function that produces the popover body. It receives ~hide, an effect you can call to close the popover (equivalent to set_is_open false), and graph. The content is rendered in the browser top layer and is not a DOM-child of the anchor.State:
?state Supply external state (is_open, set_is_open) if you want to control visibility from the outside. If omitted, an internal state is created with initial value false (closed): Bonsai.state false.Arguments and defaults:
?position Preferred side of the anchor where the popover should appear. Auto chooses the side with the most available space; Top, Bottom, Left, Right prefer that side and will fall back when necessary. Default: Position.Auto.?alignment How the popover aligns with the anchor along the cross axis. Default: Alignment.Center.?focus_on_show Whether focus should move into the popover when it opens. Default: true.?match_anchor_side_length How to size the popover relative to the anchor. Default: None.?close_on_click_outside Close the popover when the user clicks (or right-clicks) outside the popover. Default: true. The Escape key always closes the popover.Returns: a t Bonsai.t containing anchor, is_open, and set_is_open.
Notes:
anchor attribute does not itself toggle visibility. Open/close the popover by driving is_open/set_is_open, or use ~hide from within contents.component and component' are compositions of the lower-level Controller.component and attr APIs, plus gating the contents' activity on the popover being open (which is what makes on_activate / on_deactivate lifecycle hooks inside contents work).val component' :
?position:Position.t Bonsai_web.Bonsai.t ->
?alignment:Alignment.t Bonsai_web.Bonsai.t ->
?match_anchor_side_length:Match_anchor_side.t Bonsai_web.Bonsai.t ->
?focus_on_show:bool Bonsai_web.Bonsai.t ->
?close_on_click_outside:bool Bonsai_web.Bonsai.t ->
?state:
(bool Bonsai_web.Bonsai.t
* (bool -> unit Bonsai_web.Effect.t) Bonsai_web.Bonsai.t) ->
(hide:unit Bonsai_web.Effect.t Bonsai_web.Bonsai.t ->
Bonsai_web.Bonsai.graph @ local ->
Bonsai_web.Vdom.Node.t Bonsai_web.Bonsai.t) ->
Bonsai_web.Bonsai.graph @ local ->
t Bonsai_web.Bonsai.tLike component, but does not wrap contents in a card. This lets you render content with no surface (so it appears to "float"). For the meaning, defaults, and interaction of all parameters (position, alignment, focus_on_show, close_on_click_outside, width, state, contents), see the documentation on component.