Current section
Files
Jump to
Current section
Files
src/gbr/ui/admin/input/checkbox.gleam
////
//// ✅ Gleam UI input type checkbox super element.
////
import gleam/option.{type Option, Some}
import lustre/attribute as a
import lustre/element.{type Element}
import lustre/element/html
import gbr/ui/input
import gbr/ui/typo
import gbr/ui/svg
import gbr/ui/svg/form as svg_form
type Checkbox =
UICheckbox
type Render(a) =
UICheckboxRender(a)
type Input =
input.UIInput
type InputRender(a) =
input.UIInputRender(a)
type Text =
typo.UITypo
/// Checkbox super element.
///
pub opaque type UICheckbox {
UICheckbox(el: Input, checked: Bool)
}
/// Checkbox render type.
///
pub type UICheckboxRender(a) {
UICheckboxRender(in: InputRender(a), checked: Bool)
}
/// New checkbox super element.
///
pub fn new(id: String) -> Checkbox {
UICheckbox(el: input.checkbox(id), checked: False)
}
/// Set checkbox checked or not.
///
pub fn checked(in: Checkbox, checked: Bool) -> Checkbox {
UICheckbox(..in, checked:)
}
/// Set checkbox label.
///
pub fn label(in: Checkbox, label: Text) -> Checkbox {
let el =
typo.class(label, class_label)
|> input.label(in.el, _)
UICheckbox(..in, el:)
}
/// New checkbox render.
///
pub fn at(in: Checkbox) -> Render(a) {
let checked = in.checked
let in = input.at(in.el, [], [])
UICheckboxRender(in:, checked:)
}
/// Set checkbox render onclick event.
///
pub fn on_click_opt(at: Render(a), onclick: Option(a)) -> Render(a) {
let in = input.on_click_opt(at.in, onclick)
UICheckboxRender(..at, in:)
}
pub fn on_click(in: Render(a), onclick: a) -> Render(a) {
on_click_opt(in, Some(onclick))
}
/// Render checkbox super element to `lustre/element.{type Element}`.
///
pub fn render(at: Render(a)) -> Element(a) {
let UICheckboxRender(in:, checked:) = at
html.div([a.class("relative")], [
input.render(in),
decorator(checked),
])
}
// PRIVATE
//
const class_label = "flex items-center text-sm font-normal text-gray-700 cursor-pointer select-none dark:text-gray-400"
const class_decorator = "mr-3 flex h-5 w-5 items-center justify-center rounded-md border-[1.25px]"
fn decorator(checked) {
let class_checked = case checked {
True -> " border-brand-500 bg-brand-500"
False -> " bg-transparent border-gray-300 dark:border-gray-700"
}
let class_span = case checked {
False -> "opacity-0"
_ -> ""
}
html.div([a.class(class_decorator <> class_checked)], [
html.span([a.class(class_span)], [
svg.new(14, 14)
|> svg_form.checkbox()
|> svg.render(),
]),
])
}