Kwacha KultureSav anna

Documentation

Savanna — the design system

A proudly-African, dark-first design system — palette grounded in deep teal-green, accented with Kente gold, emerald, clay and indigo. Ships as a suite of installable packages usable in React, Next, Vue, Svelte, Angular or plain HTML. This page documents every layer: tokens, CSS, fonts, motifs, 91 components and Web Components.

Overview

What Savanna is, and how it's built

Savanna is layered like MUI: a framework-agnostic core (tokens, CSS, icons, motifs, fonts) plus framework bindings. The core is MIT-licensed and free; the advanced React components are commercial. You only install the packages you need.

Two variable namespaces exist by design, and it's important to know which you're using:

  • --tz-* — the React design system. Loaded by @kwacha-kulture/savanna/styles/theme.css and consumed by the @kwacha-kulture/react components (e.g. --tz-bg, --tz-border, --tz-shadow-md).
  • --sv-* — the framework-free CSS layer. Loaded by @kwacha-kulture/savanna-css and consumed by the sv-* classes and Web Components (e.g. --sv-gold, --sv-bg).

The @kwacha-kulture/savanna-tokens package is the single source of truth for the raw values behind both, and also emits a tokens.css (--sv-color-*, --sv-radius-*…) and a W3C tokens.json for design tools.

The suite

Seven packages

PackageLicenceWhat it gives youUse in
@kwacha-kulture/savanna-tokensMITDesign tokens as JS/TS, CSS custom properties and W3C JSON. Zero dependencies.Any tool / framework
@kwacha-kulture/savanna-cssMITThe entire system as framework-free CSS + vanilla JS + inline-SVG motifs.Any framework / plain HTML
@kwacha-kulture/savanna-elementsMITNative Web Components (custom elements) built on the CSS layer.Vue / Svelte / Angular / HTML
@kwacha-kulture/savanna-iconsMIT318 Adinkra, Ndebele & UI icons as React components and raw SVG, with a registry.React / SVG
@kwacha-kulture/savannaMITThe React design system: tokens, African motifs, brand marks and theme.css (--tz-* variables).React
@kwacha-kulture/reactMIT54 base React components: buttons, cards, forms, overlays, tables, free charts and utilities.React
@kwacha-kulture/react-proCommercialAdvanced React components: data grid (+ Pro), spreadsheet, kanban, gantt, tree view, rich-text editor, world map, date/time pickers, pro charts. Requires a paid licence.React

Not on npm: the Savanna Display typeface is licensed separately — download the font kit from Type under a licence that covers it.

Setup

Installation

Install only what you need. Peer dependencies: the React packages need react and react-dom ≥ 19 and motion ≥ 12; everything else is dependency-free.

@kwacha-kulture/savanna-tokensMIT

Design tokens as JS/TS, CSS custom properties and W3C JSON. Zero dependencies.

npm i @kwacha-kulture/savanna-tokens
@kwacha-kulture/savanna-cssMIT

The entire system as framework-free CSS + vanilla JS + inline-SVG motifs.

npm i @kwacha-kulture/savanna-css
@kwacha-kulture/savanna-elementsMIT

Native Web Components (custom elements) built on the CSS layer.

npm i @kwacha-kulture/savanna-elements
@kwacha-kulture/savanna-iconsMIT

318 Adinkra, Ndebele & UI icons as React components and raw SVG, with a registry.

npm i @kwacha-kulture/savanna-icons
@kwacha-kulture/savannaMIT

The React design system: tokens, African motifs, brand marks and theme.css (--tz-* variables).

npm i @kwacha-kulture/savanna
@kwacha-kulture/reactMIT

54 base React components: buttons, cards, forms, overlays, tables, free charts and utilities.

npm i @kwacha-kulture/react
@kwacha-kulture/react-proCommercial

Advanced React components: data grid (+ Pro), spreadsheet, kanban, gantt, tree view, rich-text editor, world map, date/time pickers, pro charts. Requires a paid licence.

npm i @kwacha-kulture/react-pro

Get going

Quick start, per framework

React / Next.js

