Skip to main content

Styling Guide

The T1 Component Library uses Tailwind CSS v4 with a custom design token system based on CSS custom properties. This guide explains how styling works in the library and how to use it effectively.

Tailwind CSS v4

The library uses Tailwind CSS v4, which is imported using the new @import directive:
@import "tailwindcss";
This provides access to all Tailwind utilities while maintaining our custom design system.

CSS Custom Properties (Design Tokens)

All components use CSS custom properties (CSS variables) defined in globals.css:4. These tokens ensure consistent theming across light and dark modes.

Color Tokens

:root {
  /* Primary - Deep Indigo */
  --primary: #4f46e5;
  --primary-hover: #4338ca;
  --primary-foreground: #ffffff;
  
  /* Secondary - Slate */
  --secondary: #f1f5f9;
  --secondary-hover: #e2e8f0;
  --secondary-foreground: #475569;
  
  /* Accent - Teal */
  --accent: #14b8a6;
  --accent-hover: #0d9488;
  --accent-foreground: #ffffff;
  
  /* Destructive - Rose */
  --destructive: #f43f5e;
  --destructive-hover: #e11d48;
  --destructive-foreground: #ffffff;
}

Spacing & Radius Tokens

:root {
  /* Radius */
  --radius-sm: 0.375rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;
  --radius-full: 9999px;
  
  /* Transitions */
  --transition-fast: 150ms;
  --transition-normal: 200ms;
  --transition-slow: 300ms;
}

Shadow Tokens

:root {
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
}

Dark Mode

Dark mode is automatically supported through CSS custom properties. The .dark class switches all tokens:
.dark {
  --background: #0f0f1a;
  --foreground: #f1f5f9;
  --primary: #818cf8;
  --primary-hover: #a5b4fc;
  /* ... other tokens */
}
No component changes are needed - they automatically adapt to the current theme.

Variant Styles Pattern

Components use a variant styles pattern with TypeScript Record types for type-safe styling.

Button Variant Example

From Button.tsx:16:
const variantStyles: Record<ButtonVariant, string> = {
  primary: `
    bg-primary text-primary-foreground 
    hover:bg-primary-hover 
    focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2
    shadow-sm hover:shadow-md
  `,
  secondary: `
    bg-secondary text-secondary-foreground 
    hover:bg-secondary-hover 
    focus-visible:ring-2 focus-visible:ring-secondary focus-visible:ring-offset-2
  `,
  accent: `
    bg-accent text-accent-foreground 
    hover:bg-accent-hover 
    focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2
  `,
  destructive: `
    bg-destructive text-destructive-foreground 
    hover:bg-destructive-hover 
    focus-visible:ring-2 focus-visible:ring-destructive focus-visible:ring-offset-2
  `,
  ghost: `
    bg-transparent text-foreground 
    hover:bg-secondary 
    focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2
  `,
  outline: `
    bg-transparent text-foreground 
    border-2 border-border 
    hover:bg-secondary hover:border-primary
  `,
};

Size Styles Example

From Button.tsx:53:
const sizeStyles: Record<ButtonSize, string> = {
  sm: 'px-3 py-1.5 text-sm gap-1.5',
  md: 'px-4 py-2 text-base gap-2',
  lg: 'px-6 py-3 text-lg gap-2.5',
};

Applying Styles

Styles are applied dynamically using template literals (Button.tsx:80):
<button
  className={`
    inline-flex items-center justify-center font-medium
    rounded-[var(--radius-md)]
    transition-all duration-[var(--transition-fast)]
    ${variantStyles[variant]}
    ${sizeStyles[size]}
    ${isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
    ${className}
  `}
>

Card Component Variants

From Card.tsx:19:
const variantStyles = {
  default: 'bg-card border border-border',
  bordered: 'bg-card border-2 border-border',
  elevated: 'bg-card shadow-lg border border-border/50',
};

const paddingStyles = {
  none: '',
  sm: 'p-3',
  md: 'p-5',
  lg: 'p-7',
};

Using CSS Variables in Tailwind

You can reference CSS variables directly in Tailwind classes:
// Using var() syntax
rounded-[var(--radius-md)]
duration-[var(--transition-fast)]

// Using Tailwind's theme integration
bg-primary
text-primary-foreground
border-border

Tailwind Theme Integration

The design tokens are integrated into Tailwind using the @theme directive (globals.css:124):
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
  --color-primary-hover: var(--primary-hover);
  /* ... more mappings */
}
This allows using tokens as Tailwind utilities:
<div className="bg-primary text-primary-foreground">

Animations

Custom animations are defined in globals.css:193:
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
Use them with animation classes:
<div className="animate-fade-in">
<div className="animate-slide-up">
<div className="animate-scale-in">

Best Practices

  1. Always use design tokens instead of hardcoded colors
  2. Use the variant pattern for component variations
  3. Leverage Tailwind utilities for layout and spacing
  4. Use CSS variables for values that change between themes
  5. Apply transitions for smooth interactive feedback

Example: Complete Button Styling

<Button 
  variant="primary" 
  size="md"
  className="w-full"
>
  Submit
</Button>
This applies:
  • Primary variant styles (bg-primary, hover states, focus ring)
  • Medium size styles (px-4 py-2 text-base)
  • Custom width (w-full)
  • Default transition timing (var(—transition-fast))
  • Border radius (var(—radius-md))

Build docs developers (and LLMs) love