@nine-lab/nine-ux 0.1.130 → 0.1.131

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,182 +1,66 @@
1
- /* --- [1] 부모 컴포넌트: nine-side-menu --- */
1
+ /* --- [1] 부모 컴포넌트: nine-side-menu (Shadow DOM 내부용) --- */
2
2
  :host(nine-side-menu) {
3
- /* 1. 호스트 자체 스타일 */
4
- opacity: 0.95;
5
- position: fixed;
6
- top: 0;
7
- bottom: 0;
8
- left: 0;
9
- display: flex;
10
- flex-direction: column;
11
- z-index: 1002;
12
- color: #fff;
13
- font-weight: 200;
14
- background: #181A31;
3
+ opacity: 0.95; position: fixed; top: 0; bottom: 0; left: 0;
4
+ display: flex; flex-direction: column; z-index: 1002;
5
+ color: #fff; font-weight: 200; background: #181A31;
15
6
  box-shadow: 4px 4px 10px rgba(69, 65, 78, .06);
16
- overflow: hidden;
17
- width: var(--min-width);
7
+ overflow: hidden; width: var(--min-width);
18
8
  transition: width 0.2s ease-in-out;
9
+ }
19
10
 
20
- /* 2. 상태별 너비 제어 */
21
- &.collapse {
22
- width: var(--min-width);
23
- &:hover { width: var(--max-width); }
24
- }
25
- &:not(.collapse) {
26
- width: var(--max-width);
27
- }
28
-
29
- /* 3. 내부 레이아웃 */
30
- & .body-wrapper {
31
- display: flex;
32
- flex-direction: column;
33
- align-items: flex-start;
34
- margin-top: 32px;
35
- width: 100%;
36
- flex: 1;
37
- overflow-y: auto;
38
- }
39
-
40
- /* 4. 슬롯/자식 요소 스타일 (Shadow DOM 제거 버전) */
41
-
42
- /* [Head 영역] */
43
- & nine-side-menu-head {
44
- display: flex;
45
- align-items: center;
46
- justify-content: center;
47
- padding: 10px;
48
- height: 40px;
49
- box-sizing: border-box;
50
-
51
- & .logo-box {
52
- color: #f0f0f0; white-space: nowrap; overflow: hidden;
53
- text-overflow: ellipsis; text-align: center; width: 100%;
54
- transition: width 0.5s ease-out;
55
- }
56
-
57
- & .icon-box {
58
- display: flex; align-items: center; overflow: hidden;
59
- & .icon {
60
- fill: var(--icon-color, #eee); cursor: pointer;
61
- transition: opacity 0.3s ease-in-out; display: none; opacity: 0;
62
- }
63
- }
64
-
65
- /* Head 상태 제어 */
66
- &.collapse {
67
- & .logo-box { width: 0; }
68
- & .icon:first-child { display: block; opacity: 1; }
69
- &:hover, &.hover { & .logo-box { width: 100%; } }
70
- }
71
- &:not(.collapse) {
72
- & .logo-box { width: 100%; }
73
- & .icon:nth-child(2) { display: block; opacity: 1; }
74
- & .icon-box:hover .icon:nth-child(2) { display: none; }
75
- & .icon-box:hover .icon:nth-child(3) { display: block; opacity: 1; }
76
- }
77
- }
78
-
79
- /* [Body 영역] */
80
- & nine-side-menu-body {
81
- display: flex; width: 100%; padding: 10px; height: 40px;
82
- justify-content: center; overflow: auto;
83
- & ul.side-menu-body {
84
- width: 100%; padding: 0; margin: 0;
85
- display: flex; flex-direction: column;
86
- }
87
- }
88
-
89
- /* [Item 영역] */
90
- & nine-side-menu-item {
91
- display: flex; position: relative; padding: 0; margin: 0;
92
- cursor: pointer; color: #999; font-weight: bold;
93
- max-height: 64px; opacity: 1; box-sizing: border-box;
94
- transition: max-height 0.5s ease-in-out, opacity 0.5s ease-in-out, height 0.5s ease-out;
11
+ :host(nine-side-menu.collapse) { width: var(--min-width); }
12
+ :host(nine-side-menu:not(.collapse)), :host(nine-side-menu.hover) { width: var(--max-width); }
95
13
 
96
- &.group {
97
- height: 48px;
98
- & li { list-style-type: none; }
99
- & .menubar { font-weight: 700; }
100
- }
14
+ /* 내부 레이아웃 */
15
+ .body-wrapper {
16
+ display: flex; flex-direction: column; align-items: flex-start;
17
+ margin-top: 32px; width: 100%; flex: 1; overflow-y: auto;
18
+ }
101
19
 
102
- &:not(.group) {
103
- height: 32px;
104
- & li {
105
- list-style-type: unset;
106
- &::before { content: '•'; margin-right: 8px; margin-left: 16px; }
107
- }
108
- & .menubar { font-weight: 400; }
109
- & .icon, & .expand-icon { display: none; }
110
- }
20
+ /* --- [2] 하위 요소 스타일 (Light DOM 제어) --- */
111
21
 
112
- &.active { color: #9FF2FF; background: rgba(255,255,255,0.05); }
113
- &.hide { max-height: 0; opacity: 0; overflow: hidden; }
114
- &:hover { filter: brightness(90%); }
22
+ /* 슬롯에 들어온 자식들의 공통 스타일 */
23
+ ::slotted(nine-side-menu-head), ::slotted(nine-side-menu-foot) {
24
+ display: flex; align-items: center; justify-content: center;
25
+ padding: 10px; height: 50px; box-sizing: border-box; width: 100%;
26
+ }
115
27
 
116
- /* Item 내부 요소 */
117
- & li { display: flex; align-items: center; width: calc(100% + 36px); color: inherit; }
118
- & .menubar {
119
- margin-left: 8px; white-space: nowrap; overflow: hidden;
120
- text-overflow: ellipsis; text-align: left;
121
- transition: width 0.5s ease-out, height 0.5s ease-out, padding 0.5s ease-out;
122
- }
123
- & .icon {
124
- width: 16px; height: 16px; margin-left: 8px;
125
- background-repeat: no-repeat; background-position: center; background-size: contain;
126
- transition: width 0.5s ease-out, height 0.5s ease-out, margin 0.5s ease-out;
127
- }
128
- & .expand-icon {
129
- width: 8px; height: 8px; position: absolute; right: 16px;
130
- background-repeat: no-repeat; background-position: center; background-size: auto;
131
- background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" fill="white" 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>');
132
- transition: transform 0.3s ease-in-out;
133
- }
28
+ ::slotted(nine-side-menu-item) {
29
+ display: flex; position: relative; padding: 0; margin: 0;
30
+ cursor: pointer; color: #999; font-weight: bold;
31
+ max-height: 64px; opacity: 1; box-sizing: border-box; width: 100%;
32
+ transition: max-height 0.3s, opacity 0.3s, height 0.3s;
33
+ }
134
34
 
135
- /* 확장/축소 아이콘 회전 */
136
- &:not(.expand) .expand-icon { transform: rotate(180deg); }
35
+ /* --- [3] 하위 요소 내부 UI 제어 (중요: 자식 내부는 슬롯 선택자로 제어) --- */
137
36
 
138
- /* [Collapse 모드에서의 Item 제어] */
139
- :host(.collapse:not(:hover)) & {
140
- &:not(.group) { opacity: 0; height: 0; overflow: hidden; }
141
- & li { justify-content: center; }
142
- & .icon { width: 20px; height: 20px; margin-left: 4px; }
143
- & .menubar, & .expand-icon { display: none; }
144
- }
145
- }
37
+ /* Head/Foot 내부 텍스트 아이콘 */
38
+ ::slotted(nine-side-menu-head) .logo-box, ::slotted(nine-side-menu-foot) .logo-box {
39
+ color: #f0f0f0; white-space: nowrap; overflow: hidden;
40
+ text-overflow: ellipsis; text-align: center; width: 100%;
41
+ transition: width 0.3s ease-out;
42
+ }
146
43
 
147
- /* [Foot 영역] */
148
- & nine-side-menu-foot {
149
- display: flex; align-items: center; padding: 10px; height: 40px; box-sizing: border-box;
150
- & .logo-box {
151
- color: #f0f0f0; white-space: nowrap; overflow: hidden;
152
- text-overflow: ellipsis; text-align: center; width: 100%;
153
- display: flex; justify-content: space-between;
154
- transition: width 0.5s ease-out;
155
- }
156
- & .icon-box {
157
- display: flex; align-items: center; overflow: hidden;
158
- & .icon { fill: var(--icon-color, #eee); cursor: pointer; transition: opacity 0.3s; display: none; opacity: 0; }
159
- }
160
- &.collapse {
161
- & .logo-box { width: 0; justify-content: center; }
162
- & .icon:first-child { display: block; opacity: 1; }
163
- &:hover { & .logo-box { width: 100%; justify-content: space-between; } }
164
- }
165
- &:not(.collapse) {
166
- & .logo-box { width: 100%; justify-content: space-between; }
167
- & .icon:nth-child(2) { display: block; opacity: 1; }
168
- & .icon-box:hover { & .icon:nth-child(2) { display: none; } & .icon:nth-child(3) { display: block; opacity: 1; } }
169
- }
170
- }
44
+ ::slotted(nine-side-menu-head) .icon-box, ::slotted(nine-side-menu-foot) .icon-box {
45
+ display: flex; align-items: center;
171
46
  }
172
47
 
173
- /* --- [2] 전역 애니메이션 --- */
174
- @keyframes bounce {
175
- 0%, 20%, 50%, 80%, 100% { transform: translateX(0); }
176
- 40% { transform: translateX(-10px); }
177
- 60% { transform: translateX(10px); }
48
+ /* Collapse 상태 UI 숨김 처리 */
49
+ :host(.collapse:not(.hover)) ::slotted(nine-side-menu-head) .logo-box { width: 0; opacity: 0; }
50
+ :host(.collapse:not(.hover)) ::slotted(nine-side-menu-item) .menubar { display: none; }
51
+ :host(.collapse:not(.hover)) ::slotted(nine-side-menu-item) .expand-icon { display: none; }
52
+
53
+ /* Item 상세 스타일 */
54
+ ::slotted(nine-side-menu-item) li { display: flex; align-items: center; width: 100%; list-style: none; padding: 0 12px; }
55
+ ::slotted(nine-side-menu-item).active { color: #9FF2FF; background: rgba(255,255,255,0.05); }
56
+ ::slotted(nine-side-menu-item).group { height: 48px; }
57
+ ::slotted(nine-side-menu-item).group .menubar { font-weight: 700; color: #fff; }
58
+ ::slotted(nine-side-menu-item):not(.group) { height: 32px; }
59
+ ::slotted(nine-side-menu-item):not(.group) li::before { content: '•'; margin-right: 8px; margin-left: 10px; }
60
+
61
+ ::slotted(nine-side-menu-item) .icon {
62
+ width: 18px; height: 18px; background-repeat: no-repeat; background-size: contain; margin-right: 8px;
178
63
  }
179
64
 
180
- /* 애니메이션 정의 */
181
- @keyframes rotate-in { from { transform: rotate(0deg); } to { transform: rotate(180deg); } }
182
- @keyframes rotate-out { from { transform: rotate(180deg); } to { transform: rotate(0deg); } }
65
+ /* 애니메이션 */
66
+ @keyframes bounce { 0%, 20%, 50%, 80%, 100% { transform: translateX(0); } 40% { transform: translateX(-5px); } 60% { transform: translateX(5px); } }