Examples

Examples

Real-world examples demonstrating how to use Vanilla Design System components.

Form Examples

Login Form

A complete login form with validation and error handling.

import { Box, Text, Button, Input, FormField, Checkbox } from '@beauginbey/vanilla-components';
import { useState } from 'react';

export default function App() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [remember, setRemember] = useState(false);
  const [errors, setErrors] = useState({});
  const [loading, setLoading] = useState(false);
  
  const handleSubmit = (e) => {
    e.preventDefault();
    const newErrors = {};
    
    if (!email) {
      newErrors.email = 'Email is required';
    } else if (!email.includes('@')) {
      newErrors.email = 'Please enter a valid email';
    }
    
    if (!password) {
      newErrors.password = 'Password is required';
    } else if (password.length < 8) {
      newErrors.password = 'Password must be at least 8 characters';
    }
    
    setErrors(newErrors);
    
    if (Object.keys(newErrors).length === 0) {
      setLoading(true);
      // Simulate API call
      setTimeout(() => {
        alert(`Logged in as ${email}`);
        setLoading(false);
      }, 1000);
    }
  };
  
  return (
    <Box maxWidth="400px" p={6} backgroundColor={3} borderRadius="lg">
      <Box mb={6}>
        <Text as="h2" size="2xl" weight="bold">
          Sign In
        </Text>
      </Box>
      
      <Box as="form" onSubmit={handleSubmit} display="flex" flexDirection="column" gap={4}>
        <FormField
          label="Email"
          error={errors.email}
          required
        >
          <Input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="you@example.com"
            error={!!errors.email}
          />
        </FormField>
        
        <FormField
          label="Password"
          error={errors.password}
          required
        >
          <Input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            placeholder="Enter your password"
            error={!!errors.password}
          />
        </FormField>
        
        <Box display="flex" alignItems="center" justifyContent="space-between">
          <Box display="flex" alignItems="center" gap={2}>
            <Checkbox
              id="remember"
              checked={remember}
              onChange={(e) => setRemember(e.target.checked)}
            />
            <Text as="label" htmlFor="remember" size="sm">
              Remember me
            </Text>
          </Box>
          
          <Button as="a" href="#" variant="ghost" size="sm">
            Forgot password?
          </Button>
        </Box>
        
        <Button
          type="submit"
          fullWidth
          disabled={loading}
        >
          {loading ? 'Signing in...' : 'Sign In'}
        </Button>
      </Box>
      
      <Box mt={6} textAlign="center">
        <Text size="sm" color="tertiary">
          Don't have an account?{' '}
          <Button as="a" href="#" variant="ghost" size="sm">
            Sign up
          </Button>
        </Text>
      </Box>
    </Box>
  );
}

User Settings Form

A comprehensive settings form demonstrating various form controls.

import { Box, Text, Button, Input, Select, Switch, Radio, FormField } from '@beauginbey/vanilla-components';
import { useState } from 'react';

