Skip to content
kc@kumarChandrachooda.com:~$ cd /design-system/core && read --section="01 identity" 0%
KC Design System — Sketch / Sketch

Rough it out.
One system, every component.

The sketch style redraws the system freehand in design-system-sketch.css: handwriting type, wobble borders, sticky-note labels and marker highlights, everything a degree or two off square. Same components, same markup — the notebook the classic skin was ruled up from.

Specimen

One card, re-inked and re-shaped by whatever the two columns say.

Primary chip

Set — Sketch / Sketch

Core

Identity details

The accent line and kicker reproduce the rotated section labels of the slideshow; the notched label chip comes from the “Hello” tab on the about page.
Section kicker Small kicker Hello Featured
Core

Buttons & chips

The solid button wipes to grey with a pop, like the original btn-black; the accent is the primary/brand button and hovers the same way — light wipe, ink text; the ghost outline skew-fills ink, mirroring salv-down-cv-btn.
azure dotnet hover me outline
Core

Tabs

One strip, three modes (_Tabs + .ds-tabs). The geometry is shared — the 2px rule, the accent tint and rule marking the selected tab (the rail's own current-row grammar turned horizontal), square corners because a radius meeting the rule leaves a notch, a scrolling strip with edge fades when the tabs outgrow the column — and the mode decides the element and the ARIA. --nav is anchors over real routes with aria-current (the group strip above navigates this very showcase); --panel ships as anchors and is promoted to the full tablist pattern by tabs.js once its panels are confirmed present; --display is a closed segmented radiogroup for choices about the reader's eyes rather than the content — the blog's Cards/List switch. One tab stop per strip: focus roves with the arrow keys, and selection is manual where it is expensive (a navigation) and automatic where it is free (a class toggle).
--nav: anchors over real routes, aria-current="page" on the one you are on, a count in mono beside each label. The selected tab is framed in ink on its open sides with the accent taking over the rule beneath; when the strip overflows, edge fades carry ‹ › arrows that scroll it a screenful at a time. This specimen is scenery — the live strip is at the top of this page, and each of its tabs is a document of its own.
--panel: live. The panels are siblings in this document, so this is the one mode that earns the full role="tablist" pattern — tabs.js promotes the anchors once it has confirmed every panel is present. Tab into the strip, move focus with ← → Home End, select with Enter or Space: activation is manual, because selecting swaps a panel and writes history, and arrowing across the strip should not do either seven times. The grip leading the strip is the end of its rule — drag it right to stand the strip up, left or down to lay it flat, or just press it. Standing, the accent rule moves to the left edge, the panels render next to the strip as a column, the tablist announces aria-orientation="vertical", and the choice persists for the reader in localStorage. There is no symbol for the change: a mark that stands for a change of layout is a verb, and both drawings of one ( and its rotation) turn out to be somebody else's noun. The grip's strokes stay perpendicular to the rule they cap, so the mark reports the orientation without moving, and it holds the same top-left corner whichever way the strip is lying. The announcement is one fixed label with the state on aria-pressed — "Stack tabs, toggle button, pressed" — and below 992px, where there is no room for a column beside a body, the grip is greyed and inert.

Navigate selects between different documents. The state is the route, the element is an anchor, and the back button works because the browser is doing the navigating.

--display: live. A closed segmented object — 2px ink all round, dividers between segments, ink fill on the checked one — because a rendering preference is a setting, not a set of places: it is a radiogroup, a tablist here would promise a panel that does not exist, and the address bar is never touched. Arrows select immediately (the switch is one class toggle, so the APG default is free). The real one drives the blog archive's Cards/List choice and keeps it in localStorage.
View
Core

Page hero & statline

Every listing page opens the same way: kicker, an oversized black title, a light lead and the mono .ds-statline counters whose pulsing dot marks the live count. Pages compose the pieces per surface — a breadcrumb above, chips or search below — so the hero is a pattern, not a partial.
The listing-page opener: kicker, title, lead and the mono statline with its pulsing live-count dot. Each page assembles these pieces directly — the series index adds a breadcrumb above, the archive adds search below.
The Build Log

Blog

Notes on cloud & data architecture, .NET engineering and the practice of shipping software, written from the field, with the code to back it up.

  • 4 topics
  • 3 series
  • 18 articles
Core

Badges & pills

The status vocabulary in one place: notched sheet labels, the “coming soon” pills, the draft-preview chip, date pills, the colour-coded role pills from the project cards and the tech chips. Grey consistently means “not yet”; periwinkle means live, featured or in focus.
Sheet labels: .ds-label with its notched-tab fold. Base ink for identity, accent for live series, grey for series still in drafts.
Hello Series · 4 parts Coming soon · 2 parts
Status pills: the roadmap vocabulary. .ds-card__soon-pill on coming-up cards, .ds-series-item__soon-label on roadmap rows, and the _PreviewBadge chip that appears only when the draft preview switch is on.
Coming soon Coming soon Preview
Date pills: .ds-timeline__date on the employment rail, .ds-cert__date on certification cards (with a muted prep variant for in-progress ones).
July 2021 – Aug 2022 July 2021 In preparation
Role pills & tech chips: .ds-project__role--* colour-codes the project cards so the filter row doubles as a legend; .ds-tech-chip lists the key stack.
Architect Lead Developer R&D
C# Azure Functions Terraform
Core

Empty state

The quiet placeholder (_EmptyState) when a topic or a filtered archive has nothing to show: accent line, a muted message, an optional hint and an optional onward link.
Message only: how a topic page reads when everything under it is still in drafts.

Nothing published under this topic yet.

Message, hint & link: the archive's no-results form, with a way back out of the dead end.

Nothing matched “owl-carousel”.

Try a different search or filter.

Clear search and filters
Core

Drawer

An edge-anchored overlay panel (.ds-drawer) that slides in over a scrim, right by default and --left on request, in three widths. Square corners — it is a surface, and the 2px edge frames it. The markup is one <aside> plus a trigger; the dialog role, focus trap, Escape, scrim and scroll lock come from the behaviour layer. Its rows are generic on purpose: the navigator behind the tab on the right of this page is the same component that will hold saved-for-later articles.
Anatomy. A head (title, optional sub, close), an optional tools strip, a scrolling body and an optional foot that stays put. The trigger points at the panel by id — data-ds-drawer-open="…" — and everything else (dialog role, scrim, focus trap, Escape, scroll lock) is applied by the behaviour layer.
Rows are deliberately generic. .ds-drawer-item is an index, a label and a meta column, grouped under .ds-drawer__group. That row reads as a section link in the navigator on this page, and as a saved article when the drawer becomes the read-later shelf — same component, no fork.
Core

Toast

The third overlay, and the only one nobody opens (.ds-toast): it arrives on its own and leaves on its own, so there is no panel on the page and no id to point at — the host is built on first use and a caller supplies only the message. The primary skin is the fuse: a bordered card at the bottom right whose accent underline drains left-to-right as the dwell runs out, the signature wipe run in reverse as a countdown, paused by hover or focus along with the timer behind it. The secondary is the dock chip (--dock) — the dock's position and skin, a mono kind-tag and an action word, springing up from the bottom centre with the one overshoot the system allows. Cards carry a payload; chips carry a verb. One at a time per host, always dismissible, role="alert" for failures and role="status" for everything else, entrance and exit frozen under reduced motion — the fuse is not, because it is a readout rather than decoration.
The fuse — the primary. A white bordered card at the bottom right whose bottom edge carries the accent underline, draining left-to-right as the dwell runs out: the signature wipe, run in reverse as a countdown. You can see how long the message has left, and hovering or tabbing into it pauses the drain — the bar and the timer behind it are held together, so the underline never lies about the time left. It is the workhorse because it carries a payload: a title, and under it the filename, slug or size the message is about.
The dock chip — the secondary. A dark chip springing up from the bottom centre with a mono kind-tag and an action word in violet: the dock's position and the dock's skin, and the one moment of overshoot-and-settle the system allows. It is for one-line state that comes with a verb rather than a payload — turn off, undo, view. It carries no fuse: a chip you are meant to act on should not visibly be running out, so it dwells longer and leans on the verb instead.
The two hosts are independent, so a chip stating a mode and a card confirming an action can sit on screen together — they are saying different kinds of thing. Within a host it is one at a time: a second message supersedes the first rather than stacking under it, so a burst never turns the corner into a feed. Fire both above and watch it happen.
Anatomy, held still. The same markup the behaviour layer builds, lifted out of its fixed host with the fuse stopped three-quarters through.
download

CV download started

KUMAR_CHANDRACHOODA_Resume.pdf · 412 KB

draft

Preview mode is on — drafts are visible

Raising one. There is no panel on the page and no id to point at: the host is built on first use, so a caller only supplies the message. Either window.dsToast(…) from script, or the declarative trigger every button on this page uses — which is what the CV download and the copy-link buttons will carry.
<button data-ds-toast="CV download started"
        data-ds-toast-msg="KUMAR_CHANDRACHOODA_Resume.pdf &middot; 412 KB"
        data-ds-toast-kind="success">Download</button>

dsToast({ title: 'Filter cleared', variant: 'dock', tag: 'archive',
          action: 'undo', onAction: restore });
OptionDefaultWhat it does
variantfusedock for the chip.
kindinfosuccess, warning, danger — recolours the fuse and the tag, and switches the live region from polite to assertive.
dwell3500 / 6000ms on screen; 0 stays until dismissed, and drops the fuse with it.
actionThe verb. onAction runs, then it dismisses unless the handler returns false.
tagthe kind, on a chipThe mono kind-tag.
Accessibility and motion are not the caller's problem: a failure gets role="alert" and interrupts, everything else gets role="status" and waits its turn, every toast is dismissible, and under prefers-reduced-motion the slide and the spring are frozen to a fade. The fuse is not frozen with them — it is the dwell readout rather than decoration, and hiding how long a message has left serves a reader who asked for less motion worse, not better.