Consumption: UI Libraries
UI Library Integration
Scope: UI library integration using Variable Design Standard (VDS) outputs.
Failure if ignored: components bypass generated outputs and drift from the contract.
React integration
CSS variables
Use CSS variables in React:
function Button({ children }) {
return <button className="button">{children}</button>;
}
.button {
background-color: var(--color-surface-brand);
color: var(--color-text-primary);
}
Inline styles with TypeScript
Use generated TypeScript types:
import { color, spacing } from "./tokens";
function Button({ children }: { children: React.ReactNode }) {
return (
<button
style={{
backgroundColor: color.surface.brand,
color: color.text.primary,
padding: spacing.component.button.padding,
}}
>
{children}
</button>
);
}
CSS-in-JS
Use with styled-components:
import styled from "styled-components";
import { color, spacing } from "./tokens";
const Button = styled.button`
background-color: ${color.surface.brand};
color: ${color.text.primary};
padding: ${spacing.component.button.padding};
`;
Use with emotion:
import { css } from "@emotion/react";
import { color, spacing } from "./tokens";
const buttonStyle = css`
background-color: ${color.surface.brand};
color: ${color.text.primary};
padding: ${spacing.component.button.padding};
`;
function Button({ children }) {
return <button css={buttonStyle}>{children}</button>;
}
Theme context
Use theme context for mode switching:
import { createContext, useContext, useState } from "react";
import { color } from "./tokens";
const ThemeContext = createContext({
theme: "light",
setTheme: () => {},
colors: color,
});
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const colors = {
surface: color.surface[theme],
text: color.text[theme],
};
return (
<ThemeContext.Provider value={{ theme, setTheme, colors }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
Vue integration
CSS variables
Use CSS variables in Vue:
<template>
<button class="button">
<slot></slot>
</button>
</template>
<style scoped>
.button {
background-color: var(--color-surface-brand);
color: var(--color-text-primary);
}
</style>
Style binding
Use style binding:
<template>
<button :style="buttonStyle">
<slot></slot>
</button>
</template>
<script setup>
import { color, spacing } from "./tokens";
const buttonStyle = {
backgroundColor: color.surface.brand,
color: color.text.primary,
padding: spacing.component.button.padding,
};
</script>
Provide/inject
Use provide/inject for theme:
<script setup>
import { provide, inject, ref } from "vue";
import { color } from "./tokens";
const theme = ref("light");
provide("theme", theme);
provide("colors", {
surface: color.surface[theme.value],
text: color.text[theme.value],
});
</script>
Angular integration
CSS variables
Use CSS variables in Angular:
@Component({
selector: "app-button",
template: '<button class="button"><ng-content></ng-content></button>',
styles: [
`
.button {
background-color: var(--color-surface-brand);
color: var(--color-text-primary);
}
`,
],
})
export class ButtonComponent {}
Style binding
Use style binding:
import { Component } from "@angular/core";
import { color, spacing } from "./tokens";
@Component({
selector: "app-button",
template: '<button [style]="buttonStyle"><ng-content></ng-content></button>',
})
export class ButtonComponent {
buttonStyle = {
"background-color": color.surface.brand,
color: color.text.primary,
padding: spacing.component.button.padding,
};
}
Examples
React button component
Complete React button:
import { useTheme } from "./ThemeContext";
function Button({ children, variant = "primary" }) {
const { colors } = useTheme();
const backgroundColor =
variant === "primary" ? colors.surface.brand : colors.surface.secondary;
return (
<button
style={{
backgroundColor,
color: colors.text.primary,
padding: "12px 24px",
}}
>
{children}
</button>
);
}
Vue button component
Complete Vue button:
<template>
<button :class="['button', `button--${variant}`]" :style="buttonStyle">
<slot></slot>
</button>
</template>
<script setup>
import { computed } from "vue";
import { inject } from "vue";
import { color, spacing } from "./tokens";
const props = defineProps({
variant: {
type: String,
default: "primary",
},
});
const theme = inject("theme", "light");
const colors = computed(() => ({
surface: color.surface[theme],
text: color.text[theme],
}));
const buttonStyle = computed(() => ({
backgroundColor:
props.variant === "primary"
? colors.value.surface.brand
: colors.value.surface.secondary,
color: colors.value.text.primary,
padding: spacing.component.button.padding,
}));
</script>
Implementation rules
- Use CSS variables when possible
- Use TypeScript types for type safety
- Create theme context/hooks for mode switching
- Document library integration
- Test library consumption
Failure modes
If library integration is wrong:
- Hardcoded values
- No type safety
- Broken mode switching
- Inconsistent styling
Out of scope
- React or Vue specific features (see tool docs)
- State management (separate concern)
- Component architecture (separate concern)