ANTIGRAVITY LABJP
Articles/Agents & Manager
Agents & Manager/2026-03-29Advanced

to Design Systems × AI Development— Building a Seamless Workflow with UI Stack, AutoLayout, and Variables

Comprehensive system integrating UI Stack, AutoLayout, Variables, and VRT with AI development. Implementation guide from design system architecture to multi-agent automation pipeline and VRT integration.

Design SystemsUI StackAutoLayoutVariablesVRTAI Development7

Premium Article

The fusion of design systems and AI represents the cutting edge of modern development organizations. By systematically integrating UI Stack, AutoLayout, Variables, and VRT, you can realize a development culture where designers, engineers, and AI agents work in perfect harmony. This guide covers the complete implementation patterns and operational philosophy.

UI Stack: The Five-State Framework

UI Stack, proposed by Scott Hurff, is the design principle that every UI element must account for five distinct states:

  1. Ideal State: Data is sufficient and everything functions normally
  2. Loading State: Data is being fetched; skeleton screens or spinners display
  3. Empty State: No data exists or the system is in initial state
  4. Error State: API failures, validation errors, or network issues
  5. Partial State: Only partial data available or incremental loading in progress

Ideal State Implementation Pattern

// components/ProductCard.tsx
interface ProductCardProps {
  product: Product;
  isLoading?: false;
  isEmpty?: false;
  error?: undefined;
}
 
export const ProductCard: React.FC<ProductCardProps> = ({ product }) => {
  return (
    <div style={{ padding: '12px', borderRadius: '8px', border: '1px solid #E5E7EB' }}>
      <img src={product.image} alt={product.name} />
      <h3>{product.name}</h3>
      <p>{product.description}</p>
      <span style={{ color: '#2563EB', fontWeight: 'bold' }}>
        ${product.price.toFixed(2)}
      </span>
    </div>
  );
};

Loading State Implementation Pattern

interface ProductCardProps {
  product?: undefined;
  isLoading: true;
  isEmpty?: false;
  error?: undefined;
}
 
export const ProductCardSkeleton: React.FC = () => {
  return (
    <div style={{ padding: '12px', borderRadius: '8px', backgroundColor: '#F3F4F6' }}>
      <div style={{ width: '100%', height: '200px', backgroundColor: '#E5E7EB', borderRadius: '4px' }} />
      <div style={{ marginTop: '8px', height: '20px', backgroundColor: '#E5E7EB', borderRadius: '4px' }} />
      <div style={{ marginTop: '8px', height: '16px', backgroundColor: '#E5E7EB', width: '80%', borderRadius: '4px' }} />
    </div>
  );
};

Empty State Implementation Pattern

interface ProductCardProps {
  product?: undefined;
  isLoading?: false;
  isEmpty: true;
  error?: undefined;
}
 
export const ProductCardEmpty: React.FC = () => {
  return (
    <div style={{ textAlign: 'center', padding: '32px 12px' }}>
      <p style={{ color: '#6B7280', fontSize: '14px' }}>
        No products available yet.
      </p>
      <p style={{ color: '#9CA3AF', fontSize: '12px' }}>
        Please add a new product.
      </p>
    </div>
  );
};

Error State Implementation Pattern

interface ProductCardProps {
  product?: undefined;
  isLoading?: false;
  isEmpty?: false;
  error: Error;
}
 
export const ProductCardError: React.FC<{ error: Error }> = ({ error }) => {
  return (
    <div style={{ padding: '12px', borderRadius: '8px', backgroundColor: '#FEE2E2', borderLeft: '4px solid #EF4444' }}>
      <p style={{ color: '#991B1B', fontWeight: 'bold' }}>An error occurred</p>
      <p style={{ color: '#7F1D1D', fontSize: '14px' }}>
        {error.message}
      </p>
      <button onClick={() => window.location.reload()} style={{ marginTop: '8px', padding: '6px 12px', backgroundColor: '#EF4444', color: '#FFFFFF', borderRadius: '4px', border: 'none', cursor: 'pointer' }}>
        Retry
      </button>
    </div>
  );
};

Partial State Implementation Pattern

interface ProductCardProps {
  product: Partial<Product>;
  isLoading?: false;
  isEmpty?: false;
  error?: undefined;
}
 
export const ProductCardPartial: React.FC<{ product: Partial<Product> }> = ({ product }) => {
  return (
    <div style={{ padding: '12px', borderRadius: '8px', border: '1px solid #FCD34D' }}>
      {product.image && <img src={product.image} alt={product.name} />}
      <h3>{product.name || 'Loading...'}</h3>
      {product.description ? <p>{product.description}</p> : <p style={{ color: '#9CA3AF' }}>Loading description...</p>}
    </div>
  );
};

VRT (Visual Regression Testing): Leveraging UI Stack with Login States

VRT automatically validates that UI appearance matches intent and has no unintended changes. Combined with UI Stack's five states plus login status, language settings, and dark mode variations, test scenarios expand combinatorially.

VRT Test Scenario Design Example

ProductCard Component
├─ Ideal State
│  ├─ English × Light mode
│  ├─ English × Dark mode
│  ├─ Japanese × Light mode
│  └─ Japanese × Dark mode
├─ Loading State
│  ├─ Light mode
│  └─ Dark mode
├─ Empty State
│  ├─ Light mode
│  └─ Dark mode
├─ Error State
│  ├─ Light mode
│  └─ Dark mode
└─ Partial State
   ├─ Light mode
   └─ Dark mode

Total: 14 patterns

Playwright + Percy (VRT SaaS) Automation

// e2e/product-card.spec.ts
import { test } from '@playwright/test';
import percySnapshot from '@percy/playwright';
 
test.describe('ProductCard VRT Suite', () => {
  test('Ideal State - Light Mode EN', async ({ page }) => {
    await page.goto('/components/product-card?state=ideal&lang=en&theme=light');
    await percySnapshot(page, 'ProductCard-Ideal-Light-EN');
  });
 
  test('Loading State - Dark Mode', async ({ page }) => {
    await page.goto('/components/product-card?state=loading&theme=dark');
    await percySnapshot(page, 'ProductCard-Loading-Dark');
  });
 
  test('Error State - Light Mode', async ({ page }) => {
    await page.goto('/components/product-card?state=error&theme=light');
    await percySnapshot(page, 'ProductCard-Error-Light');
  });
});

Integrated into CI/CD pipelines, visual differences are automatically detected on every PR.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
UI Stack 5-state management: implementation patterns and comprehensive test scenario design
Design system × AI integration strategy: how agents understand design specifications
VRT automation pipeline construction: building an operational system that prioritizes visual quality
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Agents & Manager2026-07-10
Tracing Why an Agent Wrote That Line Six Months Ago — Commit Granularity and Provenance Trailers
When an agent packs 14 files and 800 lines into a single commit, git blame tells you nothing six months later. Here is how I split commits at intent boundaries, recorded provenance as machine-readable Git trailers, and built a one-command path from a blamed line back to the design decision behind it.
Agents & Manager2026-07-10
When Your Agent's Files Vanish Into .gitignore — A Pre-Commit Detection Gate
When an agent writes files that match .gitignore, the diff review looks perfect but nothing lands in the commit. Here is a gate script that catches ignored build output before you push, plus the tuning it needs.
Agents & Manager2026-07-08
Measuring the Rework Rate of What You Delegate to Agents: Drawing Delegation Boundaries with Numbers, Not Instinct
How much should you hand to an agent? I drew that line by instinct for a long time. Here is a practical way to compute a per-category rework rate from your git history and redraw the delegation boundary with numbers, with working code.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →