Skip to content

Commit 170a731

Browse files
committed
Refactor status indicator
1 parent e289578 commit 170a731

File tree

4 files changed

+120
-55
lines changed

4 files changed

+120
-55
lines changed
Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,55 @@
11
import type { Meta, StoryObj } from "@storybook/react";
2-
import { StatusIndicator } from "./StatusIndicator";
2+
import { StatusIndicator, StatusIndicatorDot } from "./StatusIndicator";
33

44
const meta: Meta<typeof StatusIndicator> = {
55
title: "components/StatusIndicator",
66
component: StatusIndicator,
7-
args: {},
7+
args: {
8+
children: (
9+
<>
10+
<StatusIndicatorDot />
11+
Status
12+
</>
13+
),
14+
},
815
};
916

1017
export default meta;
1118
type Story = StoryObj<typeof StatusIndicator>;
1219

1320
export const Success: Story = {
1421
args: {
15-
color: "success",
16-
},
17-
};
18-
19-
export const SuccessOutline: Story = {
20-
args: {
21-
color: "success",
22-
variant: "outlined",
22+
variant: "success",
2323
},
2424
};
2525

26-
export const Warning: Story = {
27-
args: {
28-
color: "warning",
29-
},
30-
};
31-
32-
export const WarningOutline: Story = {
26+
export const Failed: Story = {
3327
args: {
34-
color: "warning",
35-
variant: "outlined",
28+
variant: "failed",
3629
},
3730
};
3831

39-
export const Danger: Story = {
32+
export const Stopped: Story = {
4033
args: {
41-
color: "danger",
34+
variant: "stopped",
4235
},
4336
};
4437

45-
export const DangerOutline: Story = {
38+
export const Warning: Story = {
4639
args: {
47-
color: "danger",
48-
variant: "outlined",
40+
variant: "warning",
4941
},
5042
};
5143

52-
export const Inactive: Story = {
44+
export const Starting: Story = {
5345
args: {
54-
color: "inactive",
46+
variant: "starting",
5547
},
5648
};
5749

58-
export const InactiveOutline: Story = {
50+
export const Small: Story = {
5951
args: {
60-
color: "inactive",
61-
variant: "outlined",
52+
variant: "success",
53+
size: "sm",
6254
},
6355
};
Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,84 @@
1-
import { useTheme } from "@emotion/react";
2-
import type { FC } from "react";
3-
import type { ThemeRole } from "theme/roles";
1+
import { cva, type VariantProps } from "class-variance-authority";
2+
import { createContext, useContext, type FC } from "react";
3+
import { cn } from "utils/cn";
44

5-
interface StatusIndicatorProps {
6-
color: ThemeRole;
7-
variant?: "solid" | "outlined";
8-
}
5+
const statusIndicatorVariants = cva(
6+
"font-medium inline-flex items-center gap-2",
7+
{
8+
variants: {
9+
variant: {
10+
success: "text-content-success",
11+
failed: "text-content-destructive",
12+
stopped: "text-highlight-grey",
13+
warning: "text-content-warning",
14+
starting: "text-highlight-sky",
15+
},
16+
size: {
17+
sm: "text-xs",
18+
md: "text-sm",
19+
},
20+
},
21+
defaultVariants: {
22+
variant: "success",
23+
size: "md",
24+
},
25+
},
26+
);
27+
28+
type StatusIndicatorContextValue = VariantProps<typeof statusIndicatorVariants>;
29+
30+
const StatusIndicatorContext = createContext<StatusIndicatorContextValue>({});
31+
32+
export interface StatusIndicatorProps
33+
extends React.HTMLAttributes<HTMLDivElement>,
34+
StatusIndicatorContextValue {}
935

1036
export const StatusIndicator: FC<StatusIndicatorProps> = ({
11-
color,
12-
variant = "solid",
37+
size,
38+
variant,
39+
className,
40+
...props
41+
}) => {
42+
return (
43+
<StatusIndicatorContext.Provider value={{ size, variant }}>
44+
<div
45+
className={cn(statusIndicatorVariants({ variant, size }), className)}
46+
{...props}
47+
/>
48+
</StatusIndicatorContext.Provider>
49+
);
50+
};
51+
52+
const dotVariants = cva("rounded-full inline-block border-4 border-solid", {
53+
variants: {
54+
variant: {
55+
success: "bg-content-success border-surface-green",
56+
failed: "bg-content-destructive border-surface-destructive",
57+
stopped: "bg-highlight-grey border-surface-grey",
58+
warning: "bg-content-warning border-surface-orange",
59+
starting: "bg-highlight-sky border-surface-sky",
60+
},
61+
size: {
62+
sm: "size-3 border-4",
63+
md: "size-4 border-4",
64+
},
65+
},
66+
defaultVariants: {
67+
variant: "success",
68+
size: "md",
69+
},
70+
});
71+
72+
export interface StatusIndicatorDotProps
73+
extends React.HTMLAttributes<HTMLDivElement> {}
74+
75+
export const StatusIndicatorDot: FC<StatusIndicatorDotProps> = ({
76+
className,
77+
...props
1378
}) => {
14-
const theme = useTheme();
79+
const { size, variant } = useContext(StatusIndicatorContext);
1580

1681
return (
17-
<div
18-
css={[
19-
{
20-
height: 8,
21-
width: 8,
22-
borderRadius: 4,
23-
},
24-
variant === "solid" && {
25-
backgroundColor: theme.roles[color].fill.solid,
26-
},
27-
variant === "outlined" && {
28-
border: `1px solid ${theme.roles[color].outline}`,
29-
},
30-
]}
31-
/>
82+
<div className={cn(dotVariants({ variant, size }), className)} {...props} />
3283
);
3384
};

site/src/index.css

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,27 @@
1717
--content-success: 142 72% 29%;
1818
--content-danger: 0 84% 60%;
1919
--content-warning: 27 96% 61%;
20+
--content-destructive: 0 84% 60%;
2021
--surface-primary: 0 0% 98%;
2122
--surface-secondary: 240 5% 96%;
2223
--surface-tertiary: 240 6% 90%;
2324
--surface-quaternary: 240 5% 84%;
2425
--surface-invert-primary: 240 4% 16%;
2526
--surface-invert-secondary: 240 5% 26%;
2627
--surface-destructive: 0 93% 94%;
28+
--surface-green: 141 79% 85%;
29+
--surface-grey: 240 5% 96%;
30+
--surface-orange: 34 100% 92%;
31+
--surface-sky: 201 94% 86%;
2732
--border-default: 240 6% 90%;
2833
--border-success: 142 76% 36%;
2934
--border-destructive: 0 84% 60%;
3035
--overlay-default: 240 5% 84% / 80%;
3136
--radius: 0.5rem;
3237
--highlight-purple: 262 83% 58%;
3338
--highlight-green: 143 64% 24%;
39+
--highlight-grey: 240 5% 65%;
40+
--highlight-sky: 201 90% 27%;
3441
--border: 240 5.9% 90%;
3542
--input: 240 5.9% 90%;
3643
--ring: 240 10% 3.9%;
@@ -46,20 +53,27 @@
4653
--content-disabled: 240 5% 26%;
4754
--content-success: 142 76% 36%;
4855
--content-danger: 0 91% 71%;
49-
--content-warning: 27 96% 61%;
56+
--content-warning: 31 97% 72%;
57+
--content-destructive: 0 91% 71%;
5058
--surface-primary: 240 10% 4%;
5159
--surface-secondary: 240 6% 10%;
5260
--surface-tertiary: 240 4% 16%;
5361
--surface-quaternary: 240 5% 26%;
5462
--surface-invert-primary: 240 6% 90%;
5563
--surface-invert-secondary: 240 5% 65%;
5664
--surface-destructive: 0 75% 15%;
65+
--surface-green: 145 80% 10%;
66+
--surface-grey: 240 6% 10%;
67+
--surface-orange: 13 81% 15%;
68+
--surface-sky: 204 80% 16%;
5769
--border-default: 240 4% 16%;
5870
--border-success: 142 76% 36%;
5971
--border-destructive: 0 91% 71%;
6072
--overlay-default: 240 10% 4% / 80%;
6173
--highlight-purple: 252 95% 85%;
6274
--highlight-green: 141 79% 85%;
75+
--highlight-grey: 240 4% 46%;
76+
--highlight-sky: 198 93% 60%;
6377
--border: 240 3.7% 15.9%;
6478
--input: 240 3.7% 15.9%;
6579
--ring: 240 4.9% 83.9%;

site/tailwind.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ module.exports = {
3333
success: "hsl(var(--content-success))",
3434
danger: "hsl(var(--content-danger))",
3535
link: "hsl(var(--content-link))",
36+
destructive: "hsl(var(--content-destructive))",
37+
warning: "hsl(var(--content-warning))",
3638
},
3739
surface: {
3840
primary: "hsl(var(--surface-primary))",
@@ -44,6 +46,10 @@ module.exports = {
4446
secondary: "hsl(var(--surface-invert-secondary))",
4547
},
4648
destructive: "hsl(var(--surface-destructive))",
49+
green: "hsl(var(--surface-green))",
50+
grey: "hsl(var(--surface-grey))",
51+
orange: "hsl(var(--surface-orange))",
52+
sky: "hsl(var(--surface-sky))",
4753
},
4854
border: {
4955
DEFAULT: "hsl(var(--border-default))",
@@ -55,6 +61,8 @@ module.exports = {
5561
highlight: {
5662
purple: "hsl(var(--highlight-purple))",
5763
green: "hsl(var(--highlight-green))",
64+
grey: "hsl(var(--highlight-grey))",
65+
sky: "hsl(var(--highlight-sky))",
5866
},
5967
},
6068
keyframes: {

0 commit comments

Comments
 (0)