Styles
createStyles
Create custom CSS classes with multi-variant style support.
Import
tsx
import { createStyles } from "@hope-ui/core";
tsx
import { 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.
jsx
const 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",},});
jsx
const 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:
jsx
const 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: {},},},});
jsx
const 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.
jsx
const useButtonStyles = createStyles({// ...baseStyle and variantscompoundVariants: [{variants: {variant: "solid",colorScheme: "primary",},style: {// style when both `variant="solid"` and `colorScheme="primary"` props are passed},},],});
jsx
const 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.
jsx
const useButtonStyles = createStyles({// ...baseStyle, variants and compoundVariantsdefaultVariants: {variant: "solid",colorScheme: "primary",size: "md",},});
jsx
const 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.
tsx
const useButtonStyles = createStyles({// ...baseStyle, variants, compoundVariants and defaultVariants});type ButtonVariants = HopeVariantProps<typeof useButtonStyles>;
tsx
const useButtonStyles = createStyles({// ...baseStyle, variants, compoundVariants and defaultVariants});type ButtonVariants = HopeVariantProps<typeof useButtonStyles>;
With the example above, the resulting type will look like this:
tsx
interface ButtonVariants {variant?: "solid" | "outlined" | "plain";colorScheme?: "primary" | "danger" | "neutral";size?: "sm" | "md" | "lg";isFullWidth?: boolean;}
tsx
interface 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.
jsx
const useButtonStyles = createStyles(theme => ({baseStyle: {border: `1px solid ${theme.vars.colors.neutral["300"]}`,},// ...variants, compoundVariants and defaultVariants}));
jsx
const 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.
tsx
const 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>;}
tsx
const 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>;}