Work  /  Design Systems

Design Systems

Turning a design system constraint into a shared way of working

ReVolve started with a practical delivery problem: teams were solving the same interface challenges independently, without an owner, roadmap or dedicated engineering capacity. I turned that constraint into a problem-solving strategy that connected real product work to reusable patterns, clearer decisions and adoption across teams.

Impact

From repeated friction to shared, scalable decisions

60%Faster design execution
25%Faster development
1Source of truth
6Teams aligned around reusable patterns
0Dedicated engineering allocation
100%Core components design with accessibility

CONSCEPT ENGAGEMENT ASSESSMENT

A clearer view of the work ahead.

A practical record of the complexity observed, the activities likely to help, and the work that was actually conducted.

Complexity profile

Discovery ComplexityPrimary driver5 / 5
Organisational ComplexityPrimary driver4 / 5
Product and Technical ComplexityPrimary driver4 / 5
Change and Adoption ComplexityPrimary driver5 / 5
Risk and Uncertainty3 / 5
Delivery ComplexityPrimary driver4 / 5
OVERALL COMPLEXITYTransformation programme

This was a high-complexity transformation programme because the work required more than creating reusable components. It involved diagnosing fragmented ways of working, aligning teams around shared priorities, introducing new decision-making practices, and building adoption without dedicated engineering capacity or formal system ownership.

Likely engagement

Dedicated diagnostic phase

Complete

Driving requirementDiscovery Complexity

A focused activity to reduce uncertainty, support better decisions, and move the engagement forward.

Stakeholder mapping

Complete

Driving requirementOrganisational Complexity

Made relationships, dependencies, and gaps visible so the team could prioritise the right intervention.

Multi-platform architecture audit

Complete

Driving requirementProduct and Technical Complexity

Examined the current experience and evidence to identify risks, duplication, and opportunities for improvement.

Organisation-wide change strategy

Not completed

Driving requirementChange and Adoption Complexity

A focused activity to reduce uncertainty, support better decisions, and move the engagement forward.

Risk assessment

Not completed

Driving requirementRisk and Uncertainty

Examined the current experience and evidence to identify risks, duplication, and opportunities for improvement.

Programme plan

Not completed

Driving requirementDelivery Complexity

A focused activity to reduce uncertainty, support better decisions, and move the engagement forward.

(+ 59 activities were included in this project)

The problem was bigger than a component library

ReVolve began with a delivery problem. Product teams were solving similar interface challenges independently, using different patterns, definitions and handoff practices.

There was no formal design system, no central source of truth and no dedicated engineering allocation to build one. Although there was executive support for the initiative, adoption depended on earning the trust of individual project leads and engineers.

The real challenge was not creating components. It was creating a shared way of working under real delivery pressure.

The core challenge was organisational as much as visual: I had to create adoption before I could create scale.

I diagnosed before I designed

Before defining the system, I looked for the recurring problems behind the visible inconsistency.

I mapped where teams were repeating decisions, where handoffs became ambiguous, which patterns created the most friction and which upcoming releases could benefit from shared solutions.

This helped separate symptoms from causes. The issue was not that teams lacked discipline. They lacked a shared language, a reliable decision framework and enough evidence that changing their process would make work easier.

I treated the design system as an internal product with users, adoption barriers and measurable value.

The constraints shaped the strategy

  • No dedicated developer was available to complete the system.

  • Components had to be delivered alongside active product work.

  • Project leads had different priorities and release pressures.

  • Engineers were initially cautious about changing established workflows.

  • Adoption could not be assumed or mandated.

I prioritised problems, not components

Rather than designing a complete library in isolation, I prioritised work based on five questions:

  1. Is this solving a real product problem?

  2. Can the solution be reused across teams?

  3. Will it reduce repeated decisions?

  4. Does it improve accessibility or quality?

  5. Can its value be demonstrated quickly?

This shifted the conversation from “Which components should we build?” to “Which recurring problems are expensive enough to solve once and reuse many times?”

The first priorities came from active product work. Each implementation became both a delivery contribution and a test of the emerging system.

tsx

type ComponentItem = {
  name: string;
  description: string;
  demand: number;
  reuse: number;
  accessibility: number;
  effort: number;
  adoption: number;
};

