Next: (hygguile components icon), Previous: (hygguile components fly-out), Up: API
Create a frosted glass surface, with colour washes behind it if you want them.
The frost is the panel’s own translucent tint plus hg-frost, the
framework’s rounded frost layer (see hygguile-extras.css):
whatever sits behind the panel arrives blurred and coloured through it,
so the panel reads as a pane of glass rather than an opaque card. How
strong the frost is is the panel’s to say with frost, or a page’s
in markup the component did not build: it is written as
--hg-frost-blur, and four rems stand until something says
otherwise.
The frost is not a backdrop-filter on the surface itself, and
that is the point of the layer. A browser paints a filtered backdrop in
the element’s square box and ignores its radius, which leaves a square
patch of frost at every rounded corner; neither the radius nor a clip
path on that element stops it, and clipping the surface would trap
whatever it is meant to let out of its own corner. The layer therefore
paints the frost, clips itself to the surface’s own radius, and leaves
the surface free.
The surface never clips. The decorations (the washes and the accent) are wrapped in their own rounded clip layer, which is what keeps those oversized discs inside the glass, and that layer is a plain element, which browsers clip to its radius reliably.
The layer that holds the content does not clip unless the panel asks it to with clip?, and that default is deliberate. That layer’s edge falls exactly on the content’s own edge – the surface’s padding is on the surface – so a clip there shaves whatever sits flush with it by a device pixel: the left arc of a line’s first glyph, the stroke of a table’s first cell. Clipping is a knob a panel reaches for, not a tax every panel pays.
The washes are the wallpaper trick: a few oversized, heavily blurred
discs of colour thrown across the panel, each described by
glass-wash. They are decoration, so they are hidden from
assistive technology and never take a pointer event, and the content
sits in a positioned layer of its own above them. With drift? the
discs move very slowly, out of phase with one another, so the glass has
something to frost without ever stealing attention; left alone they are
still, which is the calmer default for a panel that is often just a bit
of background. Either way the drift stops for anyone who asks for less
motion: prefers-reduced-motion turns the animation off in the
stylesheet.
The layer the discs ride in wears the panel’s own rounding and clips,
and that is still not enough for a blurred disc: a browser draws a
filter’s blur in the square box the blur reaches, so without a clip of
its own the wash leaves a faint square of ink beside each rounded
corner. The layer’s class names that clip, and a clip has to name a
radius, so it carries the framework’s default rounding as its own
default. A panel that rounds its glass differently says so in
--hg-glass-clip, on the panel or on any ancestor of the layer.
See hygguile-extras.css for the whole story, and for the
measurements that leave an explicit clip as the only cure.
A panel with no decorations has no layers, and then there is nothing to
sit above: the content is the panel’s own children and no layer is
added. That is what lets this one component be a <header>, a
<ul> or a <div> without leaving an extra element inside,
which a <ul> may not legally hold. A panel that does have
decorations gets its decorations in a rounded <div> of their own
and its content in a second one.
The panel’s contents.
A list of glass-wash descriptors, or the empty list (the default)
for a plain frosted panel.
A boolean; #t lets the washes drift.
An optional decorative node drawn inside the clipped surface, above the washes and below the content: a hairline of gradient along the top edge, for instance.
The element the surface is built from. Defaults to div; a bar
wants header and a menu wants ul.
Extra attributes for the surface, as pairs of name and value.
List of symbols saying how the surface is placed. Defaults to
(relative), which is what gives the washes something to be
absolute against. A surface pinned some other way – (sticky
top-0) for a bar – passes its own, or the empty list to place itself
with the layout classes alone.
How strong the frost is: a number of rems, or any CSS length as a
string. Defaults to #f, which declares nothing and leaves the
strength to the stylesheet’s own 4rem – the value Olive’s
backdrop-blur-md would set. A pane that wants a gentler or
heavier glass than the framework’s own passes its own, and carries no
style attribute at all when it does not.
List of symbols representing the frosted tint. Defaults to
(bg-stone-100/75 dark:bg-onyx-900/75).
List of symbols representing the corner rounding. Defaults to
(rounded-3xl).
List of symbols representing the border, or the empty list for none. Defaults to a two-pixel hairline in the stone ramp.
List of symbols representing the shadow, or the empty list for none.
Defaults to (shadow-lg).
Whether the panel hides its content’s overflow, in the layer holding the
content. Defaults to false: the washes are oversized but it is the
layer they are painted in that keeps them inside the glass, so the
content layer has no work to do unless a panel hands it some. Leaving
it open is what keeps a line’s first glyph whole – that layer’s edge is
the content’s own edge – and it keeps a surface free to let a child
escape, a bar holding a dropdown being the case worth naming. The
surface itself never carries overflow-hidden, whichever way
clip? is set.
List of symbols representing the padding classes. Defaults to
(p-6 sm:p-8).
Extra classes for the surface itself. A colour utility here replaces
the corresponding default rather than piling onto it (see
override-classes), so a surface can recolour its own glass.
Extra classes for the layer holding the content, when a layer is added,
so a panel can lay its contents out without reaching for the surface –
a (flex flex-col gap-6) hero, for instance, spaces its rows with
it.
(glass-panel (list (h1 "Hygguile"))
#:washes (list (glass-wash '(bg-naples-yellow-500/75
w-96 h-96 left-4 top-4)
#:delay -6))
#:frost 3
#:drift? #t)
(glass-panel (list (nav-link "Home" #:href "/"))
#:tag 'header
#:position '(sticky top-0)
#:rounding '()
#:border '()
#:padding '(px-4 py-4))
Describe one colour wash for glass-panel.
A wash is a description, not markup: it says what the disc is made of
and when it sets off, and the panel supplies the rest. The
classes given here are read by Olive the way any other utility
classes are, so the size (w-96), the place inside the panel
(left-4 top-4) and the colour (bg-naples-yellow-500/75)
are all just names. The panel adds the mechanics – the absolute
positioning, the heavy blur, the rounding, the fact that the disc is
decoration and never takes a pointer event – and decides whether it
drifts at all, so one wash can stand still on one panel and move on
another.
List of symbols: the disc’s size, position and colour.
A number of seconds, or any CSS time as a string. A negative delay
starts the disc part way through its cycle, which is how several washes
are kept out of phase with one another; #f (the default) leaves
it in step with the rest.
How long one drift takes: a number of seconds or any CSS time as a
string, emitted as the disc’s --hg-blob-duration, which is what
the stylesheet reads for the pace and is where its own default sits.
Omitted, a panel drifts at that default. This is what lets one panel
breathe slowly and another wander on a short leash, without a second
stylesheet or a new class.
How far the disc travels: a pair of lengths – horizontally and
vertically – or a single length, which moves it along the horizontal
axis and leaves the stylesheet’s own upward drift in place. A bare
number counts as rems, so '(2 -1) travels 2rems right and 1rem
up. Omitted, the disc travels as far as the stylesheet’s default.
(glass-wash '(bg-china-rose-500/50 w-72 h-72 right-4 top-4)
#:delay -14 #:pace 40 #:distance '(3 -2))
Next: (hygguile components icon), Previous: (hygguile components fly-out), Up: API