style.scss 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. // ── 편집 3-column 레이아웃 (rank-config__layout 패턴) ──
  2. .crew-widget-layout {
  3. display: grid;
  4. grid-template-columns: minmax(0, 500px) auto 1fr;
  5. gap: 24px;
  6. align-items: start;
  7. }
  8. // ── 좌측 패널 (미리보기, sticky) ──
  9. .crew-widget-preview {
  10. position: sticky;
  11. top: 16px;
  12. display: flex;
  13. flex-direction: column;
  14. gap: 16px;
  15. max-height: calc(100vh - 48px);
  16. overflow-y: auto;
  17. &__widget {
  18. border: 1px solid hsl(var(--border));
  19. border-radius: var(--radius);
  20. overflow: hidden;
  21. }
  22. &__widget-label {
  23. padding: 8px 14px;
  24. font-size: 0.8125rem;
  25. font-weight: 500;
  26. color: hsl(var(--muted));
  27. background: #0e0e1a;
  28. }
  29. &__widget-body {
  30. padding: 16px;
  31. min-height: 200px;
  32. background: var(--preview-bg);
  33. &--basic { background: var(--preview-bg, #1a1a2e); }
  34. &--dark { background: var(--preview-bg, #0a0a14); }
  35. &--minimal { background: var(--preview-bg, #222); }
  36. }
  37. // ── fieldset (미리보기 패널용) ────────────────────
  38. &__fieldset {
  39. border: 1px solid hsl(var(--border));
  40. border-radius: var(--radius);
  41. padding: 16px 20px 20px;
  42. margin: 0;
  43. }
  44. &__legend {
  45. font-size: 1rem;
  46. font-weight: 600;
  47. color: hsl(var(--foreground));
  48. padding: 0 8px;
  49. margin-left: -4px;
  50. }
  51. &__preview-form {
  52. display: flex;
  53. flex-direction: column;
  54. gap: 12px;
  55. }
  56. &__field {
  57. display: flex;
  58. flex-direction: column;
  59. gap: 6px;
  60. }
  61. &__field-label {
  62. font-size: 0.875rem;
  63. font-weight: 500;
  64. color: hsl(var(--foreground));
  65. }
  66. &__field-hint {
  67. margin: 0;
  68. font-size: 0.8125rem;
  69. color: hsl(var(--muted-foreground));
  70. }
  71. &__input {
  72. padding: 8px 12px;
  73. border: 1px solid hsl(var(--border));
  74. border-radius: calc(var(--radius) - 2px);
  75. background: hsl(var(--background));
  76. color: hsl(var(--foreground));
  77. font-size: 0.875rem;
  78. width: 100%;
  79. &::placeholder {
  80. color: hsl(var(--muted-foreground));
  81. }
  82. }
  83. &__preview-actions {
  84. display: flex;
  85. gap: 8px;
  86. margin-top: 4px;
  87. }
  88. &__btn {
  89. display: inline-flex;
  90. align-items: center;
  91. justify-content: center;
  92. gap: 6px;
  93. padding: 8px 16px;
  94. border: 1px solid hsl(var(--border));
  95. border-radius: calc(var(--radius) - 2px);
  96. background: hsl(var(--background));
  97. color: hsl(var(--foreground));
  98. font-size: 0.875rem;
  99. font-weight: 500;
  100. cursor: pointer;
  101. white-space: nowrap;
  102. transition: background-color 0.15s, color 0.15s;
  103. &:hover:not(:disabled) {
  104. background: hsl(var(--accent));
  105. color: hsl(var(--accent-foreground));
  106. }
  107. &:disabled {
  108. opacity: 0.5;
  109. cursor: not-allowed;
  110. }
  111. &--primary {
  112. background: hsl(var(--primary));
  113. color: hsl(var(--primary-foreground));
  114. border-color: hsl(var(--primary));
  115. &:hover:not(:disabled) {
  116. background: hsl(var(--primary) / 0.9);
  117. color: hsl(var(--primary-foreground));
  118. }
  119. }
  120. }
  121. &__preview-btn {
  122. flex: 1;
  123. }
  124. &__empty {
  125. text-align: center;
  126. padding: 24px 16px;
  127. color: hsl(var(--muted-foreground));
  128. font-size: 0.875rem;
  129. }
  130. // ── 위젯 제목 ──
  131. &__title {
  132. text-align: center;
  133. font-weight: 700;
  134. font-size: var(--preview-title-size, 18px);
  135. font-family: var(--preview-title-font, inherit);
  136. color: var(--preview-title-color, #fff);
  137. margin-bottom: 12px;
  138. text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
  139. }
  140. // ── 컬럼 헤더 ──
  141. &__columns {
  142. display: flex;
  143. align-items: center;
  144. gap: 8px;
  145. padding: 6px 12px;
  146. margin-bottom: 6px;
  147. border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  148. font-size: 0.6875rem;
  149. font-weight: 500;
  150. color: rgba(255, 255, 255, 0.5);
  151. letter-spacing: 0.03em;
  152. }
  153. &__col-rank { width: 28px; text-align: center; flex-shrink: 0; }
  154. &__col-icon { width: 28px; flex-shrink: 0; }
  155. &__col-name { flex: 1; min-width: 0; }
  156. &__col-rate { width: 50px; text-align: right; flex-shrink: 0; }
  157. &__col-amount { width: 70px; text-align: right; flex-shrink: 0; }
  158. &__col-count { width: 40px; text-align: right; flex-shrink: 0; }
  159. // ── 순위 리스트 ──
  160. &__list {
  161. display: flex;
  162. flex-direction: column;
  163. gap: 6px;
  164. }
  165. &__item {
  166. display: flex;
  167. align-items: center;
  168. gap: 8px;
  169. padding: 8px 12px;
  170. border-radius: 8px;
  171. background: rgba(255, 255, 255, 0.08);
  172. font-family: var(--row-font-family, inherit);
  173. font-size: var(--row-font-size, inherit);
  174. color: var(--row-font-color, inherit);
  175. &--1 { background: linear-gradient(135deg, rgba(255, 215, 0, 0.2), rgba(255, 215, 0, 0.05)); }
  176. &--2 { background: linear-gradient(135deg, rgba(192, 192, 192, 0.15), rgba(192, 192, 192, 0.05)); }
  177. &--3 { background: linear-gradient(135deg, rgba(205, 127, 50, 0.15), rgba(205, 127, 50, 0.05)); }
  178. }
  179. // ── 순위 배지 ──
  180. &__badge {
  181. display: inline-flex;
  182. align-items: center;
  183. justify-content: center;
  184. width: 28px;
  185. height: 28px;
  186. border-radius: 50%;
  187. font-size: 14px;
  188. font-weight: 800;
  189. flex-shrink: 0;
  190. &--1 { background: #FFD700; color: #000; }
  191. &--2 { background: #C0C0C0; color: #000; }
  192. &--3 { background: #CD7F32; color: #fff; }
  193. &--default { background: #555; color: #fff; }
  194. }
  195. // ── 크루원 아이콘 ──
  196. &__member-icon {
  197. width: 28px;
  198. height: 28px;
  199. border-radius: 50%;
  200. background: #444;
  201. flex-shrink: 0;
  202. border: 1px solid rgba(255, 255, 255, 0.15);
  203. }
  204. // ── 이름 ──
  205. &__name {
  206. flex: 1;
  207. font-weight: 600;
  208. color: #fff;
  209. min-width: 0;
  210. overflow: hidden;
  211. text-overflow: ellipsis;
  212. white-space: nowrap;
  213. }
  214. // ── 기여도 ──
  215. &__rate {
  216. width: 50px;
  217. text-align: right;
  218. flex-shrink: 0;
  219. font-size: 0.85em;
  220. color: #A0D2FF;
  221. white-space: nowrap;
  222. }
  223. // ── 후원 금액 ──
  224. &__amount {
  225. width: 70px;
  226. text-align: right;
  227. flex-shrink: 0;
  228. font-weight: 700;
  229. color: #FF6B35;
  230. font-size: 0.85em;
  231. white-space: nowrap;
  232. }
  233. // ── 후원 건수 ──
  234. &__count {
  235. width: 40px;
  236. text-align: right;
  237. flex-shrink: 0;
  238. font-size: 0.8em;
  239. color: #aaa;
  240. white-space: nowrap;
  241. }
  242. }
  243. // ── 우측 패널 (폼) ──
  244. .crew-widget-form {
  245. display: flex;
  246. flex-direction: column;
  247. gap: 0;
  248. // ── 섹션 (details 기반, 좌측 제목 / 우측 입력 그리드) ──
  249. &__section {
  250. display: grid;
  251. grid-template-columns: 140px 1fr;
  252. gap: 24px;
  253. padding: 24px 0;
  254. border-bottom: 1px solid hsl(var(--border));
  255. &:first-of-type {
  256. padding-top: 0;
  257. }
  258. // details 마커 숨김
  259. &::-webkit-details-marker {
  260. display: none;
  261. }
  262. }
  263. &__section-title {
  264. font-size: 0.875rem;
  265. font-weight: 600;
  266. color: hsl(var(--foreground));
  267. padding-top: 2px;
  268. margin: 0;
  269. cursor: pointer;
  270. user-select: none;
  271. list-style: none;
  272. &::-webkit-details-marker {
  273. display: none;
  274. }
  275. &::before {
  276. content: '▸';
  277. display: inline-block;
  278. font-size: 0.7rem;
  279. margin-right: 6px;
  280. transition: transform 0.15s;
  281. }
  282. &:hover {
  283. color: hsl(var(--foreground) / 0.7);
  284. }
  285. }
  286. // 열린 상태: 화살표 회전
  287. &__section[open] > .crew-widget-form__section-title::before {
  288. transform: rotate(90deg);
  289. }
  290. &__section-body {
  291. display: flex;
  292. flex-direction: column;
  293. gap: 17px;
  294. max-width: 520px;
  295. }
  296. // ── 필드 행 (2-column 그리드) ──
  297. &__row {
  298. display: grid;
  299. grid-template-columns: 1fr 1fr;
  300. gap: 10px;
  301. @media (max-width: 640px) {
  302. grid-template-columns: 1fr;
  303. }
  304. }
  305. // ── 개별 필드 ──
  306. &__field {
  307. display: flex;
  308. flex-direction: column;
  309. gap: 6px;
  310. }
  311. &__field-label {
  312. font-size: 0.875rem;
  313. font-weight: 500;
  314. color: hsl(var(--foreground));
  315. }
  316. &__input {
  317. padding: 8px 12px;
  318. border: 1px solid hsl(var(--border));
  319. border-radius: calc(var(--radius) - 2px);
  320. background: hsl(var(--background));
  321. color: hsl(var(--foreground));
  322. font-size: 0.875rem;
  323. width: 100%;
  324. &::placeholder {
  325. color: hsl(var(--muted-foreground));
  326. }
  327. &--color-text {
  328. flex: 1;
  329. min-width: 0;
  330. font-family: monospace;
  331. }
  332. }
  333. &__select {
  334. padding: 8px 12px;
  335. border: 1px solid hsl(var(--border));
  336. border-radius: calc(var(--radius) - 2px);
  337. background: hsl(var(--background));
  338. color: hsl(var(--foreground));
  339. font-size: 0.875rem;
  340. width: 100%;
  341. cursor: pointer;
  342. }
  343. // ── 색상 선택 필드 ──
  344. &__color-field {
  345. display: flex;
  346. align-items: center;
  347. gap: 8px;
  348. }
  349. &__color-picker {
  350. width: 36px;
  351. height: 36px;
  352. border: 1px solid hsl(var(--border));
  353. border-radius: calc(var(--radius) - 2px);
  354. background: none;
  355. cursor: pointer;
  356. padding: 2px;
  357. flex-shrink: 0;
  358. &::-webkit-color-swatch-wrapper {
  359. padding: 0;
  360. }
  361. &::-webkit-color-swatch {
  362. border: none;
  363. border-radius: 2px;
  364. }
  365. &::-moz-color-swatch {
  366. border: none;
  367. border-radius: 2px;
  368. }
  369. }
  370. // ── 체크박스 행 ──
  371. &__checkbox-label {
  372. display: inline-flex;
  373. align-items: center;
  374. gap: 8px;
  375. font-size: 0.875rem;
  376. color: hsl(var(--foreground));
  377. cursor: pointer;
  378. }
  379. // ── 순위별 폰트 접이식 (details 내부) ──
  380. &__details {
  381. border: 1px solid hsl(var(--border));
  382. border-radius: calc(var(--radius) - 2px);
  383. overflow: hidden;
  384. &[open] > .crew-widget-form__details-summary {
  385. border-bottom: 1px solid hsl(var(--border));
  386. }
  387. }
  388. &__details-summary {
  389. padding: 10px 14px;
  390. font-size: 0.8125rem;
  391. font-weight: 500;
  392. color: hsl(var(--foreground));
  393. cursor: pointer;
  394. user-select: none;
  395. list-style: none;
  396. display: flex;
  397. align-items: center;
  398. gap: 6px;
  399. transition: background-color 0.15s;
  400. &:hover {
  401. background: hsl(var(--accent) / 0.5);
  402. }
  403. &::before {
  404. content: '▸';
  405. font-size: 0.75rem;
  406. transition: transform 0.15s;
  407. }
  408. &::-webkit-details-marker {
  409. display: none;
  410. }
  411. }
  412. &__details[open] > .crew-widget-form__details-summary::before {
  413. transform: rotate(90deg);
  414. }
  415. &__details-body {
  416. display: flex;
  417. flex-direction: column;
  418. gap: 14px;
  419. padding: 14px;
  420. }
  421. // ── 버튼 ──
  422. &__btn {
  423. display: inline-flex;
  424. align-items: center;
  425. justify-content: center;
  426. padding: 8px 20px;
  427. border: 1px solid hsl(var(--border));
  428. border-radius: calc(var(--radius) - 2px);
  429. font-size: 0.875rem;
  430. font-weight: 500;
  431. cursor: pointer;
  432. background: hsl(var(--background));
  433. color: hsl(var(--foreground));
  434. transition: background-color 0.15s;
  435. &:hover:not(:disabled) {
  436. background: hsl(var(--accent));
  437. }
  438. &:disabled {
  439. opacity: 0.5;
  440. cursor: not-allowed;
  441. }
  442. &--primary {
  443. background: hsl(var(--primary));
  444. color: hsl(var(--primary-foreground));
  445. border-color: hsl(var(--primary));
  446. &:hover:not(:disabled) {
  447. background: hsl(var(--primary) / 0.9);
  448. }
  449. }
  450. }
  451. // ── 하단 버튼 ──
  452. &__footer {
  453. display: flex;
  454. gap: 8px;
  455. justify-content: center;
  456. padding-top: 20px;
  457. margin-top: 4px;
  458. }
  459. }
  460. // ── 반응형 ──
  461. @media (max-width: 1380px) {
  462. .crew-widget-form {
  463. &__section {
  464. grid-template-columns: 1fr;
  465. gap: 5px;
  466. }
  467. &__section-title {
  468. margin-bottom: 9px;
  469. }
  470. }
  471. }
  472. @media (max-width: 1120px) {
  473. .crew-widget-layout {
  474. grid-template-columns: minmax(130px, auto) auto 3fr;
  475. }
  476. }
  477. @media (max-width: 768px) {
  478. .crew-widget-layout {
  479. grid-template-columns: 1fr;
  480. }
  481. .crew-widget-preview {
  482. position: static;
  483. max-height: none;
  484. }
  485. .crew-widget-form {
  486. &__section {
  487. grid-template-columns: 1fr;
  488. gap: 8px;
  489. }
  490. &__section-title {
  491. margin-bottom: 12px;
  492. }
  493. &__section-body {
  494. max-width: none;
  495. }
  496. &__row {
  497. grid-template-columns: 1fr;
  498. }
  499. }
  500. }