const components: ComponentItem[] = [
  {
    name: "Form controls",
    description: "Inputs, validation states and accessible interaction patterns.",
    demand: 5,
    reuse: 5,
    accessibility: 5,
    effort: 3,
    adoption: 5,
  },
  {
    name: "Navigation",
    description: "Shared navigation patterns across the product ecosystem.",
    demand: 5,
    reuse: 4,
    accessibility: 4,
    effort: 4,
    adoption: 5,
  },
  {
    name: "Data tables",
    description: "Dense information patterns used by operational teams.",
    demand: 4,
    reuse: 5,
    accessibility: 4,
    effort: 4,
    adoption: 4,
  },
  {
    name: "Empty states",
    description: "Guidance patterns for missing, loading and unavailable content.",
    demand: 3,
    reuse: 4,
    accessibility: 3,
    effort: 2,
    adoption: 4,
  },
  {
    name: "Date picker",
    description: "A complex interaction with high accessibility requirements.",
    demand: 3,
    reuse: 3,
    accessibility: 5,
    effort: 5,
    adoption: 3,
  },
  {
    name: "Toast messages",
    description: "Feedback patterns for confirmations and background actions.",
    demand: 2,
    reuse: 4,
    accessibility: 4,
    effort: 2,
    adoption: 3,
  },
];

const dimensions = [
  ["demand", "Product demand"],
  ["reuse", "Reuse potential"],
  ["accessibility", "Accessibility impact"],
  ["effort", "Implementation effort"],
  ["adoption", "Adoption value"],
] as const;

const colors = {
  background: "#111111",
  surface: "#1A1A1A",
  surfaceRaised: "#242424",
  border: "#3A3A3A",
  text: "#F5F2EA",
  muted: "#A7A39A",
  orange: "#E87932",
  orangeSoft: "#F2A36C",
  grid: "#343434",
};

function scoreLabel(score: number) {
  if (score >= 5) return "Very high";
  if (score >= 4) return "High";
  if (score >= 3) return "Moderate";
  if (score >= 2) return "Low";
  return "Very low";
}

function scoreColor(score: number) {
  if (score >= 5) return colors.orange;
  if (score >= 4) return colors.orangeSoft;
  if (score >= 3) return "#C7C1B5";
  return "#77736B";
}

