Back to Chakra Ui

Styling External Libraries

apps/www/content/guides/styling-external-libraries.mdx

0.3.0-beta4.7 KB
Original Source

In this guide, we'll learn how to style external libraries using Chakra UI's styling system.

With the rise of headless component libraries like Ark UI, Radix UI, etc. it's common to want to use them while styling with Chakra UI.

Let's assume we want to style the Carousel component from Ark UI (an headless component library).

Install Ark UI

Start by installing the React version of Ark UI:

bash
npm install @ark-ui/react

Understand the Component Anatomy

Ark UI breaks each headless component into smaller, functional parts. For example, some parts of a (carousel)[https://ark-ui.com/docs/components/carousel#anatomy] would be:

  • Root: The root component of the carousel
  • Item: The item component of the carousel
  • PrevTrigger: The previous trigger component of the carousel
  • NextTrigger: The next trigger component of the carousel

Each part is flexible and can be styled independently. Once you know what each one does, it becomes easier to add custom styles to the parts.

tsx
import { Carousel } from "@ark-ui/react/carousel"

const images = Array.from(
  { length: 5 },
  (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`,
)

export const Demo = () => {
  return (
    <Carousel.Root defaultPage={0} slideCount={images.length}>
      <Carousel.Control>
        <Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
        <Carousel.NextTrigger>Next</Carousel.NextTrigger>
      </Carousel.Control>
      <Carousel.IndicatorGroup>
        {images.map((_, index) => (
          <Carousel.Indicator key={index} index={index} />
        ))}
      </Carousel.IndicatorGroup>
      <Carousel.ItemGroup>
        {images.map((image, index) => (
          <Carousel.Item key={index} index={index}>
            
          </Carousel.Item>
        ))}
      </Carousel.ItemGroup>
    </Carousel.Root>
  )
}

Styling the primitives

One way you can easily style headless primitives is to wrap within the chakra factory.

With the factory, you can apply a style object or recipe to the component.

tsx
import { Carousel as ArkCarousel } from "@ark-ui/react/carousel"
import { chakra } from "@chakra-ui/react"

const CarouselRoot = chakra(ArkCarousel.Root, {
  base: {
    display: "flex",
    flexDirection: "column",
    alignItems: "center",
  },

  variants: {},
})

const CarouselItem = chakra(ArkCarousel.Item, {
  base: {
    width: "100%",
    height: "100%",
  },
})

const CarouselIndicatorGroup = chakra(ArkCarousel.IndicatorGroup, {
  base: {
    display: "flex",
    gap: 2,
  },
})

const CarouselIndicator = chakra(ArkCarousel.Indicator, {
  base: {
    borderRadius: "full",
    bg: "bg.subtle",
    _selected: {
      bg: "teal.solid",
    },
  },
  variants: {
    size: {
      sm: {
        width: 3,
        height: 3,
      },
      md: {
        width: 4,
        height: 4,
      },
    },
  },
})

const CarouselItemGroup = chakra(ArkCarousel.ItemGroup, {
  base: {
    display: "flex",
    gap: 2,
  },
})

export const Carousel = {
  Root: CarouselRoot,
  IndicatorGroup: CarouselIndicatorGroup,
  Indicator: CarouselIndicator,
  ItemGroup: CarouselItemGroup,
  Item: CarouselItem,
  NextTrigger: ArkCarousel.NextTrigger,
  PrevTrigger: ArkCarousel.PrevTrigger,
}

Using the styled components

Now that we have the styled components, we can use them in our app.

For the PrevTrigger and NextTrigger components, we can render them as IconButton components from Chakra UI.

tsx
import { Carousel } from "@/components/ui/carousel"
import { IconButton } from "@chakra-ui/react"
import { LuArrowLeft, LuArrowRight } from "react-icons/lu"

const images = Array.from(
  { length: 5 },
  (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`,
)

export const Demo = () => {
  return (
    <Carousel.Root defaultPage={0} slideCount={images.length}>
      <Carousel.Control>
        <Carousel.PrevTrigger asChild>
          <IconButton>
            <LuArrowLeft />
          </IconButton>
        </Carousel.PrevTrigger>
        <Carousel.NextTrigger asChild>
          <IconButton>
            <LuArrowRight />
          </IconButton>
        </Carousel.NextTrigger>
      </Carousel.Control>
      <Carousel.IndicatorGroup>
        {images.map((_, index) => (
          <Carousel.Indicator key={index} index={index} />
        ))}
      </Carousel.IndicatorGroup>
      <Carousel.ItemGroup>
        {images.map((image, index) => (
          <Carousel.Item key={index} index={index}>
            
          </Carousel.Item>
        ))}
      </Carousel.ItemGroup>
    </Carousel.Root>
  )
}

And that's it! You've now styled a headless component library using Chakra UI.