A web component checkbox.
npm i -S @substrate-system/check-boximport { CheckBox } from '@substrate-system/check-box'
import '@substrate-system/check-box/css'
// tag name is at .TAG
document.body.innerHTML += `
<${CheckBox.TAG} label="Example Label Text"></${CheckBox.TAG}>
`
const box = document.querySelector(CheckBox.TAG)
box?.addEventListener('change', ev => {
console.log('Checked:', event.target.checked)
})Set the label text with the label attribute. It is rendered as text,
not HTML.
<check-box label="My label text"></check-box>If there is no label attribute, the inner text content is used
instead. Prefer the attribute: the text content is replaced when the
element renders, which breaks a framework that owns those child nodes.
Without a label, a bare <input> is rendered. Give it an accessible
name with aria-label or aria-labelledby.
If the host already contains an <input type="checkbox"> when it
connects, the element keeps that node and only adds behavior. Nothing
is replaced. Use this with a framework like Preact, so the framework
owns every node.
<check-box name="metric">
<label class="checkbox-label">
<input type="checkbox">
<span>Show metric</span>
</label>
</check-box>The label attribute is ignored in this case. The attributes that are
copied to the input (see Attributes) still are, and
controlAttributes is applied. Otherwise the inner input's own
attributes are left alone.
Takes standard input attributes.
-
checked- Boolean attribute. When present, the checkbox is checked.<check-box checked>Checked by default</check-box>
-
disabled- Boolean attribute. When present, the checkbox is disabled and cannot be interacted with.<check-box disabled>Cannot be clicked</check-box>
-
name- String attribute. Sets the name of the checkbox, useful for form submissions.<check-box name="newsletter">Subscribe to newsletter</check-box>
-
label- String attribute. The label text. See Label.
These are copied to the inner <input> and stay on the host. Removing
one from the host removes it from the input too:
checked, disabled, name, value, required, and form.
These describe the focusable control, so they are moved to the inner
<input> and removed from the host when the element renders:
id, tabindex, autofocus, and every aria-* attribute.
Use aria-describedby to link a hint or an error message to the
checkbox.
<check-box label="Show metric" aria-describedby="metric-hint">
</check-box>
<p id="metric-hint">Adds the metric to the chart.</p>These move to the inner <input> whenever they are set on the host,
including after the element renders. Removing one from the host
afterwards does nothing, because it is no longer on the host. Change or
remove it on the inner input instead, with the control property, or
set the full set with the controlAttributes property. When you
render the markup yourself, nothing is
moved: put these attributes on your <input> directly.
Getters and setters for programmatic access:
const checkbox = document.querySelector('check-box')
// Get/set checked state
console.log(checkbox.checked) // false
checkbox.checked = true
// Get/set disabled state
console.log(checkbox.disabled) // false
checkbox.disabled = true
// Get/set name
console.log(checkbox.name) // ""
checkbox.name = "myCheckbox"
// Get/set value
console.log(checkbox.value) // "on"
checkbox.value = "yes"
// The inner input
checkbox.control?.setAttribute('aria-invalid', 'true')
// Get/set the id of the inner input
console.log(checkbox.inputId) // ""
checkbox.inputId = "my-checkbox"
// Set aria-*, tabindex, and autofocus on the inner input
checkbox.controlAttributes = {
'aria-invalid': true,
tabindex: 0
}controlAttributes is the full set for the inner input. A name left out
of the object is removed from the input, and null or '' removes
everything it set. Values follow the usual attribute rules: null or
undefined removes the attribute, true sets it as an empty attribute
(or "true" for aria-*), false removes it (or sets "false" for
aria-*), and any other value is written as a string. Names other than
aria-*, tabindex, and autofocus are ignored. Use inputId for the
id. Keys are attribute names, so write tabindex, not tabIndex. A
camel-case key is ignored. A value in controlAttributes wins over a host
attribute with the same name, and leaving that name out later removes it
from the input, even if the host had supplied it before. autofocus only
takes effect if it is set before the element renders.
In a framework, pass the object as a prop. This Preact example marks the
checkbox invalid when bad is true:
html`<check-box controlAttributes=${{ 'aria-invalid': bad }}>`Import @substrate-system/check-box before the framework renders, or
before any code sets the property. Before the element is defined, Preact
writes the prop as a plain attribute instead of setting the property.
Standard HTML checkbox events are bubbled from the inner
<input type="checkbox"> element.
changeinputclick
const checkbox = document.querySelector('check-box')
checkbox.addEventListener('change', (event) => {
console.log('Checked:', event.target.checked)
})This exposes ESM and common JS via
package.json exports field.
import { CheckBox } from '@substrate-system/check-box'import '@substrate-system/check-box/css'@import url("@substrate-system/check-box/css");Or minified:
import '@substrate-system/check-box/min/css'These variables are shared with the other @substrate-system form
controls, so an app can set them once. Each one has a fallback.
:root {
--substrate-accent: black; /* the check mark */
--substrate-surface: #fff; /* the box background */
--substrate-border: currentColor; /* the box border */
--substrate-focus: currentColor; /* focus ring color */
--substrate-focus-width: 2px; /* focus ring width */
--substrate-radius: 0; /* box corners */
}--primary-accent still works as a fallback for --substrate-accent.
The label text inherits its font size.
This calls the global function customElements.define. Just import, then use
the tag in your HTML.
import '@substrate-system/check-box'<div>
<check-box></check-box>
</div>This package exposes minified JS and CSS files too. Copy them to a location that is accessible to your web server, then link to them in HTML.
cp ./node_modules/@substrate-system/check-box/dist/index.min.js ./public/check-box.min.js
cp ./node_modules/@substrate-system/check-box/dist/style.min.css ./public/check-box.css<head>
<link rel="stylesheet" href="./check-box.css">
</head>
<body>
<!-- ... -->
<script type="module" src="./check-box.min.js"></script>
</body>