function PrioritisationMatrix() {
  const [selectedName, setSelectedName] = useState("Form controls");
  const [minimumScore, setMinimumScore] = useState(0);

  const selected =
    components.find((component) => component.name === selectedName) ??
    components[0];

  const visibleComponents = useMemo(
    () =>
      components.filter(
        (component) =>
          component.demand + component.reuse + component.adoption >=
          minimumScore
      ),
    [minimumScore]
  );

  return (
    <section
      aria-label="Component prioritisation matrix"
      style={{
        width: "100%",
        padding: "clamp(20px, 4vw, 42px)",
        boxSizing: "border-box",
        border: `1px solid ${colors.border}`,
        borderRadius: 12,
        background: colors.background,
        color: colors.text,
        fontFamily:
          "Outfit, Inter, ui-sans-serif, system-ui, -apple-system, sans-serif",
      }}
    >
      <style>{`
        .priority-layout {
          display: grid;
          grid-template-columns: minmax(0, 1.35fr) minmax(280px, .65fr);
          gap: 28px;
          align-items: start;
        }

        .priority-matrix {
          position: relative;
          min-height: 420px;
          overflow: hidden;
          border: 1px solid ${colors.border};
          border-radius: 10px;
          background:
            linear-gradient(${colors.grid} 1px, transparent 1px),
            linear-gradient(90deg, ${colors.grid} 1px, transparent 1px),
            ${colors.surface};
          background-size: 20% 25%;
        }

        .priority-axis-label {
          position: absolute;
          color: ${colors.muted};
          font-family: "Geist Mono", ui-monospace, monospace;
          font-size: 10px;
          letter-spacing: .04em;
          text-transform: uppercase;
        }

        .priority-axis-y {
          left: 12px;
          top: 50%;
          writing-mode: vertical-rl;
          transform: rotate(180deg) translateY(50%);
        }

        .priority-axis-x {
          right: 18px;
          bottom: 12px;
        }

        .priority-quadrant {
          position: absolute;
          top: 0;
          right: 0;
          width: 50%;
          height: 50%;
          background: rgba(232, 121, 50, .07);
          border-left: 1px solid rgba(232, 121, 50, .18);
          border-bottom: 1px solid rgba(232, 121, 50, .18);
          pointer-events: none;
        }

        .priority-point {
          position: absolute;
          display: flex;
          align-items: center;
          justify-content: center;
          width: 82px;
          min-height: 34px;
          padding: 7px 9px;
          border: 1px solid ${colors.border};
          border-radius: 7px;
          background: ${colors.surfaceRaised};
          color: ${colors.text};
          font: 500 12px/1.1 Outfit, sans-serif;
          text-align: center;
          cursor: pointer;
          transform: translate(-50%, 50%);
          transition: transform 180ms ease, border-color 180ms ease,
            background 180ms ease, box-shadow 180ms ease;
        }

        .priority-point:hover,
        .priority-point:focus-visible {
          border-color: ${colors.orange};
          background: #302119;
          outline: none;
          transform: translate(-50%, 50%) translateY(-3px);
        }

        .priority-point[aria-pressed="true"] {
          border-color: ${colors.orange};
          background: ${colors.orange};
          color: #17120F;
          box-shadow: 0 0 0 4px rgba(232, 121, 50, .16);
        }

        .priority-detail {
          display: grid;
          gap: 20px;
          padding: 22px;
          border: 1px solid ${colors.border};
          border-radius: 10px;
          background: ${colors.surface};
        }

        .priority-bars {
          display: grid;
          gap: 13px;
        }

        .priority-bar-row {
          display: grid;
          grid-template-columns: minmax(110px, 1fr) 1.3fr auto;
          gap: 10px;
          align-items: center;
          font-size: 12px;
        }

        .priority-bar {
          height: 6px;
          overflow: hidden;
          border-radius: 99px;
          background: #33312E;
        }

        .priority-bar-fill {
          height: 100%;
          border-radius: inherit;
          background: ${colors.orange};
        }

        .priority-filter {
          display: flex;
          align-items: center;
          gap: 12px;
          margin-top: 22px;
          color: ${colors.muted};
          font-size: 12px;
        }

        .priority-filter input {
          width: 100%;
          accent-color: ${colors.orange};
        }

        @media (max-width: 780px) {
          .priority-layout {
            grid-template-columns: 1fr;
          }

          .priority-matrix {
            min-height: 360px;
          }
        }

        @media (max-width: 480px) {
          .priority-point {
            width: 68px;
            font-size: 10px;
          }

          .priority-bar-row {
            grid-template-columns: 1fr;
            gap: 5px;
          }
        }
      `}</style>

      <header style={{ display: "grid", gap: 10, marginBottom: 28 }}>
        <p
          style={{
            margin: 0,
            color: colors.orange,
            fontFamily: '"Geist Mono", ui-monospace, monospace',
            fontSize: 12,
            textTransform: "uppercase",
          }}
        >
          /decision framework
        </p>

        <h2
          style={{
            maxWidth: 700,
            margin: 0,
            fontSize: "clamp(28px, 5vw, 52px)",
            lineHeight: 0.98,
            letterSpacing: "-0.03em",
          }}
        >
          Prioritising what to solve first
        </h2>

        <p
          style={{
            maxWidth: 680,
            margin: 0,
            color: colors.muted,
            fontSize: 15,
            lineHeight: 1.55,
          }}
        >
          I used product demand, reuse potential, accessibility impact,
          implementation effort and adoption value to turn a long component
          list into a sequence of practical decisions.
        </p>
      </header>

      <div className="priority-layout">
        <div>
          <div className="priority-matrix">
            <div className="priority-quadrant" />

            <span className="priority-axis-label priority-axis-y">
              Reuse potential
            </span>

            <span className="priority-axis-label priority-axis-x">
              Product demand
            </span>

            {visibleComponents.map((component) => (
              <button
                key={component.name}
                type="button"
                className="priority-point"
                aria-pressed={selected.name === component.name}
                onClick={() => setSelectedName(component.name)}
                style={{
                  left: `${component.demand * 16.5 + 8}%`,
                  bottom: `${component.reuse * 16.5 + 8}%`,
                }}
              >
                {component.name}
              </button>
            ))}
          </div>

          <label className="priority-filter">
            <span>Show higher-priority items</span>
            <input
              type="range"
              min="0"
              max="12"
              step="1"
              value={minimumScore}
              onChange={(event) =>
                setMinimumScore(Number(event.target.value))
              }
            />
            <strong style={{ color: colors.text }}>
              {minimumScore === 0 ? "All" : minimumScore}
            </strong>
          </label>
        </div>

        <aside className="priority-detail">
          <div style={{ display: "grid", gap: 8 }}>
            <p
              style={{
                margin: 0,
                color: colors.orange,
                fontFamily: '"Geist Mono", ui-monospace, monospace',
                fontSize: 11,
                textTransform: "uppercase",
              }}
            >
              Selected priority
            </p>

            <h3
              style={{
                margin: 0,
                fontSize: 26,
                lineHeight: 1.05,
              }}
            >
              {selected.name}
            </h3>

            <p
              style={{
                margin: 0,
                color: colors.muted,
                fontSize: 14,
                lineHeight: 1.5,
              }}
            >
              {selected.description}
            </p>
          </div>

          <div className="priority-bars">
            {dimensions.map(([key, label]) => {
              const score = selected[key];

              return (
                <div className="priority-bar-row" key={key}>
                  <span>{label}</span>

                  <div
                    className="priority-bar"
                    role="progressbar"
                    aria-label={label}
                    aria-valuemin={1}
                    aria-valuemax={5}
                    aria-valuenow={score}
                  >
                    <div
                      className="priority-bar-fill"
                      style={{
                        width: `${score * 20}%`,
                        background: scoreColor(score),
                      }}
                    />
                  </div>

                  <strong style={{ color: scoreColor(score) }}>
                    {scoreLabel(score)}
                  </strong>
                </div>
              );
            })}
          </div>

          <div
            style={{
              paddingTop: 16,
              borderTop: `1px solid ${colors.border}`,
              color: colors.muted,
              fontSize: 12,
              lineHeight: 1.5,
            }}
          >
            <strong style={{ color: colors.text }}>Decision:</strong>{" "}
            {selected.demand >= 4 && selected.reuse >= 4
              ? "Prioritise early because this solves a visible problem and can scale across teams."
              : "Validate through a focused project before committing broader system capacity."}
          </div>
        </aside>
      </div>
    </section>
  );
}
render(<PrioritisationMatrix />);

