Next: (hygguile css), Previous: (hygguile components typography), Up: API
Isolate an inline run whose direction the browser should decide.
A username, a file name, a number next to a currency symbol: anything a
page does not control the script of. <bdi> keeps it from
rearranging the sentence around it.
The inline content.
Extra classes.
(p (list "Signed in as " (bdi "@ada")))
Override the bidirectional algorithm for content.
This is deliberately explicit: it is for displaying a string in the
direction opposite to its own, not for laying out a page. Pages that
need a whole region mirrored want locale instead.
The inline content.
'ltr or 'rtl. Defaults to 'rtl.
Extra classes.
(bdo "abc" #:dir 'rtl)
A disclosure whose body animates open and closed.
This is a native <details> with its content in a grid track that
moves between zero and one fraction of its height, so the browser
animates the real height without a measuring script. The reduced-motion
block in the companion stylesheet sets the transition off, and the
disclosure still opens instantly – the behaviour was never the
animation.
The always-visible caption.
The collapsible body, as a list of nodes.
Whether it starts open.
Extra classes for the <details>.
(collapse #:summary "Advanced" #:content (list (input #:label "Pattern" #:name "p")))
Render a button that copies text to the clipboard.
The button is a progressive enhancement and says so: it carries
js-only, so the no-script stylesheet hides it, and a
<noscript> beside it shows the value as selectable text instead.
A control that silently does nothing is worse than no control at all.
The value lives in a data-hg-copy attribute, not in an inline
handler, so the same script serves every copy button on the page and a
page with a Content Security Policy does not have to allow inline
JavaScript.
The value to copy.
The accessible label, shown as text only when show-text? is true.
The accessible label after a successful copy. Defaults to
"Copied".
Whether the label is visible beside the icon. Defaults to false.
Extra classes for the button.
(copy-button #:text "(use-modules (hygguile hygguile))")
Render the control that switches a page between comfortable and compact density.
The control is a progressive enhancement: it carries js-only, and
the no-script stylesheet hides it, because a density preference that
cannot be remembered is a button that lies. The script stores the
choice and sets data-density on the root element before the page
is drawn, so a reader never sees one density and then the other.
A page opts in by reading the same attribute in its own stylesheet; the framework’s data grid, field shell and sidebar already do.
The density the server rendered the page in. Defaults to
'comfortable.
The accessible label of the control.
Extra classes for the button.
(density-toggle #:current 'comfortable)
Fade content in, and do nothing at all when motion is reduced.
The duration is read from the design tokens, so the reduced-motion block that sets every token to zero turns the animation off without a second media query here. That is the whole point of the primitive: motion is a token, not a commitment sprinkled through the markup.
The children, as a list of nodes.
A motion token: 'fast, 'base (default), 'slow or
'slower.
An optional delay token or CSS time.
The element to build. Defaults to div.
Extra classes for the wrapper.
Extra attributes, as pairs of name and value.
(fade-in (list (alert ...)))
Hide content from a breakpoint up.
Olive’s responsive utilities are min-width, so there is no plain utility
that means "gone above this width"; the companion stylesheet names the
five classes this needs (hg-hidden-from-sm and friends), and this
component is the name a page uses instead of remembering them.
The children, as a list of nodes.
The breakpoint: 'sm, 'md (default), 'lg, 'xl
or '2xl.
The element to build. Defaults to div.
Extra classes for the wrapper.
Extra attributes, as pairs of name and value.
(hide (list (toolbar ...)) #:from 'md)
Place content in one of the framework’s named layers.
Every overlay has to answer the same question – which of us is on top
– and the answer stops being obvious the moment a page has a modal, a
dropdown and a toast at once. Naming a level reads the framework’s own
scale (sticky, dropdown, overlay, modal,
popover, toast, tooltip) through a custom property,
so a page can raise or lower a whole layer without hunting for a
component’s z-index.
The children, as a list of nodes.
A layer name. Defaults to 'modal.
An optional HTML identifier, for a portal target a script fills.
The element to build. Defaults to div.
Extra classes for the element.
Extra attributes, as pairs of name and value.
(layer (list (drawer ...)) #:level 'modal)
The single mount point a page gives its overlays.
Rendered once, near the end of the body, this is where scripts append a toast or a command palette. In a server-rendered page it is mostly a declaration of intent: overlays rendered by the server can sit here too, so they all share one stacking context and one place to look for them.
The identifier scripts use to find the root.
Any overlays rendered by the server, as a list of nodes.
Extra classes for the root.
(layer-root)
Clamp text to a number of lines, with an ellipsis.
This is truncate-text under the name the CSS property has, for a
page that would rather read line-clamp at the call site. The
full text stays in the DOM, so assistive technology and find-in-page
still reach it.
The text or inline nodes.
How many lines to keep. Defaults to 2.
An optional title attribute carrying the untruncated text.
The element to build. Defaults to p.
Extra classes for the text.
(line-clamp "A long summary" #:lines 3)
Mark a region’s language and writing direction.
Both attributes are inherited, so wrapping the part of a page that is in another language – or in a right-to-left script – is enough for browsers, screen readers, hyphenation and the CSS logical properties the components are written with. The framework’s own layout primitives use logical spacing, so a split or a drawer mirrors itself when it is told to.
The children, as a list of nodes.
A BCP 47 language tag, such as "ar" or "pt-BR".
'ltr, 'rtl or 'auto.
The element to build. Defaults to div.
Extra classes for the element.
Extra attributes, as pairs of name and value.
(locale (list (p "مرحبا")) #:lang "ar" #:dir 'rtl)
Show content only from a breakpoint up.
The markup is hidden plus the breakpoint’s display utility, so
the hiding is done by the same stylesheet as everything else and the
content is not fetched twice. Below the breakpoint the element is not
rendered at all (display: none), which is the correct behaviour
for a control that only makes sense on a wide screen.
The children, as a list of nodes.
The breakpoint: 'sm, 'md (default), 'lg, 'xl
or '2xl.
The display value above the breakpoint, e.g. 'block,
'flex, 'grid or 'inline-block.
The element to build. Defaults to div.
Extra classes for the wrapper.
Extra attributes, as pairs of name and value.
(show (list (table ...)) #:from 'lg)
Render the first focusable control on a page: a link that jumps past the navigation straight to the content.
A skip link is the cheapest accessibility win there is and the most
often forgotten. It sits off-screen until a keyboard reader tabs to it,
then appears at the top of the page; following it moves focus to
target, which should be the id of the page’s <main>.
The fragment the link points at, including the leading #.
Defaults to "#main".
The link text. Defaults to "Skip to content".
Extra classes for the link.
(skip-link #:target "#main")
Slide content in from an edge, or not at all when motion is reduced.
The children, as a list of nodes.
'up (default), 'down, 'start or 'end.
A motion token. Defaults to 'base.
The element to build. Defaults to div.
Extra classes for the wrapper.
Extra attributes, as pairs of name and value.
(slide-in (list (card ...)) #:from 'down)
Cut text off after a number of lines, with an ellipsis.
One line uses Olive’s truncate utility; several lines use its
line-clamp-* utilities, which is a real, painted clamp rather
than a character count, so it follows the rendered width of the type.
The full text stays in the DOM, so assistive technology and find-in-page
still reach it; a title is available for the mouse reader, but it
is off by default because it would make a second copy of the text for
anyone who can already see it.
The text or inline nodes.
How many lines to keep. Defaults to 1.
An optional title attribute carrying the untruncated text.
The element to build. Defaults to p.
Extra classes for the text.
(truncate-text "A very long description indeed" #:lines 2)
Hide content visually while leaving it available to assistive technology.
This is the framework’s ‘sr-only’ class with a name, so a page does not have to remember which utility it is. Use it for the label of an icon-only control, a section heading that would repeat what is already visible, or an instruction that only makes sense to a screen reader.
Pass #:focusable? #t for the rarer case of content that should be
hidden until it takes focus – a skip link, or a control that appears
when tabbed to. That one needs to be an element that can hold focus, so
the default tag is a <span> and callers pass #'a or
#'button as appropriate.
The text or nodes to hide.
The element to build. Defaults to span.
Whether the content becomes visible when focused. Defaults to false.
Extra classes for the wrapper.
(visually-hidden "Loading search results") (visually-hidden "Skip to content" #:tag 'a #:focusable? #t)
Next: (hygguile css), Previous: (hygguile components typography), Up: API