Checkbox

Component

Interactive examples and API documentation

Basic
Basic usage of checkbox.
Code
<%= render Hakumi::Checkbox::Component.new(id: "basic-checkbox-example", label: "Checkbox") %>
Disabled
Disabled checkbox.
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :middle) do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::Checkbox::Component.new(label: "Checkbox (Disabled)", disabled: true) %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Checkbox::Component.new(label: "Checkbox (Checked & Disabled)", checked: true, disabled: true) %>
  <% end %>
<% end %>
Controlled Checkbox
Communicated with other components.
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :middle, id: "checkbox-controlled-demo") do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::Space::Component.new(align: :center, size: :small) do |controls| %>
      <% controls.with_item do %>
        <%= render Hakumi::Typography::Text::Component.new(content: "Toggle the checkbox:") %>
      <% end %>
      <% controls.with_item do %>
        <%= render Hakumi::Button::Component.new(type: :primary, size: :small, id: "controlled-demo-btn") do %>
          Toggle
        <% end %>
      <% end %>
    <% end %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Checkbox::Component.new(
          checked: true,
          label: "Controlled Checkbox",
          id: "controlled-demo-checkbox"
        ) %>
  <% end %>
<% end %>

<script>
  (() => {
    const root = document.getElementById("checkbox-controlled-demo")
    const button = root?.querySelector("#controlled-demo-btn")
    const input = root?.querySelector("#controlled-demo-checkbox")
    if (!root || !button || !input) return

    const wire = () => {
      if (root.dataset.checkboxControlledInitialized === "true") return true

      const wrapper = input.closest(".hakumi-checkbox-wrapper")
      const api = wrapper?.hakumiComponent?.api
      if (!wrapper || !api) return false

      root.dataset.checkboxControlledInitialized = "true"
      button.addEventListener("click", () => {
        api.setChecked(!api.isChecked())
      })
      return true
    }

    if (wire()) return

    const onRegister = () => {
      if (wire()) window.removeEventListener("hakumi-component:registered", onRegister)
    }

    window.addEventListener("hakumi-component:registered", onRegister)
  })()
</script>
Checkbox Group
Generate a group of checkboxes from an array.
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :middle, id: "checkbox-group-demo") do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::Typography::Text::Component.new(content: "Groups keep each checkbox in sync with plain helpers.") %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Checkbox::Group::Component.new(
          name: "group1",
          options: ["Apple", "Pear", "Orange"],
          value: ["Apple"]
        ) %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Checkbox::Group::Component.new(
          name: "group2",
          options: [
            { label: "Apple", value: "Apple" },
            { label: "Pear", value: "Pear" },
            { label: "Orange", value: "Orange", disabled: true }
          ],
          value: ["Pear"]
        ) %>
  <% end %>
<% end %>
Check all
The indeterminate property can help you to achieve a 'check all' effect.
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :middle, id: "checkbox-check-all-demo") do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::Typography::Text::Component.new(content: "Select fruits with a single toggle:") %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Checkbox::Component.new(
          label: "Check all",
          indeterminate: true,
          id: "checkbox-check-all-toggle"
        ) %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Checkbox::Group::Component.new(
          id: "checkbox-check-all-group",
          options: ["Apple", "Pear", "Orange"],
          value: ["Apple", "Orange"]
        ) %>
  <% end %>
<% end %>

<script>
  (() => {
    const group = document.getElementById("checkbox-check-all-group")
    const input = document.getElementById("checkbox-check-all-toggle")
    if (!group || !input) return

    const wrapper = input.closest(".hakumi-checkbox-wrapper")
    if (!wrapper) return

    const wire = () => {
      const groupApi = group.hakumiComponent?.api
      const wrapperApi = wrapper.hakumiComponent?.api
      if (!groupApi || !wrapperApi) return false

      const sync = () => {
        const selected = groupApi.getValue()
        const total = groupApi.getAllValues().length
        wrapperApi.setChecked(selected.length === total)
        wrapperApi.setIndeterminate(selected.length > 0 && selected.length < total)
      }

      input.addEventListener("change", () => {
        input.checked ? groupApi.selectAll() : groupApi.clearAll()
        sync()
      })

      groupApi.onChange(sync)
      sync()
      return true
    }

    if (wire()) return

    const onRegister = () => {
      if (wire()) window.removeEventListener("hakumi-component:registered", onRegister)
    }

    window.addEventListener("hakumi-component:registered", onRegister)
  })()
</script>
Use with Grid
We can use Checkbox and Grid in Checkbox.Group, to implement complex layout.
Code
<%= render Hakumi::Checkbox::Group::Component.new(style: "width: 100%;") do %>
  <%= render Hakumi::Grid::Row::Component.new do %>
    <%= render Hakumi::Grid::Col::Component.new(span: 8) do %>
      <%= render Hakumi::Checkbox::Component.new(value: "A", label: "A") %>
    <% end %>
    <%= render Hakumi::Grid::Col::Component.new(span: 8) do %>
      <%= render Hakumi::Checkbox::Component.new(value: "B", label: "B") %>
    <% end %>
    <%= render Hakumi::Grid::Col::Component.new(span: 8) do %>
      <%= render Hakumi::Checkbox::Component.new(value: "C", label: "C") %>
    <% end %>
    <%= render Hakumi::Grid::Col::Component.new(span: 8) do %>
      <%= render Hakumi::Checkbox::Component.new(value: "D", label: "D") %>
    <% end %>
    <%= render Hakumi::Grid::Col::Component.new(span: 8) do %>
      <%= render Hakumi::Checkbox::Component.new(value: "E", label: "E") %>
    <% end %>
  <% end %>
<% end %>

Checkbox API

Prop Type Default Description
checked Boolean false Specifies whether the checkbox is selected.
disabled Boolean false Disable checkbox.
indeterminate Boolean false The indeterminate checked state of checkbox.
content String or Slot - The content (label).

Checkbox Group API

Prop Type Default Description
options Array[String] or Array[Hash] [] Option list. Strings become labels and values. Hashes support { label:, value:, disabled: } keys.
value Array[String] [] Used for setting the currently selected value.
disabled Boolean false Disable all checkboxes.
name String - The name property of all input[type='checkbox'] children.

Checkbox JavaScript API (element.hakumiCheckbox)

Prop Type Default Description
setChecked(checked) Function - Programmatically check/uncheck the checkbox.
setIndeterminate(indeterminate) Function - Toggle the visual indeterminate state.
isChecked() Function - Returns current checked state (Boolean).
isIndeterminate() Function - Returns current indeterminate state (Boolean).

Checkbox Group JavaScript API (element.hakumiCheckboxGroup)

Prop Type Default Description
getValue() Function - Returns the currently selected values.
getAllValues() Function - Returns all checkbox values rendered inside the group.
setValue(values) Function - Sets the selected values array.
selectAll() Function - Selects every checkbox in the group.
clearAll() Function - Unselects all checkboxes in the group.