export default function App() {
  const [settings, setSettings] = useState({
    name: 'John Doe',
    email: 'john@example.com',
    role: 'developer',
    notifications: {
      email: true,
      push: false,
      sms: true
    },
    theme: 'light'
  });
  
  const handleSave = () => {
    alert('Settings saved!');
  };
  
  return (
    <Box maxWidth="600px" p={6}>
      <Text as="h2" size="3xl" weight="bold" mb={6}>
        Account Settings
      </Text>
      
      <Box display="flex" flexDirection="column" gap={6}>
        {/* Profile Section */}
        <Box>
          <Text size="lg" weight="semibold" mb={4}>
            Profile Information
          </Text>
          
          <Box display="flex" flexDirection="column" gap={4}>
            <FormField label="Full Name">
              <Input
                value={settings.name}
                onChange={(e) => setSettings({...settings, name: e.target.value})}
              />
            </FormField>
            
            <FormField label="Email Address">
              <Input
                type="email"
                value={settings.email}
                onChange={(e) => setSettings({...settings, email: e.target.value})}
              />
            </FormField>
            
            <FormField label="Role">
              <Select
                value={settings.role}
                onChange={(e) => setSettings({...settings, role: e.target.value})}
              >
                <option value="developer">Developer</option>
                <option value="designer">Designer</option>
                <option value="manager">Manager</option>
                <option value="other">Other</option>
              </Select>
            </FormField>
          </Box>
        </Box>
        
        {/* Notifications Section */}
        <Box>
          <Text size="lg" weight="semibold" mb={4}>
            Notification Preferences
          </Text>
          
          <Flex flexDirection="column" gap={3}>
            <Box display="flex" alignItems="center" justifyContent="space-between">
              <Box>
                <Text weight="medium">Email Notifications</Text>
                <Text size="sm" color="tertiary">
                  Receive updates via email
                </Text>
              </Box>
              <Switch
                checked={settings.notifications.email}
                onChange={(e) => setSettings({
                  ...settings,
                  notifications: {...settings.notifications, email: e.target.checked}
                })}
              />
            </Box>
            
            <Box display="flex" alignItems="center" justifyContent="space-between">
              <Box>
                <Text weight="medium">Push Notifications</Text>
                <Text size="sm" color="tertiary">
                  Receive push notifications
                </Text>
              </Box>
              <Switch
                checked={settings.notifications.push}
                onChange={(e) => setSettings({
                  ...settings,
                  notifications: {...settings.notifications, push: e.target.checked}
                })}
              />
            </Box>
            
            <Box display="flex" alignItems="center" justifyContent="space-between">
              <Box>
                <Text weight="medium">SMS Notifications</Text>
                <Text size="sm" color="tertiary">
                  Receive SMS messages
                </Text>
              </Box>
              <Switch
                checked={settings.notifications.sms}
                onChange={(e) => setSettings({
                  ...settings,
                  notifications: {...settings.notifications, sms: e.target.checked}
                })}
              />
            </Box>
          </Box>
        </Box>
        
        {/* Theme Section */}
        <Box>
          <Text size="lg" weight="semibold" mb={4}>
            Appearance
          </Text>
          
          <Box display="flex" flexDirection="column" gap={2}>
            {['light', 'cream', 'dark'].map((theme) => (
              <Box key={theme} display="flex" alignItems="center" gap={2}>
                <Radio
                  id={theme}
                  name="theme"
                  value={theme}
                  checked={settings.theme === theme}
                  onChange={(e) => setSettings({...settings, theme: e.target.value})}
                />
                <Text as="label" htmlFor={theme}>
                  {theme.charAt(0).toUpperCase() + theme.slice(1)} Theme
                </Text>
              </Box>
            ))}
          </Box>
        </Box>
        
        {/* Actions */}
        <Box display="flex" gap={2} pt={4}>
          <Button onClick={handleSave}>
            Save Changes
          </Button>
          <Button variant="outline">
            Cancel
          </Button>
        </Box>
      </Box>
    </Box>
  );
}

Layout Examples

Dashboard Layout

A responsive dashboard layout using Flex, Grid, Container, and Section components.

import { Container, Section, Flex, Grid, Box, Text, Button } from '@beauginbey/vanilla-components';

export default function App() {
  const stats = [
    { label: 'Total Users', value: '2,543', change: '+12%' },
    { label: 'Revenue', value: '$45,234', change: '+23%' },
    { label: 'Orders', value: '1,234', change: '-5%' },
    { label: 'Conversion', value: '3.2%', change: '+2%' }
  ];
  
  return (
    <Section>
      <Container>
        {/* Header */}
        <Flex justifyContent="space-between" alignItems="center" mb={6}>
          <Text as="h1" size="3xl" weight="bold">
            Dashboard
          </Text>
          <Flex gap={2}>
          <Button variant="outline" size="sm">
            Export
          </Button>
          <Button size="sm">
            Add Widget
          </Button>
          </Flex>
        </Flex>
        
        {/* Stats Grid */}
        <Grid 
          gap={4} 
          style={{ 
            gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' 
          }}
          mb={6}
        >
        {stats.map((stat) => (
          <Box
            key={stat.label}
            p={4}
            backgroundColor="secondary"
            borderRadius="lg"
            boxShadow="base"
          >
            <Text size="sm" color="tertiary" mb={2}>
              {stat.label}
            </Text>
            <Flex alignItems="baseline" justifyContent="space-between">
              <Text size="2xl" weight="bold">
                {stat.value}
              </Text>
              <Text 
                size="sm" 
                color={stat.change.startsWith('+') ? 'success' : 'error'}
              >
                {stat.change}
              </Text>
            </Flex>
          </Box>
        ))}
      </Grid>
      
        {/* Content Area */}
        <Flex gap={6} flexDirection={{ mobile: 'column', tablet: 'row' }}>
        {/* Main Content */}
        <Box flex="1" backgroundColor="tertiary" borderRadius="lg" p={6}>
          <Text size="xl" weight="semibold" mb={4}>
            Recent Activity
          </Text>
          <Flex flexDirection="column" gap={3}>
            {[1, 2, 3, 4].map((i) => (
              <Flex
                key={i}
                p={3}
                backgroundColor={2}
                borderRadius="md"
                alignItems="center"
                justifyContent="space-between"
              >
                <Box>
                  <Text weight="medium">User activity #{i}</Text>
                  <Text size="sm" color="tertiary">
                    2 hours ago
                  </Text>
                </Box>
                <Button variant="ghost" size="sm">
                  View
                </Button>
              </Flex>
            ))}
          </Flex>
        </Box>
        
        {/* Sidebar */}
        <Box width={{ mobile: '100%', tablet: '300px' }}>
          <Box backgroundColor="tertiary" borderRadius="lg" p={6} mb={4}>
            <Text size="lg" weight="semibold" mb={3}>
              Quick Actions
            </Text>
            <Box display="flex" flexDirection="column" gap={2}>
              <Button fullWidth variant="outline" size="sm">
                Create Report
              </Button>
              <Button fullWidth variant="outline" size="sm">
                Invite Team Member
              </Button>
              <Button fullWidth variant="outline" size="sm">
                Download Data
              </Button>
            </Box>
          </Box>
          
          <Box backgroundColor="primary" borderRadius="lg" p={6}>
            <Text size="lg" weight="semibold" mb={2} color="inverse">
              Pro Tip
            </Text>
            <Text size="sm" color="inverse">
              You can customize your dashboard by clicking the "Add Widget" button above.
            </Text>
          </Box>
        </Box>
      </Flex>
    </Container>
  </Section>
  );
}

