You are looking at the documentation of the work in progress Hope UI 1.0, examples and information may be broken or outdated.

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({
// ...baseStyle
variants: {
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({
// ...baseStyle
variants: {
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 variants
compoundVariants: [
{
variants: {
variant: "solid",
colorScheme: "primary",
},
style: {
// style when both `variant="solid"` and `colorScheme="primary"` props are passed
},
},
],
});
jsx
const useButtonStyles = createStyles({
// ...baseStyle and variants
compoundVariants: [
{
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 compoundVariants
defaultVariants: {
variant: "solid",
colorScheme: "primary",
size: "md",
},
});
jsx
const useButtonStyles = createStyles({
// ...baseStyle, variants and compoundVariants
defaultVariants: {
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;
}
true/false variants become a prop with 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>;
}
Previous
The sx prop