Building the system through live product work

Every component had to prove itself in context.

I used upcoming releases as opportunities to create reusable patterns while still meeting immediate delivery needs. This made the system practical from the beginning: teams could see how a shared pattern solved a problem they already had rather than being asked to adopt an abstract future framework.

The process was iterative:

  • Identify a recurring product problem.

  • Explore the underlying causes and constraints.

  • Design a reusable pattern.

  • Validate it in a live product context.

  • Improve the documentation and implementation guidance.

  • Reuse the pattern in the next project.

This approach allowed the system to grow from evidence instead of assumptions.

Making the value visible to engineering

Engineering adoption improved when the system reduced effort in real work.

I focused on clarifying component behaviour, states, accessibility requirements and implementation expectations. Better definition reduced ambiguity during handoff and made the relationship between design decisions and technical implementation easier to understand.

The system helped create:

  • Fewer repeated UI decisions.

  • Clearer component states and behaviours.

  • More predictable handoffs.

  • More consistent implementation guidance.

  • Reusable patterns that reduced future effort.

Adoption improved when the system reduced engineering effort in real work, not when it was presented as another set of rules.

Winning adoption one project lead at a time

Without formal ownership, adoption had to be earned.

I connected system priorities to work that project leads already needed to deliver. Instead of asking teams to pause their work and adopt a separate process, I positioned ReVolve as a way to make their current work clearer, faster and more consistent.

This meant adapting the adoption approach to each team while keeping the underlying principles consistent.

  • Build relationships with project leads individually.

  • Connect system priorities to upcoming releases.

  • Create early advocates through successful delivery.

  • Use evidence from one project to support adoption in the next.

  • Make contribution and ownership easier for teams to understand.

The system became more credible each time a team experienced a measurable improvement.

Creating a foundation for consistent decisions

