Menu
Actions behind a button, in groups, moved through by the keys and typed to.
Nothing chosen yet
forSlots(MenuSlots)(Recipes.Menu({}))
Usage
The function that drew the preview, over the theme module Create a theme writes. The preview passes it the style picked above instead of its default.
export const MenuStyle = forSlots(MenuSlots)(Recipes.Menu({}))
export const Action = Schema.Literals(['Rename', 'Duplicate', 'Move', 'Delete'])
export type Action = typeof Action.Type
// Annotated: the inferred type names a foldkit internal module.
export const ActionMenu: ReturnType<typeof MenuView.create<Action>> = MenuView.create<Action>()
/** The open menu is the component's; the action chosen is the Model's. */
export interface MenuState {
readonly menu: UiMenu.Model
readonly action: Option.Option<Action>
}
export const menu = <Message>(
style: NamedStyle<typeof MenuSlots>,
state: MenuState,
toMessage: (message: UiMenu.Message) => Message,
h: HtmlBuilder<Message>,
): Html =>
h.div(
[h.Style({ display: 'grid', gap: '0.75rem', justifyItems: 'start' })],
[
h.submodel({
slotId: state.menu.id,
model: state.menu,
view: ActionMenu.view,
viewInputs: {
anchor: { placement: 'bottom-start', gap: 4, padding: 8, portal: false },
items: Action.literals,
itemToConfig: (action: Action) => ({ content: h.span([], [action]) }),
isItemDisabled: (action: Action) => action === 'Move',
buttonContent: h.span([], ['Page actions']),
toView: Menu.toView([style.mixin, ...Menu.fluid], { h }),
},
toParentMessage: toMessage,
}),
h.p(
[],
[
Option.match(state.action, {
onNone: () => 'Nothing chosen yet',
onSome: a => `Chose ${a}`,
}),
],
),
],
)