Install @kwacha-kulture/react, import the stylesheet once (in your root layout / entry), then use components. They are client components — under the Next App Router they carry "use client", so import them into client boundaries.

// app/layout.tsx (or your entry)
import '@kwacha-kulture/react/styles.css';

// any component
import { Button, Card, Field, Input } from '@kwacha-kulture/react';

export function Example() {
  return (
    <Card>
      <Field label="Email"><Input placeholder="you@africa.com" /></Field>
      <Button variant="primary">Continue</Button>
    </Card>
  );
}

For the design language (motifs, brand marks, the --tz-* theme) add @kwacha-kulture/savanna:

import '@kwacha-kulture/savanna/styles/theme.css';
import { KwachaMark } from '@kwacha-kulture/savanna/brand';
import { Sankofa } from '@kwacha-kulture/savanna/motifs';

Pro components need a licence key set once at startup:

import { setLicenseKey, DataGridPro } from '@kwacha-kulture/react-pro';
import '@kwacha-kulture/react-pro/styles.css';

setLicenseKey(process.env.NEXT_PUBLIC_SAVANNA_LICENSE!);

Vue · Svelte · Angular · plain HTML

Use the Web Components + the CSS layer. They work identically everywhere.

import '@kwacha-kulture/savanna-css/savanna.css';
import { defineSavannaElements } from '@kwacha-kulture/savanna-elements';
defineSavannaElements();

// then in any template:
// <sv-button variant="primary">Get started</sv-button>
// <sv-card>…</sv-card>  <sv-badge tone="emerald">Live</sv-badge>

No build step at all? Load from a CDN:

<link rel="stylesheet" href="https://unpkg.com/@kwacha-kulture/savanna-css/dist/savanna.css">
<script type="module">
  import { defineSavannaElements } from 'https://esm.sh/@kwacha-kulture/savanna-elements';
  defineSavannaElements();
</script>
<button class="sv-btn sv-btn-primary">Get started</button>

Design tokens only (Tailwind, Figma, native…)

import { theme, palette, space } from '@kwacha-kulture/savanna-tokens';
// or CSS variables:  import '@kwacha-kulture/savanna-tokens/tokens.css';  // --sv-color-* on :root
// or W3C JSON:       @kwacha-kulture/savanna-tokens/tokens.json  -> Style Dictionary / Figma

Foundation

Design tokens

Every value is a token. Consume them as JS/TS objects, as CSS variables, or as W3C JSON. The palette carries stops 50 → 900; components read the semantic theme, never raw stops.

Palette

Family50100300500700900
terracotta#FBEFEA#F4D5C8#E08A66#C4582E#8A3A1D#4A1F10
sienna#FAEDE6#F1CCB7#D38057#A24A20#6E2F11#3A1808
mahogany#F4E6E1#E2BCB0#A86A57#7A3A2B#4F2218#2A100A
ochre#FBF1DA#F4DCA1#E0AE4E#B8841E#7A560B#402C03
kenteGold#FFF6D9#FFE89B#F5CE5A#E0A91D#9C7308#523B02
emerald#E6F5EC#B7E0C5#5DBE82#1F8A48#0F5128#062513
indigo#E8E7F5#BCB9DF#6F69C0#3D3690#221E5C#0F0D33
clayRed#FBE7E3#F2BAAF#D9614F#B83C2E#7B2418#411008
ink#1B1813#100E0A#070605
charcoal#EDEDEC#C7C6C2#7A7873#3E3C38#26241F#0F0E0B
bone#FBF8F2#F4EEE0#D8CDB1#A89B7B#6F6448#3A3220

Semantic theme theme.*

