A box shadow as the five things an author is actually choosing, and back again.
box-shadow is one string holding four lengths, a colour and a keyword, and a control that offers
it as one string offers nothing: 0 10px 24px -4px rgba(15,23,42,.18) is not a value anyone reads
or edits, it is a value they paste. So the panel takes the shadow apart — how far right, how far
down, how soft, how much bigger, what colour, and whether it falls inside the box — and puts it
back together on every change. That is the same decomposition Chrome's own shadow editor makes,
and it is what turns "which side is the shadow on" into two numbers you can nudge.
What survives
Only the shape the panel can express: [inset] <x> <y> <blur> <spread> <colour>. A shadow with a
second layer, or a colour this cannot recognise, parse/1 refuses rather than half-reads — the
author keeps the string they wrote, in the element's own CSS, instead of watching a control
silently throw half of it away.
Anything omitted comes back as its CSS default: a missing blur is 0, a missing colour is
currentColor's stand-in here, rgba(0,0,0,.2), chosen because a shadow with no colour at all is
the one thing nobody means.
Summary
Functions
The parts a control starts from when the element has no shadow yet.
The parts a shadow is made of, or :error when this cannot hold the whole of it.
The named shadows a row of one-click presets offers.
One part changed, as the whole shadow.
The shadow a set of parts means, or nil when they mean no shadow at all.
Types
Functions
@spec default() :: t()
The parts a control starts from when the element has no shadow yet.
The parts a shadow is made of, or :error when this cannot hold the whole of it.
A blank string is :error too: nothing to take apart is not a shadow with default parts, and
offering one would make an unset control look set.
The named shadows a row of one-click presets offers.
Elevation is a scale, not a number people invent: "none, small, medium, large" is how every design system already talks about it, and the fields underneath still take anything.
One part changed, as the whole shadow.
The panel edits a single number at a time and the property holds all of them, so every control reads the current value, replaces its own part and writes the string back.
The shadow a set of parts means, or nil when they mean no shadow at all.
nil rather than "none": the panel clears an override by writing an empty value, and a control
that wrote box-shadow: none instead would leave a real declaration behind for the next reader to
wonder about.