Once recurring patterns were understood, I established the foundations that would help teams make better decisions independently.

These included:

  • Design principles and decision criteria.

  • Typography, colour, spacing and layout tokens.

  • Accessibility requirements at component level.

  • Naming and usage conventions.

  • Documentation standards.

  • Rules for extending the system responsibly.

The goal was not to standardise every design decision. It was to make the important decisions clear, repeatable and easier to scale.

tsx

type ComponentType = "button" | "input";
type ComponentState = "default" | "hover" | "focus" | "disabled";

const tokens = {
  colorBackgroundCanvas: "#111111",
  colorSurfaceDefault: "#1C1C1C",
  colorSurfaceRaised: "#292929",
  colorTextPrimary: "#F5F2EA",
  colorTextSecondary: "#A7A39A",
  colorBorderDefault: "#414141",
  colorBorderInteractive: "#E87932",
  colorActionPrimary: "#F2A36C",
  colorActionPrimaryHover: "#E87932",
  colorActionPrimaryText: "#111111",
  colorFocusRing: "rgba(232, 121, 50, .24)",
  colorDisabledOverlay: "rgba(17, 17, 17, .42)",
  sizeControlMinimum: 48,
  radiusControl: 6,
};

const stateDescriptions = {
  default: "The resting state for normal interaction.",
  hover: "Provides immediate feedback when the pointer enters the control.",
  focus: "Makes keyboard focus visible and easy to locate.",
  disabled: "Communicates that the control is temporarily unavailable.",
};

