Skip to content
design
Components

QR code

A QR code drawn dark on a light panel in every theme from the kit's own encoder, such as the code that joins the guest Wi-Fi network.

On this page

Guest Wi-Fi

Network
Althea Guest
Password
harbor-lantern-41
The guest network's join code: a phone's camera reads it and offers to join, with the password written beside it.
Code
import { Card } from "@bosunkit/components/card";
import { QrCode, wifiNetworkText } from "@bosunkit/components/qr-code";
import type { ReactElement } from "react";

export const description: string =
  "The guest network's join code on the vessel's welcome card: a phone's camera reads it and offers to join Althea " +
  "Guest, with the password written beside it for a phone that does not.";

export default function Showcase(): ReactElement {
  return (
    <Card title="Guest Wi-Fi" style={{ width: "100%", maxWidth: 420 }}>
      <div style={{ display: "flex", flexWrap: "wrap", alignItems: "center", gap: "var(--space-lg)" }}>
        <QrCode
          value={wifiNetworkText({ ssid: "Althea Guest", password: "harbor-lantern-41" })}
          label="Code to join Althea Guest with a phone's camera"
        />
        <dl style={{ margin: 0, display: "grid", gap: "var(--space-xs)" }}>
          <dt>Network</dt>
          <dd style={{ margin: 0, fontFamily: "var(--font-mono)" }}>Althea Guest</dd>
          <dt>Password</dt>
          <dd style={{ margin: 0, fontFamily: "var(--font-mono)" }}>harbor-lantern-41</dd>
        </dl>
      </div>
    </Card>
  );
}

A QR code draws a text as a square of modules that a phone's camera reads. The kit encodes it itself (byte mode, UTF-8, versions 1 to 40, the mask with the lowest penalty), and its output is pinned against two independent encoders. The dark modules are one SVG path on a light panel of its own that holds the four-module quiet zone a reader needs (ISO/IEC 18004, section 9.1). The panel and the modules swap the theme's background and text colors, so the modules are always the darker: the text on the background in Day and Bright, the background on the text in Dusk and Night. Many phone cameras fail to read a light-on-dark code, and in Night the panel is no brighter than the text already on the screen. Each module covers a whole number of device pixels: the panel is drawn at the largest size inside size at which it does, centered, so no module is a pixel wider than its neighbor. The code is an image named by label, which says what scanning it does.

wifiNetworkText({ ssid, password }) writes the text that joins a WPA or WPA2 network, WIFI:T:WPA;S:<ssid>;P:<password>;;, with each \, ;, ,, : and " in the name and the password escaped with a backslash. iOS and Android cameras offer to join the network it names.

01Say what scanning doesThe label names the result, "Code to join Althea Guest with a phone's camera", not the picture.
02Write it out tooShow what the code holds beside it, such as the network and its password, for a phone without a camera reader and for a screen reader.
03Only what may be sharedA code is read by any camera that sees the screen; put only what the crew would hand to a guest in one.

Examples

Sizes

`size` sets the side of the code's box as a CSS length; the panel is the largest inside it whose modules cover whole device pixels, and the quiet zone scales with them.
Code
import { QrCode } from "@bosunkit/components/qr-code";
import type { ReactElement } from "react";

export const description: string =
  "`size` sets the side of the code's box as a CSS length; the panel is the largest inside it whose modules cover " +
  "whole device pixels, and the quiet zone scales with them.";

export default function Sizes(): ReactElement {
  return (
    <div style={{ display: "flex", flexWrap: "wrap", alignItems: "end", gap: "var(--space-lg)" }}>
      <QrCode value="https://bosun.bot" label="Code for bosun.bot, small" size="6em" />
      <QrCode value="https://bosun.bot" label="Code for bosun.bot" />
      <QrCode value="https://bosun.bot" label="Code for bosun.bot, large" size="14em" />
    </div>
  );
}

Themes

