@madeinbruno/atelier 0.2.0 → 0.5.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/README.md +10 -4
- package/dist/index.d.ts +3 -8
- package/dist/index.js +6 -7
- package/package.json +1 -1
- package/styles.css +20 -19
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ React 18 이상이 필요해요.
|
|
|
14
14
|
|
|
15
15
|
### `Tag` — 공용 푸터
|
|
16
16
|
|
|
17
|
-
흰 옷 택(행택) 모양의 푸터예요. 택 위쪽에 한 줄 박음질이 있고,
|
|
17
|
+
흰 옷 택(행택) 모양의 푸터예요. 택 위쪽에 한 줄 박음질이 있고, 픽셀 글씨 `madeinbruno`, `SERVICE / CONTACT`가 들어가요 (`href`를 주면 밑줄 친 링크도).
|
|
18
18
|
|
|
19
19
|
```tsx
|
|
20
20
|
import { Tag } from '@madeinbruno/atelier';
|
|
@@ -27,15 +27,17 @@ export default function Footer() {
|
|
|
27
27
|
|
|
28
28
|
| prop | 기본값 | 설명 |
|
|
29
29
|
|---|---|---|
|
|
30
|
-
| `service` (필수) | | 택의
|
|
30
|
+
| `service` (필수) | | 택의 SERVICE 줄. 서비스 이름 |
|
|
31
31
|
| `email` | `pbk575@gmail.com` | CONTACT 줄 (mailto 링크) |
|
|
32
|
-
| `href` |
|
|
32
|
+
| `href` | 없음 | 택 아래 링크 (밑줄 친 주소). 주지 않으면 링크를 그리지 않아요. madeinbruno.com이 생기면 기본값으로 넣을 예정 |
|
|
33
33
|
| `since` | `EST. 2026` | 택 오른쪽 위 작은 글씨 |
|
|
34
34
|
| `eyebrow`, `message` | "Thanks for stopping by", "이 사이트도 madeinbruno에서 만들었어요." | 택 왼쪽 글. 둘 다 비우면 택만 가운데에 |
|
|
35
35
|
| `background` | `#f4f1ea` | 푸터 바탕. 서비스 바탕색에 맞추기 |
|
|
36
36
|
| `stitch` | `#9a948b` (회색) | 박음질 색 |
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
`madeinbruno` 글씨는 [Banquise](https://gitlab.com/bonjour-monde/fonderie/banquise-typeface)(Bonjour Monde, SIL Open Font License 1.1)로 쓴 글자를 SVG 그림으로 옮긴 거예요. 이 한 단어에만 쓰는 폰트라 폰트 파일을 싣지 않아요 (15KB → 1KB 미만, 글씨가 늦게 바뀌는 깜빡임도 없음).
|
|
39
|
+
|
|
40
|
+
색은 CSS 변수(`--mib-ground`, `--mib-stitch`, `--mib-ink`)로도 바꿀 수 있어요. 클래스는 모두 `mib-`로 시작해 서비스 스타일과 겹치지 않아요. 글꼴(IBM Plex Mono, 택 옆 글의 Archivo)은 `styles.css`가 Google Fonts에서 불러와요.
|
|
39
41
|
|
|
40
42
|
## 개발
|
|
41
43
|
|
|
@@ -49,6 +51,10 @@ pnpm --filter @madeinbruno/atelier dev # 고칠 때마다 다시 빌드
|
|
|
49
51
|
GitHub Actions(`.github/workflows/publish-atelier.yml`)가 배포해요.
|
|
50
52
|
|
|
51
53
|
1. 고친 뒤 `package.json`의 `version`을 올려서 `main`에 푸시해요 (버전을 안 올리면 건너뛰어요).
|
|
54
|
+
|
|
55
|
+
버전은 이렇게 올려요:
|
|
56
|
+
- **패치** (0.4.0 → 0.4.1): 모양·문구·여백 수정, 버그 수정. 쓰는 쪽 코드는 그대로.
|
|
57
|
+
- **마이너** (0.4.x → 0.5.0): 새 prop·새 컴포넌트처럼 기능이 늘어날 때. 1.0 전에는 쓰는 쪽 코드를 고쳐야 하는 변경(prop 이름 변경·삭제)도 마이너로 올리고, 1.0 이후에는 메이저로 올려요.
|
|
52
58
|
2. Actions가 빌드해서 npm 승인 대기열(staged)에 올려요.
|
|
53
59
|
3. npmjs.com에서 그 버전을 승인(2단계 인증)하면 공개돼요.
|
|
54
60
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
type TagProps = {
|
|
5
|
-
/** 이 서비스의 이름. 택의
|
|
5
|
+
/** 이 서비스의 이름. 택의 SERVICE 줄에 들어간다 (예: "hangoutwithme"). */
|
|
6
6
|
service: string;
|
|
7
7
|
/** 연락받을 이메일. 택의 CONTACT 줄에 mailto 링크로 들어간다. */
|
|
8
8
|
email?: string;
|
|
9
|
-
/** 택 아래 링크(밑줄 친 주소)가 가는 곳.
|
|
9
|
+
/** 택 아래 링크(밑줄 친 주소)가 가는 곳. 주지 않으면 링크를 그리지 않는다.
|
|
10
|
+
* madeinbruno.com이 아직 없어서 기본은 링크 없음. 사이트가 생기면 기본값을 'https://madeinbruno.com'으로 바꾼다. */
|
|
10
11
|
href?: string;
|
|
11
12
|
/** 택 오른쪽 위의 작은 글씨. */
|
|
12
13
|
since?: string;
|
|
@@ -19,12 +20,6 @@ type TagProps = {
|
|
|
19
20
|
stitch?: string;
|
|
20
21
|
className?: string;
|
|
21
22
|
};
|
|
22
|
-
/**
|
|
23
|
-
* madeinbruno 공용 푸터: 흰 옷 택(행택).
|
|
24
|
-
* 택 위쪽에 한 줄 박음질, 모서리를 깎은 모양이고, 옷 택 형식으로
|
|
25
|
-
* MADE IN BRUNO / STYLE(서비스 이름) / SIZE / CONTACT(이메일)와 madeinbruno.com 링크를 담는다.
|
|
26
|
-
* 스타일은 '@madeinbruno/atelier/styles.css'를 한 번 불러와야 적용된다.
|
|
27
|
-
*/
|
|
28
23
|
declare function Tag({ service, email, href, since, eyebrow, message, background, stitch, className, }: TagProps): react.JSX.Element;
|
|
29
24
|
|
|
30
25
|
export { Tag, type TagProps };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// src/Tag.tsx
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
var WORDMARK = "M18 0h2v2h-2zM27 0h2v1h-2zM36 0h2v2h-2zM0 2h1v1h-1zM2 2h2v1h-2zM5 2h2v1h-2zM9 2h4v1h-4zM17 2h3v1h-3zM22 2h3v1h-3zM27 2h2v6h-2zM30 2h1v1h-1zM32 2h2v1h-2zM36 2h4v1h-4zM42 2h1v1h-1zM44 2h2v1h-2zM50 2h2v5h-2zM53 2h1v1h-1zM55 2h2v1h-2zM60 2h3v1h-3zM0 3h2v5h-2zM3 3h2v5h-2zM6 3h2v5h-2zM9 3h2v1h-2zM12 3h2v2h-2zM15 3h2v4h-2zM18 3h2v4h-2zM21 3h2v1h-2zM24 3h2v1h-2zM30 3h2v5h-2zM33 3h2v5h-2zM36 3h2v4h-2zM39 3h2v4h-2zM42 3h4v1h-4zM47 3h2v4h-2zM53 3h2v5h-2zM56 3h2v5h-2zM62 3h2v4h-2zM21 4h5v1h-5zM42 4h2v4h-2zM59 4h2v3h-2zM9 5h5v1h-5zM21 5h2v2h-2zM9 6h2v1h-2zM12 6h2v1h-2zM25 6h1v1h-1zM10 7h2v1h-2zM13 7h1v1h-1zM16 7h2v1h-2zM19 7h1v1h-1zM23 7h2v1h-2zM36 7h1v1h-1zM38 7h1v1h-1zM48 7h2v1h-2zM51 7h1v1h-1zM61 7h2v1h-2z";
|
|
3
4
|
function Tag({
|
|
4
5
|
service,
|
|
5
6
|
email = "pbk575@gmail.com",
|
|
6
|
-
href
|
|
7
|
+
href,
|
|
7
8
|
since = "EST. 2026",
|
|
8
9
|
eyebrow = "Thanks for stopping by",
|
|
9
10
|
message = `\uC774 \uC0AC\uC774\uD2B8\uB3C4 madeinbruno\uC5D0\uC11C \uB9CC\uB4E4\uC5C8\uC5B4\uC694.`,
|
|
@@ -16,7 +17,7 @@ function Tag({
|
|
|
16
17
|
...stitch ? { "--mib-stitch": stitch } : {}
|
|
17
18
|
};
|
|
18
19
|
const hasMessage = Boolean(eyebrow || message);
|
|
19
|
-
const linkLabel = href
|
|
20
|
+
const linkLabel = href?.replace(/^https?:\/\//, "").replace(/\/$/, "");
|
|
20
21
|
return /* @__PURE__ */ jsx("footer", { className: ["mib-footer", className].filter(Boolean).join(" "), style, children: /* @__PURE__ */ jsxs("div", { className: hasMessage ? "mib-footer__inner" : "mib-footer__inner mib-footer__inner--solo", children: [
|
|
21
22
|
hasMessage && /* @__PURE__ */ jsxs("div", { className: "mib-footer__message", children: [
|
|
22
23
|
eyebrow && /* @__PURE__ */ jsx("p", { className: "mib-footer__eyebrow", children: eyebrow }),
|
|
@@ -25,18 +26,16 @@ function Tag({
|
|
|
25
26
|
/* @__PURE__ */ jsx("div", { className: "mib-tag-hang", children: /* @__PURE__ */ jsx("div", { className: "mib-tag", children: /* @__PURE__ */ jsxs("div", { className: "mib-tag__card", children: [
|
|
26
27
|
/* @__PURE__ */ jsx("span", { className: "mib-tag__stitch", "aria-hidden": "true" }),
|
|
27
28
|
/* @__PURE__ */ jsxs("div", { className: "mib-tag__head", children: [
|
|
28
|
-
/* @__PURE__ */ jsx("
|
|
29
|
+
/* @__PURE__ */ jsx("svg", { className: "mib-tag__brand", viewBox: "0 0 64 8", role: "img", "aria-label": "madeinbruno", children: /* @__PURE__ */ jsx("path", { d: WORDMARK }) }),
|
|
29
30
|
/* @__PURE__ */ jsx("span", { className: "mib-tag__since", children: since })
|
|
30
31
|
] }),
|
|
31
32
|
/* @__PURE__ */ jsxs("dl", { className: "mib-tag__specs", children: [
|
|
32
|
-
/* @__PURE__ */ jsx("dt", { children: "
|
|
33
|
+
/* @__PURE__ */ jsx("dt", { children: "SERVICE" }),
|
|
33
34
|
/* @__PURE__ */ jsx("dd", { children: service }),
|
|
34
|
-
/* @__PURE__ */ jsx("dt", { children: "SIZE" }),
|
|
35
|
-
/* @__PURE__ */ jsx("dd", { children: "ONE OF ONE" }),
|
|
36
35
|
/* @__PURE__ */ jsx("dt", { children: "CONTACT" }),
|
|
37
36
|
/* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("a", { href: `mailto:${email}`, children: email }) })
|
|
38
37
|
] }),
|
|
39
|
-
/* @__PURE__ */ jsxs("a", { className: "mib-tag__link", href, children: [
|
|
38
|
+
href && /* @__PURE__ */ jsxs("a", { className: "mib-tag__link", href, children: [
|
|
40
39
|
linkLabel,
|
|
41
40
|
" \u2192"
|
|
42
41
|
] })
|
package/package.json
CHANGED
package/styles.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* @madeinbruno/atelier 공용 스타일. 쓰는 쪽에서 한 번만 불러온다: import '@madeinbruno/atelier/styles.css'
|
|
2
2
|
클래스 이름은 모두 mib- 로 시작해 서비스 자체 스타일과 겹치지 않는다.
|
|
3
3
|
색은 CSS 변수로 바꿀 수 있다: --mib-ground(푸터 바탕), --mib-stitch(박음질), --mib-ink(글씨). */
|
|
4
|
-
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@500
|
|
4
|
+
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@500&family=IBM+Plex+Mono:wght@400;500&display=swap');
|
|
5
5
|
|
|
6
6
|
/* ───────── Tag: 흰 옷 택 푸터 ───────── */
|
|
7
7
|
|
|
@@ -12,9 +12,8 @@
|
|
|
12
12
|
--mib-muted: #6b655c;
|
|
13
13
|
box-sizing: border-box;
|
|
14
14
|
width: 100%;
|
|
15
|
-
|
|
15
|
+
/* 넘치는 걸 자르지 않는다: 자르면 택 위로 퍼지는 그림자가 푸터 윗변에서 끊겨, 푸터 자리만 바탕색이 달라 보인다 */
|
|
16
16
|
padding: 0 24px;
|
|
17
|
-
border-top: 1px solid rgba(31, 29, 26, 0.12);
|
|
18
17
|
background: var(--mib-ground);
|
|
19
18
|
font-family: 'IBM Plex Mono', ui-monospace, monospace;
|
|
20
19
|
color: var(--mib-ink);
|
|
@@ -38,12 +37,12 @@
|
|
|
38
37
|
.mib-footer__inner {
|
|
39
38
|
display: flex;
|
|
40
39
|
flex-wrap: wrap;
|
|
41
|
-
|
|
40
|
+
/* 택은 페이지 맨 아래 끝에 붙는다 (아래 여백 없이) */
|
|
41
|
+
align-items: flex-end;
|
|
42
42
|
justify-content: space-between;
|
|
43
43
|
gap: 32px 64px;
|
|
44
44
|
max-width: 1120px;
|
|
45
45
|
margin: 0 auto;
|
|
46
|
-
padding-bottom: 56px;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
.mib-footer__inner--solo {
|
|
@@ -80,11 +79,12 @@
|
|
|
80
79
|
.mib-tag-hang {
|
|
81
80
|
position: relative;
|
|
82
81
|
flex: 0 1 470px;
|
|
83
|
-
padding-top:
|
|
82
|
+
padding-top: 32px;
|
|
84
83
|
}
|
|
85
84
|
|
|
85
|
+
/* 아래가 화면 끝에 닿아 있으니 그림자는 위쪽으로만 옅게 */
|
|
86
86
|
.mib-tag {
|
|
87
|
-
filter: drop-shadow(0
|
|
87
|
+
filter: drop-shadow(0 -4px 16px rgba(31, 29, 26, 0.1));
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
.mib-tag__card {
|
|
@@ -92,7 +92,6 @@
|
|
|
92
92
|
display: flex;
|
|
93
93
|
flex-direction: column;
|
|
94
94
|
gap: 14px;
|
|
95
|
-
min-height: 236px;
|
|
96
95
|
padding: 46px 34px 26px;
|
|
97
96
|
background: #ffffff;
|
|
98
97
|
/* 옷 택처럼 위쪽 두 모서리를 비스듬히 깎는다 */
|
|
@@ -113,15 +112,16 @@
|
|
|
113
112
|
flex-wrap: wrap;
|
|
114
113
|
align-items: baseline;
|
|
115
114
|
justify-content: space-between;
|
|
116
|
-
gap:
|
|
115
|
+
gap: 10px 12px;
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
.mib-tag__brand {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
/* 64×8 칸 그림. 칸이 흐려지지 않게 경계를 픽셀에 맞춘다 */
|
|
120
|
+
display: block;
|
|
121
|
+
width: auto;
|
|
122
|
+
height: clamp(24px, 7.2vw, 32px);
|
|
123
|
+
fill: currentColor;
|
|
124
|
+
shape-rendering: crispEdges;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
.mib-tag__since {
|
|
@@ -159,11 +159,15 @@
|
|
|
159
159
|
|
|
160
160
|
/* 좁은 화면: 글 아래에 택이 오고, 택은 화면 폭에 맞춘다. */
|
|
161
161
|
@media (max-width: 640px) {
|
|
162
|
+
/* 좁은 화면: 택이 양옆은 띄우고 아래 끝에만 붙는다 */
|
|
163
|
+
.mib-footer {
|
|
164
|
+
padding: 0 16px;
|
|
165
|
+
}
|
|
166
|
+
|
|
162
167
|
.mib-footer__inner {
|
|
163
168
|
flex-direction: column;
|
|
164
169
|
align-items: stretch;
|
|
165
170
|
gap: 8px;
|
|
166
|
-
padding-bottom: 40px;
|
|
167
171
|
}
|
|
168
172
|
|
|
169
173
|
.mib-footer__message {
|
|
@@ -174,13 +178,10 @@
|
|
|
174
178
|
.mib-tag-hang {
|
|
175
179
|
flex: none;
|
|
176
180
|
width: 100%;
|
|
177
|
-
|
|
178
|
-
align-self: center;
|
|
179
|
-
padding-top: 24px;
|
|
181
|
+
padding-top: 16px;
|
|
180
182
|
}
|
|
181
183
|
|
|
182
184
|
.mib-tag__card {
|
|
183
|
-
min-height: 0;
|
|
184
185
|
padding: 44px 24px 24px;
|
|
185
186
|
}
|
|
186
187
|
}
|