Comprehensive theming system for defining component styles with variants, sizes, multi-part component support, and responsive theming props. This system enables consistent, theme-aware component styling with powerful customization options.
Core utilities for defining component styles with type safety and theme integration.
/**
* Props passed to style functions for theme-aware styling
*/
interface StyleFunctionProps {
colorScheme: string;
colorMode: "light" | "dark";
orientation?: "horizontal" | "vertical";
theme: Record<string, any>;
[key: string]: any;
}
/**
* Function that returns system styles based on props
*/
type SystemStyleFunction = (props: StyleFunctionProps) => SystemStyleObject;
/**
* Style object or function that can be used in component definitions
*/
type SystemStyleInterpolation = SystemStyleObject | SystemStyleFunction;
/**
* Defines component styles with type safety
* @param styles - Style object or function
* @returns The same styles with proper typing
*/
function defineStyle<T extends SystemStyleInterpolation>(styles: T): T;Usage Examples:
import { defineStyle, SystemStyleFunction } from "@chakra-ui/styled-system";
// Static style definition
const staticButtonStyle = defineStyle({
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
borderRadius: "md",
fontWeight: "semibold",
transition: "all 0.2s",
_hover: {
transform: "translateY(-2px)",
boxShadow: "lg"
},
_active: {
transform: "translateY(0)"
}
});
// Dynamic style function
const dynamicButtonStyle = defineStyle<SystemStyleFunction>(({
colorScheme,
colorMode,
theme
}) => ({
bg: `${colorScheme}.500`,
color: colorMode === "dark" ? "white" : "black",
borderColor: `${colorScheme}.600`,
_hover: {
bg: `${colorScheme}.600`,
_disabled: {
bg: `${colorScheme}.500`
}
},
_dark: {
bg: `${colorScheme}.200`,
color: "gray.800"
}
}));
// Responsive style definition
const responsiveStyle = defineStyle({
fontSize: { base: "sm", md: "md", lg: "lg" },
px: { base: 3, md: 4, lg: 6 },
py: { base: 2, md: 3 },
// Responsive pseudo-selectors
_hover: {
bg: { base: "gray.100", _dark: "gray.700" }
}
});Configuration system for single-part components with variants, sizes, and default props.
/**
* Configuration for single-part component theming
*/
interface StyleConfig {
baseStyle?: SystemStyleInterpolation;
sizes?: { [size: string]: SystemStyleInterpolation };
variants?: { [variant: string]: SystemStyleInterpolation };
defaultProps?: {
size?: string;
variant?: string;
colorScheme?: string;
};
}
/**
* Defines style configuration for single-part components
* @param config - Component style configuration
* @returns Typed style configuration object
*/
function defineStyleConfig<
BaseStyle extends SystemStyleInterpolation,
Sizes extends Record<string, SystemStyleInterpolation>,
Variants extends Record<string, SystemStyleInterpolation>
>(config: {
baseStyle?: BaseStyle;
sizes?: Sizes;
variants?: Variants;
defaultProps?: {
size?: keyof Sizes;
variant?: keyof Variants;
colorScheme?: string;
};
}): StyleConfig;Usage Examples:
import { defineStyleConfig, SystemStyleFunction } from "@chakra-ui/styled-system";
// Complete button configuration
const Button = defineStyleConfig({
// Base styles applied to all variants and sizes
baseStyle: {
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
borderRadius: "md",
fontWeight: "semibold",
transition: "all 0.2s",
cursor: "pointer",
_disabled: {
opacity: 0.4,
cursor: "not-allowed"
}
},
// Size variants
sizes: {
xs: { fontSize: "xs", px: 2, py: 1, h: 6 },
sm: { fontSize: "sm", px: 3, py: 2, h: 8 },
md: { fontSize: "md", px: 4, py: 2, h: 10 },
lg: { fontSize: "lg", px: 6, py: 3, h: 12 },
xl: { fontSize: "xl", px: 8, py: 4, h: 14 }
},
// Variant styles with color scheme support
variants: {
solid: ({ colorScheme }: StyleFunctionProps) => ({
bg: `${colorScheme}.500`,
color: "white",
_hover: {
bg: `${colorScheme}.600`,
_disabled: { bg: `${colorScheme}.500` }
},
_active: { bg: `${colorScheme}.700` }
}),
outline: ({ colorScheme }: StyleFunctionProps) => ({
border: "1px solid",
borderColor: `${colorScheme}.500`,
color: `${colorScheme}.500`,
bg: "transparent",
_hover: {
bg: `${colorScheme}.50`,
_dark: { bg: `${colorScheme}.900` }
}
}),
ghost: ({ colorScheme }: StyleFunctionProps) => ({
bg: "transparent",
color: `${colorScheme}.500`,
_hover: {
bg: `${colorScheme}.100`,
_dark: { bg: `${colorScheme}.800` }
}
}),
link: ({ colorScheme }: StyleFunctionProps) => ({
color: `${colorScheme}.500`,
_hover: {
textDecoration: "underline"
}
})
},
// Default values
defaultProps: {
size: "md",
variant: "solid",
colorScheme: "gray"
}
});
// Input field configuration
const Input = defineStyleConfig({
baseStyle: {
field: {
width: "100%",
minWidth: 0,
outline: 0,
position: "relative",
appearance: "none",
transition: "all 0.2s"
}
},
sizes: {
lg: { field: { fontSize: "lg", px: 4, h: 12, borderRadius: "md" } },
md: { field: { fontSize: "md", px: 4, h: 10, borderRadius: "md" } },
sm: { field: { fontSize: "sm", px: 3, h: 8, borderRadius: "sm" } },
xs: { field: { fontSize: "xs", px: 2, h: 6, borderRadius: "sm" } }
},
variants: {
outline: {
field: {
border: "1px solid",
borderColor: "inherit",
bg: "inherit",
_hover: { borderColor: "gray.300" },
_focus: {
borderColor: "blue.500",
boxShadow: "0 0 0 1px var(--chakra-colors-blue-500)"
}
}
},
filled: {
field: {
border: "2px solid",
borderColor: "transparent",
bg: "gray.100",
_hover: { bg: "gray.200" },
_focus: {
bg: "white",
borderColor: "blue.500"
}
}
}
},
defaultProps: {
size: "md",
variant: "outline"
}
});Configuration system for multi-part components with anatomical part definitions and coordinated styling.
/**
* Anatomy definition for multi-part components
*/
type Anatomy = { keys: string[] };
/**
* Style object for multiple component parts
*/
type PartsStyleObject<Parts extends Anatomy = Anatomy> = Partial<
Record<Parts["keys"][number], SystemStyleObject>
>;
/**
* Function that returns multi-part styles
*/
type PartsStyleFunction<Parts extends Anatomy = Anatomy> = (
props: StyleFunctionProps
) => PartsStyleObject<Parts>;
/**
* Multi-part style interpolation (object or function)
*/
type PartsStyleInterpolation<Parts extends Anatomy = Anatomy> =
| PartsStyleObject<Parts>
| PartsStyleFunction<Parts>;
/**
* Configuration interface for multi-part components
*/
interface MultiStyleConfig<Parts extends Anatomy = Anatomy> {
parts: Parts["keys"];
baseStyle?: PartsStyleInterpolation<Parts>;
sizes?: { [size: string]: PartsStyleInterpolation<Parts> };
variants?: { [variant: string]: PartsStyleInterpolation<Parts> };
defaultProps?: {
size?: string;
variant?: string;
colorScheme?: string;
};
}
/**
* Creates helpers for defining multi-part component configurations
* @param parts - Array of component part names
* @returns Helper functions for multi-part theming
*/
function createMultiStyleConfigHelpers<Part extends string>(
parts: Part[] | Readonly<Part[]>
): {
definePartsStyle<PartStyles extends PartsStyleInterpolation<{ keys: Part[] }>>(
config: PartStyles
): PartStyles;
defineMultiStyleConfig<
BaseStyle extends PartsStyleInterpolation<{ keys: Part[] }>,
Sizes extends Record<string, PartsStyleInterpolation<{ keys: Part[] }>>,
Variants extends Record<string, PartsStyleInterpolation<{ keys: Part[] }>>
>(config: {
baseStyle?: BaseStyle;
sizes?: Sizes;
variants?: Variants;
defaultProps?: {
size?: keyof Sizes;
variant?: keyof Variants;
colorScheme?: string;
};
}): MultiStyleConfig<{ keys: Part[] }>;
};Usage Examples:
import { createMultiStyleConfigHelpers } from "@chakra-ui/styled-system";
// Modal component anatomy
const modalParts = ["overlay", "dialogContainer", "dialog", "header", "body", "footer"] as const;
const { definePartsStyle, defineMultiStyleConfig } =
createMultiStyleConfigHelpers(modalParts);
// Define multi-part styles
const baseModalStyle = definePartsStyle({
overlay: {
position: "fixed",
inset: 0,
bg: "blackAlpha.600",
zIndex: "overlay"
},
dialogContainer: {
display: "flex",
alignItems: "center",
justifyContent: "center",
position: "fixed",
inset: 0,
zIndex: "modal",
p: 4
},
dialog: {
borderRadius: "lg",
bg: "white",
color: "inherit",
boxShadow: "lg",
width: "100%",
position: "relative",
_dark: {
bg: "gray.700"
}
},
header: {
px: 6,
py: 4,
fontSize: "xl",
fontWeight: "semibold"
},
body: {
px: 6,
py: 2,
flex: 1
},
footer: {
px: 6,
py: 4
}
});
// Size variants for multi-part component
const modalSizes = {
xs: definePartsStyle({
dialog: { maxW: "xs" }
}),
sm: definePartsStyle({
dialog: { maxW: "sm" }
}),
md: definePartsStyle({
dialog: { maxW: "md" }
}),
lg: definePartsStyle({
dialog: { maxW: "lg" }
}),
xl: definePartsStyle({
dialog: { maxW: "xl" }
}),
full: definePartsStyle({
dialog: {
maxW: "100vw",
minH: "100vh",
borderRadius: 0
}
})
};
// Complete multi-part configuration
const Modal = defineMultiStyleConfig({
baseStyle: baseModalStyle,
sizes: modalSizes,
defaultProps: {
size: "md"
}
});
// Card component with dynamic styling
const cardParts = ["container", "header", "body", "footer"] as const;
const cardHelpers = createMultiStyleConfigHelpers(cardParts);
const Card = cardHelpers.defineMultiStyleConfig({
baseStyle: cardHelpers.definePartsStyle(({ colorScheme }) => ({
container: {
borderRadius: "lg",
overflow: "hidden",
boxShadow: "base",
bg: "white",
_dark: { bg: "gray.800" }
},
header: {
borderBottom: "1px solid",
borderColor: "gray.200",
px: 4,
py: 3,
bg: `${colorScheme}.50`,
_dark: {
bg: `${colorScheme}.900`,
borderColor: "gray.600"
}
},
body: {
p: 4
},
footer: {
borderTop: "1px solid",
borderColor: "gray.200",
px: 4,
py: 3,
bg: "gray.50",
_dark: {
bg: "gray.700",
borderColor: "gray.600"
}
}
})),
variants: {
elevated: cardHelpers.definePartsStyle({
container: {
boxShadow: "lg",
border: "1px solid",
borderColor: "gray.200",
_dark: { borderColor: "gray.600" }
}
}),
outline: cardHelpers.definePartsStyle({
container: {
boxShadow: "none",
border: "1px solid",
borderColor: "gray.200",
_dark: { borderColor: "gray.600" }
}
})
},
defaultProps: {
variant: "elevated",
colorScheme: "gray"
}
});Utilities for resolving and applying component style configurations with responsive support.
/**
* Values passed to style configuration resolution
*/
interface StyleConfigValues {
theme: WithCSSVar<Record<string, any>>;
variant?: ResponsiveValue<string>;
size?: ResponsiveValue<string>;
colorScheme?: string;
[key: string]: any;
}
/**
* Resolves component style configuration into final styles
* @param config - Component style configuration
* @returns Function that resolves styles based on props
*/
function resolveStyleConfig(config: StyleConfig): (
props: StyleConfigValues
) => Record<string, any>;Usage Examples:
import { resolveStyleConfig } from "@chakra-ui/styled-system";
// Using the button config from above
const buttonStyleResolver = resolveStyleConfig(Button);
// Resolve styles for specific props
const buttonStyles = buttonStyleResolver({
theme: myTheme,
variant: "solid",
size: "md",
colorScheme: "blue"
});
// Responsive variant and size
const responsiveButtonStyles = buttonStyleResolver({
theme: myTheme,
variant: { base: "outline", md: "solid" },
size: { base: "sm", md: "md", lg: "lg" },
colorScheme: "green"
});
// Custom style resolution function
function createComponentStyles(
config: StyleConfig,
defaultProps: Record<string, any> = {}
) {
const resolver = resolveStyleConfig(config);
return (props: Record<string, any>) => {
const finalProps = { ...defaultProps, ...props };
return resolver(finalProps);
};
}
// Usage in component
function MyButton(props: ButtonProps) {
const styles = buttonStyleResolver({
theme: useTheme(),
...props
});
return <button style={styles} {...props} />;
}Type-safe theming properties for component configuration with theme typing support.
/**
* Theming properties interface for components
*/
interface ThemingProps<ThemeComponent extends string = any> {
/** Component variant */
variant?: ResponsiveValue<
ThemeComponent extends keyof ThemeTypings["components"]
? ThemeTypings["components"][ThemeComponent]["variants"]
: string
>;
/** Component size */
size?: ResponsiveValue<
ThemeComponent extends keyof ThemeTypings["components"]
? ThemeTypings["components"][ThemeComponent]["sizes"]
: string
>;
/** Color scheme for theming */
colorScheme?: ThemeTypings["colorSchemes"];
/** Component orientation */
orientation?: "vertical" | "horizontal";
/** Custom style configuration override */
styleConfig?: Record<string, any>;
}
/**
* Removes theming props from component props object
* @param props - Component props including theming props
* @returns Props object without theming-specific properties
*/
function omitThemingProps<T extends ThemingProps>(
props: T
): Omit<T, "styleConfig" | "size" | "variant" | "colorScheme">;Usage Examples:
import { ThemingProps, omitThemingProps } from "@chakra-ui/styled-system";
// Component with theming props
interface ButtonProps extends ThemingProps<"Button"> {
children: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
}
function Button(props: ButtonProps) {
const { children, ...rest } = props;
// Separate theming props from other props
const themingProps = {
variant: props.variant,
size: props.size,
colorScheme: props.colorScheme
};
// Get props without theming-specific ones
const componentProps = omitThemingProps(rest);
// Resolve styles
const styles = buttonStyleResolver({
theme: useTheme(),
...themingProps
});
return (
<button style={styles} {...componentProps}>
{children}
</button>
);
}
// Usage with type safety
<Button
variant="solid" // ✓ Valid variant
size="lg" // ✓ Valid size
colorScheme="blue" // ✓ Valid color scheme
onClick={handleClick} // ✓ Regular prop
customProp="value" // ✓ Passes through
/>
// Generic theming component
interface ThemedComponentProps<T extends string> extends ThemingProps<T> {
component: T;
children: React.ReactNode;
[key: string]: any;
}
function ThemedComponent<T extends string>({
component,
children,
...props
}: ThemedComponentProps<T>) {
const themingProps = {
variant: props.variant,
size: props.size,
colorScheme: props.colorScheme
};
const otherProps = omitThemingProps(props);
// Get component config from theme
const config = useTheme().components[component];
const styles = resolveStyleConfig(config)(themingProps);
return <div style={styles} {...otherProps}>{children}</div>;
}Import Examples:
// Import all component theming utilities
import {
defineStyle,
defineStyleConfig,
createMultiStyleConfigHelpers,
resolveStyleConfig,
ThemingProps,
omitThemingProps
} from "@chakra-ui/styled-system";
// Import specific modules
import { defineStyleConfig } from "@chakra-ui/styled-system/define-styles";
import { ThemingProps } from "@chakra-ui/styled-system/theming-props";
// Import types
import type {
StyleConfig,
MultiStyleConfig,
SystemStyleFunction,
StyleFunctionProps,
PartsStyleObject,
PartsStyleFunction
} from "@chakra-ui/styled-system";