@soul-refiner/design-system 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/feedback/badge/badge.tsx +94 -0
- package/src/components/feedback/badge/index.ts +2 -0
- package/src/components/feedback/chip/chip.tsx +130 -0
- package/src/components/feedback/chip/index.ts +2 -0
- package/src/components/feedback/index.ts +4 -0
- package/src/components/feedback/progress/index.ts +2 -0
- package/src/components/feedback/progress/progress.tsx +161 -0
package/package.json
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { Close } from 'icons';
|
|
4
|
+
|
|
5
|
+
type BadgeColor = 'blue' | 'red' | 'green' | 'purple' | 'orange';
|
|
6
|
+
|
|
7
|
+
const colorLookup: Record<
|
|
8
|
+
BadgeColor,
|
|
9
|
+
Record<'primary' | 'secondary' | 'bg', string>
|
|
10
|
+
> = {
|
|
11
|
+
blue: {
|
|
12
|
+
primary: 'var(--color-hue-blue-1)',
|
|
13
|
+
secondary: 'var(--color-hue-blue-2)',
|
|
14
|
+
bg: 'var(--color-hue-blue-3)',
|
|
15
|
+
},
|
|
16
|
+
green: {
|
|
17
|
+
primary: 'var(--color-green-3)',
|
|
18
|
+
secondary: 'var(--color-green-8)',
|
|
19
|
+
bg: 'var(--color-green-10)',
|
|
20
|
+
},
|
|
21
|
+
orange: {
|
|
22
|
+
primary: 'var(--color-hue-orange-1)',
|
|
23
|
+
secondary: 'var(--color-hue-orange-2)',
|
|
24
|
+
bg: 'var(--color-hue-orange-3)',
|
|
25
|
+
},
|
|
26
|
+
purple: {
|
|
27
|
+
primary: 'var(--color-hue-purple-1)',
|
|
28
|
+
secondary: 'var(--color-hue-purple-2)',
|
|
29
|
+
bg: 'var(--color-hue-purple-3)',
|
|
30
|
+
},
|
|
31
|
+
red: {
|
|
32
|
+
primary: 'var(--color-red-4)',
|
|
33
|
+
secondary: 'var(--color-red-9)',
|
|
34
|
+
bg: 'var(--color-red-10)',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export interface BadgeProps extends React.PropsWithChildren {
|
|
39
|
+
color: BadgeColor;
|
|
40
|
+
dot?: boolean;
|
|
41
|
+
onDismiss?: () => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const Badge = ({ children, color, dot, onDismiss }: BadgeProps) => {
|
|
45
|
+
const bgColor = colorLookup[color].bg;
|
|
46
|
+
const textColor = colorLookup[color].primary;
|
|
47
|
+
const borderColor = colorLookup[color].secondary;
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Component
|
|
51
|
+
$bgColor={bgColor}
|
|
52
|
+
$borderColor={borderColor}
|
|
53
|
+
$textColor={textColor}
|
|
54
|
+
>
|
|
55
|
+
{dot && <Dot $secondaryColor={textColor} />}
|
|
56
|
+
{children}
|
|
57
|
+
{onDismiss && <Close size={16} />}
|
|
58
|
+
</Component>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const Component = styled.div<{
|
|
63
|
+
$bgColor: string;
|
|
64
|
+
$borderColor: string;
|
|
65
|
+
$textColor: string;
|
|
66
|
+
}>`
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
gap: 8px;
|
|
70
|
+
padding: 1px 7px;
|
|
71
|
+
border-radius: 32px;
|
|
72
|
+
background-color: ${({ $bgColor }) => $bgColor};
|
|
73
|
+
color: ${({ $textColor }) => $textColor};
|
|
74
|
+
border: 1px solid ${({ $borderColor }) => $borderColor};
|
|
75
|
+
font-family: Inter;
|
|
76
|
+
font-size: 12px;
|
|
77
|
+
font-weight: 500;
|
|
78
|
+
line-height: 16px;
|
|
79
|
+
user-select: none;
|
|
80
|
+
|
|
81
|
+
svg {
|
|
82
|
+
fill: currentColor;
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
}
|
|
85
|
+
`;
|
|
86
|
+
|
|
87
|
+
const Dot = styled.div<{
|
|
88
|
+
$secondaryColor: string;
|
|
89
|
+
}>`
|
|
90
|
+
width: 8px;
|
|
91
|
+
height: 8px;
|
|
92
|
+
border-radius: 50%;
|
|
93
|
+
background-color: ${({ $secondaryColor }) => $secondaryColor};
|
|
94
|
+
`;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { Close } from 'icons';
|
|
4
|
+
|
|
5
|
+
type ChipColor =
|
|
6
|
+
| 'grey'
|
|
7
|
+
| 'blue'
|
|
8
|
+
| 'red'
|
|
9
|
+
| 'green'
|
|
10
|
+
| 'turquoise'
|
|
11
|
+
| 'purple'
|
|
12
|
+
| 'yellow'
|
|
13
|
+
| 'orange'
|
|
14
|
+
| 'primary-blue';
|
|
15
|
+
type ChipSize = 'small' | 'large';
|
|
16
|
+
|
|
17
|
+
const colorLookup: Record<
|
|
18
|
+
ChipColor,
|
|
19
|
+
Record<'primary' | 'secondary' | 'text', string>
|
|
20
|
+
> = {
|
|
21
|
+
'primary-blue': {
|
|
22
|
+
primary: 'var(--color-primary-blue-2)',
|
|
23
|
+
secondary: 'var(--color-white)',
|
|
24
|
+
text: 'var(--color-white)',
|
|
25
|
+
},
|
|
26
|
+
blue: {
|
|
27
|
+
primary: 'var(--color-blue-9)',
|
|
28
|
+
secondary: 'var(--color-blue-5)',
|
|
29
|
+
text: 'var(--color-grey-4)',
|
|
30
|
+
},
|
|
31
|
+
green: {
|
|
32
|
+
primary: 'var(--color-green-9)',
|
|
33
|
+
secondary: 'var(--color-green-5)',
|
|
34
|
+
text: 'var(--color-grey-4)',
|
|
35
|
+
},
|
|
36
|
+
grey: {
|
|
37
|
+
primary: 'var(--color-grey-9)',
|
|
38
|
+
secondary: 'var(--color-grey-4)',
|
|
39
|
+
text: 'var(--color-grey-4)',
|
|
40
|
+
},
|
|
41
|
+
orange: {
|
|
42
|
+
primary: 'var(--color-orange-9)',
|
|
43
|
+
secondary: 'var(--color-orange-5)',
|
|
44
|
+
text: 'var(--color-grey-4)',
|
|
45
|
+
},
|
|
46
|
+
purple: {
|
|
47
|
+
primary: 'var(--color-purple-9)',
|
|
48
|
+
secondary: 'var(--color-purple-5)',
|
|
49
|
+
text: 'var(--color-grey-4)',
|
|
50
|
+
},
|
|
51
|
+
red: {
|
|
52
|
+
primary: 'var(--color-red-9)',
|
|
53
|
+
secondary: 'var(--color-red-5)',
|
|
54
|
+
text: 'var(--color-grey-4)',
|
|
55
|
+
},
|
|
56
|
+
turquoise: {
|
|
57
|
+
primary: 'var(--color-turquoise-9)',
|
|
58
|
+
secondary: 'var(--color-turquoise-5)',
|
|
59
|
+
text: 'var(--color-grey-4)',
|
|
60
|
+
},
|
|
61
|
+
yellow: {
|
|
62
|
+
primary: 'var(--color-yellow-9)',
|
|
63
|
+
secondary: 'var(--color-yellow-9)',
|
|
64
|
+
text: 'var(--color-grey-4)',
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export interface ChipProps extends React.PropsWithChildren {
|
|
69
|
+
color: ChipColor;
|
|
70
|
+
dot?: boolean;
|
|
71
|
+
onDismiss?: () => void;
|
|
72
|
+
size: ChipSize;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const Chip = ({ children, color, dot, onDismiss, size }: ChipProps) => {
|
|
76
|
+
const bgColor = colorLookup[color].primary;
|
|
77
|
+
const textColor = colorLookup[color].text;
|
|
78
|
+
const dotColor = colorLookup[color].secondary;
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<Component $bgColor={bgColor} $size={size} $textColor={textColor}>
|
|
82
|
+
{dot && <Dot $secondaryColor={dotColor} />}
|
|
83
|
+
{children}
|
|
84
|
+
{onDismiss && <Close size={16} />}
|
|
85
|
+
</Component>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const Component = styled.div<{
|
|
90
|
+
$bgColor: string;
|
|
91
|
+
$size: ChipSize;
|
|
92
|
+
$textColor: string;
|
|
93
|
+
}>`
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
gap: 8px;
|
|
97
|
+
border-radius: 32px;
|
|
98
|
+
background-color: ${({ $bgColor }) => $bgColor};
|
|
99
|
+
color: ${({ $textColor }) => $textColor};
|
|
100
|
+
font-family: Inter;
|
|
101
|
+
user-select: none;
|
|
102
|
+
|
|
103
|
+
svg {
|
|
104
|
+
fill: currentColor;
|
|
105
|
+
cursor: pointer;
|
|
106
|
+
}
|
|
107
|
+
${({ $size }) =>
|
|
108
|
+
$size === 'small'
|
|
109
|
+
? // small
|
|
110
|
+
`
|
|
111
|
+
padding: 4px 16px;
|
|
112
|
+
font-size: 12px;
|
|
113
|
+
line-height: 16px;
|
|
114
|
+
font-weight: 500;`
|
|
115
|
+
: // large
|
|
116
|
+
`
|
|
117
|
+
padding: 8px 16px;
|
|
118
|
+
font-size: 14px;
|
|
119
|
+
line-height: 20px;
|
|
120
|
+
font-weight: 600;`}
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const Dot = styled.div<{
|
|
124
|
+
$secondaryColor: string;
|
|
125
|
+
}>`
|
|
126
|
+
width: 8px;
|
|
127
|
+
height: 8px;
|
|
128
|
+
border-radius: 50%;
|
|
129
|
+
background-color: ${({ $secondaryColor }) => $secondaryColor};
|
|
130
|
+
`;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
export { Badge } from './badge';
|
|
2
|
+
export type { BadgeProps } from './badge';
|
|
1
3
|
export { Banner } from './banner';
|
|
2
4
|
export type { BannerProps } from './banner';
|
|
3
5
|
export { Loader } from './loader';
|
|
4
6
|
export type { LoaderProps } from './loader';
|
|
5
7
|
export { Notification } from './notification';
|
|
6
8
|
export type { NotificationProps } from './notification';
|
|
9
|
+
export { Progress } from './progress';
|
|
10
|
+
export type { ProgressProps } from './progress';
|
|
7
11
|
export { Toast } from './toast';
|
|
8
12
|
export type { ToastProps } from './toast';
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { colorReference } from 'common';
|
|
4
|
+
import { Box, P } from 'components';
|
|
5
|
+
import { CheckmarkCircle, Checkmarks, Close, MinusCircle, Pause } from 'icons';
|
|
6
|
+
|
|
7
|
+
type ProgressType = 'compact' | 'detailed';
|
|
8
|
+
|
|
9
|
+
export interface ProgressProps {
|
|
10
|
+
hasError?: boolean;
|
|
11
|
+
hasIcon?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* @param progress a percentage until complete
|
|
14
|
+
*/
|
|
15
|
+
progress: number;
|
|
16
|
+
subtitle?: string;
|
|
17
|
+
sx?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
type?: ProgressType;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const Progress = ({
|
|
23
|
+
hasError,
|
|
24
|
+
progress,
|
|
25
|
+
subtitle,
|
|
26
|
+
sx,
|
|
27
|
+
title,
|
|
28
|
+
type,
|
|
29
|
+
}: ProgressProps) => {
|
|
30
|
+
const isComplete = !hasError && progress > 99;
|
|
31
|
+
const isDetailed = type === 'detailed';
|
|
32
|
+
const percent = hasError || isComplete ? 100 : progress;
|
|
33
|
+
const displayPercent = hasError ? '-' : percent + '%';
|
|
34
|
+
|
|
35
|
+
const color = hasError ? 'red-4' : isComplete ? 'green-3' : 'primary-blue-2';
|
|
36
|
+
const gradientColors: Record<'start' | 'end' | 'empty' | 'bg', string> =
|
|
37
|
+
hasError
|
|
38
|
+
? {
|
|
39
|
+
start: 'var(--color-red-6)',
|
|
40
|
+
end: 'var(--color-red-4)',
|
|
41
|
+
empty: 'var(--color-red-8)',
|
|
42
|
+
bg: 'var(--color-red-9)',
|
|
43
|
+
}
|
|
44
|
+
: isComplete
|
|
45
|
+
? {
|
|
46
|
+
start: 'var(--color-green-5)',
|
|
47
|
+
end: 'var(--color-green-3)',
|
|
48
|
+
empty: 'var(--color-green-8)',
|
|
49
|
+
bg: 'var(--color-green-9)',
|
|
50
|
+
}
|
|
51
|
+
: {
|
|
52
|
+
start: '#abcfed',
|
|
53
|
+
end: 'var(--color-primary-blue-2)',
|
|
54
|
+
empty: 'var(--color-primary-blue-3)',
|
|
55
|
+
bg: 'var(--color-primary-blue-4)',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const icon = hasError ? (
|
|
59
|
+
<Close size={24} color={color} />
|
|
60
|
+
) : isComplete ? (
|
|
61
|
+
<Checkmarks size={24} color={color} />
|
|
62
|
+
) : (
|
|
63
|
+
<Pause size={24} color={color} />
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<Box $align="center" $dir="row" $gap={16} sx={sx}>
|
|
68
|
+
{isDetailed && (
|
|
69
|
+
<IconWrapper
|
|
70
|
+
$completedDegree={Math.round(percent * 3.6)}
|
|
71
|
+
$gradientColors={gradientColors}
|
|
72
|
+
>
|
|
73
|
+
<IconInnerWrapper $bg={gradientColors.bg}>{icon}</IconInnerWrapper>
|
|
74
|
+
</IconWrapper>
|
|
75
|
+
)}
|
|
76
|
+
<Box $dir="column" $flex={1} $gap={8}>
|
|
77
|
+
<Box>
|
|
78
|
+
{title && (
|
|
79
|
+
<P $color="grey-2" $fontSize={14} $lineHeight={20}>
|
|
80
|
+
{title}
|
|
81
|
+
</P>
|
|
82
|
+
)}
|
|
83
|
+
{isComplete && (
|
|
84
|
+
<CheckmarkCircle
|
|
85
|
+
color="green-3"
|
|
86
|
+
size={24}
|
|
87
|
+
sx="margin-left: auto;"
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
{hasError && (
|
|
91
|
+
<MinusCircle color="red-4" size={24} sx="margin-left: auto;" />
|
|
92
|
+
)}
|
|
93
|
+
</Box>
|
|
94
|
+
<BarWrapper>
|
|
95
|
+
<Bar $color={colorReference[color]} $percent={percent} />
|
|
96
|
+
</BarWrapper>
|
|
97
|
+
{subtitle && (
|
|
98
|
+
<P $color="grey-4" $fontSize={12} $lineHeight={16}>
|
|
99
|
+
{subtitle}
|
|
100
|
+
</P>
|
|
101
|
+
)}
|
|
102
|
+
</Box>
|
|
103
|
+
{isDetailed && (
|
|
104
|
+
<P $color="grey-4" $textAlign="center" sx="width: 72px;">
|
|
105
|
+
{displayPercent}
|
|
106
|
+
</P>
|
|
107
|
+
)}
|
|
108
|
+
</Box>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const BarWrapper = styled.div`
|
|
113
|
+
position: relative;
|
|
114
|
+
width: 100%;
|
|
115
|
+
height: 12px;
|
|
116
|
+
border-radius: 32px;
|
|
117
|
+
background-color: var(--color-grey-8);
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
const Bar = styled.div<{
|
|
121
|
+
$color: string;
|
|
122
|
+
$percent: number;
|
|
123
|
+
}>`
|
|
124
|
+
width: ${({ $percent }) => $percent}%;
|
|
125
|
+
height: 12px;
|
|
126
|
+
background-color: ${({ $color }) => $color};
|
|
127
|
+
border-radius: 32px;
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
const IconWrapper = styled.div<{
|
|
131
|
+
$completedDegree: number;
|
|
132
|
+
$gradientColors: Record<'start' | 'end' | 'empty' | 'bg', string>;
|
|
133
|
+
}>`
|
|
134
|
+
position: relative;
|
|
135
|
+
display: block;
|
|
136
|
+
width: 45px;
|
|
137
|
+
height: 45px;
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
border-radius: 50%;
|
|
142
|
+
flex-shrink: 0;
|
|
143
|
+
background: conic-gradient(
|
|
144
|
+
${({ $gradientColors }) => $gradientColors.start},
|
|
145
|
+
${({ $gradientColors }) => $gradientColors.end}
|
|
146
|
+
${({ $completedDegree }) => $completedDegree}deg,
|
|
147
|
+
${({ $gradientColors }) => $gradientColors.empty}
|
|
148
|
+
${({ $completedDegree }) => $completedDegree}deg 360deg
|
|
149
|
+
);
|
|
150
|
+
border: 1px solid ${({ $gradientColors }) => $gradientColors.bg};
|
|
151
|
+
`;
|
|
152
|
+
|
|
153
|
+
const IconInnerWrapper = styled.div<{ $bg: string }>`
|
|
154
|
+
display: flex;
|
|
155
|
+
justify-content: center;
|
|
156
|
+
align-items: center;
|
|
157
|
+
height: 39px;
|
|
158
|
+
width: 39px;
|
|
159
|
+
border-radius: 50%;
|
|
160
|
+
background-color: ${({ $bg }) => $bg};
|
|
161
|
+
`;
|