@liner-fe/prism 1.1.19 → 1.1.21
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 +5 -13
- package/index.css +0 -138
- package/src/Configure.mdx +0 -32
- package/src/assets/design-token-cover.png +0 -0
- package/src/components/Button/index.stories.tsx +0 -213
- package/src/components/Button/index.tsx +0 -121
- package/src/components/Button/style.module.scss +0 -170
- package/src/design-token/border-radius/index.mdx +0 -8
- package/src/design-token/border-radius/index.stories.ts +0 -17
- package/src/design-token/border-radius/index.tsx +0 -29
- package/src/design-token/color/index.mdx +0 -38
- package/src/design-token/color/index.stories.ts +0 -28
- package/src/design-token/color/index.tsx +0 -28
- package/src/design-token/opacity/index.mdx +0 -8
- package/src/design-token/opacity/index.stories.ts +0 -17
- package/src/design-token/opacity/index.tsx +0 -1
- package/src/design-token/size/index.mdx +0 -8
- package/src/design-token/size/index.stories.ts +0 -17
- package/src/design-token/size/index.tsx +0 -23
- package/src/design-token/typography/index.mdx +0 -8
- package/src/design-token/typography/index.stories.ts +0 -17
- package/src/design-token/typography/index.tsx +0 -13
- package/src/index.ts +0 -2
- package/src/utils/object.ts +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liner-fe/prism",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.21",
|
|
4
4
|
"packageManager": "yarn@3.6.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "next dev",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"lint": "next lint",
|
|
9
9
|
"storybook": "storybook dev -p 6006",
|
|
10
10
|
"build-storybook": "storybook build",
|
|
11
|
+
"appendCSS": "ts-node './scripts/index.ts'",
|
|
11
12
|
"build": "bundler build --tsconfig ./tsconfig.build.json && tsc --project tsconfig.build.json",
|
|
12
13
|
"build:package": "yarn build",
|
|
13
14
|
"prepack": "yarn build"
|
|
@@ -48,6 +49,7 @@
|
|
|
48
49
|
"sass": "^1.77.6",
|
|
49
50
|
"sass-loader": "^14.2.1",
|
|
50
51
|
"storybook": "^8.1.7",
|
|
52
|
+
"ts-node": "^10.9.2",
|
|
51
53
|
"typescript": "^5.1.6",
|
|
52
54
|
"typescript-plugin-css-modules": "^5.1.0"
|
|
53
55
|
},
|
|
@@ -57,19 +59,9 @@
|
|
|
57
59
|
},
|
|
58
60
|
"main": "./lib/index.cjs",
|
|
59
61
|
"types": "./lib/index.d.ts",
|
|
60
|
-
"
|
|
61
|
-
".": {
|
|
62
|
-
"types": "./lib/index.d.ts",
|
|
63
|
-
"import": "./lib/index.mjs",
|
|
64
|
-
"require": "./lib/index.cjs"
|
|
65
|
-
},
|
|
66
|
-
"./index.css": "./index.css",
|
|
67
|
-
"./package.json": "./package.json"
|
|
68
|
-
},
|
|
62
|
+
"module": "./lib/index.mjs",
|
|
69
63
|
"files": [
|
|
70
|
-
"lib"
|
|
71
|
-
"src",
|
|
72
|
-
"index.css"
|
|
64
|
+
"lib"
|
|
73
65
|
],
|
|
74
66
|
"maintainers": [
|
|
75
67
|
{
|
package/index.css
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/* index.css */
|
|
2
|
-
._button_1jmfl_1 {
|
|
3
|
-
position: relative;
|
|
4
|
-
display: flex;
|
|
5
|
-
align-items: center;
|
|
6
|
-
justify-content: center;
|
|
7
|
-
border: none;
|
|
8
|
-
font-style: normal;
|
|
9
|
-
font-size: var(--lp-pri-font-size-16);
|
|
10
|
-
font-weight: var(--lp-pri-font-weight-700);
|
|
11
|
-
line-height: 130%;
|
|
12
|
-
overflow: hidden;
|
|
13
|
-
cursor: pointer;
|
|
14
|
-
}
|
|
15
|
-
._button_1jmfl_1:disabled {
|
|
16
|
-
background: var(--neutral-container-mid);
|
|
17
|
-
color: var(--neutral-label-tertiary);
|
|
18
|
-
cursor: not-allowed;
|
|
19
|
-
}
|
|
20
|
-
._default_1jmfl_20 {
|
|
21
|
-
color: var(--inverse-label-static-primary);
|
|
22
|
-
background: var(--lp-pri-achromatic-white);
|
|
23
|
-
}
|
|
24
|
-
._text_1jmfl_25 {
|
|
25
|
-
background: none;
|
|
26
|
-
color: var(--inverse-label-static-primary);
|
|
27
|
-
font-size: var(--lp-pri-font-size-13);
|
|
28
|
-
font-weight: var(--lp-pri-font-weight-500);
|
|
29
|
-
}
|
|
30
|
-
._text_1jmfl_25:not(:disabled):hover {
|
|
31
|
-
text-decoration: underline;
|
|
32
|
-
text-underline-offset: 0.2rem;
|
|
33
|
-
}
|
|
34
|
-
._icon_1jmfl_36 {
|
|
35
|
-
background: none;
|
|
36
|
-
}
|
|
37
|
-
._primary_1jmfl_40 {
|
|
38
|
-
background: #4058ff;
|
|
39
|
-
}
|
|
40
|
-
._primary_1jmfl_40:not(:disabled):hover {
|
|
41
|
-
background: #3346cc;
|
|
42
|
-
}
|
|
43
|
-
._secondary_1jmfl_47 {
|
|
44
|
-
background: var(--inverse-container-high);
|
|
45
|
-
}
|
|
46
|
-
._secondary_1jmfl_47:not(:disabled):hover {
|
|
47
|
-
background: #121212;
|
|
48
|
-
}
|
|
49
|
-
._tertiary_1jmfl_54 {
|
|
50
|
-
background: rgba(109, 109, 112, 0.0784313725);
|
|
51
|
-
color: var(--neutral-label-primary);
|
|
52
|
-
}
|
|
53
|
-
._tertiary_1jmfl_54:not(:disabled):hover {
|
|
54
|
-
background: #ebebeb;
|
|
55
|
-
}
|
|
56
|
-
._quaternary_1jmfl_62 {
|
|
57
|
-
color: var(--neutral-label-primary);
|
|
58
|
-
border: 1px solid var(--neutral-border-overlay-normal);
|
|
59
|
-
}
|
|
60
|
-
._quaternary_1jmfl_62:not(:disabled):hover {
|
|
61
|
-
background: #f5f5f5;
|
|
62
|
-
}
|
|
63
|
-
._quaternary_1jmfl_62:disabled {
|
|
64
|
-
background: var(--neutral-container-mid);
|
|
65
|
-
color: var(--neutral-label-tertiary);
|
|
66
|
-
opacity: 0.4;
|
|
67
|
-
}
|
|
68
|
-
._quinary_1jmfl_75 {
|
|
69
|
-
color: rgba(109, 109, 112, 0.8);
|
|
70
|
-
}
|
|
71
|
-
._quinary_1jmfl_75:not(:disabled):hover {
|
|
72
|
-
background: #f5f5f5;
|
|
73
|
-
}
|
|
74
|
-
._quinary_1jmfl_75:disabled {
|
|
75
|
-
background: var(--neutral-container-mid);
|
|
76
|
-
color: var(--neutral-label-tertiary);
|
|
77
|
-
opacity: 0.4;
|
|
78
|
-
}
|
|
79
|
-
._negative_1jmfl_87 {
|
|
80
|
-
background: var(--function-negative);
|
|
81
|
-
}
|
|
82
|
-
._negative_1jmfl_87:not(:disabled):hover {
|
|
83
|
-
background: #af1b1c;
|
|
84
|
-
}
|
|
85
|
-
._inverse_1jmfl_94 {
|
|
86
|
-
color: var(--neutral-label-primary);
|
|
87
|
-
}
|
|
88
|
-
._inverse_1jmfl_94:not(:disabled):hover {
|
|
89
|
-
background: #f5f5f5;
|
|
90
|
-
}
|
|
91
|
-
._cta_1jmfl_101 {
|
|
92
|
-
border-radius: 8px;
|
|
93
|
-
padding: 13.5px 12px;
|
|
94
|
-
font-size: var(--lp-pri-font-size-16);
|
|
95
|
-
min-width: 129px;
|
|
96
|
-
max-height: 48px;
|
|
97
|
-
}
|
|
98
|
-
._l_1jmfl_109 {
|
|
99
|
-
border-radius: 6px;
|
|
100
|
-
padding: 10.5px 8px;
|
|
101
|
-
font-size: var(--lp-pri-font-size-15);
|
|
102
|
-
min-width: 107px;
|
|
103
|
-
max-height: 40px;
|
|
104
|
-
}
|
|
105
|
-
._m_1jmfl_117 {
|
|
106
|
-
border-radius: 6px;
|
|
107
|
-
padding: 7px 6px;
|
|
108
|
-
font-size: var(--lp-pri-font-size-14);
|
|
109
|
-
font-weight: var(--lp-pri-font-weight-500);
|
|
110
|
-
min-width: 91px;
|
|
111
|
-
max-height: 32px;
|
|
112
|
-
}
|
|
113
|
-
._s_1jmfl_47 {
|
|
114
|
-
border-radius: 6px;
|
|
115
|
-
padding: 3.5px 6px;
|
|
116
|
-
font-size: var(--lp-pri-font-size-13);
|
|
117
|
-
font-weight: var(--lp-pri-font-weight-500);
|
|
118
|
-
min-width: 89px;
|
|
119
|
-
max-height: 24px;
|
|
120
|
-
}
|
|
121
|
-
._align-center_1jmfl_135 {
|
|
122
|
-
justify-content: center;
|
|
123
|
-
}
|
|
124
|
-
._align-space-between_1jmfl_139 {
|
|
125
|
-
justify-content: space-between;
|
|
126
|
-
}
|
|
127
|
-
._inverse-primary_1jmfl_143 {
|
|
128
|
-
color: var(--inverse-label-static-primary);
|
|
129
|
-
}
|
|
130
|
-
._neutral-primary_1jmfl_147 {
|
|
131
|
-
color: rgba(109, 109, 112, 0.8);
|
|
132
|
-
opacity: 0.8;
|
|
133
|
-
}
|
|
134
|
-
._inverse-static-primary_1jmfl_152 {
|
|
135
|
-
color: var(--inverse-label-static-primary);
|
|
136
|
-
}
|
|
137
|
-
/*! For license information please see index.css.LEGAL.txt */
|
|
138
|
-
/*# sourceMappingURL=index.css.map */
|
package/src/Configure.mdx
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Meta } from '@storybook/blocks';
|
|
2
|
-
import Image from 'next/image';
|
|
3
|
-
|
|
4
|
-
import Styling from './assets/design-token-cover.png';
|
|
5
|
-
|
|
6
|
-
<Meta title="Liner 디자인 시스템 온보딩 문서" />
|
|
7
|
-
|
|
8
|
-
<div className="sb-container">
|
|
9
|
-
<div className='sb-section-title'>
|
|
10
|
-
# Liner Design System에 오신 것을 환영합니다.
|
|
11
|
-
|
|
12
|
-
Liner Design System은 지속가능한 방식으로 디자인의 구성요소를 만듭니다.
|
|
13
|
-
|
|
14
|
-
</div>
|
|
15
|
-
<div>
|
|
16
|
-
<div>
|
|
17
|
-
<Image
|
|
18
|
-
src={Styling}
|
|
19
|
-
alt="A wall of logos representing different styling technologies"
|
|
20
|
-
width={200}
|
|
21
|
-
height={0}
|
|
22
|
-
style={{ width: '100%', height: 'auto', borderRadius: "10px" }}
|
|
23
|
-
/>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<h2 style={{ marginTop: '40px' }}>developer Guide</h2>
|
|
28
|
-
|
|
29
|
-
`npm i @liner-fe/design-token`
|
|
30
|
-
|
|
31
|
-
<p>마지막 수정자: 엘리엇 (2024. 06. 13)</p>
|
|
32
|
-
</div>
|
|
Binary file
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Button, ButtonProps, DefaultButton, DefaultButtonProps, IconButton, TextButton, TextButtonProps } from '.';
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof DefaultButton> = {
|
|
5
|
-
title: 'Components/Button',
|
|
6
|
-
component: DefaultButton,
|
|
7
|
-
args: {
|
|
8
|
-
children: 'Button',
|
|
9
|
-
as: 'default',
|
|
10
|
-
asChild: false,
|
|
11
|
-
level: 'primary',
|
|
12
|
-
align: 'center',
|
|
13
|
-
size: 'cta',
|
|
14
|
-
disabled: false,
|
|
15
|
-
},
|
|
16
|
-
argTypes: {
|
|
17
|
-
children: {
|
|
18
|
-
control: {
|
|
19
|
-
type: 'text',
|
|
20
|
-
},
|
|
21
|
-
description: '버튼 안에 표시할 컨텐츠',
|
|
22
|
-
},
|
|
23
|
-
as: {
|
|
24
|
-
options: ['default', 'text', 'icon'],
|
|
25
|
-
control: {
|
|
26
|
-
type: 'inline-radio',
|
|
27
|
-
},
|
|
28
|
-
description: '버튼의 종류를 설정합니다. 스토리북에서는 동작하지 않습니다',
|
|
29
|
-
},
|
|
30
|
-
asChild: {
|
|
31
|
-
control: {
|
|
32
|
-
type: 'boolean',
|
|
33
|
-
default: false,
|
|
34
|
-
},
|
|
35
|
-
description: '버튼을 부모 태그의 자식 요소로 사용할 때 사용합니다.',
|
|
36
|
-
},
|
|
37
|
-
level: {
|
|
38
|
-
options: ['primary', 'secondary', 'tertiary', 'quaternary', 'quinary', 'negative', 'inverse'],
|
|
39
|
-
control: {
|
|
40
|
-
type: 'select',
|
|
41
|
-
},
|
|
42
|
-
description: '버튼의 레벨을 설정합니다.',
|
|
43
|
-
},
|
|
44
|
-
align: {
|
|
45
|
-
options: ['center', 'spaceBetween'],
|
|
46
|
-
control: {
|
|
47
|
-
type: 'inline-radio',
|
|
48
|
-
},
|
|
49
|
-
description: '버튼 안의 컨텐츠의 정렬 방식을 설정합니다.',
|
|
50
|
-
},
|
|
51
|
-
size: {
|
|
52
|
-
options: ['cta', 'l', 'm', 's'],
|
|
53
|
-
control: {
|
|
54
|
-
type: 'inline-radio',
|
|
55
|
-
},
|
|
56
|
-
description: '버튼의 크기를 설정합니다.',
|
|
57
|
-
},
|
|
58
|
-
disabled: {
|
|
59
|
-
control: {
|
|
60
|
-
type: 'boolean',
|
|
61
|
-
default: false,
|
|
62
|
-
},
|
|
63
|
-
description: '버튼의 비활성화 여부를 설정합니다.',
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
decorators: [
|
|
67
|
-
Story => (
|
|
68
|
-
<article
|
|
69
|
-
style={{
|
|
70
|
-
display: 'flex',
|
|
71
|
-
gap: '10px',
|
|
72
|
-
flexWrap: 'wrap',
|
|
73
|
-
alignItems: 'flex-end',
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
76
|
-
<Story />
|
|
77
|
-
</article>
|
|
78
|
-
),
|
|
79
|
-
],
|
|
80
|
-
tags: ['autodocs'],
|
|
81
|
-
};
|
|
82
|
-
export default meta;
|
|
83
|
-
|
|
84
|
-
type Story = StoryObj<typeof meta>;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* 기본 버튼
|
|
88
|
-
*/
|
|
89
|
-
export const Default: Story = {
|
|
90
|
-
args: {
|
|
91
|
-
as: 'default',
|
|
92
|
-
level: 'primary',
|
|
93
|
-
align: 'center',
|
|
94
|
-
size: 'cta',
|
|
95
|
-
disabled: false,
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
render: args => <DefaultButton {...args}>{args.children}</DefaultButton>,
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* 종류별 버튼
|
|
103
|
-
*/
|
|
104
|
-
export const AS: Story = {
|
|
105
|
-
render: args => (
|
|
106
|
-
<>
|
|
107
|
-
<Button as="default">Default</Button>
|
|
108
|
-
<Button as="text" level="neutralPrimary">
|
|
109
|
-
Text
|
|
110
|
-
</Button>
|
|
111
|
-
{/* <Button as="icon">Icon</Button> */}
|
|
112
|
-
</>
|
|
113
|
-
),
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const DEFAULT_LEVEL_OPTIONS: Extract<ButtonProps, DefaultButtonProps>['level'][] = [
|
|
117
|
-
'primary',
|
|
118
|
-
'secondary',
|
|
119
|
-
'tertiary',
|
|
120
|
-
'quaternary',
|
|
121
|
-
'quinary',
|
|
122
|
-
'negative',
|
|
123
|
-
'inverse',
|
|
124
|
-
];
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Default 버튼 타입 - level 종류
|
|
128
|
-
*/
|
|
129
|
-
export const DefaultLevel: Story = {
|
|
130
|
-
render: args => (
|
|
131
|
-
<>
|
|
132
|
-
{DEFAULT_LEVEL_OPTIONS.map(level => (
|
|
133
|
-
<Button {...args} level={level} key={level}>
|
|
134
|
-
{level}
|
|
135
|
-
</Button>
|
|
136
|
-
))}
|
|
137
|
-
</>
|
|
138
|
-
),
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const DEFAULT_ALIGN_OPTIONS: Extract<ButtonProps, DefaultButtonProps>['align'][] = ['center', 'spaceBetween'];
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Default 버튼 - align 종류
|
|
145
|
-
*/
|
|
146
|
-
export const DefaultAlign: Story = {
|
|
147
|
-
render: args => (
|
|
148
|
-
<>
|
|
149
|
-
{DEFAULT_ALIGN_OPTIONS.map(align => (
|
|
150
|
-
<Button {...args} align={align} key={align}>
|
|
151
|
-
{align}
|
|
152
|
-
</Button>
|
|
153
|
-
))}
|
|
154
|
-
</>
|
|
155
|
-
),
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const DEFAULT_SIZE_OPTIONS: Extract<ButtonProps, DefaultButtonProps>['size'][] = ['cta', 'l', 'm', 's'];
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Default 버튼 - size 종류
|
|
162
|
-
*/
|
|
163
|
-
export const DefaultSize: Story = {
|
|
164
|
-
render: args => (
|
|
165
|
-
<>
|
|
166
|
-
{DEFAULT_SIZE_OPTIONS.map(size => (
|
|
167
|
-
<Button {...args} size={size} key={size}>
|
|
168
|
-
{size}
|
|
169
|
-
</Button>
|
|
170
|
-
))}
|
|
171
|
-
</>
|
|
172
|
-
),
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const TEXT_LEVEL_OPTIONS: Extract<ButtonProps, TextButtonProps>['level'][] = [
|
|
176
|
-
'inversePrimary',
|
|
177
|
-
'neutralPrimary',
|
|
178
|
-
'inverseStaticPrimary',
|
|
179
|
-
];
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Text 버튼 - level 종류
|
|
183
|
-
*/
|
|
184
|
-
export const TextLevel: Story = {
|
|
185
|
-
render: args => (
|
|
186
|
-
<div
|
|
187
|
-
style={{
|
|
188
|
-
display: 'flex',
|
|
189
|
-
width: '100%',
|
|
190
|
-
height: '50px',
|
|
191
|
-
gap: '2rem',
|
|
192
|
-
background: '#444444',
|
|
193
|
-
}}
|
|
194
|
-
>
|
|
195
|
-
{TEXT_LEVEL_OPTIONS.map(level => (
|
|
196
|
-
<Button as="text" level={level} key={level}>
|
|
197
|
-
{level}
|
|
198
|
-
</Button>
|
|
199
|
-
))}
|
|
200
|
-
</div>
|
|
201
|
-
),
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Default 버튼 - 비활성화 상태
|
|
206
|
-
*/
|
|
207
|
-
export const Disabled: Story = {
|
|
208
|
-
render: args => (
|
|
209
|
-
<Button {...args} disabled>
|
|
210
|
-
Disabled
|
|
211
|
-
</Button>
|
|
212
|
-
),
|
|
213
|
-
};
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { ButtonHTMLAttributes, forwardRef } from 'react';
|
|
2
|
-
|
|
3
|
-
import style from './style.module.scss';
|
|
4
|
-
import { VariantProps, cva } from 'class-variance-authority';
|
|
5
|
-
import { Slot } from '@radix-ui/react-slot';
|
|
6
|
-
import clsx from 'clsx';
|
|
7
|
-
|
|
8
|
-
const defaultButtonVariants = cva([style.button, style.default], {
|
|
9
|
-
variants: {
|
|
10
|
-
level: {
|
|
11
|
-
primary: style.primary,
|
|
12
|
-
secondary: style.secondary,
|
|
13
|
-
tertiary: style.tertiary,
|
|
14
|
-
quaternary: style.quaternary,
|
|
15
|
-
quinary: style.quinary,
|
|
16
|
-
negative: style.negative,
|
|
17
|
-
inverse: style.inverse,
|
|
18
|
-
},
|
|
19
|
-
align: {
|
|
20
|
-
center: style['align-center'],
|
|
21
|
-
spaceBetween: style['align-space-between'],
|
|
22
|
-
},
|
|
23
|
-
size: {
|
|
24
|
-
cta: style.cta,
|
|
25
|
-
l: style.l,
|
|
26
|
-
m: style.button,
|
|
27
|
-
s: style.s,
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
const textButtonVariants = cva([style.button, style.text], {
|
|
32
|
-
variants: {
|
|
33
|
-
level: {
|
|
34
|
-
inversePrimary: style['inverse-primary'],
|
|
35
|
-
neutralPrimary: style['neutral-primary'],
|
|
36
|
-
inverseStaticPrimary: style['inverse-static-primary'],
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
const iconButtonVariants = cva([style.button, style.icon], {
|
|
41
|
-
variants: {
|
|
42
|
-
level: {
|
|
43
|
-
primary: style.primary,
|
|
44
|
-
secondary: style.secondary,
|
|
45
|
-
tertiary: style.tertiary,
|
|
46
|
-
quaternary: style.quaternary,
|
|
47
|
-
quinary: style.quinary,
|
|
48
|
-
negative: style.negative,
|
|
49
|
-
},
|
|
50
|
-
weight: {
|
|
51
|
-
//
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
interface CommonButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
57
|
-
as?: 'default' | 'text' | 'icon';
|
|
58
|
-
asChild?: boolean;
|
|
59
|
-
}
|
|
60
|
-
export interface DefaultButtonProps extends CommonButtonProps, VariantProps<typeof defaultButtonVariants> {
|
|
61
|
-
as?: 'default';
|
|
62
|
-
asChild?: boolean;
|
|
63
|
-
level?: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'quinary' | 'negative' | 'inverse';
|
|
64
|
-
size?: 'cta' | 'l' | 'm' | 's';
|
|
65
|
-
align?: 'center' | 'spaceBetween';
|
|
66
|
-
// isLoading?: boolean;
|
|
67
|
-
// leftIcon?: ReactNode;
|
|
68
|
-
// rightIcon?: ReactNode;
|
|
69
|
-
}
|
|
70
|
-
export interface TextButtonProps extends CommonButtonProps, VariantProps<typeof textButtonVariants> {
|
|
71
|
-
as: 'text';
|
|
72
|
-
asChild?: boolean;
|
|
73
|
-
level?: 'inversePrimary' | 'neutralPrimary' | 'inverseStaticPrimary';
|
|
74
|
-
}
|
|
75
|
-
export interface IconButtonProps extends CommonButtonProps, VariantProps<typeof iconButtonVariants> {
|
|
76
|
-
as: 'icon';
|
|
77
|
-
asChild?: boolean;
|
|
78
|
-
// weight
|
|
79
|
-
}
|
|
80
|
-
export type ButtonProps = DefaultButtonProps | TextButtonProps | IconButtonProps;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* 버튼 컴포넌트
|
|
84
|
-
*/
|
|
85
|
-
export const DefaultButton = forwardRef<HTMLButtonElement, DefaultButtonProps>(
|
|
86
|
-
({ as = 'default', asChild = false, level = 'primary', align = 'center', size = 'cta', ...rest }, ref) => {
|
|
87
|
-
const Comp = asChild ? Slot : 'button';
|
|
88
|
-
|
|
89
|
-
return <Comp {...rest} className={clsx(defaultButtonVariants({ level, align, size }))} ref={ref} />;
|
|
90
|
-
}
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
export const TextButton = forwardRef<HTMLButtonElement, TextButtonProps>(
|
|
94
|
-
({ as = 'text', asChild = false, level = 'inversePrimary', ...rest }, ref) => {
|
|
95
|
-
const Comp = asChild ? Slot : 'button';
|
|
96
|
-
|
|
97
|
-
return <Comp {...rest} className={clsx(textButtonVariants({ level }))} ref={ref} />;
|
|
98
|
-
}
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>((props, ref) => {
|
|
102
|
-
const Comp = props.asChild ? Slot : 'button';
|
|
103
|
-
|
|
104
|
-
return <Comp {...props} className={clsx(iconButtonVariants({ level: props.level }))} ref={ref} />;
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
|
|
108
|
-
const Comp = props.asChild ? Slot : 'button';
|
|
109
|
-
|
|
110
|
-
switch (props.as) {
|
|
111
|
-
case 'default':
|
|
112
|
-
case undefined:
|
|
113
|
-
const { as, asChild, level = 'primary', align = 'center', size = 'cta', ...rest } = props;
|
|
114
|
-
return <Comp {...rest} className={clsx(defaultButtonVariants({ level, align, size }))} ref={ref} />;
|
|
115
|
-
case 'text':
|
|
116
|
-
const { as: textAs, asChild: textAsChild, level: textLevel = 'inversePrimary', ...textRest } = props;
|
|
117
|
-
return <Comp {...textRest} className={clsx(textButtonVariants({ level: textLevel }))} ref={ref} />;
|
|
118
|
-
// case 'icon':
|
|
119
|
-
// return <Comp {...props} className={clsx(iconButtonVariants({ level: props.level }))} ref={ref} />;
|
|
120
|
-
}
|
|
121
|
-
});
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
.button {
|
|
2
|
-
position: relative;
|
|
3
|
-
display: flex;
|
|
4
|
-
align-items: center;
|
|
5
|
-
justify-content: center;
|
|
6
|
-
border: none;
|
|
7
|
-
|
|
8
|
-
font-style: normal;
|
|
9
|
-
font-size: var(--lp-pri-font-size-16);
|
|
10
|
-
font-weight: var(--lp-pri-font-weight-700);
|
|
11
|
-
line-height: 130%; // TODO: 토큰
|
|
12
|
-
overflow: hidden;
|
|
13
|
-
|
|
14
|
-
cursor: pointer;
|
|
15
|
-
|
|
16
|
-
&:disabled {
|
|
17
|
-
background: var(--neutral-container-mid);
|
|
18
|
-
color: var(--neutral-label-tertiary);
|
|
19
|
-
cursor: not-allowed;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// as
|
|
24
|
-
.default {
|
|
25
|
-
color: var(--inverse-label-static-primary);
|
|
26
|
-
background: var(--lp-pri-achromatic-white); // TODO: 토큰
|
|
27
|
-
// color: var(--brand-container-mid);
|
|
28
|
-
}
|
|
29
|
-
.text {
|
|
30
|
-
background: none;
|
|
31
|
-
color: var(--inverse-label-static-primary);
|
|
32
|
-
font-size: var(--lp-pri-font-size-13);
|
|
33
|
-
font-weight: var(--lp-pri-font-weight-500);
|
|
34
|
-
|
|
35
|
-
&:not(:disabled):hover {
|
|
36
|
-
text-decoration: underline;
|
|
37
|
-
text-underline-offset: 0.2rem;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
.icon {
|
|
41
|
-
background: none;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// DefaultButton - level
|
|
45
|
-
.primary {
|
|
46
|
-
background: #4058ff; // TODO: 토큰 업데이트 (색상 다름)
|
|
47
|
-
|
|
48
|
-
&:not(:disabled):hover {
|
|
49
|
-
// TODO: 토큰으로 변환
|
|
50
|
-
background: #3346cc;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
.secondary {
|
|
54
|
-
background: var(--inverse-container-high);
|
|
55
|
-
|
|
56
|
-
&:not(:disabled):hover {
|
|
57
|
-
// TODO: 토큰으로 변환
|
|
58
|
-
background: #121212;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
.tertiary {
|
|
62
|
-
background: #6d6d7014;
|
|
63
|
-
color: var(--neutral-label-primary);
|
|
64
|
-
|
|
65
|
-
&:not(:disabled):hover {
|
|
66
|
-
// TODO: 토큰으로 변환
|
|
67
|
-
background: #ebebeb;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
.quaternary {
|
|
71
|
-
// TODO: 토큰 업데이트 neutral/border/overlay/normal
|
|
72
|
-
color: var(--neutral-label-primary);
|
|
73
|
-
border: 1px solid var(--neutral-border-overlay-normal);
|
|
74
|
-
|
|
75
|
-
&:not(:disabled):hover {
|
|
76
|
-
// TODO: 토큰으로 변환
|
|
77
|
-
background: #f5f5f5;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
&:disabled {
|
|
81
|
-
background: var(--neutral-container-mid);
|
|
82
|
-
color: var(--neutral-label-tertiary);
|
|
83
|
-
opacity: 0.4;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
.quinary {
|
|
87
|
-
// color: var(--neutral-label-secondary);
|
|
88
|
-
color: #6d6d70cc; // TODO: 토큰 업데이트
|
|
89
|
-
|
|
90
|
-
&:not(:disabled):hover {
|
|
91
|
-
// TODO: 토큰으로 변환
|
|
92
|
-
background: #f5f5f5;
|
|
93
|
-
}
|
|
94
|
-
&:disabled {
|
|
95
|
-
background: var(--neutral-container-mid);
|
|
96
|
-
color: var(--neutral-label-tertiary);
|
|
97
|
-
opacity: 0.4;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
.negative {
|
|
101
|
-
// TODO: funtion/container/negative
|
|
102
|
-
background: var(--function-negative);
|
|
103
|
-
|
|
104
|
-
&:not(:disabled):hover {
|
|
105
|
-
// TODO: 토큰으로 변환
|
|
106
|
-
background: #af1b1c;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
.inverse {
|
|
110
|
-
// TODO: neutral/label/static/primary
|
|
111
|
-
color: var(--neutral-label-primary);
|
|
112
|
-
|
|
113
|
-
&:not(:disabled):hover {
|
|
114
|
-
// TODO: 토큰으로 변환
|
|
115
|
-
background: #f5f5f5;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// size
|
|
120
|
-
.cta {
|
|
121
|
-
border-radius: 8px; // TODO: 토큰
|
|
122
|
-
padding: 13.5px 12px; // TODO: 토큰
|
|
123
|
-
font-size: var(--lp-pri-font-size-16);
|
|
124
|
-
min-width: 129px;
|
|
125
|
-
max-height: 48px;
|
|
126
|
-
}
|
|
127
|
-
.l {
|
|
128
|
-
border-radius: 6px; // TODO: 토큰
|
|
129
|
-
padding: 10.5px 8px; // TODO: 토큰
|
|
130
|
-
font-size: var(--lp-pri-font-size-15);
|
|
131
|
-
min-width: 107px;
|
|
132
|
-
max-height: 40px;
|
|
133
|
-
}
|
|
134
|
-
.m {
|
|
135
|
-
border-radius: 6px; // TODO: 토큰
|
|
136
|
-
padding: 7px 6px; // TODO: 토큰
|
|
137
|
-
font-size: var(--lp-pri-font-size-14);
|
|
138
|
-
font-weight: var(--lp-pri-font-weight-500);
|
|
139
|
-
min-width: 91px;
|
|
140
|
-
max-height: 32px;
|
|
141
|
-
}
|
|
142
|
-
.s {
|
|
143
|
-
border-radius: 6px; // TODO: 토큰
|
|
144
|
-
padding: 3.5px 6px; // TODO: 토큰
|
|
145
|
-
font-size: var(--lp-pri-font-size-13);
|
|
146
|
-
font-weight: var(--lp-pri-font-weight-500);
|
|
147
|
-
min-width: 89px;
|
|
148
|
-
max-height: 24px;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// align
|
|
152
|
-
.align-center {
|
|
153
|
-
justify-content: center;
|
|
154
|
-
}
|
|
155
|
-
.align-space-between {
|
|
156
|
-
justify-content: space-between;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// TextButton - level
|
|
160
|
-
.inverse-primary {
|
|
161
|
-
color: var(--inverse-label-static-primary); // TODO: 토큰 업데이트 (색상 다름)
|
|
162
|
-
}
|
|
163
|
-
.neutral-primary {
|
|
164
|
-
// color: var(--neutral-label-secondary); // TODO: 토큰 업데이트 (색상 다름)
|
|
165
|
-
color: #6d6d70cc;
|
|
166
|
-
opacity: 0.8;
|
|
167
|
-
}
|
|
168
|
-
.inverse-static-primary {
|
|
169
|
-
color: var(--inverse-label-static-primary);
|
|
170
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Color } from './index';
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: 'DesignToken/BorderRadius',
|
|
6
|
-
component: Color,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: 'fullscreen',
|
|
9
|
-
},
|
|
10
|
-
tags: ['!autodocs'],
|
|
11
|
-
} satisfies Meta<typeof Color>;
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
|
|
15
|
-
type Story = StoryObj<typeof meta>;
|
|
16
|
-
|
|
17
|
-
export const All: Story = {};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// import { radius } from '@liner-fe/design-token';
|
|
2
|
-
|
|
3
|
-
import { objectToArray } from '../../utils/object';
|
|
4
|
-
|
|
5
|
-
export const Color = () => (
|
|
6
|
-
<div style={{ display: 'flex', gap: '20px', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
|
|
7
|
-
{/* {objectToArray(radius).map(([key, value]) => {
|
|
8
|
-
return (
|
|
9
|
-
<div
|
|
10
|
-
style={{
|
|
11
|
-
backgroundColor: '#ededed',
|
|
12
|
-
borderRadius: `${value}px`,
|
|
13
|
-
width: '150px',
|
|
14
|
-
height: '150px',
|
|
15
|
-
justifyContent: 'center',
|
|
16
|
-
display: 'flex',
|
|
17
|
-
alignItems: 'center',
|
|
18
|
-
flexDirection: 'column',
|
|
19
|
-
gap: '12px',
|
|
20
|
-
fontWeight: 'bold',
|
|
21
|
-
}}
|
|
22
|
-
>
|
|
23
|
-
<div>{key}</div>
|
|
24
|
-
<div style={{ fontSize: '12px' }}>{value}px</div>
|
|
25
|
-
</div>
|
|
26
|
-
);
|
|
27
|
-
})} */}
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Canvas, Meta } from '@storybook/blocks';
|
|
2
|
-
import * as SizeStories from './index.stories.ts';
|
|
3
|
-
|
|
4
|
-
<Meta of={SizeStories} />
|
|
5
|
-
|
|
6
|
-
<div>
|
|
7
|
-
<h1>Design Token: Color 개발자 가이드</h1>
|
|
8
|
-
</div>
|
|
9
|
-
|
|
10
|
-
primitve, system로 위계가 나뉩니다.
|
|
11
|
-
|
|
12
|
-
```ts
|
|
13
|
-
const color = {
|
|
14
|
-
primitive,
|
|
15
|
-
system,
|
|
16
|
-
};
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
primitive는 원시 값(hex값과 같은 실제 값)을 매핑 하고 있습니다. system은 시멘틱한 네이밍으로 primitive를 매핑하고 있습니다.
|
|
20
|
-
|
|
21
|
-
그래서 대부분의 경우에는 system값을 사용해야하며, 불가피하게 primitive 값을 사용할 때는 프론트엔드 플래닛에 공유해주시길 바랍니다.
|
|
22
|
-
|
|
23
|
-
<h2>스타일링 라이브러리</h2>
|
|
24
|
-
|
|
25
|
-
<h3>CSS, SCSS</h3>
|
|
26
|
-
|
|
27
|
-
플랫폼: liner-space
|
|
28
|
-
|
|
29
|
-
<h3>CSS-in-js</h3>
|
|
30
|
-
|
|
31
|
-
플랫폼: liner-web, liner-be
|
|
32
|
-
|
|
33
|
-
<h3>React Native</h3>
|
|
34
|
-
|
|
35
|
-
플랫폼: liner-mobile
|
|
36
|
-
확인하지 않음
|
|
37
|
-
|
|
38
|
-
<h2>DarkMode를 구현하는 방법</h2>
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Color } from './index';
|
|
3
|
-
import { color } from '@liner-fe/design-token';
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: 'DesignToken/Color',
|
|
7
|
-
component: Color,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: 'fullscreen',
|
|
10
|
-
},
|
|
11
|
-
tags: ['!autodocs'],
|
|
12
|
-
} satisfies Meta<typeof Color>;
|
|
13
|
-
|
|
14
|
-
export default meta;
|
|
15
|
-
|
|
16
|
-
type Story = StoryObj<typeof meta>;
|
|
17
|
-
|
|
18
|
-
export const System: Story = {
|
|
19
|
-
args: {
|
|
20
|
-
type: 'system',
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const Primitive: Story = {
|
|
25
|
-
args: {
|
|
26
|
-
type: 'primitive',
|
|
27
|
-
},
|
|
28
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
interface IProps {
|
|
4
|
-
type: 'primitive' | 'system';
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export const Color = ({ type }: IProps) => {
|
|
8
|
-
// const { toggleTheme } = useDarkTheme();
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px', justifyContent: 'center', margin: '20px 0' }}>
|
|
12
|
-
{/* <div>
|
|
13
|
-
<button onClick={toggleTheme}>Dark theme</button>
|
|
14
|
-
{document.documentElement.getAttribute('color-theme')}
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
|
-
{objectToArray(type === 'primitive' ? color.color.primitive : color.color.system).map(([key, value]) => (
|
|
18
|
-
<div
|
|
19
|
-
key={key}
|
|
20
|
-
style={{ width: 200, height: 250, border: '1px solid #ededed', borderRadius: 10, textAlign: 'center' }}
|
|
21
|
-
>
|
|
22
|
-
<div style={{ backgroundColor: value, height: 150, borderRadius: '10px 10px 0 0' }}></div>
|
|
23
|
-
{key} {value}
|
|
24
|
-
</div>
|
|
25
|
-
))} */}
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Opacity } from './index';
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: 'DesignToken/Opacity',
|
|
6
|
-
component: Opacity,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: 'fullscreen',
|
|
9
|
-
},
|
|
10
|
-
tags: ['!autodocs'],
|
|
11
|
-
} satisfies Meta<typeof Opacity>;
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
|
|
15
|
-
type Story = StoryObj<typeof meta>;
|
|
16
|
-
|
|
17
|
-
export const All: Story = {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const Opacity = () => <div></div>;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Size } from './index';
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: 'DesignToken/Size',
|
|
6
|
-
component: Size,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: 'fullscreen',
|
|
9
|
-
},
|
|
10
|
-
tags: ['!autodocs'],
|
|
11
|
-
} satisfies Meta<typeof Size>;
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
|
|
15
|
-
type Story = StoryObj<typeof meta>;
|
|
16
|
-
|
|
17
|
-
export const All: Story = {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { objectToArray } from '@/utils/object';
|
|
2
|
-
|
|
3
|
-
export const Size = () => (
|
|
4
|
-
<div>
|
|
5
|
-
{/* {objectToArray(size).map(([key, value]) => {
|
|
6
|
-
return (
|
|
7
|
-
<div
|
|
8
|
-
style={{
|
|
9
|
-
backgroundColor: '#ededed',
|
|
10
|
-
width: `${value}px`,
|
|
11
|
-
height: `${value}px`,
|
|
12
|
-
justifyContent: 'center',
|
|
13
|
-
display: 'flex',
|
|
14
|
-
alignItems: 'center',
|
|
15
|
-
flexDirection: 'column',
|
|
16
|
-
gap: '12px',
|
|
17
|
-
fontWeight: 'bold',
|
|
18
|
-
}}
|
|
19
|
-
></div>
|
|
20
|
-
);
|
|
21
|
-
})} */}
|
|
22
|
-
</div>
|
|
23
|
-
);
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { Typography } from './index';
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: 'DesignToken/Typography',
|
|
6
|
-
component: Typography,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: 'fullscreen',
|
|
9
|
-
},
|
|
10
|
-
tags: ['!autodocs'],
|
|
11
|
-
} satisfies Meta<typeof Typography>;
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
|
|
15
|
-
type Story = StoryObj<typeof meta>;
|
|
16
|
-
|
|
17
|
-
export const All: Story = {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const Typography = () => (
|
|
2
|
-
<div>
|
|
3
|
-
{/* {objectToArray(font.size).map(([key, value]) => (
|
|
4
|
-
<div>
|
|
5
|
-
{key} {value}
|
|
6
|
-
</div>
|
|
7
|
-
))} */}
|
|
8
|
-
|
|
9
|
-
{/* <p style={{ fontSize: '16px', fontWeight: 500, fontFamily: 'pretendard', lineHeight: 26 }}>Blah Blah</p>
|
|
10
|
-
|
|
11
|
-
<Display type={'accent'}>Blah Blah</Display> */}
|
|
12
|
-
</div>
|
|
13
|
-
);
|
package/src/index.ts
DELETED
package/src/utils/object.ts
DELETED