Card Grid

A responsive card grid layout.

import { Box, Text, Button } from '@beauginbey/vanilla-components';

export default function App() {
  const products = [
    { id: 1, name: 'Product 1', price: '$29.99', category: 'Electronics' },
    { id: 2, name: 'Product 2', price: '$49.99', category: 'Clothing' },
    { id: 3, name: 'Product 3', price: '$19.99', category: 'Books' },
    { id: 4, name: 'Product 4', price: '$99.99', category: 'Electronics' },
    { id: 5, name: 'Product 5', price: '$39.99', category: 'Home' },
    { id: 6, name: 'Product 6', price: '$59.99', category: 'Sports' }
  ];
  
  return (
    <Box p={6}>
      <Text as="h2" size="3xl" weight="bold" mb={6}>
        Featured Products
      </Text>
      
      <Box
        display="grid"
        gap={4}
        style={{
          gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))'
        }}
      >
        {products.map((product) => (
          <Box
            key={product.id}
            backgroundColor="secondary"
            borderRadius="lg"
            overflow="hidden"
            boxShadow="base"
            display="flex"
            flexDirection="column"
          >
            {/* Product Image Placeholder */}
            <Box
              height="200px"
              backgroundColor="tertiary"
              display="flex"
              alignItems="center"
              justifyContent="center"
            >
              <Text color="secondary">Product Image</Text>
            </Box>
            
            {/* Product Details */}
            <Box p={4} display="flex" flexDirection="column" gap={2} flex="1">
              <Box flex="1">
                <Text size="lg" weight="semibold">
                  {product.name}
                </Text>
                <Text size="sm" color="tertiary">
                  {product.category}
                </Text>
              </Box>
              
              <Box display="flex" alignItems="center" justifyContent="space-between" mt={2}>
                <Text size="xl" weight="bold" color="brand">
                  {product.price}
                </Text>
                <Button size="sm">
                  Add to Cart
                </Button>
              </Box>
            </Box>
          </Box>
        ))}
      </Box>
    </Box>
  );
}

Component Composition

Modal Dialog

Creating a modal dialog by composing basic components.

import { Box, Text, Button, Input, FormField } from '@beauginbey/vanilla-components';
import { useState } from 'react';

