gyeol 0.1.0 → 0.1.2

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.
Files changed (3) hide show
  1. package/README.md +23 -1
  2. package/gyeol.css +145 -136
  3. package/package.json +9 -1
package/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
  npm install gyeol
7
7
  ```
8
8
 
9
+ 소개 사이트: https://minjaek111.github.io/gyeol/
10
+
9
11
  | 파일 | 쓰는 곳 |
10
12
  | --- | --- |
11
13
  | `gyeol.css` | 아무 웹 프로젝트(HTML, React, Vue, Svelte 등). 토큰, 팔레트, 테마, 겹 소재, 컴포넌트 클래스가 모두 들어 있어요. |
@@ -16,7 +18,8 @@ npm install gyeol
16
18
 
17
19
  ```html
18
20
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Hahmlet:wght@300;500;700;800&family=IBM+Plex+Sans+KR:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap">
19
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gyeol@0.1.0/gyeol.css">
21
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gyeol@0.1.1/gyeol.css">
22
+ <!-- 또는 unpkg: <link rel="stylesheet" href="https://unpkg.com/gyeol@0.1.1/gyeol.css"> -->
20
23
 
21
24
  <html data-palette="meok" data-theme="dark">
22
25
  <body class="gy">
@@ -27,6 +30,13 @@ npm install gyeol
27
30
  </body>
28
31
  ```
29
32
 
33
+ CDN은 jsDelivr와 unpkg 중 하나를 쓰면 돼요. 버전을 빼고 `gyeol/gyeol.css`로 쓰면 항상 최신 버전을 불러오지만, 실제 서비스에서는 버전을 고정하는 게 안전해요.
34
+
35
+ | CDN | 주소 |
36
+ | --- | --- |
37
+ | jsDelivr | `https://cdn.jsdelivr.net/npm/gyeol@0.1.1/gyeol.css` |
38
+ | unpkg | `https://unpkg.com/gyeol@0.1.1/gyeol.css` |
39
+
30
40
  번들러(Vite, Next.js 등)를 쓰면 CSS를 이렇게 불러와요.
31
41
 
