Advanced functionality for handling collections of related styles with automatic class name generation, type preservation, and support for functional styles.
Processes multiple style sets into a single object with CSS class names.
/**
* Merges style sets into processed style set with class names
* @param styleSets - One or more style set objects
* @returns Processed style set with class names for each area
*/
function mergeStyleSets<TStyleSet>(
...styleSets: Array<IStyleSet | Missing>
): IProcessedStyleSet<TStyleSet>;
function mergeStyleSets<TStyleSet1, TStyleSet2>(
styleSet1: TStyleSet1 | Missing,
styleSet2: TStyleSet2 | Missing
): IProcessedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2>>;
function mergeStyleSets<TStyleSet1, TStyleSet2, TStyleSet3>(
styleSet1: TStyleSet1 | Missing,
styleSet2: TStyleSet2 | Missing,
styleSet3: TStyleSet3 | Missing
): IProcessedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2> & ObjectOnly<TStyleSet3>>;
function mergeStyleSets<TStyleSet1, TStyleSet2, TStyleSet3, TStyleSet4>(
styleSet1: TStyleSet1 | Missing,
styleSet2: TStyleSet2 | Missing,
styleSet3: TStyleSet3 | Missing,
styleSet4: TStyleSet4 | Missing
): IProcessedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2> & ObjectOnly<TStyleSet3> & ObjectOnly<TStyleSet4>>;
// Shadow DOM overloads
function mergeStyleSets<TStyleSet>(
shadowConfig: ShadowConfig,
...styleSets: Array<IStyleSet | Missing>
): IProcessedStyleSet<TStyleSet>;Usage Examples:
import { mergeStyleSets } from "@fluentui/merge-styles";
// Basic style set
const classNames = mergeStyleSets({
container: {
padding: "20px",
backgroundColor: "white",
border: "1px solid gray"
},
header: {
fontSize: "24px",
fontWeight: "bold",
marginBottom: "10px"
},
content: {
fontSize: "16px",
lineHeight: "1.5"
}
});
// Usage: classNames.container, classNames.header, classNames.content
// Merging multiple style sets
const baseStyles = {
button: { padding: "8px 16px" },
text: { fontSize: "14px" }
};
const themeStyles = {
button: { backgroundColor: "blue", color: "white" },
text: { color: "black" }
};
const mergedClassNames = mergeStyleSets(baseStyles, themeStyles);
// Shadow DOM usage
import { makeShadowConfig } from "@fluentui/merge-styles";
const shadowConfig = makeShadowConfig("my-component", true);
const shadowClassNames = mergeStyleSets(shadowConfig, {
container: {
backgroundColor: "blue",
padding: "10px"
}
});Style set processing with explicit configuration options.
/**
* Merges style sets with explicit options
* @param styleSets - Array of style sets to merge
* @param options - Configuration options for style processing
* @returns Processed style set with class names
*/
function mergeCssSets<TStyleSet>(
styleSets: [TStyleSet | Missing],
options?: IStyleOptions
): IProcessedStyleSet<ObjectOnly<TStyleSet>>;
function mergeCssSets<TStyleSet1, TStyleSet2>(
styleSets: [TStyleSet1 | Missing, TStyleSet2 | Missing],
options?: IStyleOptions
): IProcessedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2>>;
function mergeCssSets<TStyleSet1, TStyleSet2, TStyleSet3>(
styleSets: [TStyleSet1 | Missing, TStyleSet2 | Missing, TStyleSet3 | Missing],
options?: IStyleOptions
): IProcessedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2> & ObjectOnly<TStyleSet3>>;
function mergeCssSets<TStyleSet1, TStyleSet2, TStyleSet3, TStyleSet4>(
styleSets: [TStyleSet1 | Missing, TStyleSet2 | Missing, TStyleSet3 | Missing, TStyleSet4 | Missing],
options?: IStyleOptions
): IProcessedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2> & ObjectOnly<TStyleSet3> & ObjectOnly<TStyleSet4>>;Combines style sets without CSS class generation for intermediate processing.
/**
* Combines style sets without registering CSS classes
* @param styleSets - One or more style sets to concatenate
* @returns Concatenated style set with combined styles
*/
function concatStyleSets<TStyleSet>(
...styleSets: Array<TStyleSet | Missing>
): IConcatenatedStyleSet<ObjectOnly<TStyleSet>>;
function concatStyleSets<TStyleSet1, TStyleSet2>(
styleSet1: TStyleSet1 | Missing,
styleSet2: TStyleSet2 | Missing
): IConcatenatedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2>>;
function concatStyleSets<TStyleSet1, TStyleSet2, TStyleSet3>(
styleSet1: TStyleSet1 | Missing,
styleSet2: TStyleSet2 | Missing,
styleSet3: TStyleSet3 | Missing
): IConcatenatedStyleSet<ObjectOnly<TStyleSet1> & ObjectOnly<TStyleSet2> & ObjectOnly<TStyleSet3>>;
// Shadow DOM overloads
function concatStyleSets<TStyleSet>(
shadowConfig: ShadowConfig,
...styleSets: Array<TStyleSet | Missing>
): IConcatenatedStyleSet<ObjectOnly<TStyleSet>>;Processes functional style sets that accept props for dynamic styling.
/**
* Concatenates style sets resolving functional sets with props
* @param styleProps - Props to pass to functional style sets
* @param allStyles - Style sets which can be functions or objects
* @returns Deep partial style set with resolved styles
*/
function concatStyleSetsWithProps<TStyleProps, TStyleSet extends IStyleSetBase>(
styleProps: TStyleProps,
...allStyles: (IStyleFunctionOrObject<TStyleProps, TStyleSet> | undefined)[]
): DeepPartial<TStyleSet>;Usage Examples:
import { concatStyleSetsWithProps } from "@fluentui/merge-styles";
interface ButtonProps {
variant: "primary" | "secondary";
size: "small" | "large";
disabled?: boolean;
}
const buttonStyles = (props: ButtonProps) => ({
root: {
padding: props.size === "small" ? "4px 8px" : "8px 16px",
backgroundColor: props.variant === "primary" ? "blue" : "gray",
opacity: props.disabled ? 0.5 : 1,
":hover": props.disabled ? {} : {
backgroundColor: props.variant === "primary" ? "darkblue" : "darkgray"
}
}
});
const staticStyles = {
root: {
border: "none",
borderRadius: "4px",
cursor: "pointer"
}
};
// Resolve functional styles with props
const resolvedStyles = concatStyleSetsWithProps(
{ variant: "primary", size: "large", disabled: false },
buttonStyles,
staticStyles
);interface IStyleSetBase {
[key: string]: any;
subComponentStyles?: any;
}
interface IStyleSet<TStyleSet extends IStyleSetBase = { [key: string]: any }> {
[P in keyof Omit<TStyleSet, 'subComponentStyles'>]: IStyle;
} & {
subComponentStyles?: {
[P in keyof TStyleSet['subComponentStyles']]: IStyleFunctionOrObject<any, any>;
};
}
interface IConcatenatedStyleSet<TStyleSet extends IStyleSetBase> {
[P in keyof Omit<TStyleSet, 'subComponentStyles'>]: IStyle;
} & {
subComponentStyles?: {
[P in keyof TStyleSet['subComponentStyles']]: IStyleFunction<any, any>;
};
}
interface IProcessedStyleSet<TStyleSet extends IStyleSetBase> {
[P in keyof Omit<TStyleSet, 'subComponentStyles'>]: string;
} & {
subComponentStyles: {
[P in keyof TStyleSet['subComponentStyles']]: Function;
};
}
type IStyleFunction<TStylesProps, TStyleSet extends IStyleSetBase> =
(props: TStylesProps) => DeepPartial<TStyleSet>;
type IStyleFunctionOrObject<TStylesProps, TStyleSet extends IStyleSetBase> =
IStyleFunction<TStylesProps, TStyleSet> | DeepPartial<TStyleSet>;
type ObjectOnly<TArg> = TArg extends {} ? TArg : {};Style sets support nested sub-component styles for complex component hierarchies:
interface ComponentStyleSet {
root: IStyle;
header: IStyle;
content: IStyle;
subComponentStyles?: {
button: IStyleFunctionOrObject<ButtonProps, ButtonStyleSet>;
icon: IStyleFunctionOrObject<IconProps, IconStyleSet>;
};
}
const componentStyles: ComponentStyleSet = {
root: { display: "flex", flexDirection: "column" },
header: { padding: "10px", backgroundColor: "lightgray" },
content: { flex: 1, padding: "20px" },
subComponentStyles: {
button: (props: ButtonProps) => ({
root: {
backgroundColor: props.primary ? "blue" : "gray"
}
}),
icon: {
root: { fontSize: "16px", color: "currentColor" }
}
}
};
const processedStyles = mergeStyleSets(componentStyles);
// processedStyles.subComponentStyles.button is now a function
// processedStyles.subComponentStyles.icon is now a function