Styles
createStyles
Create custom CSS classes with multi-variant style support.
Import
tsximport { createStyles } from "@hope-ui/core";
tsximport { createStyles } from "@hope-ui/core";
Usage
You can create custom CSS classes to use in your components with the createStyles function. This uses an API inspired by Vanilla Extract Recipes.
Base style
Let's say you want to create a custom Button component. First, define the base style of the component which will always be applied.
You can use theme tokens, shorthand properties, and responsive syntax to define this style.
jsxconst useButtonStyles = createStyles({baseStyle: {appearance: "none",position: "relative",display: "inline-flex",justifyContent: "center",alignItems: "center",border: "1px solid transparent",borderRadius: "md",fontFamily: "inherit",fontSize: "100%",fontWeight: "medium",lineHeight: "none",},});
jsxconst useButtonStyles = createStyles({baseStyle: {appearance: "none",position: "relative",display: "inline-flex",justifyContent: "center",alignItems: "center",border: "1px solid transparent",borderRadius: "md",fontFamily: "inherit",fontSize: "100%",fontWeight: "medium",lineHeight: "none",},});
Variants
createStyles don't use prop interpolation to define conditional style. Instead, it uses the concept of Variants, popularized by Stitches.
Under the hood, Hope UI will convert all variants to component props and apply the related style when the props are passed.
To define variants, use the variants keyword:
jsxconst useButtonStyles = createStyles({// ...baseStylevariants: {variant: {solid: {// style when the `variant="solid"` prop is passed},outlined: {},plain: {},},colorScheme: {primary: {// style when the `colorScheme="primary"` prop is passed},danger: {},neutral: {},},size: {sm: {// style when the `size="sm"` prop is passed},md: {},lg: {},},isFullWidth: {true: {// style when the `isFullWidth={true}` prop is passed},false: {},},},});
jsxconst useButtonStyles = createStyles({// ...baseStylevariants: {variant: {solid: {// style when the `variant="solid"` prop is passed},outlined: {},plain: {},},colorScheme: {primary: {// style when the `colorScheme="primary"` prop is passed},danger: {},neutral: {},},size: {sm: {// style when the `size="sm"` prop is passed},md: {},lg: {},},isFullWidth: {true: {// style when the `isFullWidth={true}` prop is passed},false: {},},},});
If you don't have the style for a variant, you still need to define it with an empty object as value (like above) to make it available in the corresponding prop.
Compound variants
In the case of needing to set styles based on a combination of variants, you can use the compoundVariants keyword.
jsxconst useButtonStyles = createStyles({// ...baseStyle and variantscompoundVariants: [{variants: {variant: "solid",colorScheme: "primary",},style: {// style when both `variant="solid"` and `colorScheme="primary"` props are passed},},],});
jsxconst useButtonStyles = createStyles({// ...baseStyle and variantscompoundVariants: [{variants: {variant: "solid",colorScheme: "primary",},style: {// style when both `variant="solid"` and `colorScheme="primary"` props are passed},},],});
Default variants
You can use the defaultVariants keyword to set a variant by default. Think of it as the default component props.
jsxconst useButtonStyles = createStyles({// ...baseStyle, variants and compoundVariantsdefaultVariants: {variant: "solid",colorScheme: "primary",size: "md",},});
jsxconst useButtonStyles = createStyles({// ...baseStyle, variants and compoundVariantsdefaultVariants: {variant: "solid",colorScheme: "primary",size: "md",},});
Creating the variant props type
You can use the HopeVariantProps utility type to extract variants from a createStyles result.
tsxconst useButtonStyles = createStyles({// ...baseStyle, variants, compoundVariants and defaultVariants});type ButtonVariants = HopeVariantProps<typeof useButtonStyles>;
tsxconst useButtonStyles = createStyles({// ...baseStyle, variants, compoundVariants and defaultVariants});type ButtonVariants = HopeVariantProps<typeof useButtonStyles>;
With the example above, the resulting type will look like this:
tsxinterface ButtonVariants {variant?: "solid" | "outlined" | "plain";colorScheme?: "primary" | "danger" | "neutral";size?: "sm" | "md" | "lg";isFullWidth?: boolean;}
tsxinterface ButtonVariants {variant?: "solid" | "outlined" | "plain";colorScheme?: "primary" | "danger" | "neutral";size?: "sm" | "md" | "lg";isFullWidth?: boolean;}
boolean type.Accessing the theme object
createStyles() can accept a function as parameter, which gives you access to the current theme.
jsxconst useButtonStyles = createStyles(theme => ({baseStyle: {border: `1px solid ${theme.vars.colors.neutral["300"]}`,},// ...variants, compoundVariants and defaultVariants}));
jsxconst useButtonStyles = createStyles(theme => ({baseStyle: {border: `1px solid ${theme.vars.colors.neutral["300"]}`,},// ...variants, compoundVariants and defaultVariants}));
Using the styles
The result of createStyles can be consumed in any components descendant of HopeProvider. It takes the variants props as parameters and return an Accessor<string> containing the CSS classes to apply.
tsxconst useButtonStyles = createStyles({// ...baseStyle, variants, compoundVariants and defaultVariants});type ButtonVariants = HopeVariantProps<typeof useButtonStyles>;function Button(props: ParentProps<ButtonVariants>) {// In this example `props` also contains the "variants"const classes = useButtonStyles(props);return <button class={classes()}>{props.children}</button>;}
tsxconst useButtonStyles = createStyles({// ...baseStyle, variants, compoundVariants and defaultVariants});type ButtonVariants = HopeVariantProps<typeof useButtonStyles>;function Button(props: ParentProps<ButtonVariants>) {// In this example `props` also contains the "variants"const classes = useButtonStyles(props);return <button class={classes()}>{props.children}</button>;}