function DesignSystemFoundations() {
  const [component, setComponent] = useState<ComponentType>("button");
  const [state, setState] = useState<ComponentState>("default");
  const [inputValue, setInputValue] = useState("");

  const isDisabled = state === "disabled";
  const isFocused = state === "focus";
  const isInteractive =
    state === "hover" || state === "focus";

  const controlBorder = isInteractive
    ? tokens.colorBorderInteractive
    : tokens.colorActionPrimary;

  const controlBackground = isInteractive
    ? tokens.colorActionPrimaryHover
    : tokens.colorActionPrimary;

  const buttonStyle: React.CSSProperties = {
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    minHeight: tokens.sizeControlMinimum,
    padding: "0 20px",
    border: `2px solid ${controlBorder}`,
    borderRadius: tokens.radiusControl,
    background: controlBackground,
    color: tokens.colorActionPrimaryText,
    font: '600 14px/1 "Outfit", sans-serif',
    cursor: isDisabled ? "not-allowed" : "pointer",
    opacity: isDisabled ? 0.42 : 1,
    boxShadow: isFocused
      ? `0 0 0 4px ${tokens.colorFocusRing}`
      : "none",
    transition: "all 180ms ease",
  };

  const inputStyle: React.CSSProperties = {
    width: "100%",
    minHeight: tokens.sizeControlMinimum,
    boxSizing: "border-box",
    padding: "0 14px",
    border: `2px solid ${
      isInteractive
        ? tokens.colorBorderInteractive
        : tokens.colorBorderDefault
    }`,
    borderRadius: tokens.radiusControl,
    outline: "none",
    background: isDisabled
      ? tokens.colorSurfaceDefault
      : tokens.colorSurfaceRaised,
    color: tokens.colorTextPrimary,
    font: '400 15px/1 "Outfit", sans-serif',
    opacity: isDisabled ? 0.42 : 1,
    boxShadow: isFocused
      ? `0 0 0 4px ${tokens.colorFocusRing}`
      : "none",
    transition: "all 180ms ease",
  };

  return (
    <section
      aria-label="Design system foundations inspector"
      style={{
        width: "100%",
        boxSizing: "border-box",
        padding: "clamp(20px, 4vw, 40px)",
        border: `1px solid ${tokens.colorBorderDefault}`,
        borderRadius: 10,
        background: tokens.colorBackgroundCanvas,
        color: tokens.colorTextPrimary,
        fontFamily: "Outfit, Inter, sans-serif",
      }}
    >
      <style>{`
        .foundation-layout {
          display: grid;
          grid-template-columns: minmax(0, 1fr) 280px;
          gap: 32px;
          align-items: start;
        }

        .foundation-preview {
          display: grid;
          align-content: center;
          min-height: 300px;
          padding: 28px;
          border: 1px solid ${tokens.colorBorderDefault};
          border-radius: 8px;
          background:
            linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
            linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px),
            ${tokens.colorSurfaceDefault};
          background-size: 24px 24px;
        }

        .foundation-control {
          display: flex;
          gap: 8px;
          margin-bottom: 24px;
        }

        .foundation-tab {
          border: 1px solid ${tokens.colorBorderDefault};
          border-radius: 5px;
          padding: 9px 12px;
          background: transparent;
          color: ${tokens.colorTextSecondary};
          font: 500 12px/1 "Geist Mono", monospace;
          cursor: pointer;
        }

        .foundation-tab:hover,
        .foundation-tab:focus-visible,
        .foundation-tab[aria-selected="true"] {
          border-color: ${tokens.colorBorderInteractive};
          background: rgba(232, 121, 50, .12);
          color: ${tokens.colorTextPrimary};
          outline: none;
        }

        .foundation-states {
          display: grid;
          gap: 8px;
        }

        .foundation-state {
          display: flex;
          align-items: center;
          justify-content: space-between;
          width: 100%;
          border: 1px solid transparent;
          border-radius: 5px;
          padding: 10px 12px;
          background: transparent;
          color: ${tokens.colorTextSecondary};
          text-align: left;
          font: 500 12px/1 "Geist Mono", monospace;
          cursor: pointer;
        }

        .foundation-state:hover,
        .foundation-state:focus-visible,
        .foundation-state[aria-pressed="true"] {
          border-color: ${tokens.colorBorderDefault};
          background: ${tokens.colorSurfaceRaised};
          color: ${tokens.colorTextPrimary};
          outline: none;
        }

        .foundation-state[aria-pressed="true"]::after {
          content: "●";
          color: ${tokens.colorBorderInteractive};
        }

        .foundation-inspector {
          display: grid;
          gap: 18px;
        }

        .foundation-token {
          display: flex;
          justify-content: space-between;
          gap: 16px;
          padding-bottom: 10px;
          border-bottom: 1px solid ${tokens.colorBorderDefault};
          color: ${tokens.colorTextSecondary};
          font-size: 12px;
        }

        .foundation-token strong {
          color: ${tokens.colorTextPrimary};
          font-family: "Geist Mono", monospace;
          font-weight: 500;
          text-align: right;
        }

        @media (max-width: 700px) {
          .foundation-layout {
            grid-template-columns: 1fr;
          }
        }
      `}</style>

      <header style={{ display: "grid", gap: 10, marginBottom: 28 }}>
        <p
          style={{
            margin: 0,
            color: tokens.colorBorderInteractive,
            font: '500 12px/1.2 "Geist Mono", monospace',
            textTransform: "uppercase",
          }}
        >
          /foundations
        </p>

        <h2
          style={{
            maxWidth: 680,
            margin: 0,
            fontSize: "clamp(28px, 5vw, 52px)",
            lineHeight: 0.98,
            letterSpacing: "-0.03em",
          }}
        >
          Small rules, consistent behaviour
        </h2>

        <p
          style={{
            maxWidth: 620,
            margin: 0,
            color: tokens.colorTextSecondary,
            fontSize: 15,
            lineHeight: 1.55,
          }}
        >
          A simple foundation inspector showing how semantic tokens become
          predictable component states.
        </p>
      </header>

      <div className="foundation-control" role="tablist">
        {(["button", "input"] as ComponentType[]).map((type) => (
          <button
            key={type}
            type="button"
            role="tab"
            aria-selected={component === type}
            className="foundation-tab"
            onClick={() => setComponent(type)}
          >
            {type === "button" ? "Button" : "Input"}
          </button>
        ))}
      </div>

      <div className="foundation-layout">
        <div className="foundation-preview">
          <div
            style={{
              display: "grid",
              gap: 12,
              width: "min(100%, 360px)",
              margin: "auto",
            }}
          >
            <p
              style={{
                margin: 0,
                color: tokens.colorTextSecondary,
                font: '500 11px/1.2 "Geist Mono", monospace',
                textTransform: "uppercase",
              }}
            >
              {component} / {state}
            </p>

            {component === "button" ? (
              <button
                type="button"
                disabled={isDisabled}
                style={buttonStyle}
              >
                Continue
              </button>
            ) : (
              <input
                aria-label="Preview input"
                disabled={isDisabled}
                value={inputValue}
                onChange={(event) => setInputValue(event.target.value)}
                placeholder="Enter your email"
                style={inputStyle}
              />
            )}

            <p
              style={{
                margin: 0,
                color: tokens.colorTextSecondary,
                fontSize: 13,
                lineHeight: 1.5,
              }}
            >
              {stateDescriptions[state]}
            </p>
          </div>
        </div>

        <aside className="foundation-inspector">
          <div>
            <p
              style={{
                margin: "0 0 10px",
                color: tokens.colorBorderInteractive,
                font: '500 11px/1.2 "Geist Mono", monospace',
                textTransform: "uppercase",
              }}
            >
              Component states
            </p>

            <div className="foundation-states">
              {(
                ["default", "hover", "focus", "disabled"] as ComponentState[]
              ).map((option) => (
                <button
                  key={option}
                  type="button"
                  className="foundation-state"
                  aria-pressed={state === option}
                  onClick={() => setState(option)}
                >
                  {option}
                </button>
              ))}
            </div>
          </div>

          <div>
            <p
              style={{
                margin: "0 0 12px",
                color: tokens.colorBorderInteractive,
                font: '500 11px/1.2 "Geist Mono", monospace',
                textTransform: "uppercase",
              }}
            >
              Semantic tokens
            </p>

            <div style={{ display: "grid", gap: 12 }}>
              <div className="foundation-token">
                <span>Primary action</span>
                <strong>colorActionPrimary</strong>
              </div>

              <div className="foundation-token">
                <span>Interactive border</span>
                <strong>colorBorderInteractive</strong>
              </div>

              <div className="foundation-token">
                <span>Minimum control size</span>
                <strong>sizeControlMinimum</strong>
              </div>

              <div className="foundation-token">
                <span>Focus indicator</span>
                <strong>colorFocusRing</strong>
              </div>

              <div className="foundation-token">
                <span>Control radius</span>
                <strong>radiusControl</strong>
              </div>
            </div>
          </div>

          <div
            style={{
              paddingTop: 16,
              borderTop: `1px solid ${tokens.colorBorderDefault}`,
              color: tokens.colorTextSecondary,
              fontSize: 12,
              lineHeight: 1.5,
            }}
          >
            <strong style={{ color: tokens.colorTextPrimary }}>
              Accessibility:
            </strong>{" "}
            visible focus, 48px interaction height, readable contrast and
            disabled-state feedback.
          </div>
        </aside>
      </div>
    </section>
  );
}
render(<DesignSystemFoundations />);

