Skip to content
Rahul Jadhav
Selected work
Reusable UI componentsIndependent demonstration

Component Lab

A small, working set of accessible components — buttons, form controls, tabs, a dialog, and a filterable table — built on shared tokens to show how I approach UI engineering.

Context
Independent demonstration built for this site. Not a client project or shipped product; all data is fictional.
Date
2026
My role
Design and implementation
Scope
Design tokensComponent API designAccessibilityResponsive behaviour

The need

Portfolio screenshots show what a product looks like, but not how its components behave. This lab lets you use the components directly: tab through them, open the dialog, filter the table, and trigger each state.

Key workflows

  1. 01Navigate the whole demo with a keyboard, including tabs with arrow keys.
  2. 02Open and dismiss a dialog without losing your place on the page.
  3. 03Search and filter a table, and see loading, empty, and error states.
  4. 04Validate a form field and read the error where it occurs.

Try the components

Independent demonstration · fictional data

Buttons

Four variants, two sizes, and loading and disabled states.

Invite a teammate

Design decisions

Tokens before components
Colour, radius, and spacing come from the same tokens as the rest of this site, so a component cannot drift from the system it lives in.
Every state is designed
Loading, empty, and error states are first-class variants of the table, each with a clear next action.
Restraint
One accent colour, one border weight, two radii. Hierarchy comes from type and spacing rather than decoration.

Engineering decisions and tradeoffs

Native elements first
Buttons are buttons, inputs have labels, and the dialog uses the native <dialog> element for focus handling and Escape-to-close, reducing custom code.
ARIA where native elements stop
Tabs follow the WAI-ARIA tabs pattern with roving tabindex and arrow-key support, because there is no native equivalent.
Small, explicit component APIs
Components take a variant and size rather than arbitrary class names, which keeps usage consistent across screens. Escape hatches exist but are not the default.

Stack

  • React
  • TypeScript
  • Tailwind CSS
  • Native <dialog>
  • WAI-ARIA tabs pattern

What the demo includes

  • Button variants with visible focus and disabled states.
  • Labelled text input and select with inline validation.
  • Keyboard-accessible tabs.
  • A modal dialog using the native element.
  • A searchable, filterable table with loading, empty, and error states.

Lessons

  • Using the platform — <dialog>, <button>, <label> — removes a surprising amount of accessibility code.
  • Designing empty and error states early changes the component's API, so it is worth doing first.