Qr Code

Component

Interactive examples and API documentation

Basic
The most basic usage.
Code
<%= render Hakumi::QrCode::Component.new(
  value: "https://hakumi.com"
) %>
With Icon
QRCode with icon overlay.
Code
<%= render Hakumi::QrCode::Component.new(
  value: "https://hakumi.com",
  icon: :scan,
  icon_size: 48
) %>
Status
The status can be controlled by the value status.
Active
Loading
Expired
Scanned
Code
<%= render Hakumi::Space::Component.new(size: :large) do |space| %>
  <% [ :active, :loading, :expired, :scanned ].each do |state| %>
    <% space.with_item do %>
      <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |status_space| %>
        <% status_space.with_item do %>
          <%= render(Hakumi::Typography::Text::Component.new(weight: :strong)) { state.to_s.capitalize } %>
        <% end %>
        <% status_space.with_item do %>
          <%= render Hakumi::QrCode::Component.new(
            value: "https://hakumi.com/#{state}",
            status: state
          ) %>
        <% end %>
      <% end %>
    <% end %>
  <% end %>
<% end %>
Custom Status Render
Customize the rendering logic of the QR code in different states.
Code
<%= render Hakumi::QrCode::Component.new(
  value: "https://hakumi.com/custom-status",
  status: :expired,
  status_render: ->(status) do
    render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |space|
      space.with_item do
        render(Hakumi::Typography::Text::Component.new(weight: :strong)) { "Status: #{status}" }
      end
      space.with_item do
        render(Hakumi::Button::Component.new(type: :primary, size: :small)) { "Refresh" }
      end
    end
  end
) %>
Custom Render Type
Customize rendering by type, providing canvas and svg.
Canvas
SVG
Code
<%= render Hakumi::Space::Component.new(size: :large) do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |type_space| %>
      <% type_space.with_item do %>
        <%= render(Hakumi::Typography::Text::Component.new(weight: :strong)) { "Canvas" } %>
      <% end %>
      <% type_space.with_item do %>
        <%= render Hakumi::QrCode::Component.new(
          value: "https://hakumi.com/canvas",
          type: :canvas
        ) %>
      <% end %>
    <% end %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |type_space| %>
      <% type_space.with_item do %>
        <%= render(Hakumi::Typography::Text::Component.new(weight: :strong)) { "SVG" } %>
      <% end %>
      <% type_space.with_item do %>
        <%= render Hakumi::QrCode::Component.new(
          value: "https://hakumi.com/svg",
          type: :svg
        ) %>
      <% end %>
    <% end %>
  <% end %>
<% end %>
Custom Size
Adjust the size of the QR code.
Resize with JS API
Code
<%= render Hakumi::Space::Component.new(size: :large) do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::QrCode::Component.new(
      value: "https://hakumi.com/size-small",
      size: 120
    ) %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::QrCode::Component.new(
      value: "https://hakumi.com/size-large",
      size: 220
    ) %>
  <% end %>

  <% space.with_item do %>
    <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small, block: true) do |interactive| %>
      <% interactive.with_item do %>
        <%= render Hakumi::Typography::Text::Component.new(strong: true) do %>
          Resize with JS API
        <% end %>
      <% end %>

      <% interactive.with_item do %>
        <%= render Hakumi::QrCode::Component.new(
          id: "qr-code-resize",
          value: "https://hakumi.com/resize",
          size: 160,
          type: :canvas
        ) %>
      <% end %>

      <% interactive.with_item do %>
        <%= render Hakumi::Space::Component.new(size: :small) do |buttons| %>
          <% [ { label: "120px", size: 120 }, { label: "200px", size: 200 }, { label: "260px", size: 260 } ].each do |option| %>
            <% buttons.with_item do %>
              <%= render(Hakumi::Button::Component.new(
                type: :default,
                data: { "qr-resize": option[:size] }
              )) { option[:label] } %>
            <% end %>
          <% end %>
        <% end %>
      <% end %>
    <% end %>
  <% end %>
<% end %>

<script>
  (function() {
    var target = document.getElementById("qr-code-resize")
    if (!target) return

    var buttons = document.querySelectorAll("[data-qr-resize]")
    if (!buttons.length) return

    var wire = function() {
      if (!target.hakumiQrCode || typeof target.hakumiQrCode.setSize !== "function") {
        return false
      }

      buttons.forEach(function(button) {
        button.addEventListener("click", function() {
          var nextSize = Number(button.getAttribute("data-qr-resize"))
          target.hakumiQrCode.setSize(nextSize)
        })
      })

      return true
    }

    if (wire()) return

    var onReady = function() {
      if (wire()) {
        document.removeEventListener("turbo:load", onReady)
        window.removeEventListener("load", onReady)
      }
    }

    document.addEventListener("turbo:load", onReady)
    window.addEventListener("load", onReady)
  })()