Night
Dusk
Day
Bright
The guest network's code in each of the four themes: dark modules on a light panel every time, the panel in Night the Night text color, so it is no brighter than the text around it.
Code
import { Card } from "@bosunkit/components/card";
import { QrCode, wifiNetworkText } from "@bosunkit/components/qr-code";
import { PresentationScope } from "@bosunkit/provider";
import type { Theme } from "@bosunkit/tokens/theme";
import type { ReactElement } from "react";

export const description: string =
  "The guest network's code in each of the four themes: dark modules on a light panel every time, the panel in " +
  "Night the Night text color, so it is no brighter than the text around it.";

const THEMES: readonly { readonly theme: Theme; readonly name: string }[] = [
  { theme: "night", name: "Night" },
  { theme: "dusk", name: "Dusk" },
  { theme: "day", name: "Day" },
  { theme: "bright", name: "Bright" },
];

export default function Themes(): ReactElement {
  return (
    <div
      style={{ width: "100%", display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(10em, 1fr))", gap: 10 }}
    >
      {THEMES.map((entry: { readonly theme: Theme; readonly name: string }): ReactElement => (
        <PresentationScope key={entry.theme} theme={entry.theme}>
          <Card footer={entry.name}>
            <QrCode
              value={wifiNetworkText({ ssid: "Althea Guest", password: "harbor-lantern-41" })}
              label={`Code to join Althea Guest with a phone's camera, in ${entry.name}`}
              size="8em"
            />
          </Card>
        </PresentationScope>
      ))}
    </div>
  );
}

Error correction

The same text at levels L, M, Q and H: more error correction takes more modules, and reads through a smudge or a fold on a printed card.
Code
import { QrCode } from "@bosunkit/components/qr-code";
import type { ReactElement } from "react";

export const description: string =
  "The same text at levels L, M, Q and H: more error correction takes more modules, and reads through a smudge or " +
  "a fold on a printed card.";

export default function ErrorCorrection(): ReactElement {
  return (
    <div style={{ display: "flex", flexWrap: "wrap", alignItems: "end", gap: "var(--space-lg)" }}>
      <QrCode
        value="https://bosun.bot/althea"
        label="Code for the vessel's page, level L"
        errorCorrection="L"
        size="7em"
      />
      <QrCode value="https://bosun.bot/althea" label="Code for the vessel's page, level M" size="7em" />
      <QrCode
        value="https://bosun.bot/althea"
        label="Code for the vessel's page, level Q"
        errorCorrection="Q"
        size="7em"
      />
      <QrCode
        value="https://bosun.bot/althea"
        label="Code for the vessel's page, level H"
        errorCorrection="H"
        size="7em"
      />
    </div>
  );
}

A visible alternative to scanning

Keep the destination or pairing instruction beside the code. Scanning is unavailable to some readers and can fail because of glare, camera focus or another device's display. Do not make a QR code the only route to required information. Verify the actual printed or displayed size with a real camera.

Treat an embedded secret or pairing token as sensitive content: the picture can be photographed, cached or copied. The caller owns authorization, expiry and any regeneration. A valid QR encoding does not establish that its payload is safe to share or that the destination remains available.

Props

PropTypeDefaultDescription
valuerequiredstring–The text the code holds, such as wifiNetworkText({ ssid, password }) for a network's join code.
labelrequiredstring–What the code is for, as its accessible name: "Code to join Althea Guest with a phone's camera".
errorCorrectionQrErrorCorrection | undefined"M"How much of the symbol can be damaged and still read; M (about 15 %) by default.
sizestring | undefined"10em"The width and height of the box the code takes, as a CSS length; 10em by default. The panel is drawn at the largest size inside it whose modules cover whole device pixels, centered.
classNamestring | undefined–Classes added to the <svg>.
testIdstring | undefined–data-testid on the <svg>.
refRef<SVGSVGElement> | undefined–The <svg> element.
Do
Put the guest network's code on screen with its name and password written beside it.
Don't
Don't put the crew network's password in a code on a screen guests can see; a camera across the saloon reads it.

Sources: ZXing, Barcode contents: Wi-Fi network config; Project Nayuki, QR Code generator library.