TokenValue
theme.bg#0B0907
theme.bgRaised#16140F
theme.bgInset#070605
theme.bgPattern#100E0A
theme.bgOverlayrgba(7, 6, 5, 0.72)
theme.text#FBF8F2
theme.textStrong#FFFFFF
theme.textMuted#D8CDB1
theme.textSubtle#7A7873
theme.textInverse#0B0907
theme.borderrgba(216, 205, 177, 0.14)
theme.borderStrongrgba(245, 206, 90, 0.42)
theme.borderMotif#9C7308
theme.primary#E0A91D
theme.primaryHover#F5CE5A
theme.primaryInk#0B0907
theme.secondary#C4582E
theme.secondaryHover#E08A66
theme.emerald#1F8A48
theme.emeraldHover#5DBE82
theme.indigo#3D3690
theme.indigoHover#6F69C0
theme.success#1F8A48
theme.warning#B8841E
theme.danger#B83C2E
theme.info#6F69C0
theme.focusRing#F5CE5A
theme.focusRingSoftrgba(245, 206, 90, 0.35)

Spacing, radii & shadows

spacerem
00
10.25rem
20.5rem
30.75rem
41rem
51.25rem
61.5rem
82rem
102.5rem
123rem
164rem
205rem
246rem
radiivalue
none0
sm4px
md8px
lg14px
xl20px
pill999px
shadowskind
smwarm, gold-tinted
mdwarm, gold-tinted
lgwarm, gold-tinted
glowwarm, gold-tinted

Typography scale

fontSizesvalue
display4rem
h13rem
h22.25rem
h31.75rem
h41.375rem
h51.125rem
h61rem
body1rem
small0.875rem
caption0.75rem
overline0.6875rem
fontWeightsvalue
regular400
medium500
semibold600
bold700
black800
lineHeightsvalue
tight1.1
snug1.25
normal1.5
relaxed1.7
letterSpacingsvalue
tight-0.02em
normal0em
wide0.04em
overline0.18em

Make it yours

Theming & dark mode

Savanna is dark-first by design. Re-branding means overriding a couple of accent variables — no rebuild needed.

Re-colour the CSS layer

/* your stylesheet, loaded AFTER savanna.css */
:root {
  --sv-gold: #C4582E;       /* new accent */
  --sv-gold-soft: #E08A66;
  --sv-emerald: #1F8A48;
}

Prefer no code? Ship the templates' bundled customize.html — pick a preset or your own colours, preview live, and copy the CSS.

Re-colour the React system

Override the --tz-* variables from theme.css, or generate a fresh set from the tokens at build time with css(prefix) from @kwacha-kulture/savanna-tokens.

The CSS layer also supports a light theme on demand: set data-theme="light" on the <html> element (the bundled data-theme-toggle does this and persists it).

Type

Fonts

Three typefaces, bound to CSS variables so you can swap them:

RoleTypefaceVariable
DisplaySora (headings, prices)--sv-display
BodyDM Sans--sv-body
MonoJetBrains Mono--sv-mono

Loading options: (1) next/font in a React app, binding --font-display / --font-body / --font-mono; (2) the Google-Fonts <link> that @kwacha-kulture/savanna-css exports as FONT_LINK; or (3) self-host and point the variables at your files. A system fallback stack means everything still renders offline.

import { FONT_LINK } from '@kwacha-kulture/savanna-css';
// FONT_LINK is a <link> string for Sora + DM Sans + JetBrains Mono.

A bespoke display face, Savanna Display, is sold separately (woff2/woff/ttf/otf) — it's a drop-in for the --sv-display / --font-display slot.

@kwacha-kulture/savanna-css

The framework-free CSS layer

Import savanna.css and compose with sv-* classes — in any framework or plain HTML. Theming variables are listed under Theming.

Buttons

ClassDescription
sv-btnBase button — carries the Kente stripe on its top edge.
sv-btn-primaryGold-gradient primary action (with gold glow).
sv-btn-emerald · sv-btn-secondary · sv-btn-ghostEmerald · clay · outline variants.
sv-btn-lg · sv-btn-smLarge / small sizes.
sv-icon-btnSquare icon button; add a .sv-count child for a badge.

Cards & surfaces

ClassDescription
sv-cardElevated card with the Kente top-stripe.
sv-card-plainCard without the stripe.
sv-card-watermarkFaint motif watermark, absolutely positioned inside a card.
sv-kente-stripA woven 5-colour Kente divider bar.
sv-kente-bg · sv-adinkraSubtle Kente / Adinkra background texture on any container.
sv-stat · sv-feature · sv-plan · sv-tileStat card · feature card · pricing plan · media tile.

