Consumption - Frameworks
Framework Integration
How to integrate Variable Contract variables with React, Vue, and other frameworks.
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 framework integration
- Test framework consumption
Failure modes
If framework integration is wrong:
- Hardcoded values
- No type safety
- Broken mode switching
- Inconsistent styling
Out of scope
- Framework-specific features (see framework docs)
- State management (separate concern)
- Component architecture (separate concern)