export default function App() {
  const [isOpen, setIsOpen] = useState(false);
  const [email, setEmail] = useState('');
  
  const handleSubmit = (e) => {
    e.preventDefault();
    alert(`Subscribed with email: ${email}`);
    setIsOpen(false);
    setEmail('');
  };
  
  return (
    <>
      <Button onClick={() => setIsOpen(true)}>
        Open Modal
      </Button>
      
      {isOpen && (
        <>
          {/* Backdrop */}
          <Box
            position="fixed"
            top={0}
            left={0}
            right={0}
            bottom={0}
            backgroundColor="primary"
            opacity={0.5}
            onClick={() => setIsOpen(false)}
            style={{ zIndex: 1000 }}
          />
          
          {/* Modal */}
          <Box
            position="fixed"
            style={{
              top: '50%',
              left: '50%',
              transform: 'translate(-50%, -50%)',
              zIndex: 1001,
              width: '90%',
              maxWidth: '500px'
            }}
          >
            <Box
              backgroundColor="primary"
              borderRadius="lg"
              boxShadow="lg"
              p={6}
            >
              <Box display="flex" justifyContent="space-between" alignItems="center" mb={4}>
                <Text as="h3" size="xl" weight="bold">
                  Subscribe to Newsletter
                </Text>
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => setIsOpen(false)}
                ></Button>
              </Box>
              
              <Text color="secondary" mb={4}>
                Get the latest updates and news delivered to your inbox.
              </Text>
              
              <Box as="form" onSubmit={handleSubmit}>
                <FormField label="Email Address" required>
                  <Input
                    type="email"
                    value={email}
                    onChange={(e) => setEmail(e.target.value)}
                    placeholder="you@example.com"
                    required
                  />
                </FormField>
                
                <Box display="flex" gap={2} mt={6}>
                  <Button type="submit" fullWidth>
                    Subscribe
                  </Button>
                  <Button
                    type="button"
                    variant="outline"
                    fullWidth
                    onClick={() => setIsOpen(false)}
                  >
                    Cancel
                  </Button>
                </Box>
              </Box>
            </Box>
          </Box>
        </>
      )}
    </>
  );
}

Notification Banner

A dismissible notification banner component.

import { Box, Text, Button } from '@beauginbey/vanilla-components';
import { useState } from 'react';

export default function App() {
  const [notifications, setNotifications] = useState([
    { id: 1, type: 'success', message: 'Your changes have been saved successfully!' },
    { id: 2, type: 'warning', message: 'Your session will expire in 5 minutes.' },
    { id: 3, type: 'error', message: 'Failed to load data. Please try again.' },
    { id: 4, type: 'info', message: 'New features are now available in your account.' }
  ]);
  
  const removeNotification = (id) => {
    setNotifications(notifications.filter(n => n.id !== id));
  };
  
  const getNotificationStyle = (type) => {
    switch(type) {
      case 'success':
        return { borderColor: 'var(--vanilla-color-feedback-success)', textColor: 'success' };
      case 'warning':
        return { borderColor: 'var(--vanilla-color-feedback-warning)', textColor: 'warning' };
      case 'error':
        return { borderColor: 'var(--vanilla-color-feedback-error)', textColor: 'error' };
      case 'info':
        return { borderColor: 'var(--vanilla-color-feedback-info)', textColor: 'info' };
      default:
        return { borderColor: 'var(--vanilla-color-border-primary)', textColor: 'primary' };
    }
  };
  
  const getIcon = (type) => {
    switch(type) {
      case 'success': return '✓';
      case 'warning': return '⚠';
      case 'error': return '✕';
      case 'info': return 'ℹ';
      default: return '';
    }
  };
  
  return (
    <Box display="flex" flexDirection="column" gap={3}>
      {notifications.map((notification) => {
        const style = getNotificationStyle(notification.type);
        return (
          <Box
            key={notification.id}
            p={4}
            backgroundColor="tertiary"
            borderRadius="md"
            display="flex"
            alignItems="center"
            justifyContent="space-between"
            style={{
              border: '2px solid ' + style.borderColor
            }}
          >
            <Box display="flex" alignItems="center" gap={3}>
              <Text size="lg" color={style.textColor}>
                {getIcon(notification.type)}
              </Text>
              <Text>{notification.message}</Text>
            </Box>
            
            <Button
              variant="ghost"
              size="sm"
              onClick={() => removeNotification(notification.id)}
            >
              Dismiss
            </Button>
          </Box>
        );
      })}
      
      {notifications.length === 0 && (
        <Box p={8} textAlign="center">
          <Text color="tertiary">No notifications</Text>
          <Box mt={4}>
            <Button
              variant="outline"
              size="sm"
              onClick={() => setNotifications([
                { id: Date.now(), type: 'success', message: 'Here is a new notification!' }
              ])}
            >
              Add Notification
            </Button>
          </Box>
        </Box>
      )}
    </Box>
  );
}

Theme Integration

See the Theming page for examples of how components adapt to different themes.