- 手风琴 (Accordion)
- 警告 (Alert)
- 警告对话框 (Alert Dialog)
- 宽高比 (Aspect Ratio)
- 头像 (Avatar)
- 徽章 (Badge)
- 面包屑 (Breadcrumb)
- 按钮 (Button)
- 按钮组 (Button Group)
- 日历 (Calendar)
- 卡片 (Card)
- 轮播图 (Carousel)
- 图表 (Chart)
- 复选框 (Checkbox)
- 折叠面板 (Collapsible)
- 组合框 (Combobox)
- 命令面板 (Command)
- 上下文菜单 (Context Menu)
- 数据表格 (Data Table)
- 日期选择器 (Date Picker)
- 对话框 (Dialog)
- 抽屉 (Drawer)
- 下拉菜单 (Dropdown Menu)
- 空状态 (Empty)
- 字段 (Field)
- 表单 (Form)
- 悬停卡片 (Hover Card)
- 输入框 (Input)
- 输入组 (Input Group)
- 验证码输入 (Input OTP)
- 项 (Item)
- 键盘按键 (Kbd)
- 标签 (Label)
- 菜单栏 (Menubar)
- 原生选择器 (Native Select)
- 导航菜单 (Navigation Menu)
- 数字输入框 (Number Field)
- 分页 (Pagination)
- 引脚输入 (Pin Input)
- 气泡卡片 (Popover)
- 进度条 (Progress)
- 单选框组 (Radio Group)
- 范围日历 (Range Calendar)
- 可调整大小 (Resizable)
- 滚动区域 (Scroll Area)
- 选择器 (Select)
- 分隔线 (Separator)
- 侧边栏抽屉 (Sheet)
- 侧边栏 (Sidebar)
- 骨架屏 (Skeleton)
- 滑块 (Slider)
- 轻量提示 (Sonner)
- 加载动画 (Spinner)
- 步骤条 (Stepper)
- 开关 (Switch)
- 表格 (Table)
- 标签页 (Tabs)
- 标签输入 (Tags Input)
- 文本域 (Textarea)
- 吐司提示 (Toast)
- 切换按钮 (Toggle)
- 切换按钮组 (Toggle Group)
- 工具提示 (Tooltip)
- 排版 (Typography)
柱状图 - 交互式
显示过去 3 个月的访问者总数
隆重推出 图表 (Charts)。这是一套你可以复制粘贴到应用中的图表组件集合。
图表的设计旨在开箱即用,效果出众。它们能与其他组件良好协作,并支持全面自定义以适配你的项目。
组件
我们底层使用了 Unovis。
我们在设计 chart 组件时,充分考虑了组合性。 你可以使用 Unovis 组件构建图表,并仅在需要的地方引入自定义组件(例如 ChartTooltip)。
<script setup lang="ts">
import { VisGroupedBar, VisXYContainer } from '@unovis/vue'
import { ChartContainer, ChartTooltipContent } from '@/components/ui/chart'
</script>
<template>
<ChartContainer :config="chartConfig">
<VisXYContainer :data="data">
<VisGroupedBar :x="(d) => d.month" :y="(d) => d.value" />
<ChartTooltip :template="componentToString(chartConfig, ChartTooltipContent)" />
</VisXYContainer>
</ChartContainer>
</template>我们不对 Unovis 进行封装,这意味着你不会被锁死在特定的抽象层中。当 Unovis 发布新版本时,你可以按照官方的升级路径更新你的图表。
组件完全属于你.
安装
pnpm dlx shadcn-vue@latest add chart
使用方法
<script setup lang="ts">
import type { ChartConfig } from '@/components/ui/chart'
import { VisGroupedBar, VisXYContainer } from '@unovis/vue'
import {
ChartContainer,
ChartCrosshair,
ChartTooltip,
ChartTooltipContent,
componentToString,
} from '@/components/ui/chart'
const chartData = [
{ date: new Date("2024-01-01"), desktop: 186, mobile: 80 },
{ date: new Date("2024-02-01"), desktop: 305, mobile: 200 },
{ date: new Date("2024-03-01"), desktop: 237, mobile: 120 },
];
type Data = (typeof chartData)[number]
const chartConfig = {
desktop: {
label: "Desktop",
color: "var(--chart-1)",
},
mobile: {
label: "Mobile",
color: "var(--chart-2)",
},
} satisfies ChartConfig
</script>
<template>
<ChartContainer :config="chartConfig" class="min-h-[400px] w-full">
<VisXYContainer :data="chartData">
<VisGroupedBar
:x="(d: Data) => d.date"
:y="[(d: Data) => d.desktop, (d: Data) => d.mobile]"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
/>
<ChartTooltip />
<ChartCrosshair
:template="
componentToString(chartConfig, ChartTooltipContent, {
labelFormatter(d) {
return new Date(d).toLocaleDateString('en-US', {
month: 'long',
});
},
})
"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
/>
</VisXYContainer>
</ChartContainer>
</template>创建你的第一个图表
让我们来构建你的第一个图表。我们将构建一个柱状图,并添加网格、坐标轴、提示信息和图例。
首先定义你的数据
以下数据代表了每个月的桌面端和移动端用户数量。
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
]定义你的图表配置
图表配置用于存储图表的配置项。你可以在这里设置人类可读的字符串,例如标签、图标和用于主题化的颜色令牌。
import type { ChartConfig } from '@/components/ui/chart'
const chartConfig = {
desktop: {
label: 'Desktop',
color: 'var(--chart-1)',
},
mobile: {
label: 'Mobile',
color: 'var(--chart-2)',
},
} satisfies ChartConfig构建你的图表
现在,你可以使用 Unovis 组件来构建你的图表了。
<script setup lang="ts">
import type { ChartConfig } from '@/components/ui/chart'
import { VisGroupedBar, VisXYContainer } from '@unovis/vue'
import { ChartContainer } from '@/components/ui/chart'
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
]
type Data = typeof chartData[number]
const chartConfig = {
desktop: {
label: 'Desktop',
color: '#2563eb',
},
mobile: {
label: 'Mobile',
color: '#60a5fa',
},
} satisfies ChartConfig
</script>
<template>
<ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
<VisXYContainer :data="chartData">
<VisGroupedBar
:x="(d: Data) => d.date"
:y="[(d: Data) => d.desktop, (d: Data) => d.mobile]"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
:rounded-corners="4"
bar-padding="0.1"
group-padding="0"
/>
</VisXYContainer>
</ChartContainer>
</template><script setup lang="ts">
import type { ChartConfig } from '@/components/ui/chart'
import { VisGroupedBar, VisXYContainer } from '@unovis/vue'
import { ChartContainer } from '@/components/ui/chart'
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
]
type Data = typeof chartData[number]
const chartConfig = {
desktop: {
label: 'Desktop',
color: '#2563eb',
},
mobile: {
label: 'Mobile',
color: '#60a5fa',
},
} satisfies ChartConfig
</script>
<template>
<ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
<VisXYContainer :data="chartData">
<VisGroupedBar
:x="(d: Data) => d.date"
:y="[(d: Data) => d.desktop, (d: Data) => d.mobile]"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
:rounded-corners="4"
bar-padding="0.1"
group-padding="0"
/>
</VisXYContainer>
</ChartContainer>
</template>添加坐标轴
要向图表添加坐标轴,我们使用 VisAxis 组件。
导入 VisAxis 组件
import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'将 VisAxis 组件添加到你的图表中
<template>
<VisAxis
type="x"
:x="(d: Data) => d.date"
:tick-line="false"
:domain-line="false"
:grid-line="false"
:tick-format="(d: number) => {
const date = new Date(d)
return date.toLocaleDateString('en-US', {
month: 'short',
})
}"
:tick-values="chartData.map(d => d.date)"
/>
<VisAxis
type="y"
:tick-format="(d: number) => ''"
:tick-line="false"
:domain-line="false"
:grid-line="true"
/>
</template><script setup lang="ts">
import type { ChartConfig } from '@/components/ui/chart'
import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'
import { ChartContainer } from '@/components/ui/chart'
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
]
type Data = typeof chartData[number]
const chartConfig = {
desktop: {
label: 'Desktop',
color: '#2563eb',
},
mobile: {
label: 'Mobile',
color: '#60a5fa',
},
} satisfies ChartConfig
</script>
<template>
<ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
<VisXYContainer :data="chartData">
<VisGroupedBar
:x="(d: Data) => d.date"
:y="[(d: Data) => d.desktop, (d: Data) => d.mobile]"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
:rounded-corners="4"
bar-padding="0.1"
group-padding="0"
/>
<VisAxis
type="x"
:x="(d: Data) => d.date"
:tick-line="false"
:domain-line="false"
:grid-line="false"
:tick-format="(d: number) => {
const date = new Date(d)
return date.toLocaleDateString('en-US', {
month: 'short',
})
}"
:tick-values="chartData.map(d => d.date)"
/>
<VisAxis
type="y"
:tick-format="(d: number) => ''"
:tick-line="false"
:domain-line="false"
:grid-line="true"
/>
</VisXYContainer>
</ChartContainer>
</template>添加提示信息 (Tooltip)
要添加提示信息,我们将使用来自 chart 的自定义组件 ChartTooltip 和 ChartTooltipContent。
导入 ChartTooltip 和 ChartTooltipContent 组件
import { ChartTooltip, ChartTooltipContent, componentToString } from '@/components/ui/chart'将这些组件添加到你的图表中
<ChartTooltip />
<ChartCrosshair :template="componentToString(chartConfig, ChartTooltipContent)" /><script setup lang="ts">
import type { ChartConfig } from '@/components/ui/chart'
import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'
import { ChartContainer, ChartCrosshair, ChartTooltip, ChartTooltipContent, componentToString } from '@/components/ui/chart'
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
]
type Data = typeof chartData[number]
const chartConfig = {
desktop: {
label: 'Desktop',
color: '#2563eb',
},
mobile: {
label: 'Mobile',
color: '#60a5fa',
},
} satisfies ChartConfig
</script>
<template>
<ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
<VisXYContainer :data="chartData">
<VisGroupedBar
:x="(d: Data) => d.date"
:y="[(d: Data) => d.desktop, (d: Data) => d.mobile]"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
:rounded-corners="4"
bar-padding="0.1"
group-padding="0"
/>
<VisAxis
type="x"
:x="(d: Data) => d.date"
:tick-line="false"
:domain-line="false"
:grid-line="false"
:tick-format="(d: number) => {
const date = new Date(d)
return date.toLocaleDateString('en-US', {
month: 'short',
})
}"
:tick-values="chartData.map(d => d.date)"
/>
<VisAxis
type="y"
:tick-format="(d: number) => ''"
:tick-line="false"
:domain-line="false"
:grid-line="true"
/>
<ChartTooltip />
<ChartCrosshair
:template="componentToString(chartConfig, ChartTooltipContent, {
labelFormatter(d) {
return new Date(d).toLocaleDateString('en-US', {
month: 'long',
})
},
})"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
/>
</VisXYContainer>
</ChartContainer>
</template>悬停查看提示信息。很简单,对吧?只需两个组件,我们就得到了精美的提示信息。
添加图例
我们对图例进行同样的操作。我们将使用来自 chart 的 ChartLegend 和 ChartLegendContent 组件。
导入 ChartLegendContent 组件。
import { ChartLegendContent } from '@/components/ui/chart'将这些组件添加到你的图表中。
<template>
<ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
<VisXYContainer :data="chartData" />
<ChartLegendContent />
</ChartContainer>
</template><script setup lang="ts">
import type { ChartConfig } from '@/components/ui/chart'
import { VisAxis, VisGroupedBar, VisXYContainer } from '@unovis/vue'
import { ChartContainer, ChartCrosshair, ChartLegendContent, ChartTooltip, ChartTooltipContent, componentToString } from '@/components/ui/chart'
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
]
type Data = typeof chartData[number]
const chartConfig = {
desktop: {
label: 'Desktop',
color: '#2563eb',
},
mobile: {
label: 'Mobile',
color: '#60a5fa',
},
} satisfies ChartConfig
</script>
<template>
<ChartContainer :config="chartConfig" class="min-h-[200px] w-full">
<VisXYContainer :data="chartData">
<VisGroupedBar
:x="(d: Data) => d.date"
:y="[(d: Data) => d.desktop, (d: Data) => d.mobile]"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
:rounded-corners="4"
bar-padding="0.1"
group-padding="0"
/>
<VisAxis
type="x"
:x="(d: Data) => d.date"
:tick-line="false"
:domain-line="false"
:grid-line="false"
:tick-format="(d: number) => {
const date = new Date(d)
return date.toLocaleDateString('en-US', {
month: 'short',
})
}"
:tick-values="chartData.map(d => d.date)"
/>
<VisAxis
type="y"
:tick-format="(d: number) => ''"
:tick-line="false"
:domain-line="false"
:grid-line="true"
/>
<ChartTooltip />
<ChartCrosshair
:template="componentToString(chartConfig, ChartTooltipContent, {
labelFormatter(d) {
return new Date(d).toLocaleDateString('en-US', {
month: 'long',
})
},
})"
:color="[chartConfig.desktop.color, chartConfig.mobile.color]"
/>
</VisXYContainer>
<ChartLegendContent />
</ChartContainer>
</template>完成。你已经构建了第一个图表!接下来做什么?
图表配置
图表配置是定义图表标签、图标和颜色的地方。
它有意与图表数据解耦。
这允许你在不同图表间共享配置和颜色令牌。它也可以独立工作,适用于你的数据或颜色令牌远程存储或采用不同格式的情况。
<script setup lang="ts">
import type { ChartConfig } from '@/components/ui/chart'
import { Monitor } from 'lucide-vue-next'
const chartConfig = {
desktop: {
label: 'Desktop',
icon: Monitor,
// A color like 'hsl(220, 98%, 61%)' or 'var(--color-name)'
color: 'var(--chart-1)',
// OR a theme object with 'light' and 'dark' keys
theme: {
light: 'var(--chart-1)',
dark: 'var(--chart-2)',
},
},
} satisfies ChartConfig
</script>主题化
图表具有内置的主题支持。你可以使用 CSS 变量(推荐)或任何颜色格式的颜色值,如 hex、hsl 或 oklch。
CSS 变量
在你的 CSS 文件中定义颜色
@layer base {
:root {
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
}
.dark {
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
}
}将颜色添加到你的 chartConfig 中
const chartConfig = {
desktop: {
label: 'Desktop',
color: 'var(--chart-1)',
},
mobile: {
label: 'Mobile',
color: 'var(--chart-2)',
},
} satisfies ChartConfighex、hsl 或 oklch
你也可以直接在图表配置中定义颜色。使用你喜欢的颜色格式即可。
const chartConfig = {
desktop: {
label: 'Desktop',
color: '#2563eb',
},
} satisfies ChartConfig使用颜色
要在图表中使用主题颜色,请使用 var(--color-KEY) 格式引用它们。
组件
<VisGroupedBar
:x="(d) => d.month"
:y="(d) => d.desktop"
color="var(--color-desktop)"
/>图表数据
const chartData = [
{ browser: 'chrome', visitors: 275, fill: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, fill: 'var(--color-safari)' },
]提示信息
图表提示信息包含标签、名称、指示器和数值。你可以组合使用它们来自定义你的提示信息。
你可以使用 hideLabel 和 hideIndicator 属性开启/关闭这些功能,并使用 indicator 属性自定义指示器样式。
使用 labelKey 和 nameKey 来为提示信息的标签和名称指定自定义键。
图表库自带 ChartTooltip 和 ChartTooltipContent 组件。你可以使用这两个组件向图表添加自定义提示信息。
import { ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'<template>
<ChartTooltip />
<ChartCrosshair
:template="componentToString(chartConfig, ChartTooltipContent)"
/>
</template>属性 (Props)
使用以下属性来自定义提示信息。
| 属性 | 类型 | 描述 |
|---|---|---|
labelKey | string | 用于标签的配置或数据键。 |
nameKey | string | 用于名称的配置或数据键。 |
indicator | dot(点)、line(线)或 dashed(虚线) | 提示信息的指示器样式。 |
hideLabel | boolean | 是否隐藏标签。 |
hideIndicator | boolean | 是否隐藏指示器。 |
颜色
颜色会自动从图表配置中引用。
自定义
若要为提示信息的标签和名称使用自定义键,请使用 labelKey 和 nameKey 属性。
const chartData = [
{ browser: 'chrome', visitors: 187, fill: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, fill: 'var(--color-safari)' },
]
const chartConfig = {
visitors: {
label: 'Total Visitors',
},
chrome: {
label: 'Chrome',
color: 'var(--chart-1)',
},
safari: {
label: 'Safari',
color: 'var(--chart-2)',
},
} satisfies ChartConfig<template>
<ChartCrosshair
:template="componentToString(chartConfig, ChartTooltipContent, {
labelKey: 'visitors',
nameKey: 'browser',
})"
/>
</template>这将使用 Total Visitors 作为标签,并使用 Chrome 和 Safari 作为提示信息的名称。
图例
你可以使用自定义的 <ChartLegendContent> 组件为图表添加图例。
import { ChartLegendContent } from '@/components/ui/chart'<template>
<ChartLegendContent />
</template>颜色
颜色会自动从图表配置中引用。
自定义
若要为图例名称使用自定义键,请使用 nameKey 属性。
const chartData = [
{ browser: 'chrome', visitors: 187, fill: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, fill: 'var(--color-safari)' },
]
const chartConfig = {
chrome: {
label: 'Chrome',
color: 'hsl(var(--chart-1))',
},
safari: {
label: 'Safari',
color: 'hsl(var(--chart-2))',
},
} satisfies ChartConfig<template>
<ChartLegendContent name-key="browser" />
</template>这将使用 Chrome 和 Safari 作为图例名称。