32
42
  ```js
@@ -41,6 +51,18 @@ color('meok', 'dark', 'accent'); // '#85aeff'
41
51
  - `data-palette`: `meok`(기본) · `jjok` · `cheongja` · `songhwa` · `yeonji` · `jaju`
42
52
  - `data-theme`: `dark`(기본) · `light` · `system`
43
53
  - 컴포넌트 클래스는 모두 `gy-` 접두사를 써서 기존 CSS와 겹치지 않아요.
54
+ - 화면 일부만 다른 팔레트나 테마로 바꿀 수 있어요(0.1.2부터). 그 범위 안의 색과 글자색이 모두 다시 계산돼요.
55
+
56
+ ```html
57
+ <html data-palette="meok" data-theme="dark">
58
+ <section data-palette="yeonji" data-theme="light">이 영역만 연지 · 라이트</section>
59
+ <section data-palette="cheongja">테마를 빼면 바깥 테마(다크)를 따라가요</section>
60
+ </html>
61
+ ```
62
+
63
+ ```js
64
+ setPalette('jaju', document.querySelector('#promo')); // 특정 요소에만 적용
65
+ ```
44
66
 
45
67
  | 컴포넌트 | 클래스 |
46
68
  | --- | --- |
package/gyeol.css CHANGED
@@ -1,136 +1,145 @@
1
- /*!
2
- * 결 gyeol — layered-paper design system
3
- * 사용법: <html data-palette="meok" data-theme="dark">
4
- * data-palette: meok | jjok | cheongja | songhwa | yeonji | jaju (기본 meok)
5
- * data-theme: dark | light | system (기본 dark)
6
- * 모든 컴포넌트 클래스는 gy- 접두사를 써서 다른 CSS와 충돌하지 않아요.
7
- * 글꼴: https://fonts.googleapis.com/css2?family=Hahmlet:wght@300;500;700;800&family=IBM+Plex+Sans+KR:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap
8
- */
9
-
10
- /* ---------- tokens ---------- */
11
- :root{
12
- --h:255; --c:.012; --ah:var(--h); --ac:var(--c);
13
- --bg: oklch(96.5% calc(var(--c)*.12) var(--h));
14
- --bg-2: oklch(92.5% calc(var(--c)*.22) var(--h));
15
- --ink: oklch(23% calc(var(--c)*.35) var(--h));
16
- --ink-2: oklch(43% calc(var(--c)*.25) var(--h));
17
- --ink-3: oklch(50% calc(var(--c)*.18) var(--h));
18
- --line: oklch(84% calc(var(--c)*.22) var(--h));
19
- --paper: oklch(99.2% calc(var(--c)*.05) var(--h));
20
- --accent: oklch(49% var(--ac) var(--ah));
21
- --accent-soft: oklch(90% calc(var(--ac)*.45) var(--ah));
22
- --on-accent: oklch(99% 0 0);
23
- --stain: oklch(80% calc(var(--c)*.9 + .03) calc(var(--h) + 70));
24
- --ok: oklch(50% .13 150); --warn: oklch(54% .13 65); --err: oklch(52% .19 25);
25
- --shadow: 0 1px 0 oklch(100% 0 0 / .7) inset, 0 18px 40px -22px oklch(25% .06 var(--h) / .35), 0 2px 6px -2px oklch(25% .04 var(--h) / .12);
26
- --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='a'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .32 0'/></filter><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='.012 .32' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 -.42'/></filter><rect width='100%' height='100%' filter='url(%23a)'/><rect width='100%' height='100%' filter='url(%23b)'/></svg>");
27
- --grain-o: .4;
28
-
29
- --f-display: "Hahmlet", "Nanum Myeongjo", "Apple SD Gothic Neo", serif;
30
- --f-body: "IBM Plex Sans KR", "Apple SD Gothic Neo", "Malgun Gothic", system-ui, sans-serif;
31
- --f-mono: "IBM Plex Mono", ui-monospace, "Consolas", monospace;
32
-
33
- --pun-1:4px; --pun-2:8px; --pun-3:12px; --pun-4:16px; --pun-6:24px; --pun-8:32px; --pun-12:48px; --pun-16:64px;
34
- --r-1:6px; --r-2:12px; --r-3:20px; --r-4:28px; --r-pill:999px;
35
- --ease-bleed: cubic-bezier(.2,.7,.2,1);
36
- --t-1:120ms; --t-2:220ms; --t-3:420ms;
37
- }
38
- @media (prefers-color-scheme: dark){ :root[data-theme="system"]{
39
- --bg: oklch(17% calc(var(--c)*.22) var(--h)); --bg-2: oklch(21% calc(var(--c)*.3) var(--h));
40
- --ink: oklch(95% calc(var(--c)*.08) var(--h)); --ink-2: oklch(79% calc(var(--c)*.15) var(--h)); --ink-3: oklch(70% calc(var(--c)*.15) var(--h));
41
- --line: oklch(33% calc(var(--c)*.25) var(--h)); --paper: oklch(29% calc(var(--c)*.25) var(--h));
42
- --accent: oklch(76% var(--ac) var(--ah)); --accent-soft: oklch(33% calc(var(--ac)*.55) var(--ah)); --on-accent: oklch(18% .03 var(--ah));
43
- --stain: oklch(48% calc(var(--c)*.9 + .03) calc(var(--h) + 70));
44
- --ok: oklch(74% .14 150); --warn: oklch(80% .13 75); --err: oklch(72% .16 25);
45
- --shadow: 0 1px 0 oklch(100% 0 0 / .07) inset, 0 20px 44px -20px oklch(5% .02 var(--h) / .7), 0 2px 6px -2px oklch(5% 0 0 / .4);
46
- --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='a'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .22 0'/></filter><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='.012 .32' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 -.4'/></filter><rect width='100%' height='100%' filter='url(%23a)'/><rect width='100%' height='100%' filter='url(%23b)'/></svg>");
47
- --grain-o: .35; color-scheme: dark;
48
- }}
49
- :root:not([data-theme="light"]):not([data-theme="system"]){
50
- --bg: oklch(17% calc(var(--c)*.22) var(--h)); --bg-2: oklch(21% calc(var(--c)*.3) var(--h));
51
- --ink: oklch(95% calc(var(--c)*.08) var(--h)); --ink-2: oklch(79% calc(var(--c)*.15) var(--h)); --ink-3: oklch(70% calc(var(--c)*.15) var(--h));
52
- --line: oklch(33% calc(var(--c)*.25) var(--h)); --paper: oklch(29% calc(var(--c)*.25) var(--h));
53
- --accent: oklch(76% var(--ac) var(--ah)); --accent-soft: oklch(33% calc(var(--ac)*.55) var(--ah)); --on-accent: oklch(18% .03 var(--ah));
54
- --stain: oklch(48% calc(var(--c)*.9 + .03) calc(var(--h) + 70));
55
- --ok: oklch(74% .14 150); --warn: oklch(80% .13 75); --err: oklch(72% .16 25);
56
- --shadow: 0 1px 0 oklch(100% 0 0 / .07) inset, 0 20px 44px -20px oklch(5% .02 var(--h) / .7), 0 2px 6px -2px oklch(5% 0 0 / .4);
57
- --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='a'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .22 0'/></filter><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='.012 .32' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 -.4'/></filter><rect width='100%' height='100%' filter='url(%23a)'/><rect width='100%' height='100%' filter='url(%23b)'/></svg>");
58
- --grain-o: .35; color-scheme: dark;
59
- }
60
- :root[data-palette="meok"] {--h:255;--c:.012;--ah:265;--ac:.14}
61
- :root[data-palette="jjok"] {--h:265;--c:.14}
62
- :root[data-palette="cheongja"]{--h:178;--c:.075}
63
- :root[data-palette="songhwa"] {--h:98; --c:.12}
64
- :root[data-palette="yeonji"] {--h:16; --c:.16}
65
- :root[data-palette="jaju"] {--h:330;--c:.13}
66
-
67
- /* ---------- base (opt-in: add class="gy" to <body>) ---------- */
68
- .gy{margin:0;color:var(--ink);background:var(--bg);font:400 16px/1.65 var(--f-body);-webkit-font-smoothing:antialiased}
69
- .gy :focus-visible{outline:2px solid var(--accent);outline-offset:3px;box-shadow:0 0 0 7px color-mix(in oklch, var(--accent) 22%, transparent)}
70
-
71
- /* ---------- material: 겹 ---------- */
72
- .gy-gyeop{position:relative;isolation:isolate;background:color-mix(in oklch, var(--paper) var(--thick,74%), transparent);-webkit-backdrop-filter:blur(var(--blur,14px)) saturate(1.2);backdrop-filter:blur(var(--blur,14px)) saturate(1.2);border:1px solid color-mix(in oklch, var(--paper) 50%, var(--line));border-radius:var(--r-3);box-shadow:var(--shadow)}
73
- .gy-gyeop::before{content:"";position:absolute;inset:0;border-radius:inherit;background-image:var(--grain);opacity:var(--grain-o);pointer-events:none;z-index:-1}
74
- .gy-hol{--thick:46%;--blur:6px}
75
- .gy-du {--thick:72%;--blur:14px}
76
- .gy-se {--thick:90%;--blur:24px}
77
-
78
- /* ---------- button ---------- */
79
- .gy-btn{--bg-b:var(--accent);--fg-b:var(--on-accent);appearance:none;border:0;cursor:pointer;font:600 15px/1 var(--f-body);color:var(--fg-b);background:var(--bg-b);padding:13px 20px;border-radius:var(--r-2);display:inline-flex;align-items:center;gap:8px;text-decoration:none;transition:transform var(--t-1) var(--ease-bleed), box-shadow var(--t-3) var(--ease-bleed)}
80
- .gy-btn:hover{box-shadow:0 0 0 1px var(--bg-b), 0 6px 22px -4px color-mix(in oklch, var(--bg-b) 60%, transparent)}
81
- .gy-btn:active{transform:translateY(1px) scale(.985)}
82
- .gy-btn--ink{--bg-b:var(--ink);--fg-b:var(--bg)}
83
- .gy-btn--paper{--fg-b:var(--ink);background:color-mix(in oklch, var(--paper) 74%, transparent);border:1px solid var(--line);backdrop-filter:blur(12px)}
84
- .gy-btn--paper:hover{box-shadow:0 6px 22px -8px color-mix(in oklch, var(--ink) 40%, transparent)}
85
- .gy-btn--ghost{--fg-b:var(--accent);background:transparent}
86
- .gy-btn--ghost:hover{background:color-mix(in oklch, var(--accent) 10%, transparent);box-shadow:none}
87
- .gy-btn--danger{--bg-b:var(--err);--fg-b:oklch(99% 0 0)}
88
- .gy-btn--sm{padding:9px 14px;font-size:14px;border-radius:10px}
89
- .gy-btn:disabled{opacity:.45;cursor:not-allowed;box-shadow:none}
90
-
91
- /* ---------- switch: <button class="gy-switch" role="switch" aria-checked="true"> ---------- */
92
- .gy-switch{appearance:none;border:0;cursor:pointer;width:50px;height:30px;border-radius:var(--r-pill);background:var(--line);position:relative;transition:background var(--t-2) var(--ease-bleed);flex:none}
93
- .gy-switch::after{content:"";position:absolute;top:3px;left:3px;width:24px;height:24px;border-radius:50%;background:var(--paper);box-shadow:0 2px 6px oklch(0% 0 0 / .25);transition:transform var(--t-2) var(--ease-bleed)}
94
- .gy-switch[aria-checked="true"]{background:var(--accent)}
95
- .gy-switch[aria-checked="true"]::after{transform:translateX(20px);background:oklch(99% 0 0)}
96
-
97
- /* ---------- segmented: buttons with aria-pressed ---------- */
98
- .gy-seg{display:inline-flex;padding:4px;border-radius:var(--r-pill);background:color-mix(in oklch, var(--ink) 7%, transparent);gap:2px}
99
- .gy-seg button{appearance:none;border:0;background:transparent;color:var(--ink-2);font:500 14px/1 var(--f-body);padding:8px 14px;border-radius:var(--r-pill);cursor:pointer}
100
- .gy-seg button[aria-pressed="true"]{background:var(--paper);color:var(--ink);box-shadow:0 1px 3px oklch(0% 0 0 / .14)}
101
-
102
- /* ---------- chip ---------- */
103
- .gy-chip{appearance:none;cursor:pointer;border:1px solid var(--line);background:transparent;color:var(--ink-2);font:500 14px/1 var(--f-body);padding:8px 13px;border-radius:var(--r-pill)}
104
- .gy-chip[aria-pressed="true"]{background:var(--accent-soft);border-color:transparent;color:var(--ink)}
105
-
106
- /* ---------- field ---------- */
107
- .gy-field{display:flex;flex-direction:column;gap:6px}
108
- .gy-field label{font-size:13px;font-weight:500;color:var(--ink-2)}
109
- .gy-field input,.gy-field textarea,.gy-field select{font:400 15px var(--f-body);color:var(--ink);background:color-mix(in oklch, var(--paper) 80%, transparent);border:1px solid var(--line);border-radius:var(--r-2);padding:11px 13px;transition:border-color var(--t-2), box-shadow var(--t-3) var(--ease-bleed)}
110
- .gy-field :is(input,textarea,select):focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 5px color-mix(in oklch, var(--accent) 18%, transparent), 0 0 18px 2px color-mix(in oklch, var(--accent) 22%, transparent)}
111
- .gy-field small{font-size:13px;color:var(--ink-3)}
112
- .gy-field--error :is(input,textarea,select){border-color:var(--err)}
113
- .gy-field--error small{color:var(--err)}
114
-
115
- /* ---------- checkbox: <label class="gy-check"><input type="checkbox"> 텍스트</label> ---------- */
116
- .gy-check{display:flex;gap:10px;align-items:center;font-size:15px;cursor:pointer}
117
- .gy-check input{appearance:none;width:20px;height:20px;border-radius:6px;border:1.5px solid var(--ink-3);display:grid;place-items:center;margin:0;cursor:pointer}
118
- .gy-check input:checked{background:var(--accent);border-color:var(--accent)}
119
- .gy-check input:checked::after{content:"";width:9px;height:5px;border:2px solid var(--on-accent);border-top:0;border-right:0;transform:rotate(-45deg) translate(1px,-1px)}
120
-
121
- /* ---------- badge ---------- */
122
- .gy-badge{font:600 12px/1 var(--f-body);padding:7px 11px;border-radius:var(--r-pill);display:inline-flex;align-items:center;gap:5px;color:var(--accent);background:color-mix(in oklch, var(--accent) 13%, transparent)}
123
- .gy-badge::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
124
- .gy-badge--ok{color:var(--ok);background:color-mix(in oklch, var(--ok) 14%, transparent)}
125
- .gy-badge--warn{color:var(--warn);background:color-mix(in oklch, var(--warn) 16%, transparent)}
126
- .gy-badge--err{color:var(--err);background:color-mix(in oklch, var(--err) 14%, transparent)}
127
-
128
- /* ---------- progress: <div class="gy-progress" style="--p:60%"><i></i></div> ---------- */
129
- .gy-progress{height:8px;border-radius:var(--r-pill);background:color-mix(in oklch, var(--ink) 9%, transparent);overflow:hidden}
130
- .gy-progress > i{display:block;height:100%;width:var(--p,0%);border-radius:inherit;background:linear-gradient(90deg, color-mix(in oklch, var(--accent) 50%, transparent), var(--accent))}
131
-
132
- /* ---------- toast / tooltip ---------- */
133
- .gy-toast{display:flex;align-items:center;gap:12px;padding:12px 16px;font-size:14.5px}
134
- .gy-tooltip{font-size:13px;padding:7px 11px;border-radius:10px;background:var(--ink);color:var(--bg)}
135
-
136
- @media (prefers-reduced-motion: reduce){.gy *,.gy *::before,.gy *::after{transition:none!important;animation:none!important}}
1
+ /*!
2
+ * 결 gyeol — layered-paper design system
3
+ * 사용법: <html data-palette="meok" data-theme="dark">
4
+ * data-palette: meok | jjok | cheongja | songhwa | yeonji | jaju (기본 meok)
5
+ * data-theme: dark | light | system (기본 dark)
6
+ * 화면 일부만 다른 팔레트·테마로: <section data-palette="yeonji" data-theme="light"> (0.1.2+)
7
+ * 모든 컴포넌트 클래스는 gy- 접두사를 써서 다른 CSS와 충돌하지 않아요.
8
+ * 글꼴: https://fonts.googleapis.com/css2?family=Hahmlet:wght@300;500;700;800&family=IBM+Plex+Sans+KR:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap
9
+ */
10
+
11
+ /* ---------- tokens ---------- */
12
+ :root{
13
+ --h:255; --c:.012; --ah:265; --ac:.14; /* 기본 팔레트: 먹 + 쪽빛 강조 */
14
+ --f-display: "Hahmlet", "Nanum Myeongjo", "Apple SD Gothic Neo", serif;
15
+ --f-body: "IBM Plex Sans KR", "Apple SD Gothic Neo", "Malgun Gothic", system-ui, sans-serif;
16
+ --f-mono: "IBM Plex Mono", ui-monospace, "Consolas", monospace;
17
+
18
+ --pun-1:4px; --pun-2:8px; --pun-3:12px; --pun-4:16px; --pun-6:24px; --pun-8:32px; --pun-12:48px; --pun-16:64px;
19
+ --r-1:6px; --r-2:12px; --r-3:20px; --r-4:28px; --r-pill:999px;
20
+ --ease-bleed: cubic-bezier(.2,.7,.2,1);
21
+ --t-1:120ms; --t-2:220ms; --t-3:420ms;
22
+
23
+ }
24
+ /* 색 토큰: 루트와, 팔레트·테마를 따로 지정한 모든 요소에서 다시 계산돼요 */
25
+ :root, [data-palette], [data-theme]{
26
+ --bg: oklch(96.5% calc(var(--c)*.12) var(--h));
27
+ --bg-2: oklch(92.5% calc(var(--c)*.22) var(--h));
28
+ --ink: oklch(23% calc(var(--c)*.35) var(--h));
29
+ --ink-2: oklch(43% calc(var(--c)*.25) var(--h));
30
+ --ink-3: oklch(50% calc(var(--c)*.18) var(--h));
31
+ --line: oklch(84% calc(var(--c)*.22) var(--h));
32
+ --paper: oklch(99.2% calc(var(--c)*.05) var(--h));
33
+ --accent: oklch(49% var(--ac) var(--ah));
34
+ --accent-soft: oklch(90% calc(var(--ac)*.45) var(--ah));
35
+ --on-accent: oklch(99% 0 0);
36
+ --stain: oklch(80% calc(var(--c)*.9 + .03) calc(var(--h) + 70));
37
+ --ok: oklch(50% .13 150); --warn: oklch(54% .13 65); --err: oklch(52% .19 25);
38
+ --shadow: 0 1px 0 oklch(100% 0 0 / .7) inset, 0 18px 40px -22px oklch(25% .06 var(--h) / .35), 0 2px 6px -2px oklch(25% .04 var(--h) / .12);
39
+ --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='a'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .32 0'/></filter><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='.012 .32' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .7 -.42'/></filter><rect width='100%' height='100%' filter='url(%23a)'/><rect width='100%' height='100%' filter='url(%23b)'/></svg>");
40
+ --grain-o: .4;
41
+
42
+ color-scheme: light;
43
+ }
44
+ @media (prefers-color-scheme: dark){ :root[data-theme="system"], :root[data-theme="system"] [data-palette]:not([data-theme]):not([data-theme="light"] *){
45
+ --bg: oklch(17% calc(var(--c)*.22) var(--h)); --bg-2: oklch(21% calc(var(--c)*.3) var(--h));
46
+ --ink: oklch(95% calc(var(--c)*.08) var(--h)); --ink-2: oklch(79% calc(var(--c)*.15) var(--h)); --ink-3: oklch(70% calc(var(--c)*.15) var(--h));
47
+ --line: oklch(33% calc(var(--c)*.25) var(--h)); --paper: oklch(29% calc(var(--c)*.25) var(--h));
48
+ --accent: oklch(76% var(--ac) var(--ah)); --accent-soft: oklch(33% calc(var(--ac)*.55) var(--ah)); --on-accent: oklch(18% .03 var(--ah));
49
+ --stain: oklch(48% calc(var(--c)*.9 + .03) calc(var(--h) + 70));
50
+ --ok: oklch(74% .14 150); --warn: oklch(80% .13 75); --err: oklch(72% .16 25);
51
+ --shadow: 0 1px 0 oklch(100% 0 0 / .07) inset, 0 20px 44px -20px oklch(5% .02 var(--h) / .7), 0 2px 6px -2px oklch(5% 0 0 / .4);
52
+ --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='a'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .22 0'/></filter><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='.012 .32' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 -.4'/></filter><rect width='100%' height='100%' filter='url(%23a)'/><rect width='100%' height='100%' filter='url(%23b)'/></svg>");
53
+ --grain-o: .35; color-scheme: dark;
54
+ }}
55
+ :root:not([data-theme="light"]):not([data-theme="system"]), [data-theme="dark"],
56
+ :root:not([data-theme="light"]):not([data-theme="system"]) [data-palette]:not([data-theme]):not([data-theme="light"] *){
57
+ --bg: oklch(17% calc(var(--c)*.22) var(--h)); --bg-2: oklch(21% calc(var(--c)*.3) var(--h));
58
+ --ink: oklch(95% calc(var(--c)*.08) var(--h)); --ink-2: oklch(79% calc(var(--c)*.15) var(--h)); --ink-3: oklch(70% calc(var(--c)*.15) var(--h));
59
+ --line: oklch(33% calc(var(--c)*.25) var(--h)); --paper: oklch(29% calc(var(--c)*.25) var(--h));
60
+ --accent: oklch(76% var(--ac) var(--ah)); --accent-soft: oklch(33% calc(var(--ac)*.55) var(--ah)); --on-accent: oklch(18% .03 var(--ah));
61
+ --stain: oklch(48% calc(var(--c)*.9 + .03) calc(var(--h) + 70));
62
+ --ok: oklch(74% .14 150); --warn: oklch(80% .13 75); --err: oklch(72% .16 25);
63
+ --shadow: 0 1px 0 oklch(100% 0 0 / .07) inset, 0 20px 44px -20px oklch(5% .02 var(--h) / .7), 0 2px 6px -2px oklch(5% 0 0 / .4);
64
+ --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='a'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .22 0'/></filter><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='.012 .32' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 -.4'/></filter><rect width='100%' height='100%' filter='url(%23a)'/><rect width='100%' height='100%' filter='url(%23b)'/></svg>");
65
+ --grain-o: .35; color-scheme: dark;
66
+ }
67
+ [data-palette="meok"] {--h:255;--c:.012;--ah:265;--ac:.14}
68
+ [data-palette="jjok"] {--h:265;--c:.14; --ah:265;--ac:.14}
69
+ [data-palette="cheongja"]{--h:178;--c:.075;--ah:178;--ac:.075}
70
+ [data-palette="songhwa"] {--h:98; --c:.12; --ah:98; --ac:.12}
71
+ [data-palette="yeonji"] {--h:16; --c:.16; --ah:16; --ac:.16}
72
+ [data-palette="jaju"] {--h:330;--c:.13; --ah:330;--ac:.13}
73
+ /* 화면 일부에 팔레트·테마를 따로 지정하면 글자색도 그 범위의 먹색을 따라가요 */
74
+ :where([data-palette], [data-theme]):not(:root){color:var(--ink)}
75
+
76
+ /* ---------- base (opt-in: add class="gy" to <body>) ---------- */
77
+ .gy{margin:0;color:var(--ink);background:var(--bg);font:400 16px/1.65 var(--f-body);-webkit-font-smoothing:antialiased}
78
+ .gy :focus-visible{outline:2px solid var(--accent);outline-offset:3px;box-shadow:0 0 0 7px color-mix(in oklch, var(--accent) 22%, transparent)}
79
+
80
+ /* ---------- material: 겹 ---------- */
81
+ .gy-gyeop{position:relative;isolation:isolate;background:color-mix(in oklch, var(--paper) var(--thick,74%), transparent);-webkit-backdrop-filter:blur(var(--blur,14px)) saturate(1.2);backdrop-filter:blur(var(--blur,14px)) saturate(1.2);border:1px solid color-mix(in oklch, var(--paper) 50%, var(--line));border-radius:var(--r-3);box-shadow:var(--shadow)}
82
+ .gy-gyeop::before{content:"";position:absolute;inset:0;border-radius:inherit;background-image:var(--grain);opacity:var(--grain-o);pointer-events:none;z-index:-1}
83
+ .gy-hol{--thick:46%;--blur:6px}
84
+ .gy-du {--thick:72%;--blur:14px}
85
+ .gy-se {--thick:90%;--blur:24px}
86
+
87
+ /* ---------- button ---------- */
88
+ .gy-btn{--bg-b:var(--accent);--fg-b:var(--on-accent);appearance:none;border:0;cursor:pointer;font:600 15px/1 var(--f-body);color:var(--fg-b);background:var(--bg-b);padding:13px 20px;border-radius:var(--r-2);display:inline-flex;align-items:center;gap:8px;text-decoration:none;transition:transform var(--t-1) var(--ease-bleed), box-shadow var(--t-3) var(--ease-bleed)}
89
+ .gy-btn:hover{box-shadow:0 0 0 1px var(--bg-b), 0 6px 22px -4px color-mix(in oklch, var(--bg-b) 60%, transparent)}
90
+ .gy-btn:active{transform:translateY(1px) scale(.985)}
91
+ .gy-btn--ink{--bg-b:var(--ink);--fg-b:var(--bg)}
92
+ .gy-btn--paper{--fg-b:var(--ink);background:color-mix(in oklch, var(--paper) 74%, transparent);border:1px solid var(--line);backdrop-filter:blur(12px)}
93
+ .gy-btn--paper:hover{box-shadow:0 6px 22px -8px color-mix(in oklch, var(--ink) 40%, transparent)}
94
+ .gy-btn--ghost{--fg-b:var(--accent);background:transparent}
95
+ .gy-btn--ghost:hover{background:color-mix(in oklch, var(--accent) 10%, transparent);box-shadow:none}
96
+ .gy-btn--danger{--bg-b:var(--err);--fg-b:oklch(99% 0 0)}
97
+ .gy-btn--sm{padding:9px 14px;font-size:14px;border-radius:10px}
98
+ .gy-btn:disabled{opacity:.45;cursor:not-allowed;box-shadow:none}
99
+
100
+ /* ---------- switch: <button class="gy-switch" role="switch" aria-checked="true"> ---------- */
101
+ .gy-switch{appearance:none;border:0;cursor:pointer;width:50px;height:30px;border-radius:var(--r-pill);background:var(--line);position:relative;transition:background var(--t-2) var(--ease-bleed);flex:none}
102
+ .gy-switch::after{content:"";position:absolute;top:3px;left:3px;width:24px;height:24px;border-radius:50%;background:var(--paper);box-shadow:0 2px 6px oklch(0% 0 0 / .25);transition:transform var(--t-2) var(--ease-bleed)}
103
+ .gy-switch[aria-checked="true"]{background:var(--accent)}
104
+ .gy-switch[aria-checked="true"]::after{transform:translateX(20px);background:oklch(99% 0 0)}
105
+
106
+ /* ---------- segmented: buttons with aria-pressed ---------- */
107
+ .gy-seg{display:inline-flex;padding:4px;border-radius:var(--r-pill);background:color-mix(in oklch, var(--ink) 7%, transparent);gap:2px}
108
+ .gy-seg button{appearance:none;border:0;background:transparent;color:var(--ink-2);font:500 14px/1 var(--f-body);padding:8px 14px;border-radius:var(--r-pill);cursor:pointer}
109
+ .gy-seg button[aria-pressed="true"]{background:var(--paper);color:var(--ink);box-shadow:0 1px 3px oklch(0% 0 0 / .14)}
110
+
111
+ /* ---------- chip ---------- */
112
+ .gy-chip{appearance:none;cursor:pointer;border:1px solid var(--line);background:transparent;color:var(--ink-2);font:500 14px/1 var(--f-body);padding:8px 13px;border-radius:var(--r-pill)}
113
+ .gy-chip[aria-pressed="true"]{background:var(--accent-soft);border-color:transparent;color:var(--ink)}
114
+
115
+ /* ---------- field ---------- */
116
+ .gy-field{display:flex;flex-direction:column;gap:6px}
117
+ .gy-field label{font-size:13px;font-weight:500;color:var(--ink-2)}
118
+ .gy-field input,.gy-field textarea,.gy-field select{font:400 15px var(--f-body);color:var(--ink);background:color-mix(in oklch, var(--paper) 80%, transparent);border:1px solid var(--line);border-radius:var(--r-2);padding:11px 13px;transition:border-color var(--t-2), box-shadow var(--t-3) var(--ease-bleed)}
119
+ .gy-field :is(input,textarea,select):focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 5px color-mix(in oklch, var(--accent) 18%, transparent), 0 0 18px 2px color-mix(in oklch, var(--accent) 22%, transparent)}
120
+ .gy-field small{font-size:13px;color:var(--ink-3)}
121
+ .gy-field--error :is(input,textarea,select){border-color:var(--err)}
122
+ .gy-field--error small{color:var(--err)}
123
+
124
+ /* ---------- checkbox: <label class="gy-check"><input type="checkbox"> 텍스트</label> ---------- */
125
+ .gy-check{display:flex;gap:10px;align-items:center;font-size:15px;cursor:pointer}
126
+ .gy-check input{appearance:none;width:20px;height:20px;border-radius:6px;border:1.5px solid var(--ink-3);display:grid;place-items:center;margin:0;cursor:pointer}
127
+ .gy-check input:checked{background:var(--accent);border-color:var(--accent)}
128
+ .gy-check input:checked::after{content:"";width:9px;height:5px;border:2px solid var(--on-accent);border-top:0;border-right:0;transform:rotate(-45deg) translate(1px,-1px)}
129
+
130
+ /* ---------- badge ---------- */
131
+ .gy-badge{font:600 12px/1 var(--f-body);padding:7px 11px;border-radius:var(--r-pill);display:inline-flex;align-items:center;gap:5px;color:var(--accent);background:color-mix(in oklch, var(--accent) 13%, transparent)}
132
+ .gy-badge::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
133
+ .gy-badge--ok{color:var(--ok);background:color-mix(in oklch, var(--ok) 14%, transparent)}
134
+ .gy-badge--warn{color:var(--warn);background:color-mix(in oklch, var(--warn) 16%, transparent)}
135
+ .gy-badge--err{color:var(--err);background:color-mix(in oklch, var(--err) 14%, transparent)}
136
+
137
+ /* ---------- progress: <div class="gy-progress" style="--p:60%"><i></i></div> ---------- */
138
+ .gy-progress{height:8px;border-radius:var(--r-pill);background:color-mix(in oklch, var(--ink) 9%, transparent);overflow:hidden}
139
+ .gy-progress > i{display:block;height:100%;width:var(--p,0%);border-radius:inherit;background:linear-gradient(90deg, color-mix(in oklch, var(--accent) 50%, transparent), var(--accent))}
140
+
141
+ /* ---------- toast / tooltip ---------- */
142
+ .gy-toast{display:flex;align-items:center;gap:12px;padding:12px 16px;font-size:14.5px}
143
+ .gy-tooltip{font-size:13px;padding:7px 11px;border-radius:10px;background:var(--ink);color:var(--bg)}
144
+
145
+ @media (prefers-reduced-motion: reduce){.gy *,.gy *::before,.gy *::after{transition:none!important;animation:none!important}}
package/package.json CHANGED
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "name": "gyeol",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "결 gyeol — 한지를 겹겹이 올리는 디자인 시스템. CSS, Tailwind preset, DTCG design tokens.",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/minjaeK111/gyeol.git"
9
+ },
10
+ "homepage": "https://minjaek111.github.io/gyeol/",
11
+ "bugs": {
12
+ "url": "https://github.com/minjaeK111/gyeol/issues"
13
+ },
6
14
  "type": "module",
7
15
  "main": "./index.cjs",
8
16
  "module": "./index.mjs",