</script>
Custom Color
Customize foreground and background colors.
Code
<%= render Hakumi::QrCode::Component.new(
  value: "https://hakumi.com/color",
  color: "#1677ff",
  bg_color: "#e6f4ff"
) %>
Download QRCode
Download the QRCode image via the public API.
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :middle) do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::QrCode::Component.new(
      value: "https://hakumi.com/download",
      id: "qr-code-download"
    ) %>
  <% end %>
  <% space.with_item do %>
    <%= render(Hakumi::Button::Component.new(id: "qr-code-download-button", type: :primary)) { "Download QRCode" } %>
  <% end %>
<% end %>

<script>
  (() => {
    const button = document.getElementById("qr-code-download-button")
    const qr = document.getElementById("qr-code-download")
    if (!button || !qr) return

    const wire = () => {
      if (!qr.hakumiQrCode) return false
      button.addEventListener("click", () => qr.hakumiQrCode.download("hakumi-qr-code"))
      return true
    }

    if (wire()) return

    const onReady = () => {
      if (wire()) {
        document.removeEventListener("turbo:load", onReady)
        window.removeEventListener("load", onReady)
      }
    }

    document.addEventListener("turbo:load", onReady)
    window.addEventListener("load", onReady)
  })()
</script>
Error Level
Set the error correction level.
Level L
Level M
Level Q
Level H
Code
<%= render Hakumi::Space::Component.new(size: :large) do |space| %>
  <% [ :L, :M, :Q, :H ].each do |level| %>
    <% space.with_item do %>
      <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |level_space| %>
        <% level_space.with_item do %>
          <%= render(Hakumi::Typography::Text::Component.new(weight: :strong)) { "Level #{level}" } %>
        <% end %>
        <% level_space.with_item do %>
          <%= render Hakumi::QrCode::Component.new(
            value: "https://hakumi.com/level-#{level}",
            error_level: level
          ) %>
        <% end %>
      <% end %>
    <% end %>
  <% end %>
<% end %>
With Popover
Advanced usage with popover.
Code
<%= render Hakumi::Popover::Component.new(
  title: "Scan me",
  body: render(Hakumi::QrCode::Component.new(value: "https://hakumi.com/popover")),
  trigger: "hover",
  placement: "bottom"
) do %>
  <%= render(Hakumi::Button::Component.new(type: :primary)) { "Hover to view" } %>
<% end %>
Programmatic
Render a QRCode with HakumiComponents.renderComponent.
Awaiting render...
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :middle) do |space| %>
  <% space.with_item do %>
    <%= render(Hakumi::Button::Component.new(id: "qr-code-programmatic-button", type: :primary)) { "Render QRCode" } %>
  <% end %>
  <% space.with_item do %>
    <%= render Hakumi::Flex::Component.new(
      id: "qr-code-programmatic-target",
      align: :center,
      justify: :center,
      style: "min-height: 180px;"
    ) do %>
      <%= render(Hakumi::Typography::Text::Component.new(type: :secondary)) { "Awaiting render..." } %>
    <% end %>
  <% end %>
<% end %>

<script>
  (() => {
    const button = document.getElementById("qr-code-programmatic-button")
    const target = document.getElementById("qr-code-programmatic-target")
    if (!button || !target) return

    const wire = () => {
      if (!window.HakumiComponents?.renderComponent) return false

      button.addEventListener("click", async () => {
        await window.HakumiComponents.renderComponent("qr_code", {
          target,
          params: {
            value: "https://hakumi.com/render",
            size: 180,
            type: "svg",
            error_level: "H"
          }
        })
      })

      return true
    }

    if (wire()) return

    const onReady = () => {
      if (wire()) {
        document.removeEventListener("turbo:load", onReady)
        window.removeEventListener("load", onReady)
      }
    }

    document.addEventListener("turbo:load", onReady)
    window.addEventListener("load", onReady)
  })()
</script>

QRCode Ruby Props

Prop Type Default Description
value String - Value encoded in the QR code.
size Number 160 QR code size in pixels.
type Symbol :canvas Render type (:canvas or :svg).
color String "#000000d9" Foreground color.
bg_color String "#ffffff" Background color.
icon String - Icon URL overlay.
icon_size Number 40 Icon size in pixels.
status Symbol :active Status (:active, :expired, :loading, :scanned).
status_render Proc | ViewComponent or String - Custom status render callback or component.
bordered Boolean true Whether to display a border.
error_level Symbol :M Error correction level (:L, :M, :Q, :H).
download_name String - Default filename for downloads.
aria_label String "QR Code" Accessibility label.

JavaScript API (element.hakumiQrCode)

Prop Type Default Description
getValue() Function - Returns the current QR value.
setValue(value) Function - Updates the QR value and re-renders.
getSize() Function - Returns the current size in pixels.
setSize(size) Function - Sets the size (px) and updates layout + render.
getType() Function - Returns the renderer type (:canvas or :svg).
setType(type) Function - Switches renderer between canvas / svg.
setColors({ color, bgColor }) Function - Overrides foreground/background colors.
setErrorLevel(level) Function - Changes error correction level (:L/:M/:Q/:H).
getDataUrl() Function - Returns a data URL for the rendered QR code.
download(filename) Function - Downloads the QR code image.
rerender() Function - Forces a re-render of the QR code.
getState() Function - Returns { value, size, type, errorLevel, status }.