@nine-lab/nine-ux 0.1.141 → 0.1.142

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.
@@ -1,162 +1,377 @@
1
1
  @charset "utf-8";
2
2
 
3
3
  /* ==========================================================================
4
- [1] 메인 컴포넌트 (SideMenu - 호스트 스타일)
4
+ [MAIN INTEGRATED SIDE MENU COMPONENT]
5
5
  ========================================================================== */
6
- :host {
7
- display: flex;
8
- flex-direction: column;
9
- }
6
+ :host(nine-side-menu) {
7
+ opacity: 0.95;
8
+ position: fixed;
9
+ top: 0;
10
+ bottom: 0;
11
+ left: 0;
12
+ display: block;
13
+ z-index: 1002;
14
+ color: #fff;
15
+ font-weight: 200;
16
+ background: #181A31;
17
+ --background: #333;
18
+ -webkit-box-shadow: 4px 4px 10px rgba(69, 65, 78, .06);
19
+ -moz-box-shadow: 4px 4px 10px rgba(69, 65, 78, .06);
20
+ box-shadow: 4px 4px 10px rgba(69, 65, 78, .06);
21
+ overflow: hidden;
22
+ width: var(--min-width);
23
+ --transition: all .3s;
24
+ transition: width 0.2s ease-in-out;
10
25
 
11
- /* ==========================================================================
12
- [2] 헤더 영역 (SideMenuHead)
13
- ========================================================================== */
14
- nine-side-menu-head {
15
- display: flex;
16
- align-items: center;
17
- padding: 10px;
18
- height: 40px;
19
- justify-content: center;
20
- }
26
+ /* 상태별 전체 너비 및 바운스 애니메이션 */
27
+ &.collapse {
28
+ width: var(--min-width);
29
+ }
30
+ &:not(.collapse) {
31
+ width: var(--max-width);
32
+ }
33
+ &.collapse.hover {
34
+ width: var(--max-width);
35
+ animation: nineMenuBounce 0.5s ease-in-out 1;
36
+ }
21
37
 
22
- nine-side-menu-head .logo-box {
23
- color: #f0f0f0;
24
- white-space: nowrap;
25
- overflow: hidden;
26
- text-overflow: ellipsis;
27
- text-align: center;
28
- width: 100%;
29
- }
38
+ /* 본문 스크롤 감싸는 영역 */
39
+ .body-wrapper {
40
+ display: flex;
41
+ flex-direction: column;
42
+ align-items: flex-start;
43
+ margin-top: 32px;
44
+ height: 100%;
45
+ overflow: auto;
46
+ }
30
47
 
31
- /* 접힌 상태일 때 로고 너비 축소 */
32
- nine-side-menu.collapse nine-side-menu-head .logo-box {
33
- width: 0;
34
- transition: width 0.5s ease-out;
35
- }
36
- /* 펼쳐진 상태이거나 호버 시 로고 보임 */
37
- nine-side-menu:not(.collapse) nine-side-menu-head .logo-box,
38
- nine-side-menu.hover nine-side-menu-head .logo-box {
39
- width: 100%;
40
- }
48
+ /* --------------------------------------------------------------------------
49
+ [1] 헤더 영역 (nine-side-menu-head)
50
+ -------------------------------------------------------------------------- */
51
+ nine-side-menu-head {
52
+ display: flex;
53
+ align-items: center;
54
+ padding: 10px;
55
+ height: 40px;
56
+ justify-content: center;
41
57
 
42
- nine-side-menu-head .icon-box {
43
- display: flex;
44
- align-items: center;
45
- overflow: hidden;
46
- }
58
+ .logo-box {
59
+ color: #f0f0f0;
60
+ white-space: nowrap;
61
+ overflow: hidden;
62
+ text-overflow: ellipsis;
63
+ text-align: center;
64
+ width: 100%;
65
+ }
47
66
 
48
- nine-side-menu-head .icon {
49
- fill: var(--icon-color, #eee);
50
- cursor: pointer;
51
- transition: opacity 0.3s ease-in-out;
52
- }
67
+ .icon-box {
68
+ display: flex;
69
+ align-items: center;
70
+ overflow: hidden;
53
71
 
54
- nine-side-menu-head .icon-box svg {
55
- display: none;
56
- opacity: 0;
57
- transition: opacity 0.3s ease-in-out;
58
- }
72
+ svg {
73
+ display: none;
74
+ opacity: 0;
75
+ transition: opacity 0.3s ease-in-out;
76
+ }
77
+ }
59
78
 
60
- /* 케이스 A: 메뉴가 접혀있을 때 -> 1번 노출 */
61
- nine-side-menu.collapse nine-side-menu-head .icon:nth-of-type(1) {
62
- display: block;
63
- opacity: 1;
64
- }
79
+ .icon {
80
+ fill: var(--icon-color, #eee);
81
+ cursor: pointer;
82
+ transition: opacity 0.3s ease-in-out;
83
+ }
84
+ }
65
85
 
66
- /* 케이스 B: 메뉴가 펼쳐져 있을 때 -> 1번 숨김, 2번 노출 */
67
- nine-side-menu:not(.collapse) nine-side-menu-head .icon:nth-of-type(1) {
68
- display: none;
69
- opacity: 0;
70
- }
71
- nine-side-menu:not(.collapse) nine-side-menu-head .icon:nth-of-type(2) {
72
- display: block;
73
- opacity: 1;
74
- }
75
- nine-side-menu:not(.collapse) nine-side-menu-head .icon:nth-of-type(3) {
76
- display: none;
77
- opacity: 0;
78
- }
86
+ /* 헤더 상태별 유기적 스위칭 명세 */
87
+ &.collapse nine-side-menu-head .logo-box {
88
+ width: 0;
89
+ justify-content: center;
90
+ transition: width 0.5s ease-out;
91
+ }
92
+ &.collapse.hover nine-side-menu-head .logo-box,
93
+ &:not(.collapse) nine-side-menu-head .logo-box {
94
+ width: 100%;
95
+ justify-content: space-between;
96
+ }
79
97
 
80
- /* 케이스 C: 아이콘 박스 호버 시 -> 2번 숨김, 3번 노출 */
81
- nine-side-menu:not(.collapse) nine-side-menu-head .icon-box:hover .icon:nth-of-type(2) {
82
- display: none;
83
- opacity: 0;
84
- }
85
- nine-side-menu:not(.collapse) nine-side-menu-head .icon-box:hover .icon:nth-of-type(3) {
86
- display: block;
87
- opacity: 1;
88
- }
98
+ &.collapse nine-side-menu-head .icon:nth-of-type(1) {
99
+ display: block;
100
+ opacity: 1;
101
+ }
102
+ &:not(.collapse) {
103
+ nine-side-menu-head .icon:nth-of-type(1) {
104
+ display: none;
105
+ opacity: 0;
106
+ }
107
+ nine-side-menu-head .icon:nth-of-type(2) {
108
+ display: block;
109
+ opacity: 1;
110
+ }
111
+ nine-side-menu-head .icon:nth-of-type(3) {
112
+ display: none;
113
+ opacity: 0;
114
+ }
115
+ nine-side-menu-head .icon-box:hover {
116
+ .icon:nth-of-type(2) {
117
+ display: none;
118
+ opacity: 0;
119
+ }
120
+ .icon:nth-of-type(3) {
121
+ display: block;
122
+ opacity: 1;
123
+ }
124
+ }
125
+ }
89
126
 
90
- /* ==========================================================================
91
- [3] 푸터 영역 (SideMenuFoot)
92
- ========================================================================== */
93
- nine-side-menu-foot {
94
- display: flex;
95
- align-items: center;
96
- padding: 10px;
97
- height: 40px;
98
- justify-content: center;
99
- }
127
+ /* --------------------------------------------------------------------------
128
+ [2] 바디 컨테이너 영역 (nine-side-menu-body)
129
+ -------------------------------------------------------------------------- */
130
+ nine-side-menu-body {
131
+ display: flex;
132
+ align-items: center;
133
+ padding: 10px;
134
+ height: 40px;
135
+ }
100
136
 
101
- nine-side-menu-foot .logo-box {
102
- color: #f0f0f0;
103
- white-space: nowrap;
104
- overflow: hidden;
105
- text-overflow: ellipsis;
106
- text-align: center;
107
- width: 100%;
108
- }
137
+ /* --------------------------------------------------------------------------
138
+ [3] 푸터 영역 (nine-side-menu-foot)
139
+ -------------------------------------------------------------------------- */
140
+ nine-side-menu-foot {
141
+ display: flex;
142
+ align-items: center;
143
+ padding: 10px;
144
+ height: 40px;
145
+ justify-content: center;
109
146
 
110
- nine-side-menu.collapse nine-side-menu-foot .logo-box {
111
- width: 0;
112
- transition: width 0.5s ease-out;
113
- }
114
- nine-side-menu:not(.collapse) nine-side-menu-foot .logo-box,
115
- nine-side-menu.hover nine-side-menu-foot .logo-box {
116
- width: 100%;
117
- }
147
+ .logo-box {
148
+ color: #f0f0f0;
149
+ white-space: nowrap;
150
+ overflow: hidden;
151
+ text-overflow: ellipsis;
152
+ text-align: center;
153
+ width: 100%;
154
+ }
118
155
 
119
- nine-side-menu-foot .icon-box {
120
- display: flex;
121
- align-items: center;
122
- overflow: hidden;
123
- }
156
+ .icon-box {
157
+ display: flex;
158
+ align-items: center;
159
+ overflow: hidden;
124
160
 
125
- nine-side-menu-foot .icon {
126
- fill: var(--icon-color, #eee);
127
- cursor: pointer;
128
- transition: opacity 0.3s ease-in-out;
129
- }
161
+ svg {
162
+ display: none;
163
+ opacity: 0;
164
+ transition: opacity 0.3s ease-in-out;
165
+ }
166
+ }
130
167
 
131
- nine-side-menu-foot .icon-box svg {
132
- display: none;
133
- opacity: 0;
134
- transition: opacity 0.3s ease-in-out;
135
- }
168
+ .icon {
169
+ fill: var(--icon-color, #eee);
170
+ cursor: pointer;
171
+ transition: opacity 0.3s ease-in-out;
172
+ }
173
+ }
136
174
 
137
- nine-side-menu.collapse nine-side-menu-foot .icon:nth-of-type(1) {
138
- display: block;
139
- opacity: 1;
140
- }
175
+ /* 푸터 상태별 유기적 스위칭 명세 */
176
+ &.collapse nine-side-menu-foot .logo-box {
177
+ width: 0;
178
+ justify-content: center;
179
+ transition: width 0.5s ease-out;
180
+ }
181
+ &.collapse.hover nine-side-menu-foot .logo-box,
182
+ &:not(.collapse) nine-side-menu-foot .logo-box {
183
+ width: 100%;
184
+ justify-content: space-between;
185
+ }
141
186
 
142
- nine-side-menu:not(.collapse) nine-side-menu-foot .icon:nth-of-type(1) {
143
- display: none;
144
- opacity: 0;
145
- }
146
- nine-side-menu:not(.collapse) nine-side-menu-foot .icon:nth-of-type(2) {
147
- display: block;
148
- opacity: 1;
149
- }
150
- nine-side-menu:not(.collapse) nine-side-menu-foot .icon:nth-of-type(3) {
151
- display: none;
152
- opacity: 0;
187
+ &.collapse nine-side-menu-foot .icon:nth-of-type(1) {
188
+ display: block;
189
+ opacity: 1;
190
+ }
191
+ &:not(.collapse) {
192
+ nine-side-menu-foot .icon:nth-of-type(1) {
193
+ display: none;
194
+ opacity: 0;
195
+ }
196
+ nine-side-menu-foot .icon:nth-of-type(2) {
197
+ display: block;
198
+ opacity: 1;
199
+ }
200
+ nine-side-menu-foot .icon:nth-of-type(3) {
201
+ display: none;
202
+ opacity: 0;
203
+ }
204
+ nine-side-menu-foot .icon-box:hover {
205
+ .icon:nth-of-type(2) {
206
+ display: none;
207
+ opacity: 0;
208
+ }
209
+ .icon:nth-of-type(3) {
210
+ display: block;
211
+ opacity: 1;
212
+ }
213
+ }
214
+ }
215
+
216
+ /* --------------------------------------------------------------------------
217
+ [4] 메뉴 아이템 목록 영역 (nine-side-menu-item)
218
+ -------------------------------------------------------------------------- */
219
+ nine-side-menu-item {
220
+ padding: 0;
221
+ margin: 0;
222
+ position: relative;
223
+ display: flex;
224
+ align-items: unset;
225
+ background-color: unset;
226
+ cursor: pointer;
227
+ max-height: 64px;
228
+ opacity: 1;
229
+ transition: opacity 0.5s ease-out, height 0.5s ease-out, max-height 0.5s ease-in-out;
230
+
231
+ &.group {
232
+ height: 48px;
233
+
234
+ .menubar { font-weight: 700; }
235
+ li { list-style-type: none; }
236
+ }
237
+
238
+ &:not(.group) {
239
+ height: 32px;
240
+
241
+ .menubar { font-weight: 400; }
242
+
243
+ li {
244
+ list-style-type: unset;
245
+
246
+ &::before {
247
+ content: '•';
248
+ margin-right: 8px;
249
+ margin-left: 16px;
250
+ }
251
+ }
252
+
253
+ .icon { display: none; }
254
+ }
255
+
256
+ &.active {
257
+ color: #9FF2FF;
258
+ }
259
+
260
+ &:hover {
261
+ filter: brightness(90%);
262
+ }
263
+
264
+ /* 아코디언 하이드 규칙 */
265
+ &.hide {
266
+ max-height: 0;
267
+ height: 0 !important;
268
+ opacity: 0;
269
+ padding: 0;
270
+ overflow: hidden;
271
+ }
272
+
273
+ .menubar {
274
+ display: inline-block;
275
+ white-space: nowrap;
276
+ overflow: hidden;
277
+ text-overflow: ellipsis;
278
+ transition: height 0.5s ease-out, padding 0.5s ease-out, width 0.5s ease-out, padding-left 0.5s ease-out;
279
+ text-align: left;
280
+ margin-left: 8px;
281
+ }
282
+
283
+ li {
284
+ display: flex;
285
+ align-items: center;
286
+ padding: 0;
287
+ margin: 0;
288
+ position: relative;
289
+ color: unset;
290
+ font-weight: bold;
291
+ width: calc(100% + 36px);
292
+ }
293
+
294
+ .icon {
295
+ position: relative;
296
+ left: 0;
297
+ width: 16px;
298
+ height: 16px;
299
+ background-repeat: no-repeat;
300
+ background-position: center center;
301
+ background-size: contain;
302
+ margin-left: 8px;
303
+ transition: width 0.5s ease-out, height 0.5s ease-out;
304
+
305
+ &.icon-home {
306
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="lightgray" viewBox="0 0 16 16"><path d="M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5"/></svg>');
307
+ }
308
+
309
+ &.icon-base {
310
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" viewBox="0 0 16 16"><path d="M0 .5A.5.5 0 0 1 .5 0h15a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5H14v2h1.5a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5H14v2h1.5a.5.5 0 0 1-.5.5H.5a.5.5 0 0 1-.5-.5v-3a.5.5 0 0 1 .5-.5H2v-2H.5a.5.5 0 0 1-.5-.5v-3A.5.5 0 0 1 .5 6H2V4H.5a.5.5 0 0 1-.5-.5zM3 4v2h4.5V4zm5.5 0v2H13V4zM3 10v2h4.5v-2zm5.5 0v2H13v-2zM1 1v2h3.5V1zm4.5 0v2h5V1zm6 0v2H15V1zM1 7v2h3.5V7zm4.5 0v2h5V7zm6 0v2H15V7zM1 13v2h3.5v-2zm4.5 0v2h5v-2zm6 0v2H15v-2z"/></svg>');
311
+ }
312
+ }
313
+
314
+ .expand-icon {
315
+ width: 8px;
316
+ height: 8px;
317
+ position: absolute;
318
+ right: 16px;
319
+ background-repeat: no-repeat;
320
+ background-position: center;
321
+ background-size: auto;
322
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" fill="white" class="bi bi-caret-down-fill" viewBox="0 0 16 16"><path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/></svg>');
323
+ animation: nineMenuRotateOut 0.3s ease-in-out forwards;
324
+ }
325
+
326
+ &:not(.expand) .expand-icon {
327
+ transform: rotate(180deg);
328
+ animation: nineMenuRotateIn 0.3s ease-in-out forwards;
329
+ }
330
+
331
+ a {
332
+ color: #999;
333
+ text-decoration: none;
334
+
335
+ &:hover {
336
+ color: #ccc;
337
+ text-decoration: underline;
338
+ }
339
+ }
340
+ }
341
+
342
+ /* 아이템 상태별 축소 명세 */
343
+ &.collapse:not(.hover) {
344
+ nine-side-menu-item:not(.group) {
345
+ opacity: 0;
346
+ height: 0;
347
+ }
348
+ nine-side-menu-item .menubar {
349
+ width: 0;
350
+ padding-left: unset;
351
+ display: none;
352
+ }
353
+ nine-side-menu-item li {
354
+ justify-content: center;
355
+ }
356
+ nine-side-menu-item .icon {
357
+ width: 20px;
358
+ height: 20px;
359
+ margin-left: 4px;
360
+ }
361
+ nine-side-menu-item .expand-icon {
362
+ display: none;
363
+ }
364
+ }
153
365
  }
154
366
 
155
- nine-side-menu:not(.collapse) nine-side-menu-foot .icon-box:hover .icon:nth-of-type(2) {
156
- display: none;
157
- opacity: 0;
367
+ /* ==========================================================================
368
+ [GLOBAL KEYFRAMES]
369
+ ========================================================================== */
370
+ @keyframes nineMenuRotateIn {
371
+ from { transform: rotate(0deg); }
372
+ to { transform: rotate(180deg); }
158
373
  }
159
- nine-side-menu:not(.collapse) nine-side-menu-foot .icon-box:hover .icon:nth-of-type(3) {
160
- display: block;
161
- opacity: 1;
374
+ @keyframes nineMenuRotateOut {
375
+ from { transform: rotate(180deg); }
376
+ to { transform: rotate(0deg); }
162
377
  }