kwon-ui 0.1.0 → 0.2.0
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/CATALOG.md +31 -10
- package/CHANGELOG.md +30 -0
- package/README.md +2 -2
- package/claude/ADOPTING.md +15 -7
- package/dist/classes.json +8 -1
- package/dist/kwon-ui.css +89 -4
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +2 -2
- package/dist/react/layout.d.ts +14 -2
- package/dist/react/layout.js +14 -3
- package/dist/react/tone.d.ts +5 -0
- package/dist/react/tone.js +8 -0
- package/dist/react/type.d.ts +4 -2
- package/dist/react/type.js +4 -4
- package/package.json +2 -2
package/CATALOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# kwon-ui 카탈로그
|
|
2
2
|
|
|
3
|
-
버전 0.
|
|
3
|
+
버전 0.2.0. 이 파일은 `npm run build` 가 `src/catalog/manifest.tsx` 에서 만든다. 직접 고치지 않는다.
|
|
4
4
|
|
|
5
5
|
화면을 만들기 전에 이 목록에서 고른다. 여기 없는 조각이 필요하면 페이지에서 새로 만들지 않고, kwon-ui 에 추가를 제안한다.
|
|
6
6
|
|
|
@@ -23,16 +23,17 @@ import { Page, PageHead, Section, SectionHead, Rows, Row, Pill, TextLink } from
|
|
|
23
23
|
|---|---|---|---|
|
|
24
24
|
| 첫 화면 제목 | `<Display>` | `.n-display` | 첫 화면의 제목. 한 페이지에 한 번만 씁니다. |
|
|
25
25
|
| 구간 제목 | `<Title>` | `.n-title` | 구간과 페이지의 제목. 한 문장 한 줄로 쓰고, ** 로 감싼 핵심 낱말 한두 개만 진하게 둡니다. |
|
|
26
|
-
| 본문 | `<Body>` | `.n-body` | 읽는 문단. 한 구간에 한두 문단까지 둡니다. |
|
|
26
|
+
| 본문 | `<Body>` | `.n-body` | 읽는 문단. 한 구간에 한두 문단까지 둡니다. 목록에서 줄마다 먼저 읽혀야 하는 낱말(기관 이름)은 line 에 ** 로 감싸 진하게 둡니다. 작은 글 안에서도 같은 hi 를 씁니다. |
|
|
27
27
|
| 작은 제목 | `<CardTitle>` | `.n-card-title` | 목록 줄이나 카드 안의 제목. 본문과 같은 크기이고 진한 글자입니다. |
|
|
28
28
|
| 작은 글 | `<Small>` | `.n-small` | 캡션, 기준, 라벨. 숫자 폭을 맞춰야 하면 num 을 줍니다. |
|
|
29
29
|
| 페이지와 페이지 머리 | `<Page>` `<PageHead>` | `.n-page` | 하위 페이지의 맨 바깥과 머리. 제목 한 줄, 문단 하나, 버튼 줄로 시작합니다. |
|
|
30
|
-
| 구간 | `<Section>` | `.n-sect` | 페이지를 이루는 구간 하나. 위아래 여백(넓은 화면 128/96px)과 내용 폭을 줍니다. |
|
|
30
|
+
| 구간 | `<Section>` | `.n-sect` | 페이지를 이루는 구간 하나. 위아래 여백(넓은 화면 128/96px)과 내용 폭을 줍니다. rule 은 앞 구간과의 사이에 가는 선을 내용 폭만큼 긋습니다. slim 은 문장 하나와 버튼 하나뿐인 짧은 구간의 여백(넓은 화면 80px)입니다. |
|
|
31
31
|
| 구간 머리 | `<SectionHead>` | `.n-head` | 구간의 시작. 왼쪽에 한 줄 제목, 오른쪽에 본문. rule 을 주면 가는 선 아래에서 시작합니다. |
|
|
32
32
|
| 가는 선 | (클래스만) | `.n-rule` | 내용 위에 가는 선 하나를 긋습니다. 구간 머리의 선은 SectionHead 의 rule 로 긋습니다. |
|
|
33
|
-
| 줄 목록 | `<Rows>` `<Row>` | `.n-rows` | 항목이 여럿일 때. 왼쪽 200px 에 작은 라벨, 오른쪽에 본문 한 칸. |
|
|
33
|
+
| 줄 목록 | `<Rows>` `<Row>` | `.n-rows` | 항목이 여럿일 때. 왼쪽 200px 에 작은 라벨, 오른쪽에 본문 한 칸. 라벨과 본문은 첫 줄의 글자 밑선이 맞습니다. |
|
|
34
34
|
| 검은 판 | `<Panel>` | `.n-panel` | 앞뒤 구간과 구분해야 하는 구간 하나(후기, 수강료처럼). 한 페이지에 두세 번까지. |
|
|
35
35
|
| 그림 틀 | `<Media>` | `.n-media` | 그림과 영상을 담는 틀. 기본 4:3, wide 는 16:9. 안의 img, video 가 틀을 채웁니다. |
|
|
36
|
+
| 사진 판 | `<PhotoPanel>` | `.n-photo` | 어둡게 누른 사진 위 왼쪽 아래에 제목 한 줄과 문단 하나를 둡니다. 강의 현장처럼 사진이 내용인 구간에 씁니다. media 에 img 나 video 를 넘기면 판을 채웁니다. |
|
|
36
37
|
| 연도별 이력 | (클래스만) | `.n-timeline` | 해마다 쌓인 이력. 왼쪽에 연도, 오른쪽에 그 해의 줄들. 많으면 앞의 몇 줄만 보이고 '외 N건'으로 접습니다. |
|
|
37
38
|
| 문의 띠 | `<CtaBand>` | `.n-cta-band` | 페이지 끝의 마지막 행동. 왼쪽에 한 줄 문장, 오른쪽에 버튼 줄. 한 페이지에 하나. |
|
|
38
39
|
| 알약 버튼 | `<Pill>` | `.n-pill` | 한 화면의 주 행동 하나. 높이 48px. ghost 는 어두운 면(둘째 행동이 꼭 버튼이어야 할 때). |
|
|
@@ -65,12 +66,13 @@ import { Page, PageHead, Section, SectionHead, Rows, Row, Pill, TextLink } from
|
|
|
65
66
|
|
|
66
67
|
### 본문
|
|
67
68
|
|
|
68
|
-
`<Body>` · `.n-body`
|
|
69
|
+
`<Body>` · `.n-body` `.hi`
|
|
69
70
|
|
|
70
|
-
읽는 문단. 한 구간에 한두 문단까지 둡니다.
|
|
71
|
+
읽는 문단. 한 구간에 한두 문단까지 둡니다. 목록에서 줄마다 먼저 읽혀야 하는 낱말(기관 이름)은 line 에 ** 로 감싸 진하게 둡니다. 작은 글 안에서도 같은 hi 를 씁니다. 문단마다 강조를 넣는 데 쓰지 않습니다. 굵기는 바꾸지 않고 색만 올립니다.
|
|
71
72
|
|
|
72
73
|
```tsx
|
|
73
74
|
<Body>현재 업무와 자료를 함께 살펴보고 먼저 만들 것을 정합니다.</Body>
|
|
75
|
+
<Body as="li" line="**○○전자** 임원 AI 워크숍" />
|
|
74
76
|
```
|
|
75
77
|
|
|
76
78
|
### 작은 제목
|
|
@@ -117,15 +119,18 @@ import { Page, PageHead, Section, SectionHead, Rows, Row, Pill, TextLink } from
|
|
|
117
119
|
|
|
118
120
|
### 구간
|
|
119
121
|
|
|
120
|
-
`<Section>` · `.n-sect` `.n-wrap`
|
|
122
|
+
`<Section>` · `.n-sect` `.n-wrap` `.ruled` `.slim`
|
|
121
123
|
|
|
122
|
-
페이지를 이루는 구간 하나. 위아래 여백(넓은 화면 128/96px)과 내용 폭을 줍니다. 여백을 구간마다 따로 정하지 않습니다.
|
|
124
|
+
페이지를 이루는 구간 하나. 위아래 여백(넓은 화면 128/96px)과 내용 폭을 줍니다. rule 은 앞 구간과의 사이에 가는 선을 내용 폭만큼 긋습니다. slim 은 문장 하나와 버튼 하나뿐인 짧은 구간의 여백(넓은 화면 80px)입니다. 여백을 구간마다 따로 정하지 않습니다. 구간 머리에 선이 있으면(SectionHead 의 rule) 구간에는 긋지 않습니다.
|
|
123
125
|
|
|
124
126
|
```tsx
|
|
125
|
-
<Section id="courses">
|
|
127
|
+
<Section id="courses" rule>
|
|
126
128
|
<SectionHead title="**직무별** 교육 과정" />
|
|
127
129
|
…
|
|
128
130
|
</Section>
|
|
131
|
+
<Section id="team" slim rule>
|
|
132
|
+
…
|
|
133
|
+
</Section>
|
|
129
134
|
```
|
|
130
135
|
|
|
131
136
|
### 구간 머리
|
|
@@ -154,7 +159,7 @@ import { Page, PageHead, Section, SectionHead, Rows, Row, Pill, TextLink } from
|
|
|
154
159
|
|
|
155
160
|
`<Rows>`, `<Row>` · `.n-rows` `.n-row` `.n-row-label` `.wide-label`
|
|
156
161
|
|
|
157
|
-
항목이 여럿일 때. 왼쪽 200px 에 작은 라벨, 오른쪽에 본문 한 칸. 한 줄을 번호, 이름, 설명 세 칸으로 나누지 않습니다.
|
|
162
|
+
항목이 여럿일 때. 왼쪽 200px 에 작은 라벨, 오른쪽에 본문 한 칸. 라벨과 본문은 첫 줄의 글자 밑선이 맞습니다. 한 줄을 번호, 이름, 설명 세 칸으로 나누지 않습니다.
|
|
158
163
|
|
|
159
164
|
```tsx
|
|
160
165
|
<Rows as="ol">
|
|
@@ -188,6 +193,19 @@ import { Page, PageHead, Section, SectionHead, Rows, Row, Pill, TextLink } from
|
|
|
188
193
|
</Media>
|
|
189
194
|
```
|
|
190
195
|
|
|
196
|
+
### 사진 판
|
|
197
|
+
|
|
198
|
+
`<PhotoPanel>` · `.n-photo` `.n-photo-in`
|
|
199
|
+
|
|
200
|
+
어둡게 누른 사진 위 왼쪽 아래에 제목 한 줄과 문단 하나를 둡니다. 강의 현장처럼 사진이 내용인 구간에 씁니다. media 에 img 나 video 를 넘기면 판을 채웁니다. 한 페이지에 하나까지 둡니다. 글이 길면 사진 판에 넣지 않습니다.
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
<PhotoPanel media={<Image src="/hall.jpg" alt="강의 현장" fill sizes="100vw" />}>
|
|
204
|
+
<Title line="**강의 현장**에서 다듬은 과정입니다" label="강사" />
|
|
205
|
+
<Body>실습에 쓰는 자료와 순서는 수업을 거치며 고쳐 왔습니다.</Body>
|
|
206
|
+
</PhotoPanel>
|
|
207
|
+
```
|
|
208
|
+
|
|
191
209
|
### 연도별 이력
|
|
192
210
|
|
|
193
211
|
`.n-timeline` `.n-tl-year` `.n-tl-more` `.chev`
|
|
@@ -287,6 +305,9 @@ import { Page, PageHead, Section, SectionHead, Rows, Row, Pill, TextLink } from
|
|
|
287
305
|
| `--n-ghost` | `rgba(255, 255, 255, 0.08)` |
|
|
288
306
|
| `--n-ghost-hover` | `rgba(255, 255, 255, 0.16)` |
|
|
289
307
|
| `--n-focus` | `rgba(255, 255, 255, 0.55)` |
|
|
308
|
+
| `--n-shade` | `rgba(0, 0, 0, 0.82)` |
|
|
309
|
+
| `--n-shade-soft` | `rgba(0, 0, 0, 0.1)` |
|
|
310
|
+
| `--n-on-photo` | `rgba(255, 255, 255, 0.62)` |
|
|
290
311
|
| `--n-fs-display` | `clamp(34px, 3.8vw, 50px)` |
|
|
291
312
|
| `--n-fs-title` | `clamp(26px, 2.4vw, 32px)` |
|
|
292
313
|
| `--n-fs-body` | `18px` |
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# 바뀐 것
|
|
2
2
|
|
|
3
|
+
## 0.2.0 (2026-11-16)
|
|
4
|
+
|
|
5
|
+
스킬캠퍼스에 넣으면서 앱이 덧붙여 쓰던 여섯 가지를 올렸다. 없어진 이름은 없다.
|
|
6
|
+
|
|
7
|
+
더한 것
|
|
8
|
+
|
|
9
|
+
- 선으로 시작하는 구간: `.n-sect.ruled`, `<Section rule>`. 앞 구간과의 사이에 가는 선을 내용 폭만큼 긋는다.
|
|
10
|
+
- 짧은 구간: `.n-sect.slim`, `<Section slim>`. 문장 하나와 버튼 하나뿐인 줄. 위아래 64px, 넓은 화면 80px.
|
|
11
|
+
- 본문 안의 진한 낱말: `.hi`, `hi()`, `<Body line>`. `n-body`와 `n-small` 안에서 색만 올린다. 굵기는 그대로다.
|
|
12
|
+
- 사진 판: `.n-photo`, `.n-photo-in`, `<PhotoPanel>`. 어둡게 누른 사진 위 왼쪽 아래에 글을 둔다.
|
|
13
|
+
- 토큰 셋(모두 30개): `--n-shade`, `--n-shade-soft`(사진 위의 그늘), `--n-on-photo`(사진 위에서 받쳐 주는 말).
|
|
14
|
+
|
|
15
|
+
바뀐 값
|
|
16
|
+
|
|
17
|
+
- 줄 목록 `.n-row`: 라벨과 본문의 첫 줄 밑선을 맞춘다(`align-items: baseline`). 본문 칸은 `minmax(0, 1fr)`이라 긴 낱말이 칸을 밀지 않는다.
|
|
18
|
+
- 글자 링크 `.n-link`: 줄 높이를 1.6으로 정했다. 앱의 바탕 줄 높이를 물려받아 앱마다 높이가 달랐다(홈페이지 24px, 스킬캠퍼스 24.75px).
|
|
19
|
+
|
|
20
|
+
근거
|
|
21
|
+
|
|
22
|
+
- 구간 선: 스킬캠퍼스 세 페이지의 구간 17곳. Projects 랜딩에도 같은 자리에 선이 있다(그쪽은 선이 바깥 여백까지 닿는다).
|
|
23
|
+
- 짧은 구간: 스킬캠퍼스 세 페이지의 구간 5곳.
|
|
24
|
+
- 줄 목록: 스킬캠퍼스와 Projects 랜딩이 둘 다 밑선 맞춤과 `minmax(0, 1fr)`을 덧붙여 쓰고 있었다.
|
|
25
|
+
- 진한 낱말: 연도별 이력의 기관 이름. 홈페이지는 유틸리티(`text-white`)로, 스킬캠퍼스는 `b`에 규칙을 덧붙여 쓰고 있었다.
|
|
26
|
+
- 사진 판: 홈페이지의 교육 문의 판(`.n-closing`)과 스킬캠퍼스의 강사 판. 그늘, 사진을 누르는 정도, 안쪽 여백, 넓은 화면 높이(560px)는 두 곳이 같다. 두 곳이 다른 값은 스킬캠퍼스 쪽을 따랐다: 좁은 화면 높이 480px, 제목과 문단 사이 16px, 사진 위 회색 글자 62%.
|
|
27
|
+
|
|
28
|
+
확인
|
|
29
|
+
|
|
30
|
+
- 스킬캠퍼스 공개 네 페이지를 0.1.0과 0.2.0에서 요소별로 대조했다(화면 폭 390·768·1024·1440). 앱의 덧붙임을 지우고도 세 페이지는 차이가 없고, 한 페이지에서 글자 링크 두 곳의 높이만 1px 줄었다. 사진 판은 픽셀이 같다.
|
|
31
|
+
- 홈페이지 원본 CSS와 계산된 스타일을 대조했다. 넣을 때 달라지는 값은 `claude/ADOPTING.md`의 '넣을 때 알아 둘 차이'에 적었다.
|
|
32
|
+
|
|
3
33
|
## 0.1.0 (2026-11-16)
|
|
4
34
|
|
|
5
35
|
첫 판. kwonandcompany.com 밤 테마에서 여러 화면이 같이 쓰는 핵심만 값 그대로 옮겼다.
|
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ npm install kwon-ui --save-exact
|
|
|
8
8
|
|
|
9
9
|
## 들어 있는 것
|
|
10
10
|
|
|
11
|
-
- **토큰과 CSS** (`kwon-ui/kwon-ui.css`): 색, 글자 크기 셋, 모서리, 폭. 글자(`n-title`, `n-body`, `n-small`), 뼈대(`n-sect`, `n-head`, `n-rows`, `n-panel`), 조작부(`n-pill`, `n-link`).
|
|
12
|
-
- **컴포넌트** (`kwon-ui`): `Page`, `PageHead`, `Section`, `SectionHead`, `Rows`, `Row`, `Panel`, `Media`, `CtaBand`, `Pill`, `TextLink`, `Actions`, `Title`, `Body`, `Small` 등. 서버에서 그려지는 평범한 마크업입니다.
|
|
11
|
+
- **토큰과 CSS** (`kwon-ui/kwon-ui.css`): 색, 글자 크기 셋, 모서리, 폭. 글자(`n-title`, `n-body`, `n-small`), 뼈대(`n-sect`, `n-head`, `n-rows`, `n-panel`, `n-photo`), 조작부(`n-pill`, `n-link`).
|
|
12
|
+
- **컴포넌트** (`kwon-ui`): `Page`, `PageHead`, `Section`, `SectionHead`, `Rows`, `Row`, `Panel`, `Media`, `PhotoPanel`, `CtaBand`, `Pill`, `TextLink`, `Actions`, `Title`, `Body`, `Small` 등. 서버에서 그려지는 평범한 마크업입니다.
|
|
13
13
|
- **목록** ([CATALOG.md](CATALOG.md)): 조각마다 언제 쓰는지와 사용 예. 화면을 만들기 전에 먼저 읽습니다.
|
|
14
14
|
- **검사기** (`kwon-ui check`): 앱 코드에서 색·글자 값을 직접 쓴 곳, 시스템 조각을 다시 정의한 곳을 찾습니다. 이미 있는 위반은 기준선에 적어 두고 늘어날 때만 실패합니다.
|
|
15
15
|
|
package/claude/ADOPTING.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## 1. 설치
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install kwon-ui@0.
|
|
8
|
+
npm install kwon-ui@0.2.0 --save-exact
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
정확한 버전을 고정합니다. 올릴 때는 `CHANGELOG.md`를 읽고 한 앱씩 올립니다.
|
|
@@ -22,7 +22,10 @@ import "./globals.css";
|
|
|
22
22
|
- 앱의 CSS가 `@layer`로 묶여 있고 kwon-ui도 같은 층에 넣어야 하면 CSS에서 `@import "kwon-ui/kwon-ui.css" layer(components);`로 부릅니다.
|
|
23
23
|
- 층 없이 부르면 kwon-ui의 규칙이 Tailwind 유틸리티보다 우선합니다. 그래서 조각에는 margin과 폭이 없습니다.
|
|
24
24
|
- 페이지 맨 바깥에 `.night`가 있어야 합니다.
|
|
25
|
-
-
|
|
25
|
+
- Next.js 16과 Tailwind 4에서 `@import "kwon-ui/kwon-ui.css" layer(components);`가 개발 서버(webpack)와 운영 빌드(Turbopack) 모두에서 되는 것을 확인했습니다(스킬캠퍼스, 2026-11-16). 컴포넌트와 `tone()`도 서버 컴포넌트에서 그대로 불러와 씁니다.
|
|
26
|
+
- 같은 층에 넣으면 특이도와 순서가 그대로 적용됩니다. kwon-ui의 규칙은 `.night .n-…`(클래스 둘)이라, 같은 요소에 붙은 앱의 한 클래스짜리 규칙(`.cp-offer { padding-top: … }`)은 집니다. 앱 쪽을 `.n-sect.cp-offer`처럼 클래스 둘로 씁니다.
|
|
27
|
+
- `.night`는 글자색을 흰색으로 둡니다. 앱의 기본 글자색이 다르면 바깥 요소에서 한 번 정합니다(`.cp.night { color: var(--n-soft); }`).
|
|
28
|
+
- 개발 서버가 떠 있는 채로 브랜치를 바꿔 CSS 파일이 사라졌다 생기면 옛 CSS가 남습니다. 불러오는 CSS 파일을 한 번 저장(touch)하면 다시 만들어집니다.
|
|
26
29
|
|
|
27
30
|
## 3. 앱에 있던 같은 정의 지우기
|
|
28
31
|
|
|
@@ -70,7 +73,7 @@ npx kwon-ui baseline
|
|
|
70
73
|
|
|
71
74
|
## 6. Claude Code 훅
|
|
72
75
|
|
|
73
|
-
파일을 저장할 때마다 그 파일만 검사해서, 위반이 늘었으면 내용을 모델에게 바로 돌려줍니다. 작업 공간의 Claude Code 설정(`.claude/settings.json`)에 한 번 겁니다.
|
|
76
|
+
파일을 저장할 때마다 그 파일만 검사해서, 위반이 늘었으면 내용을 모델에게 바로 돌려줍니다. 작업 공간의 Claude Code 설정(`.claude/settings.json`)에 한 번 겁니다. 아래 모양으로 걸어 실제로 되돌아오는 것을 확인했습니다(2026-11-16).
|
|
74
77
|
|
|
75
78
|
```json
|
|
76
79
|
{
|
|
@@ -78,7 +81,7 @@ npx kwon-ui baseline
|
|
|
78
81
|
"PostToolUse": [
|
|
79
82
|
{
|
|
80
83
|
"matcher": "Edit|Write",
|
|
81
|
-
"hooks": [{ "type": "command", "command": "node /경로/kwon-ui/claude/hook.mjs" }]
|
|
84
|
+
"hooks": [{ "type": "command", "command": "command -v node >/dev/null 2>&1 || exit 0; node /경로/kwon-ui/claude/hook.mjs", "timeout": 20 }]
|
|
82
85
|
}
|
|
83
86
|
]
|
|
84
87
|
}
|
|
@@ -91,9 +94,14 @@ npx kwon-ui baseline
|
|
|
91
94
|
|
|
92
95
|
[APP-CLAUDE.md](APP-CLAUDE.md)의 문구를 앱의 CLAUDE.md에 넣습니다.
|
|
93
96
|
|
|
97
|
+
## 넣기 전과 후를 대조하는 법
|
|
98
|
+
|
|
99
|
+
넣기 전의 화면에서 모든 요소의 자리(x, y, 폭, 높이)와 계산된 스타일을 기록해 두고, 넣은 뒤 같은 방법으로 기록해 요소 순서대로 맞춰 봅니다. 화면 폭은 390, 768, 1024, 1440 네 가지로 잽니다. 같은 화면을 두 번 재서 차이가 0인지 먼저 확인합니다(움직이는 조각은 빼고 잽니다). 남는 차이가 kwon-ui의 값을 받아들인 것뿐이면 끝입니다. 스킬캠퍼스는 이 방법으로 네 페이지를 대조했고, 페이지 길이 차이는 16,000px 가운데 4px 안팎이었습니다.
|
|
100
|
+
|
|
94
101
|
## 넣을 때 알아 둘 차이
|
|
95
102
|
|
|
96
|
-
0.1.0
|
|
103
|
+
값의 기준은 kwonandcompany.com입니다. 0.1.0은 계산된 스타일이 홈페이지와 같고, 0.2.0에서 아래 두 가지가 달라졌습니다. 다른 두 제품은 손으로 옮기면서 생긴 작은 차이가 있어, 넣으면 그만큼 바뀝니다.
|
|
97
104
|
|
|
98
|
-
-
|
|
99
|
-
-
|
|
105
|
+
- kwonandcompany.com: 줄 목록의 라벨이 본문 첫 줄의 밑선에 맞춰져 넓은 화면에서 4px 내려갑니다(`items-baseline`을 이미 준 줄은 그대로입니다). 교육 문의의 사진 판(`n-closing`)을 `n-photo`로 바꾸면 1024px 미만에서 최소 높이가 560px → 480px, 제목과 문단 사이가 20px → 16px, 제목의 회색 글자가 50% → 62%가 됩니다. 문단과 버튼 줄 사이는 버튼 줄을 `n-actions`로 두면 40px 그대로입니다. 사진 판 안의 `mt-5`, `mt-10`은 뺍니다.
|
|
106
|
+
- Projects 랜딩: 제목 줄 간격 1.25 → 1.2, 본문 1.55 → 1.5, 알약 버튼 글자 사이 0.01em과 간격 10px, 글자 링크 간격 8px, 구간 머리의 세로 정렬(위 → 가운데). 구간 사이의 선(`n-sect n-rule`)을 `n-sect ruled`로 바꾸면 선이 바깥 여백만큼 짧아져 내용 폭과 같아집니다.
|
|
107
|
+
- 스킬캠퍼스(2026-11-16 공개 네 페이지에 넣음): 변수 이름을 바꿨습니다(`--hi`, `--mid`, `--line` 등 → `--n-hi`, `--n-mid`, `--n-line`). 바뀐 값은 작은 글 줄 간격 1.5 → 1.45, 글자 링크의 줄 높이 1.4 → 1.6, 줄 목록 라벨의 글자 사이 0, 검은 판의 z-index 1입니다. 0.2.0으로 올리면서 앱이 덧붙여 쓰던 규칙(구간 선, 짧은 구간, 줄 목록의 첫 줄 맞춤, 진한 낱말, 사진 판)을 지웠습니다.
|
package/dist/classes.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.2.0",
|
|
3
3
|
"scope": "night",
|
|
4
4
|
"classes": [
|
|
5
5
|
"n-actions",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"n-page",
|
|
15
15
|
"n-page-head",
|
|
16
16
|
"n-panel",
|
|
17
|
+
"n-photo",
|
|
18
|
+
"n-photo-in",
|
|
17
19
|
"n-pill",
|
|
18
20
|
"n-row",
|
|
19
21
|
"n-row-label",
|
|
@@ -31,9 +33,11 @@
|
|
|
31
33
|
"modifiers": [
|
|
32
34
|
"chev",
|
|
33
35
|
"ghost",
|
|
36
|
+
"hi",
|
|
34
37
|
"lo",
|
|
35
38
|
"lo-inline",
|
|
36
39
|
"ruled",
|
|
40
|
+
"slim",
|
|
37
41
|
"wide",
|
|
38
42
|
"wide-label"
|
|
39
43
|
],
|
|
@@ -53,6 +57,9 @@
|
|
|
53
57
|
"--n-ghost",
|
|
54
58
|
"--n-ghost-hover",
|
|
55
59
|
"--n-focus",
|
|
60
|
+
"--n-shade",
|
|
61
|
+
"--n-shade-soft",
|
|
62
|
+
"--n-on-photo",
|
|
56
63
|
"--n-fs-display",
|
|
57
64
|
"--n-fs-title",
|
|
58
65
|
"--n-fs-body",
|
package/dist/kwon-ui.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* kwon-ui 0.
|
|
1
|
+
/* kwon-ui 0.2.0. 이 파일은 빌드 결과다. 앱에서 고치지 않는다. 원본: src/css/ */
|
|
2
2
|
|
|
3
3
|
/* ── tokens.css ── */
|
|
4
4
|
/*
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
--n-ghost-hover: rgba(255, 255, 255, 0.16);
|
|
29
29
|
--n-focus: rgba(255, 255, 255, 0.55);
|
|
30
30
|
|
|
31
|
+
/* 사진 위: 글 뒤를 누르는 그늘 두 단계, 사진 위에서 받쳐 주는 말의 색 */
|
|
32
|
+
--n-shade: rgba(0, 0, 0, 0.82);
|
|
33
|
+
--n-shade-soft: rgba(0, 0, 0, 0.1);
|
|
34
|
+
--n-on-photo: rgba(255, 255, 255, 0.62);
|
|
35
|
+
|
|
31
36
|
/* 글자 크기. 읽는 글은 제목, 본문, 작은 글 셋이다. display 는 첫 화면 제목, control 은 버튼과 링크 */
|
|
32
37
|
--n-fs-display: clamp(34px, 3.8vw, 50px);
|
|
33
38
|
--n-fs-title: clamp(26px, 2.4vw, 32px);
|
|
@@ -143,6 +148,10 @@ html:has(.night) body {
|
|
|
143
148
|
letter-spacing: 0;
|
|
144
149
|
color: var(--n-mid);
|
|
145
150
|
}
|
|
151
|
+
/* 본문과 작은 글 안의 진한 낱말(기관 이름, 핵심 구절). 굵기는 그대로 두고 색만 올린다 */
|
|
152
|
+
.night :is(.n-body, .n-small) .hi {
|
|
153
|
+
color: var(--n-hi);
|
|
154
|
+
}
|
|
146
155
|
/* 숫자가 세로로 줄이 맞아야 하는 곳(연도, 금액) */
|
|
147
156
|
.night .n-num {
|
|
148
157
|
font-variant-numeric: tabular-nums;
|
|
@@ -188,6 +197,25 @@ html:has(.night) body {
|
|
|
188
197
|
}
|
|
189
198
|
}
|
|
190
199
|
|
|
200
|
+
/* 짧은 구간: 문장 하나와 버튼 하나뿐인 줄 */
|
|
201
|
+
.night .n-sect.slim {
|
|
202
|
+
padding-block: 64px;
|
|
203
|
+
}
|
|
204
|
+
@media (min-width: 1024px) {
|
|
205
|
+
.night .n-sect.slim {
|
|
206
|
+
padding-block: 80px;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/* 선으로 시작하는 구간: 앞 구간과의 사이에 가는 선을 내용 폭만큼 긋는다 */
|
|
210
|
+
.night .n-sect.ruled::before {
|
|
211
|
+
content: "";
|
|
212
|
+
position: absolute;
|
|
213
|
+
top: 0;
|
|
214
|
+
left: max(var(--n-gutter), calc(50% - var(--n-wrap) / 2 + var(--n-gutter)));
|
|
215
|
+
right: max(var(--n-gutter), calc(50% - var(--n-wrap) / 2 + var(--n-gutter)));
|
|
216
|
+
border-top: 1px solid var(--n-line);
|
|
217
|
+
}
|
|
218
|
+
|
|
191
219
|
/* 가는 선 하나(위쪽) */
|
|
192
220
|
.night .n-rule {
|
|
193
221
|
border-top: 1px solid var(--n-line);
|
|
@@ -232,23 +260,24 @@ html:has(.night) body {
|
|
|
232
260
|
margin-bottom: 0;
|
|
233
261
|
}
|
|
234
262
|
|
|
235
|
-
/* 줄 목록: 왼쪽 200px 라벨, 오른쪽
|
|
263
|
+
/* 줄 목록: 왼쪽 200px 라벨, 오른쪽 본문. 라벨과 본문은 첫 줄의 글자 밑선을 맞추고, 긴 낱말이 칸을 밀지 않게 한다 */
|
|
236
264
|
.night .n-rows {
|
|
237
265
|
border-top: 1px solid var(--n-line);
|
|
238
266
|
}
|
|
239
267
|
.night .n-row {
|
|
240
268
|
display: grid;
|
|
241
269
|
gap: 8px 24px;
|
|
270
|
+
align-items: baseline;
|
|
242
271
|
padding: 24px 0;
|
|
243
272
|
border-bottom: 1px solid var(--n-line);
|
|
244
273
|
}
|
|
245
274
|
@media (min-width: 768px) {
|
|
246
275
|
.night .n-row {
|
|
247
|
-
grid-template-columns: 200px 1fr;
|
|
276
|
+
grid-template-columns: 200px minmax(0, 1fr);
|
|
248
277
|
padding: 28px 0;
|
|
249
278
|
}
|
|
250
279
|
.night .n-row.wide-label {
|
|
251
|
-
grid-template-columns: 280px 1fr;
|
|
280
|
+
grid-template-columns: 280px minmax(0, 1fr);
|
|
252
281
|
}
|
|
253
282
|
}
|
|
254
283
|
.night .n-row > .n-row-label {
|
|
@@ -305,6 +334,60 @@ html:has(.night) body {
|
|
|
305
334
|
object-fit: cover;
|
|
306
335
|
}
|
|
307
336
|
|
|
337
|
+
/* 사진 판: 어둡게 누른 사진 위 왼쪽 아래에 글. 사진(img, video)은 판을 채운다.
|
|
338
|
+
쌓이는 순서(사진, 그늘, 글)는 판 안에 가둔다(isolation). 글의 z-index 가 판 밖의 요소와 겨루지 않는다 */
|
|
339
|
+
.night .n-photo {
|
|
340
|
+
position: relative;
|
|
341
|
+
isolation: isolate;
|
|
342
|
+
overflow: hidden;
|
|
343
|
+
display: flex;
|
|
344
|
+
align-items: flex-end;
|
|
345
|
+
min-height: 480px;
|
|
346
|
+
border-radius: var(--n-radius);
|
|
347
|
+
background: var(--n-card);
|
|
348
|
+
}
|
|
349
|
+
@media (min-width: 1024px) {
|
|
350
|
+
.night .n-photo {
|
|
351
|
+
min-height: 560px;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
.night .n-photo > img,
|
|
355
|
+
.night .n-photo > video {
|
|
356
|
+
position: absolute;
|
|
357
|
+
inset: 0;
|
|
358
|
+
width: 100%;
|
|
359
|
+
height: 100%;
|
|
360
|
+
object-fit: cover;
|
|
361
|
+
filter: saturate(0.8) brightness(0.62);
|
|
362
|
+
}
|
|
363
|
+
.night .n-photo::after {
|
|
364
|
+
content: "";
|
|
365
|
+
position: absolute;
|
|
366
|
+
inset: 0;
|
|
367
|
+
background: linear-gradient(to top, var(--n-shade), var(--n-shade-soft) 65%);
|
|
368
|
+
}
|
|
369
|
+
.night .n-photo-in {
|
|
370
|
+
position: relative;
|
|
371
|
+
z-index: 1;
|
|
372
|
+
display: grid;
|
|
373
|
+
gap: 16px;
|
|
374
|
+
padding: 40px 28px;
|
|
375
|
+
max-width: 640px;
|
|
376
|
+
}
|
|
377
|
+
@media (min-width: 1024px) {
|
|
378
|
+
.night .n-photo-in {
|
|
379
|
+
padding: 64px;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/* 사진 위에서는 받쳐 주는 말을 조금 밝게 둔다(50% 회색은 사진 위에서 묻힌다) */
|
|
383
|
+
.night .n-photo .n-title .lo-inline {
|
|
384
|
+
color: var(--n-on-photo);
|
|
385
|
+
}
|
|
386
|
+
/* 판 안에 버튼 줄이 있으면 문단과 40px 띄운다(안쪽 간격 16px에 더한다) */
|
|
387
|
+
.night .n-photo-in > .n-actions {
|
|
388
|
+
margin-top: 24px;
|
|
389
|
+
}
|
|
390
|
+
|
|
308
391
|
/* 문의 띠: 왼쪽 문장, 오른쪽 버튼 */
|
|
309
392
|
.night .n-cta-band {
|
|
310
393
|
display: grid;
|
|
@@ -368,6 +451,8 @@ html:has(.night) body {
|
|
|
368
451
|
align-items: center;
|
|
369
452
|
gap: 8px;
|
|
370
453
|
font-size: var(--n-fs-control);
|
|
454
|
+
/* 줄 높이를 물려받지 않고 정한다(앱마다 바탕 줄 높이가 달라 링크 높이가 달라졌다) */
|
|
455
|
+
line-height: 1.6;
|
|
371
456
|
font-weight: 500;
|
|
372
457
|
color: var(--n-hi);
|
|
373
458
|
transition: opacity 0.2s;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { tone, titleText } from "./tone.js";
|
|
1
|
+
export { tone, titleText, hi } from "./tone.js";
|
|
2
2
|
export { cx } from "./util.js";
|
|
3
3
|
export type { PolyProps } from "./util.js";
|
|
4
4
|
export { Display, Title, Body, CardTitle, Small } from "./type.js";
|
|
5
|
-
export { Page, PageHead, Section, SectionHead, Rows, Row, Panel, Media, CtaBand } from "./layout.js";
|
|
5
|
+
export { Page, PageHead, Section, SectionHead, Rows, Row, Panel, Media, PhotoPanel, CtaBand } from "./layout.js";
|
|
6
6
|
export { Pill, TextLink, Actions } from "./controls.js";
|
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { tone, titleText } from "./tone.js";
|
|
1
|
+
export { tone, titleText, hi } from "./tone.js";
|
|
2
2
|
export { cx } from "./util.js";
|
|
3
3
|
export { Display, Title, Body, CardTitle, Small } from "./type.js";
|
|
4
|
-
export { Page, PageHead, Section, SectionHead, Rows, Row, Panel, Media, CtaBand } from "./layout.js";
|
|
4
|
+
export { Page, PageHead, Section, SectionHead, Rows, Row, Panel, Media, PhotoPanel, CtaBand } from "./layout.js";
|
|
5
5
|
export { Pill, TextLink, Actions } from "./controls.js";
|
package/dist/react/layout.d.ts
CHANGED
|
@@ -17,9 +17,14 @@ export declare function PageHead({ title, label, lead, actions, className, child
|
|
|
17
17
|
className?: string;
|
|
18
18
|
children?: ReactNode;
|
|
19
19
|
}): import("react").JSX.Element;
|
|
20
|
-
/**
|
|
21
|
-
|
|
20
|
+
/**
|
|
21
|
+
* 구간. 안쪽은 내용 폭(1064px)으로 감싼다. bare 를 주면 감싸지 않는다(화면 끝까지 쓰는 내용).
|
|
22
|
+
* rule 은 앞 구간과의 사이에 가는 선을 긋고, slim 은 문장 하나와 버튼 하나뿐인 짧은 구간의 여백을 준다.
|
|
23
|
+
*/
|
|
24
|
+
export declare function Section<T extends ElementType = "section">({ as, bare, rule, slim, className, children, ...rest }: PolyProps<T, BoxProps & {
|
|
22
25
|
bare?: boolean;
|
|
26
|
+
rule?: boolean;
|
|
27
|
+
slim?: boolean;
|
|
23
28
|
}>): import("react").JSX.Element;
|
|
24
29
|
/** 구간 머리: 왼쪽에 한 줄 제목, 오른쪽에 본문(children). 본문이 없으면 제목이 한 줄 전체를 쓴다. */
|
|
25
30
|
export declare function SectionHead({ title, label, rule, as, className, children, }: {
|
|
@@ -45,6 +50,13 @@ export declare function Panel<T extends ElementType = "section">({ as, className
|
|
|
45
50
|
export declare function Media<T extends ElementType = "div">({ as, wide, className, ...rest }: PolyProps<T, BoxProps & {
|
|
46
51
|
wide?: boolean;
|
|
47
52
|
}>): import("react").JSX.Element;
|
|
53
|
+
/**
|
|
54
|
+
* 사진 판. 어둡게 누른 사진 위 왼쪽 아래에 제목과 문단을 둔다. media 에 img 나 video(프레임워크의 이미지 컴포넌트)를 넘긴다.
|
|
55
|
+
* 한 페이지에 하나, 밝은 곳이 필요한 자리에 쓴다.
|
|
56
|
+
*/
|
|
57
|
+
export declare function PhotoPanel<T extends ElementType = "div">({ as, media, className, children, ...rest }: PolyProps<T, BoxProps & {
|
|
58
|
+
media?: ReactNode;
|
|
59
|
+
}>): import("react").JSX.Element;
|
|
48
60
|
/** 문의 띠: 왼쪽 한 줄 문장(과 짧은 문단), 오른쪽 버튼 줄. 페이지 끝에 하나 둔다. */
|
|
49
61
|
export declare function CtaBand({ title, label, body, actions, className, }: {
|
|
50
62
|
title: string;
|
package/dist/react/layout.js
CHANGED
|
@@ -10,10 +10,13 @@ export function Page({ as, className, ...rest }) {
|
|
|
10
10
|
export function PageHead({ title, label, lead, actions, className, children, }) {
|
|
11
11
|
return (_jsxs("header", { className: cx("n-wrap n-page-head", className), children: [_jsxs("div", { className: "n-head", children: [_jsx("h1", { className: "n-title", children: titleText(title, label) }), lead ? _jsx("p", { className: "n-body", children: lead }) : null] }), actions ? _jsx("div", { className: "n-actions", children: actions }) : null, children] }));
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* 구간. 안쪽은 내용 폭(1064px)으로 감싼다. bare 를 주면 감싸지 않는다(화면 끝까지 쓰는 내용).
|
|
15
|
+
* rule 은 앞 구간과의 사이에 가는 선을 긋고, slim 은 문장 하나와 버튼 하나뿐인 짧은 구간의 여백을 준다.
|
|
16
|
+
*/
|
|
17
|
+
export function Section({ as, bare, rule, slim, className, children, ...rest }) {
|
|
15
18
|
const Tag = as ?? "section";
|
|
16
|
-
return (_jsx(Tag, { className: cx("n-sect", className), ...rest, children: bare ? children : _jsx("div", { className: "n-wrap", children: children }) }));
|
|
19
|
+
return (_jsx(Tag, { className: cx("n-sect", slim && "slim", rule && "ruled", className), ...rest, children: bare ? children : _jsx("div", { className: "n-wrap", children: children }) }));
|
|
17
20
|
}
|
|
18
21
|
/** 구간 머리: 왼쪽에 한 줄 제목, 오른쪽에 본문(children). 본문이 없으면 제목이 한 줄 전체를 쓴다. */
|
|
19
22
|
export function SectionHead({ title, label, rule, as, className, children, }) {
|
|
@@ -41,6 +44,14 @@ export function Media({ as, wide, className, ...rest }) {
|
|
|
41
44
|
const Tag = as ?? "div";
|
|
42
45
|
return _jsx(Tag, { className: cx("n-media", wide && "wide", className), ...rest });
|
|
43
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* 사진 판. 어둡게 누른 사진 위 왼쪽 아래에 제목과 문단을 둔다. media 에 img 나 video(프레임워크의 이미지 컴포넌트)를 넘긴다.
|
|
49
|
+
* 한 페이지에 하나, 밝은 곳이 필요한 자리에 쓴다.
|
|
50
|
+
*/
|
|
51
|
+
export function PhotoPanel({ as, media, className, children, ...rest }) {
|
|
52
|
+
const Tag = as ?? "div";
|
|
53
|
+
return (_jsxs(Tag, { className: cx("n-photo", className), ...rest, children: [media, _jsx("div", { className: "n-photo-in", children: children })] }));
|
|
54
|
+
}
|
|
44
55
|
/** 문의 띠: 왼쪽 한 줄 문장(과 짧은 문단), 오른쪽 버튼 줄. 페이지 끝에 하나 둔다. */
|
|
45
56
|
export function CtaBand({ title, label, body, actions, className, }) {
|
|
46
57
|
const heading = _jsx("h2", { className: "n-title", children: titleText(title, label) });
|
package/dist/react/tone.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ import { type ReactNode } from "react";
|
|
|
6
6
|
* label 을 주면 화면 낭독기만 읽는 구간 이름을 앞에 붙인다(보이는 문장에 구간 이름이 없을 때).
|
|
7
7
|
*/
|
|
8
8
|
export declare function tone(line: string, label?: string): ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* 본문 안의 진한 낱말. 글은 "**진한 낱말** 나머지" 꼴로 쓴다.
|
|
11
|
+
* ** 로 감싼 곳만 진한 글자(.hi)이고, 나머지는 본문 기본색 그대로다. n-body 나 n-small 안에서 쓴다.
|
|
12
|
+
*/
|
|
13
|
+
export declare function hi(line: string): ReactNode;
|
|
9
14
|
/**
|
|
10
15
|
* 제목 글. ** 표시가 있으면 두 톤으로, 없으면 전부 진한 글자로 그린다.
|
|
11
16
|
* (tone 은 표시가 없는 글을 전부 회색으로 그리므로, 표시 없는 제목은 이 함수를 거친다.)
|
package/dist/react/tone.js
CHANGED
|
@@ -10,6 +10,14 @@ export function tone(line, label) {
|
|
|
10
10
|
const parts = line.split(/(\*\*[^*]+\*\*)/).filter(Boolean);
|
|
11
11
|
return (_jsxs(_Fragment, { children: [label ? _jsxs("span", { className: "n-sr", children: [label, ". "] }) : null, parts.map((p, i) => p.startsWith("**") && p.endsWith("**") ? (_jsx(Fragment, { children: p.slice(2, -2) }, i)) : (_jsx("span", { className: "lo-inline", children: p }, i)))] }));
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* 본문 안의 진한 낱말. 글은 "**진한 낱말** 나머지" 꼴로 쓴다.
|
|
15
|
+
* ** 로 감싼 곳만 진한 글자(.hi)이고, 나머지는 본문 기본색 그대로다. n-body 나 n-small 안에서 쓴다.
|
|
16
|
+
*/
|
|
17
|
+
export function hi(line) {
|
|
18
|
+
const parts = line.split(/(\*\*[^*]+\*\*)/).filter(Boolean);
|
|
19
|
+
return (_jsx(_Fragment, { children: parts.map((p, i) => p.startsWith("**") && p.endsWith("**") ? (_jsx("span", { className: "hi", children: p.slice(2, -2) }, i)) : (_jsx(Fragment, { children: p }, i))) }));
|
|
20
|
+
}
|
|
13
21
|
/**
|
|
14
22
|
* 제목 글. ** 표시가 있으면 두 톤으로, 없으면 전부 진한 글자로 그린다.
|
|
15
23
|
* (tone 은 표시가 없는 글을 전부 회색으로 그리므로, 표시 없는 제목은 이 함수를 거친다.)
|
package/dist/react/type.d.ts
CHANGED
|
@@ -16,8 +16,10 @@ type TextProps = {
|
|
|
16
16
|
className?: string;
|
|
17
17
|
children?: ReactNode;
|
|
18
18
|
};
|
|
19
|
-
/** 본문. */
|
|
20
|
-
export declare function Body<T extends ElementType = "p">({ as, className, ...rest }: PolyProps<T, TextProps
|
|
19
|
+
/** 본문. line 을 주면 "**진한 낱말** 나머지" 꼴에서 ** 로 감싼 곳만 진하게 그린다. */
|
|
20
|
+
export declare function Body<T extends ElementType = "p">({ as, line, className, children, ...rest }: PolyProps<T, TextProps & {
|
|
21
|
+
line?: string;
|
|
22
|
+
}>): import("react").JSX.Element;
|
|
21
23
|
/** 목록이나 카드 안의 작은 제목. 본문과 같은 크기이고 진한 글자다. */
|
|
22
24
|
export declare function CardTitle<T extends ElementType = "h3">({ as, className, ...rest }: PolyProps<T, TextProps>): import("react").JSX.Element;
|
|
23
25
|
/** 작은 글: 캡션, 기준, 라벨. num 을 주면 숫자 폭을 맞춘다. */
|
package/dist/react/type.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { titleText } from "./tone.js";
|
|
2
|
+
import { hi, titleText } from "./tone.js";
|
|
3
3
|
import { cx } from "./util.js";
|
|
4
4
|
/** 첫 화면 제목. 한 페이지에 한 번만 쓴다. */
|
|
5
5
|
export function Display({ as, line, label, className, children, ...rest }) {
|
|
@@ -11,10 +11,10 @@ export function Title({ as, line, label, className, children, ...rest }) {
|
|
|
11
11
|
const Tag = as ?? "h2";
|
|
12
12
|
return (_jsx(Tag, { className: cx("n-title", className), ...rest, children: children ?? (line ? titleText(line, label) : null) }));
|
|
13
13
|
}
|
|
14
|
-
/** 본문. */
|
|
15
|
-
export function Body({ as, className, ...rest }) {
|
|
14
|
+
/** 본문. line 을 주면 "**진한 낱말** 나머지" 꼴에서 ** 로 감싼 곳만 진하게 그린다. */
|
|
15
|
+
export function Body({ as, line, className, children, ...rest }) {
|
|
16
16
|
const Tag = as ?? "p";
|
|
17
|
-
return _jsx(Tag, { className: cx("n-body", className), ...rest });
|
|
17
|
+
return (_jsx(Tag, { className: cx("n-body", className), ...rest, children: children ?? (line ? hi(line) : null) }));
|
|
18
18
|
}
|
|
19
19
|
/** 목록이나 카드 안의 작은 제목. 본문과 같은 크기이고 진한 글자다. */
|
|
20
20
|
export function CardTitle({ as, className, ...rest }) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kwon-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "권앤컴퍼니의 세 제품(홈페이지, 스킬캠퍼스, Projects)이 같이 쓰는 디자인 시스템: 토큰, 글자, 뼈대, 컴포넌트, 검사기",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"bin": {
|
|
27
|
-
"kwon-ui": "
|
|
27
|
+
"kwon-ui": "bin/kwon-ui.mjs"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
30
|
"dist",
|