diff --git a/web/src/components/ui/charts/BusterChartLegend/LegendItem.tsx b/web/src/components/ui/charts/BusterChartLegend/LegendItem.tsx index 639aebd95..9c6b5c89f 100644 --- a/web/src/components/ui/charts/BusterChartLegend/LegendItem.tsx +++ b/web/src/components/ui/charts/BusterChartLegend/LegendItem.tsx @@ -1,10 +1,10 @@ -import React, { useMemo, useEffect, useLayoutEffect } from 'react'; -import { BusterChartLegendItem, BusterChartLegendProps } from './interfaces'; -import { Text, Title } from '@/components/ui'; +import React, { useMemo } from 'react'; +import { type BusterChartLegendItem, type BusterChartLegendProps } from './interfaces'; import { createStyles } from 'antd-style'; import { useMemoizedFn } from 'ahooks'; import { LegendItemDot } from './LegendDot'; import { AnimatePresence, motion } from 'framer-motion'; +import { cn } from '@/lib/utils'; export const LegendItem: React.FC<{ item: BusterChartLegendItem; @@ -112,12 +112,13 @@ const LegendItemStandard = React.memo( {hasHeadline && ( - + <span + className={cn( + 'text-md leading-none font-semibold!', + !inactive ? 'text-foreground' : 'text-text-secondary' + )}> {headline?.titleAmount} - + )} @@ -134,10 +135,11 @@ const LegendItemStandard = React.memo( inactive={item.inactive} /> - + {headlinePreText && ( {formattedName} - + ); diff --git a/web/src/components/ui/charts/BusterChartLegend/stories/LegendItem.stories.tsx b/web/src/components/ui/charts/BusterChartLegend/stories/LegendItem.stories.tsx new file mode 100644 index 000000000..1e9568722 --- /dev/null +++ b/web/src/components/ui/charts/BusterChartLegend/stories/LegendItem.stories.tsx @@ -0,0 +1,152 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { LegendItem } from '../LegendItem'; +import { ChartType } from '../../interfaces'; + +const meta = { + title: 'Base/Charts/LegendItem', + component: LegendItem, + parameters: { + layout: 'centered' + }, + tags: ['autodocs'], + args: { + item: { + color: '#1677ff', + inactive: false, + type: ChartType.Line, + formattedName: 'Sample Legend', + id: '1', + serieName: 'series1' + } + }, + argTypes: { + item: { + control: 'object', + description: 'The legend item configuration' + }, + onClickItem: { + action: 'clicked', + description: 'Function called when the legend item is clicked' + }, + onFocusItem: { + action: 'focused', + description: 'Function called when the legend item is focused' + }, + onHoverItem: { + action: 'hovered', + description: 'Function called when the legend item is hovered' + } + } +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// Basic legend item +export const Basic: Story = { + args: { + item: { + color: '#1677ff', + inactive: false, + type: ChartType.Line, + formattedName: 'Basic Legend', + id: '1', + serieName: 'series1' + } + } +}; + +// Inactive legend item +export const Inactive: Story = { + args: { + item: { + color: '#1677ff', + inactive: true, + type: ChartType.Line, + formattedName: 'Inactive Legend', + id: '2', + serieName: 'series2' + } + } +}; + +// Bar type legend item +export const BarType: Story = { + args: { + item: { + color: '#52c41a', + inactive: false, + type: ChartType.Bar, + formattedName: 'Bar Legend', + id: '3', + serieName: 'series3' + } + } +}; + +// Scatter type legend item +export const ScatterType: Story = { + args: { + item: { + color: '#722ed1', + inactive: false, + type: ChartType.Scatter, + formattedName: 'Scatter Legend', + id: '4', + serieName: 'series4' + } + } +}; + +// With headline +export const WithHeadline: Story = { + args: { + item: { + color: '#f5222d', + inactive: false, + type: ChartType.Line, + formattedName: 'Revenue', + id: '5', + serieName: 'series5', + headline: { + type: 'current', + titleAmount: '$50,000' + } + } + } +}; + +// With average headline +export const WithAverageHeadline: Story = { + args: { + item: { + color: '#fa8c16', + inactive: false, + type: ChartType.Line, + formattedName: 'Monthly Sales', + id: '6', + serieName: 'series6', + headline: { + type: 'average', + titleAmount: '$25,000' + } + } + } +}; + +// Interactive example with all handlers +export const WithFocusEvent: Story = { + args: { + item: { + color: '#eb2f96', + inactive: false, + type: ChartType.Line, + formattedName: 'Interactive Legend', + id: '7', + serieName: 'series7' + }, + onClickItem: (item) => alert(`Clicked: ${item.formattedName}`), + onFocusItem: (item) => alert(`Focused: ${item.formattedName}`) + // onHoverItem: (item, isHover) => alert(`Hover: ${item.formattedName} ${isHover}`) + } +}; diff --git a/web/src/styles/tailwind.css b/web/src/styles/tailwind.css index 2d47852e6..86a71d837 100644 --- a/web/src/styles/tailwind.css +++ b/web/src/styles/tailwind.css @@ -91,6 +91,12 @@ --color-ring: var(--color-item-hover); --color-popover: var(--color-background); --color-popover-foreground: var(--color-foreground); + + /* text color */ + --color-text-default: var(--color-foreground); + --color-text-disabled: var(--color-gray-light); + --color-text-secondary: var(--color-gray-dark); + --color-text-tertiary: var(--color-gray-light); } @import './tailwindAnimations.css';