Style Guide
This style guide provides practical guidelines for using DS-Bridge components and design tokens to build consistent, accessible, and beautiful user interfaces.
Design Principles
Every design decision in DS-Bridge aligns with our core principles:
Consistency
Use the same patterns, components, and tokens throughout your application. Consistency builds familiarity and trust.
Clarity
Keep interfaces simple and intuitive. Users should understand what to do without reading documentation.
Accessibility
Build for everyone. Every component meets WCAG 2.1 AAA standards.
Performance
Fast is a feature. Optimize for speed and efficiency.
Component Usage Guidelines
Buttons
Use buttons for actions, not navigation (use links for that).
✅ Good:
<DsButton @click="saveChanges">Save Changes</DsButton>
<DsButton color="error" @click="deleteItem">Delete</DsButton>❌ Bad:
<!-- Don't use buttons for navigation -->
<DsButton @click="goToPage">View Profile</DsButton>
<!-- Use links instead -->
<a href="/profile">View Profile</a>Button Hierarchy:
- Filled (primary): Main action (save, submit, create)
- Outlined (secondary): Secondary actions (cancel, back)
- Text (tertiary): Low-priority actions (skip, dismiss)
<!-- Primary action -->
<DsButton>Save</DsButton>
<!-- Secondary action -->
<DsButton variant="outlined">Cancel</DsButton>
<!-- Tertiary action -->
<DsButton variant="text">Skip</DsButton>Forms
Group related fields with consistent spacing:
<form :style="{ display: 'flex', flexDirection: 'column', gap: tokens.spacing.lg }">
<!-- Name group -->
<div :style="{ display: 'flex', flexDirection: 'column', gap: tokens.spacing.xs }">
<label for="name">Name</label>
<input id="name" type="text" />
</div>
<!-- Email group -->
<div :style="{ display: 'flex', flexDirection: 'column', gap: tokens.spacing.xs }">
<label for="email">Email</label>
<input id="email" type="email" />
</div>
<!-- Actions -->
<div :style="{ display: 'flex', gap: tokens.spacing.md, marginTop: tokens.spacing.md }">
<DsButton variant="outlined">Cancel</DsButton>
<DsButton type="submit">Submit</DsButton>
</div>
</form>Form Validation:
- Show errors inline, near the field
- Use semantic colors (error, warning, success)
- Provide clear, actionable error messages
<div>
<label for="email">Email</label>
<input id="email" type="email" :class="{ error: hasError }" />
<span v-if="hasError" :style="{ color: tokens.colors.error, fontSize: tokens.typography.fontSize.sm }">
Please enter a valid email address
</span>
</div>Layout Patterns
Page Layout
Use consistent spacing for page structure:
<template>
<div :style="pageStyles">
<!-- Header -->
<header :style="headerStyles">
<h1>Page Title</h1>
</header>
<!-- Main content -->
<main :style="mainStyles">
<section :style="sectionStyles">
<h2>Section Title</h2>
<p>Content</p>
</section>
</main>
<!-- Footer -->
<footer :style="footerStyles">
Footer content
</footer>
</div>
</template>
<script setup>
import { tokens } from 'ds-bridge/tokens';
const pageStyles = {
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
};
const headerStyles = {
padding: `${tokens.spacing.lg} ${tokens.spacing.xl}`,
borderBottom: `1px solid ${tokens.colors.divider}`,
};
const mainStyles = {
flex: 1,
padding: `${tokens.spacing.xl} ${tokens.spacing.lg}`,
};
const sectionStyles = {
marginBottom: tokens.spacing.xxl,
};
const footerStyles = {
padding: tokens.spacing.lg,
borderTop: `1px solid ${tokens.colors.divider}`,
backgroundColor: tokens.colors.surfaceVariant,
};
</script>Card Layout
Cards group related content:
<div :style="{
backgroundColor: tokens.colors.surface,
borderRadius: tokens.borderRadius.md,
boxShadow: tokens.shadows.sm,
padding: tokens.spacing.lg,
marginBottom: tokens.spacing.md
}">
<h3 :style="{ marginBottom: tokens.spacing.md, color: tokens.colors.textHigh }">
Card Title
</h3>
<p :style="{ marginBottom: tokens.spacing.md, color: tokens.colors.textMedium }">
Card description with proper typography and spacing.
</p>
<div :style="{ display: 'flex', gap: tokens.spacing.sm }">
<DsButton variant="text">Learn More</DsButton>
<DsButton>Take Action</DsButton>
</div>
</div>Grid Layout
Use CSS Grid for responsive layouts:
<div :style="{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
gap: tokens.spacing.lg,
padding: tokens.spacing.xl
}">
<div v-for="item in items" :key="item.id" class="grid-item">
{{ item.name }}
</div>
</div>Color Usage
Text Hierarchy
Use text colors to create visual hierarchy:
<div>
<!-- High emphasis - headings, important content -->
<h2 :style="{ color: tokens.colors.textHigh }">
Main Heading
</h2>
<!-- Medium emphasis - body text -->
<p :style="{ color: tokens.colors.textMedium }">
This is body text with standard emphasis.
</p>
<!-- Low emphasis - supporting text -->
<span :style="{ color: tokens.colors.textLow, fontSize: tokens.typography.fontSize.sm }">
Updated 2 hours ago
</span>
</div>Semantic Colors
Use semantic colors to convey meaning:
<!-- Error message -->
<div :style="{
backgroundColor: tokens.colors.errorLight,
color: tokens.colors.error,
padding: tokens.spacing.md,
borderRadius: tokens.borderRadius.sm,
borderLeft: `4px solid ${tokens.colors.error}`
}">
Error: Unable to save changes
</div>
<!-- Success message -->
<div :style="{
backgroundColor: tokens.colors.successLight,
color: tokens.colors.success,
padding: tokens.spacing.md,
borderRadius: tokens.borderRadius.sm,
borderLeft: `4px solid ${tokens.colors.success}`
}">
Success: Changes saved!
</div>
<!-- Warning message -->
<div :style="{
backgroundColor: tokens.colors.warningLight,
color: tokens.colors.warning,
padding: tokens.spacing.md,
borderRadius: tokens.borderRadius.sm,
borderLeft: `4px solid ${tokens.colors.warning}`
}">
Warning: This action cannot be undone
</div>
<!-- Info message -->
<div :style="{
backgroundColor: tokens.colors.infoLight,
color: tokens.colors.info,
padding: tokens.spacing.md,
borderRadius: tokens.borderRadius.sm,
borderLeft: `4px solid ${tokens.colors.info}`
}">
Info: You have unsaved changes
</div>Typography Usage
Heading Hierarchy
Use proper heading levels for structure:
<article>
<h1 :style="headingStyles(1)">Page Title</h1>
<section>
<h2 :style="headingStyles(2)">Section Title</h2>
<p>Section content...</p>
<h3 :style="headingStyles(3)">Subsection</h3>
<p>Subsection content...</p>
</section>
</article>const headingStyles = (level: number) => ({
fontFamily: tokens.typography.fontFamily.base,
fontWeight: tokens.typography.fontWeight.bold,
lineHeight: tokens.typography.lineHeight.tight,
color: tokens.colors.textHigh,
fontSize:
level === 1 ? tokens.typography.fontSize['3xl'] :
level === 2 ? tokens.typography.fontSize['2xl'] :
level === 3 ? tokens.typography.fontSize.xl :
tokens.typography.fontSize.lg,
});Body Text
Use appropriate sizes for content:
<!-- Primary content -->
<p :style="{
fontSize: tokens.typography.fontSize.base,
lineHeight: tokens.typography.lineHeight.normal,
color: tokens.colors.textMedium
}">
This is the main body text.
</p>
<!-- Secondary content -->
<p :style="{
fontSize: tokens.typography.fontSize.sm,
lineHeight: tokens.typography.lineHeight.normal,
color: tokens.colors.textLow
}">
This is supporting text.
</p>Spacing Patterns
Vertical Rhythm
Maintain consistent vertical spacing:
<div>
<h2 :style="{ marginBottom: tokens.spacing.md }">Section Title</h2>
<p :style="{ marginBottom: tokens.spacing.md }">First paragraph</p>
<p :style="{ marginBottom: tokens.spacing.md }">Second paragraph</p>
<p :style="{ marginBottom: tokens.spacing.xl }">Last paragraph before next section</p>
<h2 :style="{ marginBottom: tokens.spacing.md }">Next Section</h2>
</div>Horizontal Rhythm
Use consistent gaps in flex/grid layouts:
<!-- Button group -->
<div :style="{ display: 'flex', gap: tokens.spacing.md }">
<DsButton variant="outlined">Cancel</DsButton>
<DsButton>Save</DsButton>
</div>
<!-- Card grid -->
<div :style="{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: tokens.spacing.lg }">
<div>Card 1</div>
<div>Card 2</div>
<div>Card 3</div>
</div>Accessibility Guidelines
Keyboard Navigation
Ensure all interactive elements are keyboard accessible:
<!-- Proper button (keyboard accessible by default) -->
<DsButton @click="handleClick">Click me</DsButton>
<!-- If using div as button (not recommended), add keyboard support -->
<div
role="button"
tabindex="0"
@click="handleClick"
@keydown.enter="handleClick"
@keydown.space.prevent="handleClick"
>
Custom button
</div>ARIA Labels
Provide labels for icon-only buttons:
<!-- Icon button with label -->
<DsButton aria-label="Close dialog" @click="closeDialog">
<v-icon icon="mdi-close" />
</DsButton>
<!-- Link with aria-label -->
<a href="/profile" aria-label="View your profile">
<v-icon icon="mdi-account" />
</a>Color Contrast
Always ensure sufficient contrast:
<!-- Good contrast -->
<div :style="{
backgroundColor: tokens.colors.primary,
color: tokens.colors.textInverse
}">
High contrast text
</div>
<!-- Check contrast ratio -->
<!-- textHigh on surface: 15.8:1 (AAA) -->
<!-- primary on white: 7.2:1 (AAA) -->Focus States
Ensure visible focus indicators:
<style>
button:focus-visible {
outline: 2px solid var(--ds-color-primary);
outline-offset: 2px;
border-radius: var(--ds-radius-sm);
}
</style>Responsive Design
Mobile-First Approach
Start with mobile styles, enhance for larger screens:
<script setup>
import { tokens } from 'ds-bridge/tokens';
import { computed, onMounted, ref } from 'vue';
const isMobile = ref(false);
onMounted(() => {
isMobile.value = window.innerWidth < 768;
window.addEventListener('resize', () => {
isMobile.value = window.innerWidth < 768;
});
});
const containerStyles = computed(() => ({
padding: isMobile.value ? tokens.spacing.md : tokens.spacing.xl,
fontSize: isMobile.value ? tokens.typography.fontSize.sm : tokens.typography.fontSize.base,
}));
</script>Responsive Grids
Use auto-fit for responsive columns:
<div :style="{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
gap: tokens.spacing.lg
}">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>Best Practices Summary
DO
✅ Use design tokens for all values ✅ Maintain consistent spacing and typography ✅ Follow accessibility guidelines (WCAG 2.1 AAA) ✅ Use semantic HTML elements ✅ Provide keyboard navigation ✅ Test with screen readers ✅ Ensure color contrast ratios ✅ Use semantic colors for meaning
DON'T
❌ Hardcode colors, spacing, or font sizes ❌ Use divs for buttons or links ❌ Rely solely on color to convey information ❌ Create custom components that duplicate existing ones ❌ Ignore keyboard accessibility ❌ Use small font sizes (< 12px) ❌ Mix arbitrary values with tokens
Component Checklist
When creating new components:
- [ ] Uses design tokens (no hardcoded values)
- [ ] Keyboard accessible (Tab, Enter, Space)
- [ ] Screen reader friendly (ARIA labels, semantic HTML)
- [ ] Proper focus states
- [ ] Color contrast meets WCAG AAA
- [ ] Responsive on mobile and desktop
- [ ] Consistent with existing components
- [ ] Documented with examples
- [ ] Unit tested
- [ ] Accessibility tested
Learn More
- Design Tokens: Token system overview
- Colors: Color palette and usage
- Typography: Type system
- Spacing: Spacing scale
- Components: Component library
Questions about usage? Review the component documentation for detailed examples.