Forms

ClassDescription
sv-inputText input / textarea — gold left-edge + inset.
sv-tagChip/tag with a gold left border.
sv-pills · sv-pillPill group · a single pill (add .active).

Badges & display

ClassDescription
sv-badgeBase badge.
sv-badge-gold · sv-badge-emerald · sv-badge-terracottaTone variants.
sv-avatarAvatar with the signature conic-gradient ring.
sv-priceDisplay-font price text in gold.

Layout

ClassDescription
sv-containerMax-width (1160px) centred container with padding.
sv-sectionVertical section rhythm (80px block padding).
sv-grid + sv-cols-2/3/4Responsive grid; columns collapse on small screens.
sv-row · sv-between · sv-centerFlex row · space-between row · text-centre.

Typography

ClassDescription
sv-eyebrowMono uppercase kicker with a Kente tick.
sv-goldAnimated shimmering gold gradient text.
sv-muted · sv-dimMuted / dim text colour.
sv-monoMonospace (JetBrains Mono).

Chrome & overlays

ClassDescription
sv-header · sv-nav · sv-brand · sv-nav-linksSticky header, nav bar, brand lockup, nav links.
sv-app · sv-side · sv-topbar · sv-contentApp shell: sidebar layout, top bar, content region.
sv-menu · sv-menu-popDropdown menu.
sv-drawer · sv-scrimSlide-in drawer (e.g. cart) + backdrop.
sv-acc · sv-acc-q · sv-acc-aAccordion (question / answer).
sv-tableData table (sortable headers via [data-sort]).
sv-hero · sv-hero-img · sv-hero-canvasCinematic hero, ken-burns image bg, generative canvas.

Theming variables

