CONTROLS
Live components from the library. Hover to brighten, press to invert, tab to see the dashed focus ring.
class="ac-btn" ac-btn--filled ac-btn--dim ac-btn--block [disabled]
<!-- or drive it with ARIA: --> <button class="ac-btn" aria-pressed="true">
--block takes the full
width of whatever it is in, which is what you want at the foot of a narrow instrument
column where a key floated left reads as unfinished:
More than one filled button in a region. Inverse video means "the machine is doing this"; two of them means neither reads.
class="ac-btn ac-btn--sm" ac-btn ac-btn--lg
--sm on a touch panel: it computes to about 30px tall, under the
44px hit-target floor. Use it only in dense, mouse-driven tooling.
class="ac-btn ac-btn--lg ac-btn--pad ac-grow"
A row of pads without .ac-grow (or min-width:0) —
the 130px min-width floor will overflow a narrow viewport.
.ac-rounded, lower row
.ac-classic — which is the default, so the lower row is what a page looks like untouched.
The four corners are not cut the same. These keys were drawn as solid objects lit from
the top left, so the far corner is barely cut and the near one is cut hardest — 2 / 4 / 8 / 4 px running
down the diagonal. Cut all four alike and the key reads as an octagon instead of an object. The extrusion
is offset along that same diagonal, which is why the bottom and right edges carry a heavy band and the top
and left stay a single stroke: one claim about where the light is, made twice.
A filled key is IN — the band flips to the top and left, because the near
face of a sunken key is the upper one. The key does not move: a transform reads correctly but contributes
to scrollable overflow, and a latched key flush against its container pushed 4px past it. A box-shadow
costs nothing either way, so the light moves and the geometry does not.
Locked keeps neither edge nor halo: inert hardware does not glow. Labels park top-left
wherever a key is taller than its text, which is the classic face — a label plus room for a value.
Fn is .ac-btn--pad, the 96px touch pad, and it composes with either corner.
Keypad digits are exempt and stay centered; one character has no label/value split to serve.
<!-- classic is the default; these are the ways to say otherwise -->
<div class="ac-rounded"> … </div> <!-- one region back to the arc -->
<div class="ac-classic"> … </div> <!-- one region back to the cut -->
<html data-ac-style-classic="off"> <!-- the whole page; what the demo switch writes -->
Both corner styles in one region. They are two readings of the same hardware, and mixing them says the panel was assembled from two of them. Scope either class to a whole frame, or set the flag on the root — this specimen is the documented exception.
Firefox and older Safari have no corner-shape, so they quantize
the radius to a hard 2px instead of cutting a chamfer. Deliberate: that is the same statement in a
property every engine has had for fifteen years, so both positions of the switch mean something
everywhere. The extrusion and the top-left label are identical on both paths.
aria-selected="true" is the truth for assistive tech and
is what the CSS styles; .ac-tab--active is the same fact as a class, for a
consumer whose own component sets a class and not ARIA. The JS module writes both, along
with tabindex — only the selected tab is tabbable, which is the roving-focus
half of the tablist model. Driving this from React or Vue? Write the same attributes
yourself and skip the module entirely; nothing here reads back.
<div class="ac-tabs" role="tablist" data-ac="tabs" aria-label="Console views">
<button class="ac-tab ac-tab--active" role="tab" aria-selected="true"
tabindex="0" id="key-1" aria-controls="panel-1">Functions</button>
<button class="ac-tab" role="tab" aria-selected="false" tabindex="-1"
id="key-2" aria-controls="panel-2">Alarms</button>
</div>
<div id="panel-1" role="tabpanel" aria-labelledby="key-1"> … </div>
<div id="panel-2" role="tabpanel" aria-labelledby="key-2" hidden> … </div>
Navigation between pages — that is .ac-nav. Tabs swap a region,
not a screen.
<label class="ac-field">
<span class="ac-field__label">Title:</span>
<input class="ac-input" type="text">
</label>
<span class="ac-select"><select class="ac-input">…</select></span>
<label class="ac-check"><input type="checkbox"><span>Spare</span></label>
A single yes/no setting the operator flips — that reads better as an
.ac-toggle, which states ON or OFF in words.
.ac-radio--disabled. Like the
disabled checkbox and the disabled key, it drops to faint and loses its halo —
inert hardware does not glow. Set the class alongside the input's own
disabled; the class styles the label, the attribute is what actually stops
the click.
<label class="ac-radio"><input type="radio" name="mode"><span>Auto</span></label>
<label class="ac-radio ac-radio--disabled"><input type="radio" disabled>…</label>
More than about five options — that is an .ac-select.
<button class="ac-toggle" data-ac="toggle" aria-pressed="false">…</button>
<label class="ac-toggle ac-toggle--input">…<input type="checkbox">…</label>
--dense, with __key--wide on the Enter key so it spans two of the
three columns — the layout every calculator and entry keypad settles on, because the key you
press last is the one worth making hard to miss:
.ac-keypad--dense is the same pad with the gap and the key floor pulled in, for
a mouse-driven panel or a sidebar where the full pad does not fit — it is a
concession, not a variant to reach for first, and it drops below the 44px touch
target the full pad is built to clear. Digits stay centered under either corner style; a
single character has no label-and-value split for the classic top-left label to
serve.
<div class="ac-keypad"><button class="ac-btn ac-keypad__key">7</button>…</div>
<div class="ac-keypad ac-keypad--dense"> <!-- mouse-driven only -->
<button class="ac-btn ac-keypad__key ac-keypad__key--wide">Ent</button>
Any screen with a keyboard attached. This exists because there is no keyboard
in a projection booth. And --dense on a touch panel, for the same reason
.ac-btn--sm does not belong on one.
<dialog>, so Escape and focus trapping come from the browser.
.ac-dialog--wide is the second and last size, for
the one case a confirm box cannot serve: a dialog carrying a table or a form of
more than about four fields, where the default measure would wrap every row. There is no
small variant and no full-screen one — a dialog narrower than this is a banner, and a
dialog the size of the screen is a screen.
<dialog class="ac-dialog"><form method="dialog">
<h2 class="ac-dialog__title">Confirm</h2>
<div class="ac-dialog__body">…</div>
<div class="ac-dialog__actions">…</div>
</form></dialog>
<dialog class="ac-dialog ac-dialog--wide"> <!-- a table, or a real form -->
Anything the operator must see machine state behind. A modal on a control
surface hides the panel; use an .ac-banner instead.