Components
19 components. Web, slides and diagrams.
React 18, no build step: load bundle.css and bundle.js and use window.KDA. Props are typed in index.d.ts. Examples use sample content.
Structure
SectionMarkerEyebrowType
HeadlineActions
TextLinkButtonIconButtonContent
DetailBlockExperienceListRoleCardTestimonialArticleCardForms
FieldSurfaces
GlassPanelIllustration
NodeFieldSlides
CoverSlideSlideDiagrams
LayerGridPipelineComparisonStructure
SectionMarker
Numbered chapter marker that opens every major section, set in eyebrow over a line hairline.
Provide: number ("01"–"05", zero-padded), title (a short poetic chapter name), optional context (the plain-English discipline, right-aligned).
- Do: keep chapter numbers sequential down the page; pair the poetic
titlewith a literalcontext("The distance between idea & impact" / "Transformation"). - Do: sit it
space-10below the viewport top so it clears the fixed header. - Don't: use it inside cards: use
Eyebrowthere. - Mobile (<800px): hide
context.
Eyebrow
Uppercase label (eyebrow, text-subtle) that sets up the headline beneath it.
Provide: a short phrase, usually a three-beat list with full stops ("Technology. Transformation. AI.") or a plain descriptor ("Strategy through to delivery").
- Use
tone="accent"(accent-soft) only on glass dialogs. - One eyebrow per block,
space-5above the headline. - Don't: write sentences in it; don't use it as a button.
Type
Headline
The signature two-beat headline: a plain statement in ink, then a turn in text-muted (or accent-soft with tone="mint").
Provide: lead and second: two short sentences that complete each other ("Think deeply. / Share openly."). level 1 for the hero only.
- Sizes:
xl→display-xl(hero),l→display-l(chapters),m→display-m(dialogs),s→heading(in-section). - Manrope Light 300 with −0.06em tracking, never bold a headline.
- Mint
secondbeat at most once per screen; the rest are muted. - Don't: end with an exclamation mark; don't stack more than two beats.
Actions
TextLink
The site's primary call to action: text, generous gap, and a mint arrow, underlined with accent-line. There are no filled CTA buttons on pages.
Provide: a label in sentence case and an href. Arrow: ↗ leaves the section or site, ↓ scrolls on the page, →/← step through a sequence.
size="big"(link-big, 30px) once per page, in the closing section.- Hover opens the gap (32 → 43px) and turns the label
accent. - Don't: put two links side by side with the same arrow; don't box it.
Button
Filled mint button for committing a form, and a ghost chip for utility toggles.
Provide: a one-word or two-word label; arrow glyph (↗ for send); type="submit" inside forms.
primary:accent-softfill (dark) /accent(light),on-accentlabel,radius-sm,shadow-button. Only for form submission.ghost: smallsurfacechip for controls like "Pause motion".- Navigation is never a button: use
TextLink.
IconButton
38px round control (radius-round, line-strong border) for carousels, pause/play and closing dialogs.
Provide: label (required: the accessible name) and a glyph child (← → ↑ ↓ Ⅱ). variant="close" renders × and rotates 90° on hover.
- Pair prev/next with a counter in
caption("01 / 05"). - Disabled state: 25% opacity, no hover.
Content
DetailBlock
A hairline-topped block that grounds a chapter in something concrete: a venture, a teaching post, a programme.
Provide: number (a label such as "In practice" or "Teaching"), title, a one- or two-sentence body, optional link.
- Max width
measure-chapter. Body inbody-s,text. - One per chapter,
space-5below the chapter paragraph.
ExperienceList
Ruled list of organisation and role: the "See the whole" experience index.
Provide: items of {name, role}. Names in list-strong / ink-strong, roles in text-muted.
- Three visible rows when used as a rolling carousel; pair with
IconButtoncontrols and a pause. - Real organisations and titles only.
RoleCard
Square card for one role or offer in the "Many roles" sequence; the active card lifts, brightens and shows its mint corner arrow.
Provide: number, title, image (a moody, desaturated photo or render: the card darkens its lower half so the title reads), href, active.
- Five across on desktop (
space-4gap); one at a time on mobile. - Title uses
title-card; its whites and the active mint number are fixed values because they always sit on themediaground and image scrim, in both themes. - Don't: use bright stock photos or faces looking at camera.
Testimonial
A real, attributed recommendation: photo, name, role and relationship, and the one line that matters.
Provide: quote (verbatim, one or two sentences pulled from the full recommendation), name, role, relation, photo.
- Only real recommendations with permission, never invented or paraphrased quotes.
- Offer the full text behind a "Read full recommendation +" disclosure.
ArticleCard
Notebook teaser: image, category and index, date and kind, title, "Read the story ↗".
Provide: title, href, category (Personal, Resources…), index, date (16 Feb 2026: day, short month, year), kind (Essay), optional image and excerpt.
- Three across under "Ideas, in practice."; the title turns
accent-softon hover. - Titles keep the article's own casing.
Forms
Field
Labelled input or textarea in the contact dialog: 12px label above, field well with shadow-field, radius-sm.
Provide: label (plain question or noun: "Your name", "What would you like to talk about?"), hint for "(optional)", error text when invalid.
- Focus: 2px
focusoutline, offset 2px. - Errors:
dangerborder plus the written message, never colour alone. - Two fields per row on desktop (
space-4gap), one below 600px.
Surfaces
GlassPanel
Frosted glass panel (radius-lg, shadow-glass, space-7 padding) for the contact dialog and announcements. It floats over the node-field background.
Provide: eyebrow, title + titleEm (the mint beat), intro, onClose, and the form or content as children. Wrap in a <dialog> for modal use.
- The blur needs something behind it; on a flat ground it falls back to
surface-glass. - Width
measure-dialog. One per screen.
Illustration
NodeField
The brand's one illustration: pale nodes joined by hairlines, with a single mint spark. It fills its container.
Provide: a sized, positioned container. Set density to the job (sparse behind reading, balanced for heroes and covers, dense only as a full-bleed image with no type), bias away from the words (right when copy sits left), and a seed to fix the layout.
- On screen it drifts slowly and shows a Pause motion control (
Ⅱ). Passanimate={false}for slides, print and exports; reduced-motion users always get a still field. - Colours come from the theme: nodes and hairlines in
ink, the spark inaccent. It works on Night and Paper. - One spark (
sparks, default 1). Two at most on a wide hero. - Don't: colour it with the logo spectrum, crowd it, or run it behind long body copy at
balancedor above.
Slides
CoverSlide
The deck cover: lockup top-left, eyebrow, a two-line display title, numbered contents and a footer.
Provide: eyebrow ("Subject · Month Year"), lead (line one, ink) and second (line two, text-muted), contents as {number, name, sub} (two to four items), logo, footer ("Prepared for … by Keith de Alwis, status.
artplaces a graphic from the Illustration group on the right, faded into the ground behind the type (Night covers only; the orbital sphere is the default choice).fieldinstead adds a still, generated node field, which also works on Paper.- Contents numbers are mint: the cover's one signal.
- Don't: add a third title line, a subtitle paragraph or imagery other than the node field.
Slide
A 1280 × 720 content slide: eyebrow, two-beat title, lockup top-right, one body and a footer rule with meta and status.
Provide: eyebrow ("Subject · Deck · Section"), lead and second (two beats on one line), logo (kda-lockup-transparent.png on Night, kda-lockup-paper.png on Paper, from the Logos group), footer ("Subject · Slide name · Month Year"), status ("Draft · de-alwis.com"; every footer carries the site), and one diagram or idea as children. intro adds a one-sentence lead under the title.
theme="dark"(Night) for screen,theme="light"(Paper) for print and documents; omit to inherit. Pass the logo file that matches the theme.- Fixed canvas: scale the slide with a CSS transform to fit, never reflow it. Export at 2× or 4×.
- One title, one idea. Mint marks one category per slide.
- Don't: put the status in a header chip, add shadows, or add vendor logos or icons.
Diagrams
LayerGrid
A stack of labelled bands for architecture and operating-model slides: channels down to platform, one row per layer.
Provide: rows with a two-digit number, a name, a short caption and cells of {title, sub}. Mark the focal category with focus on its cells. legend names each box style used.
- Row
kind:cells(default; plain cells joined bylinehairlines),pipeline(cells in sequence, joined by mint→),external(dashedline-strongboxes for outside systems). focusboxes a cell inaccentoveraccent-tint. Use it for one category only (the MVP, the scope of this phase), even if that category spans rows.- Sublabels list technology or contents separated with
·. Up to six cells a row. - Don't: box every cell, colour rows differently, or add icons or vendor logos.
Pipeline
Numbered steps left to right, joined by mint arrows, with optional data stores dropped below the steps that write to them.
Provide: steps of {number, name, tech, note}. Add output: {label, name, tech} to a step that writes somewhere: it draws a line-strong connector labelled in slide-label and a store box underneath. Mark the step that matters with focus.
- Three to six steps. Step names are verbs or short nouns ("Ingest", "Graph update").
techis what does the work;noteis what comes out.- For feedback loops or many-to-many routing, draw the diagram as SVG with the same tokens instead of forcing it into this component.
- Don't: number steps that aren't a real sequence.
Comparison
A ruled table for "today vs proposed", option trade-offs or before-and-after, one row per layer or decision.
Provide: columns of {label, width, kind} and rows of cells. A cell is a string, or {text, muted, accent, dot}.
- Column
kind:label(first column, Manrope),text(default),strong(the recommended column, inink),tag(uppercase move: Change, Keep, Add). - Write unknowns as "Not documented" with
muted. Never fill a gap with a guess. dotputs a mint dot before a cell to mark rows in scope; say what the dot means in a legend line under the table.accenton the one tag that needs attention (usually "Change"). Leave the rest intext-subtle.

