Woven edge

The brand's signature: a selvedge, the woven edge that stops cloth fraying, drawn wherever a field of colour meets cotton.

Atom · stable · v2.0.0 · owner: Site system lead · contract 19 of 20 points (open: figma)

Do and don't

Do: Saffron thread under a dye field

Rendered by woven-edge.ts

Open example: Woven edge · Do: Saffron thread under a dye field Use the full-page example to follow page links.

The join of a field and cotton.

Do: Ink thread next to saffron

Rendered by woven-edge.ts

Open example: Woven edge · Do: Ink thread next to saffron Use the full-page example to follow page links.

It stays visible beside the saffron call to action.

Don't: As a divider between tiles

Rendered by woven-edge.ts

Open example: Woven edge · Don't: As a divider between tiles Use the full-page example to follow page links.

Inside a grid it is a generic line, not a selvedge.

Don't: Saffron next to saffron

Rendered by woven-edge.ts

Open example: Woven edge · Don't: Saffron next to saffron Use the full-page example to follow page links.

The threads disappear into the field.

Rules

RuleWhyCheck
The edge sits at every join between a dye or ink field and cotton, and nowhere else.One rule, applied everywhere, is what makes it read as a system; the edge used once then never was the owner's first complaint.Automated: scripts/site/system/compose.ts (inserts it) and scripts/site/system/check-pages.ts (verifies every built page)
Only the composer places the edge; templates never draw it.If templates drew it, each would decide differently.Automated: scripts/site/system/check.ts (no template renders .selvedge)

API

PropTypeRequiredDefaultWhat it does
threadsaffron | ink | indigo | madder | teal | contextNo"saffron"The thread colour: saffron next to dye or ink fields, ink next to saffron; context lets the surrounding element set it (the footer).

Contract details

The full contract: identity, anatomy, variants, states, tokens, layout, motion, accessibility, content, tests

Identity

AspectValue
Idwoven-edge
LayerAtoms
Categorybrand
OwnerSite system lead
Statusstable
Version2.0.0
Sourceapps/showcase/site/system/atoms/woven-edge.ts (private repository; the contract and the render function are this one module)
VersionDateChange
1.0.02026-10-25The selvedge strip at the foot of page heads and the top of the footer.
2.0.02026-10-26One rule: the edge sits at every join between a dye or ink field and cotton, and nowhere else; the composer places it (D-SITE-003).

Use when

  • Every join between a dye or ink field and cotton, in both directions. Why: A selvedge runs along both edges of a cloth; a field is a cloth, so it has an edge on each side (D-SITE-003).

Do not use when

  • As a divider between tiles or paragraphs. Why: Used as a divider it becomes a generic line and stops meaning 'cloth'.
  • Between two cotton sections or inside a field. Why: There is no join of field and cotton there, so the rule does not place one.

Anatomy

PartWhat it is
rootspan.selvedge, aria-hidden, 18 px tall: three rows of 12 px squares on cotton, drawn with CSS gradients.

Made of: tokens:colour, tokens:selvedge.

Used in: library-overview.

Variants

VariantWhenWhy
saffron threadNext to an indigo, madder, teal or ink field.Saffron shows on every dark ground and echoes the action colour.
ink threadNext to a saffron field.Saffron on saffron would vanish.

States

StateRendered or not applicable
defaultdefault
hoverNot applicable: The woven edge is not interactive, so it has no hover state.
focus-visibleNot applicable: The woven edge does not take focus; links and buttons inside it carry their own focus ring.
activeNot applicable: The woven edge cannot be pressed.
disabledNot applicable: The woven edge has nothing to disable.
loadingNot applicable: The woven edge is rendered at build time and is complete when the page loads.
emptyNot applicable: The woven edge is not rendered without content; the builder skips it.
errorNot applicable: The woven edge shows no data that can fail.
currentNot applicable: The woven edge has no current item.
visitedNot applicable: The woven edge is not a link.
expandedNot applicable: The woven edge does not open or close.

Tokens

PartToken
root.height--selvedge-height (18 px)
square.size--selvedge-square (12 px)
row.height--selvedge-row (6 px)
ground--cotton
thread--saffron, or --ink next to saffron
--woven-edge-edge-maddervar(--madder)
--woven-edge-height-selvedge-heightvar(--selvedge-height)
--woven-edge-background-color-cottonvar(--cotton)
--woven-edge-background-image-selvedge-squarevar(--selvedge-square)
--woven-edge-background-size-selvedge-rowvar(--selvedge-row)
--woven-edge-background-position-selvedge-rowvar(--selvedge-row)
--woven-edge-edge-indigovar(--indigo)
--woven-edge-edge-saffronvar(--saffron)
--woven-edge-edge-tealvar(--teal)
--woven-edge-edge-inkvar(--ink)
--woven-edge-background-image-edgevar(--edge)

Layout

AspectValue
breakpointsRequired review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; full width at every size.
wrappingNot text.
textExpansionNot text.

Spacing and rhythm

AspectValue
internalThree 6 px rows.
externalNone: it sits exactly on the join.
rhythmPlaced by the composer between sections, never by a template.

Motion

AspectValue
NoneThe edge is cloth, and cloth does not move.

Runtime and reuse

  1. Render-only element; mount any registered child enhancements separately. Preserve required Site CSS, fonts, responsive and locale rules from nativeElement.

Accessibility passport

AspectValue
rolepresentation (aria-hidden)
nameNone
keyboardNot interactive.
focusNot focusable.
screenReaderSilent.
contrastDecorative; hidden in forced-colours mode.
targetNot a target.

Content

SlotLengthVoice
decorative thread (no text)No label, caption or child text; the existing thread enum or surrounding context supplies colour.Silent decoration at a field/cotton join; explain the join in adjacent page content if needed.

Good: “A silent saffron edge between an indigo page head and cotton body.” · “An ink edge between a saffron call to action and the cotton footer.”

Bad: “A labelled divider announcing a new section.” · “A saffron edge between two cotton paragraphs.”

Japanese: The same silent, aria-hidden edge is used on Japanese pages. It has no translatable copy or accessible name; Japanese section titles remain in their owning templates.

Icons and illustrations

  • art:edge-master

Decisions and exceptions

Usage

213 uses across the built pages (measured by npm run site:system).

Tests

AspectValue
unittests/unit/site-system.test.ts: renders every do and don't example through the registry and checks the classes it owns
visualNot yet: there are no screenshot baselines; the Library page is checked for sideways scroll at 1440 px by tests/site/system.spec.ts
a11ytests/site/system.spec.ts: axe (0 serious or critical) on the element's Library page in light and dark
parityscripts/site/system/check.ts: Library examples are rendered by the same render function the site imports

Figma

not-yet: The Loom Site Figma library is the last stage of the plan; this element is not mapped yet.

Open in Storybook

Start with a conversation about your system.

We read your system, show you what we found, and agree with your team what to fix first.