Skip to the object
Tactile UI

Compass

A liquid-damped compass. The card swings past the mark and settles while a lit display reads the bearing. Your hand turns the knurled bezel, one click a degree.

What it is for

An angle input and an angle readout that people believe.

Installnpx shadcn add https://tactileui.dev/r/compass.json

Controls

Where it points. Turn the bezel in the preview to change it.

The liquid: low swings past and rings; 1 and above arrive without passing.

Card

Degrees only, cardinal points, or an aviation heading card (3, 6, 12…).

Finish

Auto follows the page: aluminium on Aluminium, Porcelain and Daylight, graphite on AMOLED, and on Graphite, Black, Phosphor, Night, Paper and E-paper a dial drawn from that finish’s own tokens. A dark dial reads its display on a VFD.

0 fills its frame; any other value is the dial’s diameter, shrunk only to fit.

0 is from above, clockwise. The sheen stays with the lamp as the card turns.

A wind or heading readout: it turns to values from code, not the hand.

The lit readout in the hub.

Everything you set here is what the Code and Prompt tabs give you.

Seats open in 11 days. Want one email that morning?

Datasheet

Mechanism
Short way damped spring, Detented bezel, Heightfield turned metal, Phase baked knurl, Room fixed sheen, Split turning print, Lit display readout, Device orientation, Sleeping loop, Fit to host
Stack
Vanilla ES modules, Canvas 2D, CSS
Needs
Nothing, no dependencies
States
12 documented
Version
0.1.0
Licence
Free, source open to everyone

States

  1. At restThe card's N sits boxed under the bezel's index and the bearing is under the lubber; the display reads it; the loop is asleep.
  2. Turning the bezelDrag anywhere on the dial: the bezel follows the hand in 1° detents with no lag; the card follows it through the liquid; input fires on every degree.
  3. SwingingAfter a turn or a flick the card passes the mark and swings back (about a tenth of the swing at the default damping) and settles within two seconds; the display reads the card as it swings.
  4. KeyboardArrows step 1°, Shift or Page keys 10°, Home goes north; values wrap from 359 to 0; change fires on each key.
  5. From codesetValue() swings it to a bearing without firing input or change: a wind feed or a heading stream.
  6. Read-onlyA readout: the hand does nothing and aria-readonly says so.
  7. Device compassuseSensor() asks for permission and lets the device's own heading drive it; off by default.
  8. AluminiumA bead-blasted aluminium bezel, a black anodised lip ring, a warm-white card and a reflective LCD.
  9. GraphiteA soft-touch graphite bezel, a black card with light print and a glowing VFD.
  10. SmallUnder a 90 px card radius it drops the 1° ticks, it leaves off labels too small to read, and under 96 px across it hides the display.
  11. Off screen or hiddenThe loop pauses mid-swing and finishes when it is back; a returning tab advances one clamped frame.
  12. Reduced motionIt points at once and no frame is requested; keys and drags still set it.

Notes

As an input it is a real slider (0–359, spoken as "274 degrees, west", arrows, Shift, Page keys, Home for north) for a heading, a bearing, a camera or antenna azimuth, a solar tracker. As a readout it is a wind direction on an energy or weather dashboard, a vehicle or drone heading in a fleet console, or a device's own orientation from its compass sensor.

Original. Canvas 2D for the instrument, DOM for the lit display (the kit's LCD on aluminium, VFD on graphite). The housing is a heightfield shaded per pixel once per size and finish; the knurl is baked at three phases of its 3° pitch so its teeth light by where they are as the bezel turns in 1° detents. A frame is five drawImage calls. The integrator assigns cut (0 is not a valid cut, so the field is left out).

Using it

Copy the compass folder from its package next to your page, link its stylesheet and construct it on an element. The Code tab above writes the example at any settings, and for React, Vue, Svelte or a custom element (Using a framework).

Options

OptionTypeDefaultWhat it does
bearingnumber, 0 to 3590Where it points. Turn the bezel in the preview to change it.
dampingnumber, 0.1 to 1.50.6The liquid: low swings past and rings; 1 and above arrive without passing.
carddegrees · cardinal · aviation'cardinal'Degrees only, cardinal points, or an aviation heading card (3, 6, 12…).
finishauto · aluminium · graphite'auto'Auto follows the page: aluminium on Aluminium, Porcelain and Daylight, graphite on AMOLED, and on Graphite, Black, Phosphor, Night, Paper and E-paper a dial drawn from that finish’s own tokens. A dark dial reads its display on a VFD.
sizenumber, 0 to 640'fit'0 fills its frame; any other value is the dial’s diameter, shrunk only to fit.
lightnumber, 0 to 3453150 is from above, clockwise. The sheen stays with the lamp as the card turns.
readonlybooleanfalseA wind or heading readout: it turns to values from code, not the hand.
displaybooleantrueThe lit readout in the hub.
labeltext'Heading'Accessible name

Methods

new Compass(element, options)
Builds it inside the element with these options.
value
The bearing the compass is set to, 0–359.
heading
Where the card is pointing right now (it lags the value while it swings).
state
setValue(v, { instant = false } = {})
Turn to a bearing.
update(opts = {})
Change options in place.
useSensor()
Let the device's own compass drive it.
stopSensor()
Stop following the device’s own compass.
destroy()
Stops it and cleans up after it.

Events it fires, which bubble from the element: input, change.