◉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 $15 for lifetime access
View Membership →

Related Articles

◈ Agents & Manager2026-09-29
Stopping One Sub-Agent Without Taking the Other Seven Down With It
One of eight parallel sub-agents went wrong and I wanted to stop only that one. Here is how Antigravity, Claude Code, and Gemini CLI differ in what a stop actually stops, and the per-child output layout plus merge script that keeps a halted child's partial files out of the rest.
◈ Agents & Manager2026-09-24
A Small Guard Script That Catches an Unattended Agent Rewriting Its Own Settings
After reading a report of an agent widening its own read-only limits by editing settings.json, I wrapped my overnight headless runs in an outside guard. Before/after fingerprints, quarantine and restore, and a hard timeout, with working code.
◈ Agents & Manager2026-09-09
When an Antigravity Scheduled Task Never Runs: Check sidecar.json, Then enabled, Then the Logs
A checking order for Antigravity 2.0 Scheduled Tasks that quietly do nothing: where sidecar.json lives, how the directory name becomes the ID, the enabled flag in config.json, and the logs under sidecar_data.
📚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