VariablePurpose
--sv-bgDeep teal-green ground (#0A1A1F).
--sv-surface · --sv-surface2 · --sv-insetRaised / raised-2 / inset surfaces.
--sv-text · --sv-muted · --sv-dimText · muted · dim.
--sv-gold · --sv-gold-softKente-gold accent — override these to re-brand.
--sv-emerald · --sv-clay · --sv-indigoSecondary accents.
--sv-line · --sv-line-strongBorders.
--sv-r-sm · --sv-r · --sv-r-lg · --sv-pillCorner radii.
--sv-shadow · --sv-glow-goldElevation shadow · gold glow.
--sv-display · --sv-body · --sv-monoFont families.
--sv-kenteThe repeating Kente gradient used on stripes and button edges.

No framework needed

JavaScript behaviours

The CSS layer ships a dependency-free behaviour script. In a bundler call initBehaviors() once; in plain HTML include savanna.js. Then wire interactions declaratively with data-* attributes:

import { initBehaviors } from '@kwacha-kulture/savanna-css';
initBehaviors(); // idempotent; no-op on the server
Attribute / hookBehaviour
data-nav-toggle="#sel"Toggle .open on the target element (mobile nav / sidebar).
data-theme-toggleFlip light/dark; the choice persists to localStorage.
.sv-menu + .sv-menu-btnDropdown: click the button to open, click-away to close.
data-cart-open / data-cart-closeOpen / close the cart drawer (#sv-cart).
data-add-to-cart data-name data-price data-imgAdd an item to the persistent (localStorage) cart.
data-cart-count / data-cart-subtotal / data-cart-listLive targets: item count · subtotal · rendered item list.
data-search-open (or press “/”)Open the cross-page search overlay (#sv-ovl); reads an inline JSON index.
data-search="#grid" / data-search-allLive-filter [data-item] elements within a grid / across the page.
data-filter-group="#grid" + data-filterFilter pills that show/hide [data-tags] items.
data-tabs (buttons) + data-panelsTabbed panels: the nth button shows the nth panel.
data-pillsSingle-select pill group (e.g. product variants).
data-bill-toggle + data-price-m / data-price-yMonthly/annual pricing toggle that swaps the price text.
data-form [data-endpoint] [data-redirect] [data-ok]Validated form: inline errors, success state, optional POST + redirect.
data-consent="1|dismiss"Accept / dismiss the cookie-consent bar (#sv-consent).
sv-reveal (+ sv-d1…sv-d4)Fade-and-rise when scrolled into view (staggered delays).
data-count [data-suffix] [data-prefix]Animated count-up when the element enters the viewport.
data-kente-canvasGenerative Kente/Adinkra particle field on a <canvas>.
table.sv-table th[data-sort]Click a header to sort the column.

Heritage

African motifs

Real Adinkra glyphs, woven Kente, Bogolan mudcloth, Ndebele borders, and the Kwacha brand mark — available three ways.

As SVG-string builders (any framework)

import { adinkra, mark, kenteStrip, bogolan, ndebeleBorder, ADINKRA_NAMES } from '@kwacha-kulture/savanna-css';

el.innerHTML = adinkra('sankofa', 48);   // returns an <svg> string
el.innerHTML = mark(40);                 // the Kwacha roundel
// ADINKRA_NAMES -> ["sankofa","gyenyame","akoma","dwennimmen","nyamedua","eban"]

As React components

import { Sankofa, GyeNyame, KenteStrip, BogolanStamp } from '@kwacha-kulture/savanna/motifs';
import { KwachaMark, KwachaWordmark, KwachaLogo } from '@kwacha-kulture/savanna/brand';

<Sankofa size={48} /> <KwachaMark size={40} />

As Web Components

<sv-adinkra name="sankofa" size="48"></sv-adinkra>
<sv-mark size="40"></sv-mark>
sankofagyenyameakomadwennimmennyameduaeban

@kwacha-kulture/savanna-icons

Icons

318 Adinkra, Ndebele and UI glyphs — as tree-shakeable React components and raw SVG, with a typed registry.

import { Icon, IconSankofa, svgString } from '@kwacha-kulture/savanna-icons';

<Icon name="sankofa" size={24} />   // by name
<IconSankofa size={24} />           // named component
svgString('sankofa', 24);           // raw SVG string — usable anywhere

// browse / filter:
import { iconRegistry, ICON_CATEGORIES, ICON_COUNT } from '@kwacha-kulture/savanna-icons/registry';

@kwacha-kulture/react + react-pro

React components (91)

free 49 free (MIT, in @kwacha-kulture/react) · pro 30 pro · premium 12 premium (both in the commercial @kwacha-kulture/react-pro). Every component below is a complete reference; open the live gallery for interactive demos and copyable code.

Forms · 18

ComponentTierDescriptionKey propsImport from
ButtonfreeThe primary action control — variants, sizes, loading state.variant, size, loading, leftIcon, rightIcon@kwacha-kulture/react
InputfreeA labelled text input with error + hint states.label, error, hint, leftIcon@kwacha-kulture/react
TextareafreeA multi-line text field.rows, error, hint@kwacha-kulture/react
SelectfreeA styled native select.options, value, onChange@kwacha-kulture/react
CheckboxfreeA checkbox with label.checked, label, onChange@kwacha-kulture/react
RadiofreeA radio option.name, value, label@kwacha-kulture/react
TogglefreeAn on/off switch.checked, onChange@kwacha-kulture/react
SliderfreeA range slider with a gold fill and label.value, min, max, step, onChange@kwacha-kulture/react
ComboboxproA searchable, filterable select.options, value, onChange@kwacha-kulture/react-pro
AutocompleteproA multi-select autocomplete with chips and type-to-filter.options, value, onChange, multiple@kwacha-kulture/react-pro
Search FieldfreeA search input with a leading icon and a clear/cancel button.value, onValueChange, onClear@kwacha-kulture/react
Transfer ListproA dual-list picker with checkboxes and move-all/selected.left, right, onChange, titles@kwacha-kulture/react-pro
Date PickerproA date input with a popover month calendar.value, onChange, label@kwacha-kulture/react-pro
Time PickerproA compact HH:MM time picker with hour + minute steppers.value, onChange, minuteStep@kwacha-kulture/react-pro
Rich Text EditorpremiumA formatting toolbar over a contentEditable surface — bold/italic, headings, lists, quote, links.defaultValue, onChange, placeholder@kwacha-kulture/react-pro
DropzonefreeA drag-and-drop (or click) file upload area.onFiles, accept, multiple, hint@kwacha-kulture/react
MentionspremiumA textarea with @-mention autocomplete — type @ to pick people.value, onChange, options, rows@kwacha-kulture/react-pro
Color PickerpremiumAn HSV colour picker — saturation/value field, hue slider and hex input.value, onChange@kwacha-kulture/react-pro

Layout · 5

ComponentTierDescriptionKey propsImport from
BoxfreeA polymorphic styled div with shorthand padding/margin/bg/radius props.as, p, px, py, m, bg, radius, border, shadow@kwacha-kulture/react
ContainerfreeA centred, max-width content frame (sm/md/lg/xl).maxWidth, gutter@kwacha-kulture/react
GridfreeA CSS-grid wrapper with column count and gap.cols, gap, rows@kwacha-kulture/react
StackfreeA flex wrapper with direction, gap, align and justify.direction, gap, align, justify, wrap@kwacha-kulture/react
Image ListproA responsive image grid with hover captions.images, cols, gap, radius, ratio@kwacha-kulture/react-pro

Data Display · 15

ComponentTierDescriptionKey propsImport from
CardfreeA surface for grouping content, with a kente accent option.title, accentTop, padding@kwacha-kulture/react
BadgefreeA small status/label pill.variant, children@kwacha-kulture/react
TagfreeA removable tag/chip.onRemove, children@kwacha-kulture/react
AvatarfreeA user/brand avatar with fallback initials.src, name, size@kwacha-kulture/react
CounterproAn animated count-up for metrics — parses prefix/suffix.value, duration@kwacha-kulture/react-pro
TablefreeA sortable, striped data table with sticky headers and row hover.columns, rows, sortable, striped@kwacha-kulture/react
StatproA KPI tile with value and up/down delta — for dashboards.label, value, delta, icon@kwacha-kulture/react-pro
TimelineproA vertical event timeline with motif nodes.items@kwacha-kulture/react-pro
Avatar GroupproOverlapping avatars with an overflow count.people, max, size@kwacha-kulture/react-pro
ChipfreeA compact chip with avatar/icon, delete and click — filled or outlined.label, icon, avatar, color, variant, onDelete@kwacha-kulture/react
Data GridpremiumA full data grid — sortable, per-column filtering, column resize & pin, pagination, and row selection.columns, rows, pageSize, selectable, getRowId@kwacha-kulture/react-pro
KanbanpremiumA drag-and-drop board — move cards between columns.columns, onChange@kwacha-kulture/react-pro
Data Grid PropremiumA virtualized data grid — only visible rows mount (handles thousands of rows) — with inline editing, keyboard navigation (arrows/Enter/Esc) and per-column validation.columns(+editable/validate), rows, rowHeight, height, onCellEdit@kwacha-kulture/react-pro
CalendarpremiumA month calendar / scheduler with per-day events and selection.events, value, onSelect@kwacha-kulture/react-pro
SpreadsheetpremiumA lightweight spreadsheet — editable cells, formula bar and live column sums.rows, cols, initial, onChange@kwacha-kulture/react-pro

Feedback · 11

ComponentTierDescriptionKey propsImport from
SpinnerfreeA loading spinner.size@kwacha-kulture/react
SkeletonfreeA loading placeholder shimmer.width, height@kwacha-kulture/react
Empty StatefreeA friendly empty/zero-data panel.title, description, action@kwacha-kulture/react
TooltipfreeA hover/focus tooltip.content, placement@kwacha-kulture/react
Live BadgeproA pulsing "live/now" indicator.label, color@kwacha-kulture/react-pro
AlertfreeAn inline message — info, success, warning, or danger.tone, title, onDismiss@kwacha-kulture/react
BannerfreeA full-width announcement bar with an action.tone, action, onDismiss@kwacha-kulture/react
ProgressfreeA linear progress bar with optional label and value.value, max, label, showValue@kwacha-kulture/react
Progress RingproA circular progress indicator with a centred value.value, size, stroke, tone@kwacha-kulture/react-pro
RatingproA fractional star rating, read-only or interactive.value, max, onChange, readOnly@kwacha-kulture/react-pro
SnackbarfreeA positioned, auto-hiding notification with an action.open, message, action, tone, position, autoHideMs@kwacha-kulture/react

Overlay · 5

ComponentTierDescriptionKey propsImport from
ModalfreeA centred dialog.open, onClose, title@kwacha-kulture/react
DrawerproA slide-in side panel.open, side, onClose@kwacha-kulture/react-pro
Popover MenuproAn anchored dropdown menu.items, trigger@kwacha-kulture/react-pro
Info ModalproA richer informational dialog with motif framing.open, title, motif@kwacha-kulture/react-pro
BackdropfreeA full-screen dimmer for loading or focus states.open, blur, onClick@kwacha-kulture/react

Navigation · 11

ComponentTierDescriptionKey propsImport from
TabsfreeTabbed navigation with an animated indicator.items, value, onChange@kwacha-kulture/react
AccordionfreeCollapsible content sections.items@kwacha-kulture/react
BreadcrumbsfreeA path trail with a custom separator.items, separator@kwacha-kulture/react
PaginationfreePage controls with ellipsis and prev/next.page, pageCount, onChange@kwacha-kulture/react
Segmented ControlfreeA pill-style segmented toggle for switching views.items, value, onChange, size@kwacha-kulture/react
StepperproA horizontal multi-step progress indicator.steps, current@kwacha-kulture/react-pro
App BarfreeA top application bar with leading, title and actions.title, leading, actions, color, elevated@kwacha-kulture/react
Bottom NavigationproA mobile-style bottom tab bar with icons and labels.items, value, onChange@kwacha-kulture/react-pro
MenuproA full dropdown menu — sections, icons, shortcuts, danger items.trigger, sections, align@kwacha-kulture/react-pro
Command PalettepremiumA ⌘K command palette — search, grouped results, full keyboard navigation.open, onClose, commands@kwacha-kulture/react-pro
Tree ViewpremiumAn expandable hierarchical tree.nodes, defaultExpanded@kwacha-kulture/react-pro

Media · 2

ComponentTierDescriptionKey propsImport from
Image ViewerproA full-screen lightbox with zoom and keyboard navigation.images, open, index, onClose, onIndexChange@kwacha-kulture/react-pro
Audio PlayerproA compact audio player with a deterministic waveform scrubber.src, title, artist, seed@kwacha-kulture/react-pro

Charts · 7

ComponentTierDescriptionKey propsImport from
SparklinefreeA tiny inline trend line for KPI tiles.data, color, width, height, fill@kwacha-kulture/react
Line ChartproAn area line chart with gridlines and points.data, color, height@kwacha-kulture/react-pro
Bar ChartfreeA labelled vertical bar chart.data, color, height@kwacha-kulture/react
Donut ChartproA ring chart with a legend and percentages.segments, size, thickness@kwacha-kulture/react-pro
Area ChartfreeA responsive gradient area chart with a hover readout — the premium time-series.data, color, height, unit@kwacha-kulture/react
World MappremiumA choropleth world map — colour countries by a value and hover for a per-country readout. Compact public-domain geometry baked in (178 countries), joined by ISO alpha-2; every colour is a prop.data[{code,value}], colorLow, colorHigh, valueSuffix, renderTooltip@kwacha-kulture/react-pro
GanttpremiumA Gantt chart — tasks as bars over a unit timeline, with progress fill.tasks, units, unitLabel, labelWidth@kwacha-kulture/react-pro

Motion · 3

ComponentTierDescriptionKey propsImport from
RevealfreeScroll-reveal wrapper (fade/slide in on view).delay, children@kwacha-kulture/react
Tilt CardproA 3D pointer-tilt card.max, children@kwacha-kulture/react-pro
MagneticproA pointer-magnetic element.strength, children@kwacha-kulture/react-pro

Typography · 5

ComponentTierDescriptionKey propsImport from
EyebrowfreeA small uppercase kicker label.color, children@kwacha-kulture/react
Kente RulefreeA woven kente divider, optionally labelled.label@kwacha-kulture/react
King NameproA carved-gold name display in the regal lockup.name@kwacha-kulture/react-pro
KbdfreeA keyboard-key glyph for shortcuts.children@kwacha-kulture/react
DividerfreeA functional separator, optionally labelled or vertical.orientation, label@kwacha-kulture/react

Motifs · 6

ComponentTierDescriptionKey propsImport from
Kente StripfreeA woven colour-band strip that fills its width.height@kwacha-kulture/react
Ndebele BorderfreeA geometric Ndebele border band.height, color@kwacha-kulture/react
SankofafreeThe Sankofa Adinkra symbol.size, color@kwacha-kulture/react
Gye NyamefreeThe Gye Nyame Adinkra symbol.size, color@kwacha-kulture/react
DwennimmenproThe Dwennimmen (ram’s horns) Adinkra symbol.size, color@kwacha-kulture/react-pro
Bogolan StampproA mudcloth (bogolan) stamp motif.size, color@kwacha-kulture/react-pro

Brand · 3

ComponentTierDescriptionKey propsImport from
Kwacha MarkfreeThe Sankofa-in-roundel brand mark.size@kwacha-kulture/react
Kwacha WordmarkproA two-tone wordmark lockup.lead, accent, fontSize@kwacha-kulture/react-pro
Kwacha LogoproThe full mark + wordmark lockup.lead, accent, markSize@kwacha-kulture/react-pro

Example usage

import { Button } from '@kwacha-kulture/react';

<Button variant="primary">Continue</Button>

@kwacha-kulture/savanna-elements

Web Components

Native custom elements built on the CSS layer, encapsulated with a shadow root and the Savanna stylesheet adopted — drop-in for Vue, Svelte, Angular, Solid or plain HTML.

ElementAttributes
<sv-button>variant, size
<sv-card>plain
<sv-badge>tone (gold · emerald · terracotta)
<sv-input>placeholder, type, value
<sv-mark>size
<sv-adinkra>name, size
import { defineSavannaElements } from '@kwacha-kulture/savanna-elements';
defineSavannaElements();  // registers every element (idempotent, SSR-safe)

For everyone

Accessibility

  • Keyboard-navigable components with visible focus rings (--sv-line-strong / --tz-focus-ring).
  • Motion respects prefers-reduced-motion — reveals, count-ups, ken-burns and the generative canvas fall back to static.
  • Dark-mode contrast is tuned to meet WCAG AA on text; the accent is intentional against the deep ground.
  • Semantic landmarks (<header>, <nav>, <main>, <footer>) and ARIA labels on icon-only controls.
  • Audio never autoplays and always exposes a mute; images are lazy-loaded.

Patterns

Recipes

A hero with the generative canvas (CSS layer)

<section class="sv-hero sv-kente-bg">
  <canvas class="sv-hero-canvas" data-kente-canvas></canvas>
  <div class="sv-container">
    <p class="sv-eyebrow">Proudly African</p>
    <h1>Build the continent's <span class="sv-gold">next great thing.</span></h1>
    <a class="sv-btn sv-btn-lg sv-btn-primary" href="#">Get started</a>
  </div>
</section>

A form (React)

import { Field, Input, Textarea, Button } from '@kwacha-kulture/react';

<form>
  <Field label="Name"><Input placeholder="Amara Okafor" /></Field>
  <Field label="Message" hint="We reply within a day"><Textarea rows={4} /></Field>
  <Button variant="primary">Send</Button>
</form>

The fine print

Versioning, licence & support

Packages follow semver and version independently. The core (tokens, css, elements, icons, savanna, react) is MIT. @kwacha-kulture/react-pro is commercial — it installs from public npm but requires a paid licence (call setLicenseKey()); see its LICENSE.

Questions, licences and the Savanna Display font: savanna.venanciogomani.net. Source: GitHub.