Listbox
One value from a list that opens under its button.
forSlots(ListboxSlots)(Recipes.Listbox({}))
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 ListboxStyle = forSlots(ListboxSlots)(Recipes.Listbox({}))
export const Frequency = Schema.Literals(['Hourly', 'Daily', 'Weekly', 'Monthly'])
export type Frequency = typeof Frequency.Type
export const FrequencyBox: ReturnType<typeof ListboxView.create<Frequency>> =
ListboxView.create<Frequency>()
/** The open list and its highlight are the component's; the choice is the Model's. */
export interface ListboxState {
readonly listbox: UiListbox.Model
readonly frequency: Option.Option<Frequency>
}
export const listbox = <Message>(
style: NamedStyle<typeof ListboxSlots>,
state: ListboxState,
toMessage: (message: UiListbox.Message) => Message,
h: HtmlBuilder<Message>,
): Html =>
h.submodel({
slotId: state.listbox.id,
model: state.listbox,
view: FrequencyBox.view,
viewInputs: {
anchor: { placement: 'bottom-start', gap: 4, padding: 8, portal: false },
items: Frequency.literals,
maybeSelectedValue: state.frequency,
itemToConfig: (frequency: Frequency) => ({ content: h.span([], [frequency]) }),
buttonContent: h.span([], [Option.getOrElse(state.frequency, () => 'Back up…')]),
toView: Listbox.toView([style.mixin, ...Listbox.fluid], { h }),
},
toParentMessage: toMessage,
})