Patterns
The chequer, the wordmark field and the paper grain: how a brand surface gets its texture.
Examples
Overview
One component, six variants. chequer, houndstooth, twill and wordmark are fields: a motif
repeated until it is the surface. dissolve is the transition between two surfaces. grain is the
stock the other fields print on.
import { Pattern } from "@rogo-technologies/brand/pattern";
<div className="bg-marketing-forest text-marketing-primary relative">
<Pattern variant="wordmark" />
{children}
</div>;None of them paint a colour. Every tone is currentColor at low alpha, so a pattern takes the
ink of whatever it sits on and one component serves every band on the site. Set the ink with a text
colour, text-marketing-primary on the brand greens. All four are decorative: aria-hidden, no
content, no pointer events.
| Prop | Default | What it does |
|---|---|---|
variant | "chequer" | chequer, houndstooth, twill, wordmark, dissolve or grain. |
scale | 1 | Size of one repeat. On dissolve, leave it off to size from CSS. |
intensity | 1 | Weight of the pattern, where 1 is the tuned default. Fields only. |
rowCount | 16 | Length of the run, in rows. dissolve only. |
className | - | Masks, blend modes, positioning. |
The three fields fill their container, so they want a position: relative parent and nothing else.
The dissolve is the odd one and knowingly so: it is a band with a height of its own, so it sits in
flow rather than over a ground.
Chequer
Circles inset in a checkerboard. The brand's board, and the default.
<Pattern className="[mask-image:linear-gradient(to_left,transparent,#000_60%)]" />Give it an edge to fade into. A field that stops at a hard edge reads as a panel someone pasted on. Mask it toward the content, as the Felix manifesto flanks do, so it has no visible boundary. And keep the reading column clear: type over the chequer loses its ground.
Below desktop, check the width you have left. A few cells either side of a column reads as a
stray stripe, not a field. The manifesto band drops the pattern entirely on narrow viewports rather
than shrinking it.
Houndstooth
The pied-de-poule, generated from the cloth it imitates: a four-thread colour check in a 2/2 twill weave, so the hooks land where a loom would put them. This is the landing hero's field.
<Pattern variant="houndstooth" />For the cursor-following form, use InteractivePattern: the same field, with the weave itself
answering the pointer. Every run near the cursor swells from its centre on a spring and holds its
heat for a moment, so the pointer combs a slowly cooling trail into the cloth, and a press drops a
wave that rolls through the whole field, ringing the threads as it passes. There is no cursor
glow: each thread bolds as it grows and its ink catches a faint sheen as it springs, so the light
follows the weave's own geometry rather than a disc around the pointer. Mouse-only by design:
without a fine hover pointer the response never renders, and reduced motion follows the pointer
with no trail, wave, or springing.
The response is drawn on the GPU, and the plain field stays underneath it. A machine without
WebGL 2, or with hardware acceleration switched off, keeps the static Pattern and loses only the
interaction, so the band it sits in reads the same either way.
import { InteractivePattern } from "@rogo-technologies/brand/interactive-pattern";
<InteractivePattern variant="houndstooth" intensity={0.9} />;Twill
Courses of slanted bricks, each column half a course out of step with its neighbour. The case-study cards' weave.
<Pattern variant="twill" />Wordmark
ROGO broken over two lines, RO above GO, set at display size and repeated until it is the surface. The chequer's two tones exactly, so the two boards are one material and a page can run from one into the other without a seam.
<Pattern variant="wordmark" scale={1.2} intensity={0.7} />It is typeset, not tiled, and both the tracking and the leading are positive. Broken over two lines the mark stops being a word to read along and becomes a lockup to read as a unit, so what the field needs is ground around each one; too little and the halves pull apart, and an RO reads with the GO of its neighbour. Every second line steps half a repeat across, which is the chequer's own half-cell offset, so each GO sits between the ROs above it and the gaps never stack into columns down the page.
The field stays one flat tone. The marks are drawn opaque inside a single group carrying the ink
alpha, rather than each carrying it themselves. At this setting nothing overlaps, but per-mark alpha
compounds wherever two marks do cross, and a crossing brighter than the marks around it reads as a
blotch rather than as an overlap, so tightening the setting back would blotch the board. It is the
same rule the chequer's single evenodd path is drawn under, and it is what keeps the two boards in
the same two shades no matter how many marks pile up.
It is a field, not a headline. At scale 1 a repeat is 190px wide and holds one lockup, which
is large enough to be read as the wordmark up close and to settle into texture at a glance. Push it
much smaller and it turns to mush; much larger and a section shows one word, which is a graphic
rather than a pattern.
Never over a reading column. Letterforms behind letterforms is the one place a field genuinely costs legibility. It belongs on chrome: a hero flank, a footer band, a CTA panel. And it wants a mask into the content, like the chequer does.
Dissolve
The chequer thickening row by row until it is a solid bar. This is how the site reaches its dark end: through the pattern, not through a colour change or a gradient.
<Pattern variant="dissolve" className="[--chequer-scale:0.65] desktop:[--chequer-scale:1]" />There is no gradient in it. The ground stays the ground, and what the eye reads as a ramp is the ink coverage rising from a third of each cell to all of it. Two custom properties say which surfaces it runs between:
| Property | Default | What it does |
|---|---|---|
--chequer-ground | --marketing-bg | The surface it starts from. |
--chequer-ink | --marketing-dark | The surface it ends on. |
Both ends have to be real. The solid last row is a promise that the next surface is that colour. Run it into a footer that is a different dark and the seam shows. Equally, a dissolve between two surfaces of the same colour is decoration with nothing to do, so the site footer skips it on pages that already end dark.
Animate from the solid end. Scaling from the open end flashes ground above the dark surface.
Anchor the transform to the welded row (origin-bottom for the footer) and the short edge left
over opens onto the page's own colour, where it cannot be seen.
To animate it, reach past Pattern for the geometry and own the rows yourself. The split exists so a
consumer can drive them on whatever motion runtime it uses:
import { chequerDissolveRows } from "@rogo-technologies/brand/chequer-dissolve";
const ROWS = chequerDissolveRows();
<div aria-hidden className="chequer-dissolve">
{ROWS.map((row, index) => (
<motion.div key={index} className="chequer-dissolve-row" style={row} variants={ROW} />
))}
</div>;Grain
Not a motif: a procedural fractal-noise layer that makes a flat fill read as printed stock. Drawn in code rather than shipped as a bitmap, so it is resolution-independent, weightless, and tints with whatever it lies on.
<Pattern variant="grain" />It blends with soft-light, so it shades the fill rather than greying it. scale moves the noise's
frequency rather than a tile: a coarser grain is a lower frequency, which is why the two run
inverse. On light grounds drop intensity toward 0.45, since the default is tuned for the brand
greens and reads dirty on cream.
One texture per surface. Grain over the chequer is two treatments fighting for the same ground, and both lose.
Where they come from
All four live in @rogo-technologies/brand, and the dissolve's row styling needs the brand
stylesheet:
@import "@rogo-technologies/brand/styles";Each field's geometry sits in its own motif module, chequer-motif.ts and wordmark-motif.ts,
with no renderer attached, because the boards are also drawn outside React: the Open Graph image is
rasterised from an SVG string, not from a component tree, and the two have to describe the same
board. If you need one somewhere React does not reach, build it from the motif rather than redrawing
it. Both read their two tones from pattern-tones.ts, which is the only reason they are guaranteed
to be the same shades.
Brand only. These are --marketing-* surfaces, and neither the fields nor the grain belongs in
product code.