使用高级 Chakra UI 组件,更快地构建 💎

了解更多

外部库样式

2025年4月1日

在本指南中,我们将学习如何使用 Chakra UI 的样式系统为外部库设置样式。

随着 Ark UI、Radix UI 等无头组件库的兴起,通常会希望在使用它们的同时,也使用 Chakra UI 来设置样式。

假设我们想为 Ark UI(一个无头组件库)的 Carousel 组件设置样式。

安装 Ark UI

首先安装 React 版本的 Ark UI

npm install @ark-ui/react

理解组件解剖

Ark UI 将每个无头组件分解为更小、功能性的部分。例如,轮播组件的一些部分(https://ark-ui.com/react/docs/components/carousel#anatomy将会是

每个部分都非常灵活,可以独立设置样式。一旦您了解了每个部分的作用,就可以更容易地为这些部分添加自定义样式。

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}>
            <img src={image} alt={`Slide ${index}`} />
          </Carousel.Item>
        ))}
      </Carousel.ItemGroup>
    </Carousel.Root>
  )
}

为原始组件设置样式

一种可以轻松为无头原始组件设置样式的方法是将其包裹在 chakra 工厂函数中。

使用工厂函数,您可以将样式对象或样式配方应用于组件。

components/ui/carousel.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,
}

使用样式化组件

现在我们有了样式化组件,可以在应用程序中使用它们。

对于 PrevTriggerNextTrigger 组件,我们可以将它们渲染为 Chakra UI 的 IconButton 组件。

pages/index.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}>
            <img src={image} alt={`Slide ${index}`} />
          </Carousel.Item>
        ))}
      </Carousel.ItemGroup>
    </Carousel.Root>
  )
}

就是这样!您现在已经使用 Chakra UI 为无头组件库设置了样式。