From personal advocacy to shared ownership

Initially, ReVolve depended heavily on my involvement. I had to explain the value, support implementation and resolve uncertainty directly with teams.

Over time, successful implementations changed that dynamic. Project leads began endorsing the system, engineers saw the practical benefits and teams became more confident using shared patterns without direct supervision.

The transition was gradual:

  1. Initial resistance and local constraints.

  2. Pilot components connected to active releases.

  3. Visible improvements in speed, consistency and accessibility.

  4. Project-lead endorsement and continued reuse.

  5. Engineering adoption through demonstrated value.

  6. Shared ownership of the system and its future direction.

Measuring the outcome

ReVolve created value beyond a more consistent visual language. It improved how design, product and engineering worked together.

The measurable impact included:

  • More than 60% faster design execution.

  • 25% faster development.

  • Reduced duplication across design and engineering.

  • More consistent product experiences.

  • Improved accessibility across shared components.

  • Greater confidence in cross-functional delivery.

The most important result was not the library itself. It was the decision-making system that formed around it.

Reflection: designing the conditions for better decisions

ReVolve reinforced that design leadership is not only about creating solutions. It is about creating the conditions for teams to make better decisions consistently, even when time, resources and formal authority are limited.

The work required diagnosis, prioritisation, negotiation, experimentation and communication as much as visual design.

Design leadership is measured by the quality of decisions a team can make without you in the room.

For me, ReVolve became a proof of how I lead as a Product Designer: by setting direction, working through constraints, building alignment and turning design strategy into measurable improvements for both teams and products.