@usefidel/design-system 0.2.0 → 0.3.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/dist/fidel.manifest.json +2 -2
- package/dist/index.cjs +170 -2
- package/dist/index.css +250 -0
- package/dist/index.d.cts +82 -2
- package/dist/index.d.ts +82 -2
- package/dist/index.js +167 -1
- package/package.json +2 -2
package/dist/fidel.manifest.json
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
Button: () => Button
|
|
23
|
+
Button: () => Button,
|
|
24
|
+
DiffSection: () => DiffSection,
|
|
25
|
+
MismatchCard: () => MismatchCard
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(index_exports);
|
|
26
28
|
|
|
@@ -48,7 +50,173 @@ function Button({
|
|
|
48
50
|
rightIcon != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "fds-button__icon", "aria-hidden": "true", children: rightIcon })
|
|
49
51
|
] });
|
|
50
52
|
}
|
|
53
|
+
|
|
54
|
+
// src/components/MismatchCard/MismatchCard.tsx
|
|
55
|
+
var import_react = require("react");
|
|
56
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
57
|
+
function MismatchCard({
|
|
58
|
+
title,
|
|
59
|
+
properties,
|
|
60
|
+
collapsedCount = 2,
|
|
61
|
+
defaultExpanded = false,
|
|
62
|
+
className,
|
|
63
|
+
...rest
|
|
64
|
+
}) {
|
|
65
|
+
const [expanded, setExpanded] = (0, import_react.useState)(defaultExpanded);
|
|
66
|
+
const canToggle = properties.length > collapsedCount;
|
|
67
|
+
const visible = expanded || !canToggle ? properties : properties.slice(0, collapsedCount);
|
|
68
|
+
const classes = ["fds-mismatch-card", className].filter(Boolean).join(" ");
|
|
69
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: classes, ...rest, children: [
|
|
70
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fds-mismatch-card__content", children: [
|
|
71
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "fds-mismatch-card__title", title, children: title }),
|
|
72
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fds-mismatch-card__rows", children: visible.map((prop, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fds-mismatch-card__row", children: [
|
|
73
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fds-mismatch-card__label", children: prop.label }),
|
|
74
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fds-mismatch-card__values", children: [
|
|
75
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fds-mismatch-card__live", children: prop.live }),
|
|
76
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fds-mismatch-card__design", children: prop.design })
|
|
77
|
+
] })
|
|
78
|
+
] }, `${prop.label}-${i}`)) })
|
|
79
|
+
] }),
|
|
80
|
+
canToggle && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
81
|
+
"button",
|
|
82
|
+
{
|
|
83
|
+
type: "button",
|
|
84
|
+
className: "fds-mismatch-card__toggle",
|
|
85
|
+
"aria-expanded": expanded,
|
|
86
|
+
onClick: () => setExpanded((v) => !v),
|
|
87
|
+
children: [
|
|
88
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chevron, { direction: expanded ? "up" : "down" }),
|
|
89
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fds-mismatch-card__toggle-label", children: expanded ? "Show less" : "Show more" })
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
] });
|
|
94
|
+
}
|
|
95
|
+
function Chevron({ direction }) {
|
|
96
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
97
|
+
"svg",
|
|
98
|
+
{
|
|
99
|
+
className: `fds-mismatch-card__chevron fds-mismatch-card__chevron--${direction}`,
|
|
100
|
+
width: "20",
|
|
101
|
+
height: "20",
|
|
102
|
+
viewBox: "0 0 20 20",
|
|
103
|
+
fill: "none",
|
|
104
|
+
"aria-hidden": "true",
|
|
105
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
106
|
+
"path",
|
|
107
|
+
{
|
|
108
|
+
d: "M6 8.5 10 12l4-3.5",
|
|
109
|
+
stroke: "currentColor",
|
|
110
|
+
strokeWidth: "1.6",
|
|
111
|
+
strokeLinecap: "round",
|
|
112
|
+
strokeLinejoin: "round"
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/components/DiffSection/DiffSection.tsx
|
|
120
|
+
var import_react2 = require("react");
|
|
121
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
122
|
+
function plural(n, one, many) {
|
|
123
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
124
|
+
}
|
|
125
|
+
function DiffSection({
|
|
126
|
+
number,
|
|
127
|
+
name,
|
|
128
|
+
mismatchCount,
|
|
129
|
+
elements,
|
|
130
|
+
defaultExpanded = false,
|
|
131
|
+
className,
|
|
132
|
+
...rest
|
|
133
|
+
}) {
|
|
134
|
+
const [expanded, setExpanded] = (0, import_react2.useState)(defaultExpanded);
|
|
135
|
+
const count = mismatchCount ?? elements.reduce((sum, el) => sum + el.properties.length, 0);
|
|
136
|
+
const classes = ["fds-diff-section", className].filter(Boolean).join(" ");
|
|
137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: classes, "data-expanded": expanded ? "true" : void 0, ...rest, children: [
|
|
138
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
139
|
+
"button",
|
|
140
|
+
{
|
|
141
|
+
type: "button",
|
|
142
|
+
className: "fds-diff-section__header",
|
|
143
|
+
"aria-expanded": expanded,
|
|
144
|
+
onClick: () => setExpanded((v) => !v),
|
|
145
|
+
children: [
|
|
146
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "fds-diff-section__head-left", children: [
|
|
147
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chevron2, { open: expanded }),
|
|
148
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__number", children: number }),
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__name", children: name })
|
|
150
|
+
] }),
|
|
151
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__count", children: plural(count, "mismatch", "mismatches") })
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
),
|
|
155
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fds-diff-section__body", children: elements.map((el, ei) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fds-diff-section__element", children: [
|
|
156
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fds-diff-section__element-head", children: [
|
|
157
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__element-name", children: el.name }),
|
|
158
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__element-count", children: plural(el.properties.length, "property", "properties") })
|
|
159
|
+
] }),
|
|
160
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fds-diff-section__lines", children: el.properties.map((line, li) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fds-diff-section__line", children: [
|
|
161
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__prop", children: line.property }),
|
|
162
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "fds-diff-section__delta", children: [
|
|
163
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__live", children: line.live }),
|
|
164
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Arrow, {}),
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fds-diff-section__design", children: line.design })
|
|
166
|
+
] })
|
|
167
|
+
] }, `${line.property}-${li}`)) })
|
|
168
|
+
] }, `${el.name}-${ei}`)) })
|
|
169
|
+
] });
|
|
170
|
+
}
|
|
171
|
+
function Chevron2({ open }) {
|
|
172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
173
|
+
"svg",
|
|
174
|
+
{
|
|
175
|
+
className: `fds-diff-section__chevron${open ? " fds-diff-section__chevron--open" : ""}`,
|
|
176
|
+
width: "12",
|
|
177
|
+
height: "12",
|
|
178
|
+
viewBox: "0 0 12 12",
|
|
179
|
+
fill: "none",
|
|
180
|
+
"aria-hidden": "true",
|
|
181
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
182
|
+
"path",
|
|
183
|
+
{
|
|
184
|
+
d: "M4.5 3 8 6l-3.5 3",
|
|
185
|
+
stroke: "currentColor",
|
|
186
|
+
strokeWidth: "1.3",
|
|
187
|
+
strokeLinecap: "round",
|
|
188
|
+
strokeLinejoin: "round"
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
function Arrow() {
|
|
195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
196
|
+
"svg",
|
|
197
|
+
{
|
|
198
|
+
className: "fds-diff-section__arrow",
|
|
199
|
+
width: "10",
|
|
200
|
+
height: "10",
|
|
201
|
+
viewBox: "0 0 10 10",
|
|
202
|
+
fill: "none",
|
|
203
|
+
"aria-hidden": "true",
|
|
204
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
205
|
+
"path",
|
|
206
|
+
{
|
|
207
|
+
d: "M1.5 5h6.5M5.5 2.5 8 5 5.5 7.5",
|
|
208
|
+
stroke: "currentColor",
|
|
209
|
+
strokeWidth: "1",
|
|
210
|
+
strokeLinecap: "round",
|
|
211
|
+
strokeLinejoin: "round"
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
}
|
|
51
217
|
// Annotate the CommonJS export names for ESM import in node:
|
|
52
218
|
0 && (module.exports = {
|
|
53
|
-
Button
|
|
219
|
+
Button,
|
|
220
|
+
DiffSection,
|
|
221
|
+
MismatchCard
|
|
54
222
|
});
|
package/dist/index.css
CHANGED
|
@@ -123,3 +123,253 @@
|
|
|
123
123
|
color: #a3a3a3;
|
|
124
124
|
cursor: not-allowed;
|
|
125
125
|
}
|
|
126
|
+
|
|
127
|
+
/* src/components/MismatchCard/mismatch-card.css */
|
|
128
|
+
.fds-mismatch-card {
|
|
129
|
+
box-sizing: border-box;
|
|
130
|
+
display: flex;
|
|
131
|
+
flex-direction: column;
|
|
132
|
+
align-items: center;
|
|
133
|
+
gap: 14px;
|
|
134
|
+
width: max-content;
|
|
135
|
+
max-width: 368px;
|
|
136
|
+
padding: var(--spacing-6);
|
|
137
|
+
background: rgba(255, 255, 255, 0.4);
|
|
138
|
+
backdrop-filter: blur(24px);
|
|
139
|
+
-webkit-backdrop-filter: blur(24px);
|
|
140
|
+
border: 2px solid var(--color-accent);
|
|
141
|
+
border-radius: var(--radius-lg);
|
|
142
|
+
box-shadow: 0 15px 35px 0 rgba(151, 151, 151, 0.2);
|
|
143
|
+
font-family: var(--font-body);
|
|
144
|
+
overflow: clip;
|
|
145
|
+
}
|
|
146
|
+
.fds-mismatch-card *,
|
|
147
|
+
.fds-mismatch-card *::before,
|
|
148
|
+
.fds-mismatch-card *::after {
|
|
149
|
+
box-sizing: border-box;
|
|
150
|
+
}
|
|
151
|
+
.fds-mismatch-card__content {
|
|
152
|
+
display: flex;
|
|
153
|
+
flex-direction: column;
|
|
154
|
+
align-items: flex-start;
|
|
155
|
+
gap: var(--spacing-5);
|
|
156
|
+
width: 320px;
|
|
157
|
+
}
|
|
158
|
+
.fds-mismatch-card__title {
|
|
159
|
+
margin: 0;
|
|
160
|
+
width: 100%;
|
|
161
|
+
font-family: var(--font-display);
|
|
162
|
+
font-weight: var(--font-weight-semibold);
|
|
163
|
+
font-size: 16px;
|
|
164
|
+
line-height: 24px;
|
|
165
|
+
letter-spacing: -0.0288px;
|
|
166
|
+
color: var(--color-text);
|
|
167
|
+
white-space: nowrap;
|
|
168
|
+
overflow: hidden;
|
|
169
|
+
text-overflow: ellipsis;
|
|
170
|
+
}
|
|
171
|
+
.fds-mismatch-card__rows {
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
align-items: flex-start;
|
|
175
|
+
gap: var(--spacing-3);
|
|
176
|
+
width: 100%;
|
|
177
|
+
}
|
|
178
|
+
.fds-mismatch-card__row {
|
|
179
|
+
display: flex;
|
|
180
|
+
flex-direction: column;
|
|
181
|
+
align-items: flex-start;
|
|
182
|
+
gap: var(--spacing-2);
|
|
183
|
+
width: 100%;
|
|
184
|
+
border-bottom: 1px solid var(--color-border-strong);
|
|
185
|
+
}
|
|
186
|
+
.fds-mismatch-card__label {
|
|
187
|
+
width: 100%;
|
|
188
|
+
font-weight: var(--font-weight-medium);
|
|
189
|
+
font-size: 14px;
|
|
190
|
+
line-height: 22px;
|
|
191
|
+
color: var(--color-text-secondary);
|
|
192
|
+
}
|
|
193
|
+
.fds-mismatch-card__values {
|
|
194
|
+
display: flex;
|
|
195
|
+
justify-content: space-between;
|
|
196
|
+
width: 100%;
|
|
197
|
+
padding: var(--spacing-1) 0;
|
|
198
|
+
font-weight: var(--font-weight-medium);
|
|
199
|
+
font-size: 14px;
|
|
200
|
+
line-height: 22px;
|
|
201
|
+
white-space: nowrap;
|
|
202
|
+
}
|
|
203
|
+
.fds-mismatch-card__live {
|
|
204
|
+
color: var(--color-actual-text);
|
|
205
|
+
}
|
|
206
|
+
.fds-mismatch-card__design {
|
|
207
|
+
color: #262626;
|
|
208
|
+
}
|
|
209
|
+
.fds-mismatch-card__toggle {
|
|
210
|
+
display: flex;
|
|
211
|
+
align-items: center;
|
|
212
|
+
gap: 2px;
|
|
213
|
+
width: 320px;
|
|
214
|
+
padding: var(--spacing-2) 0;
|
|
215
|
+
border: 0;
|
|
216
|
+
background: none;
|
|
217
|
+
border-radius: var(--radius-md);
|
|
218
|
+
cursor: pointer;
|
|
219
|
+
font-family: var(--font-display);
|
|
220
|
+
font-weight: var(--font-weight-semibold);
|
|
221
|
+
font-size: 14px;
|
|
222
|
+
line-height: 20px;
|
|
223
|
+
color: var(--color-text-secondary);
|
|
224
|
+
}
|
|
225
|
+
.fds-mismatch-card__chevron {
|
|
226
|
+
flex-shrink: 0;
|
|
227
|
+
color: currentColor;
|
|
228
|
+
}
|
|
229
|
+
.fds-mismatch-card__chevron--up {
|
|
230
|
+
transform: rotate(180deg);
|
|
231
|
+
}
|
|
232
|
+
.fds-mismatch-card__toggle-label {
|
|
233
|
+
white-space: nowrap;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* src/components/DiffSection/diff-section.css */
|
|
237
|
+
.fds-diff-section {
|
|
238
|
+
box-sizing: border-box;
|
|
239
|
+
display: flex;
|
|
240
|
+
flex-direction: column;
|
|
241
|
+
align-items: stretch;
|
|
242
|
+
width: 100%;
|
|
243
|
+
background: var(--color-surface-raised);
|
|
244
|
+
font-family: var(--font-body);
|
|
245
|
+
}
|
|
246
|
+
.fds-diff-section[data-expanded=true] {
|
|
247
|
+
gap: var(--spacing-3);
|
|
248
|
+
padding-bottom: 14px;
|
|
249
|
+
}
|
|
250
|
+
.fds-diff-section *,
|
|
251
|
+
.fds-diff-section *::before,
|
|
252
|
+
.fds-diff-section *::after {
|
|
253
|
+
box-sizing: border-box;
|
|
254
|
+
}
|
|
255
|
+
.fds-diff-section__header {
|
|
256
|
+
display: flex;
|
|
257
|
+
align-items: center;
|
|
258
|
+
justify-content: space-between;
|
|
259
|
+
width: 100%;
|
|
260
|
+
padding: var(--spacing-4) var(--spacing-4) var(--spacing-4) var(--spacing-6);
|
|
261
|
+
border: 0;
|
|
262
|
+
border-bottom: 1px solid var(--color-border);
|
|
263
|
+
background: #fafafa;
|
|
264
|
+
cursor: pointer;
|
|
265
|
+
text-align: left;
|
|
266
|
+
font-family: inherit;
|
|
267
|
+
}
|
|
268
|
+
.fds-diff-section[data-expanded=true] .fds-diff-section__header {
|
|
269
|
+
border-bottom-color: var(--color-border-light);
|
|
270
|
+
}
|
|
271
|
+
.fds-diff-section__head-left {
|
|
272
|
+
display: flex;
|
|
273
|
+
align-items: center;
|
|
274
|
+
gap: var(--spacing-2);
|
|
275
|
+
}
|
|
276
|
+
.fds-diff-section__chevron {
|
|
277
|
+
flex-shrink: 0;
|
|
278
|
+
color: var(--color-text-secondary);
|
|
279
|
+
transition: transform 150ms ease;
|
|
280
|
+
}
|
|
281
|
+
.fds-diff-section__chevron--open {
|
|
282
|
+
transform: rotate(90deg);
|
|
283
|
+
}
|
|
284
|
+
.fds-diff-section__number {
|
|
285
|
+
font-family: var(--font-mono);
|
|
286
|
+
font-weight: var(--font-weight-regular);
|
|
287
|
+
font-size: 12px;
|
|
288
|
+
line-height: 18px;
|
|
289
|
+
letter-spacing: -0.24px;
|
|
290
|
+
color: var(--color-text-secondary);
|
|
291
|
+
}
|
|
292
|
+
.fds-diff-section__name {
|
|
293
|
+
font-weight: var(--font-weight-medium);
|
|
294
|
+
font-size: 14px;
|
|
295
|
+
line-height: 22px;
|
|
296
|
+
color: var(--color-text);
|
|
297
|
+
}
|
|
298
|
+
.fds-diff-section__count {
|
|
299
|
+
font-weight: var(--font-weight-regular);
|
|
300
|
+
font-size: 14px;
|
|
301
|
+
line-height: 22px;
|
|
302
|
+
color: var(--color-text-secondary);
|
|
303
|
+
white-space: nowrap;
|
|
304
|
+
}
|
|
305
|
+
.fds-diff-section__body {
|
|
306
|
+
display: flex;
|
|
307
|
+
flex-direction: column;
|
|
308
|
+
gap: var(--spacing-3);
|
|
309
|
+
}
|
|
310
|
+
.fds-diff-section__element {
|
|
311
|
+
display: flex;
|
|
312
|
+
flex-direction: column;
|
|
313
|
+
gap: 14px;
|
|
314
|
+
padding: 6px var(--spacing-5) 6px var(--spacing-6);
|
|
315
|
+
}
|
|
316
|
+
.fds-diff-section__element-head {
|
|
317
|
+
display: flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
gap: var(--spacing-2);
|
|
320
|
+
}
|
|
321
|
+
.fds-diff-section__element-name {
|
|
322
|
+
font-weight: var(--font-weight-medium);
|
|
323
|
+
font-size: 14px;
|
|
324
|
+
line-height: 22px;
|
|
325
|
+
color: var(--color-text);
|
|
326
|
+
}
|
|
327
|
+
.fds-diff-section__element-count {
|
|
328
|
+
font-weight: var(--font-weight-regular);
|
|
329
|
+
font-size: 12px;
|
|
330
|
+
line-height: 18px;
|
|
331
|
+
color: var(--color-text-secondary);
|
|
332
|
+
}
|
|
333
|
+
.fds-diff-section__lines {
|
|
334
|
+
display: flex;
|
|
335
|
+
flex-direction: column;
|
|
336
|
+
padding-left: 18px;
|
|
337
|
+
border-left: 1px solid var(--color-border);
|
|
338
|
+
margin-left: 2px;
|
|
339
|
+
}
|
|
340
|
+
.fds-diff-section__line {
|
|
341
|
+
display: flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
justify-content: space-between;
|
|
344
|
+
width: 100%;
|
|
345
|
+
}
|
|
346
|
+
.fds-diff-section__prop {
|
|
347
|
+
font-family: var(--font-mono);
|
|
348
|
+
font-weight: var(--font-weight-regular);
|
|
349
|
+
font-size: 14px;
|
|
350
|
+
line-height: 22px;
|
|
351
|
+
letter-spacing: -0.28px;
|
|
352
|
+
color: var(--color-text-secondary);
|
|
353
|
+
white-space: nowrap;
|
|
354
|
+
}
|
|
355
|
+
.fds-diff-section__delta {
|
|
356
|
+
display: flex;
|
|
357
|
+
align-items: center;
|
|
358
|
+
gap: var(--spacing-1);
|
|
359
|
+
font-family: var(--font-mono);
|
|
360
|
+
font-weight: var(--font-weight-medium);
|
|
361
|
+
font-size: 14px;
|
|
362
|
+
line-height: 22px;
|
|
363
|
+
letter-spacing: -0.28px;
|
|
364
|
+
white-space: nowrap;
|
|
365
|
+
}
|
|
366
|
+
.fds-diff-section__live {
|
|
367
|
+
color: #ef4444;
|
|
368
|
+
}
|
|
369
|
+
.fds-diff-section__arrow {
|
|
370
|
+
flex-shrink: 0;
|
|
371
|
+
color: var(--color-text-muted);
|
|
372
|
+
}
|
|
373
|
+
.fds-diff-section__design {
|
|
374
|
+
color: #1e8902;
|
|
375
|
+
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { ButtonHTMLAttributes, ReactNode, HTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
type ButtonVariant = 'primary' | 'outlined' | 'text' | 'neutral';
|
|
5
5
|
type ButtonSize = 'x-small' | 'small' | 'medium' | 'big';
|
|
@@ -20,4 +20,84 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
20
20
|
*/
|
|
21
21
|
declare function Button({ variant, size, leftIcon, rightIcon, type, className, children, ...rest }: ButtonProps): react.JSX.Element;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
interface MismatchProperty {
|
|
24
|
+
/** Property label, e.g. "color", "font-size". */
|
|
25
|
+
label: string;
|
|
26
|
+
/**
|
|
27
|
+
* Value on the live page — what actually shipped. Rendered in the
|
|
28
|
+
* live/error register (red). Left column, per the Live → Design framing.
|
|
29
|
+
*/
|
|
30
|
+
live: string;
|
|
31
|
+
/**
|
|
32
|
+
* Value in the design — the intended target. Rendered in the design
|
|
33
|
+
* register (neutral). Right column.
|
|
34
|
+
*/
|
|
35
|
+
design: string;
|
|
36
|
+
}
|
|
37
|
+
interface MismatchCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
38
|
+
/** Element title (its name or text). Single line — truncates with ellipsis. */
|
|
39
|
+
title: string;
|
|
40
|
+
/** The property mismatches to show. */
|
|
41
|
+
properties: MismatchProperty[];
|
|
42
|
+
/**
|
|
43
|
+
* How many rows are visible before the "Show more" toggle appears.
|
|
44
|
+
* @default 2
|
|
45
|
+
*/
|
|
46
|
+
collapsedCount?: number;
|
|
47
|
+
/** Render expanded on first paint. @default false */
|
|
48
|
+
defaultExpanded?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Fidel design-system MismatchCard — the card shown when hovering a
|
|
52
|
+
* highlighted mismatch region on a validation screenshot.
|
|
53
|
+
*
|
|
54
|
+
* Presentational only: it knows nothing about the diff taxonomy. Callers map
|
|
55
|
+
* their own data (e.g. a ValidationDiff) onto `title` + `properties`.
|
|
56
|
+
*
|
|
57
|
+
* Framing is Live → Design (founder decision 2026-04-24): the left value is
|
|
58
|
+
* what shipped (live), the right value is the design target. When there are
|
|
59
|
+
* more than `collapsedCount` properties, a Show more / Show less toggle
|
|
60
|
+
* reveals the rest.
|
|
61
|
+
*/
|
|
62
|
+
declare function MismatchCard({ title, properties, collapsedCount, defaultExpanded, className, ...rest }: MismatchCardProps): react.JSX.Element;
|
|
63
|
+
|
|
64
|
+
interface DiffPropertyLine {
|
|
65
|
+
/** Property name, e.g. "font-size". Rendered in mono. */
|
|
66
|
+
property: string;
|
|
67
|
+
/** Value on the live page — what shipped. Left of the arrow (error register). */
|
|
68
|
+
live: string;
|
|
69
|
+
/** Value in the design — the target. Right of the arrow (success register). */
|
|
70
|
+
design: string;
|
|
71
|
+
}
|
|
72
|
+
interface DiffElement {
|
|
73
|
+
/** Element name, e.g. `"Pricing"`. */
|
|
74
|
+
name: string;
|
|
75
|
+
/** Property mismatches for this element. */
|
|
76
|
+
properties: DiffPropertyLine[];
|
|
77
|
+
}
|
|
78
|
+
interface DiffSectionProps extends HTMLAttributes<HTMLDivElement> {
|
|
79
|
+
/** Ordinal shown before the name, e.g. "01". Caller controls padding. */
|
|
80
|
+
number: string;
|
|
81
|
+
/** Section name, e.g. "Nav". */
|
|
82
|
+
name: string;
|
|
83
|
+
/**
|
|
84
|
+
* Count shown on the right of the header. Defaults to the total number of
|
|
85
|
+
* property lines across all elements.
|
|
86
|
+
*/
|
|
87
|
+
mismatchCount?: number;
|
|
88
|
+
/** Elements in this section, each with its own property mismatches. */
|
|
89
|
+
elements: DiffElement[];
|
|
90
|
+
/** Render expanded on first paint. @default false */
|
|
91
|
+
defaultExpanded?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Fidel design-system DiffSection — a numbered, collapsible section in the
|
|
95
|
+
* mismatch drawer. Collapsed it shows just the header (`01 Nav · 2
|
|
96
|
+
* mismatches`); expanded it lists each element and its property deltas.
|
|
97
|
+
*
|
|
98
|
+
* Presentational only — no diff taxonomy. Framing is Live → Design (founder
|
|
99
|
+
* decision 2026-04-24): each delta reads `live → design`.
|
|
100
|
+
*/
|
|
101
|
+
declare function DiffSection({ number, name, mismatchCount, elements, defaultExpanded, className, ...rest }: DiffSectionProps): react.JSX.Element;
|
|
102
|
+
|
|
103
|
+
export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type DiffElement, type DiffPropertyLine, DiffSection, type DiffSectionProps, MismatchCard, type MismatchCardProps, type MismatchProperty };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { ButtonHTMLAttributes, ReactNode, HTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
type ButtonVariant = 'primary' | 'outlined' | 'text' | 'neutral';
|
|
5
5
|
type ButtonSize = 'x-small' | 'small' | 'medium' | 'big';
|
|
@@ -20,4 +20,84 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
20
20
|
*/
|
|
21
21
|
declare function Button({ variant, size, leftIcon, rightIcon, type, className, children, ...rest }: ButtonProps): react.JSX.Element;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
interface MismatchProperty {
|
|
24
|
+
/** Property label, e.g. "color", "font-size". */
|
|
25
|
+
label: string;
|
|
26
|
+
/**
|
|
27
|
+
* Value on the live page — what actually shipped. Rendered in the
|
|
28
|
+
* live/error register (red). Left column, per the Live → Design framing.
|
|
29
|
+
*/
|
|
30
|
+
live: string;
|
|
31
|
+
/**
|
|
32
|
+
* Value in the design — the intended target. Rendered in the design
|
|
33
|
+
* register (neutral). Right column.
|
|
34
|
+
*/
|
|
35
|
+
design: string;
|
|
36
|
+
}
|
|
37
|
+
interface MismatchCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
38
|
+
/** Element title (its name or text). Single line — truncates with ellipsis. */
|
|
39
|
+
title: string;
|
|
40
|
+
/** The property mismatches to show. */
|
|
41
|
+
properties: MismatchProperty[];
|
|
42
|
+
/**
|
|
43
|
+
* How many rows are visible before the "Show more" toggle appears.
|
|
44
|
+
* @default 2
|
|
45
|
+
*/
|
|
46
|
+
collapsedCount?: number;
|
|
47
|
+
/** Render expanded on first paint. @default false */
|
|
48
|
+
defaultExpanded?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Fidel design-system MismatchCard — the card shown when hovering a
|
|
52
|
+
* highlighted mismatch region on a validation screenshot.
|
|
53
|
+
*
|
|
54
|
+
* Presentational only: it knows nothing about the diff taxonomy. Callers map
|
|
55
|
+
* their own data (e.g. a ValidationDiff) onto `title` + `properties`.
|
|
56
|
+
*
|
|
57
|
+
* Framing is Live → Design (founder decision 2026-04-24): the left value is
|
|
58
|
+
* what shipped (live), the right value is the design target. When there are
|
|
59
|
+
* more than `collapsedCount` properties, a Show more / Show less toggle
|
|
60
|
+
* reveals the rest.
|
|
61
|
+
*/
|
|
62
|
+
declare function MismatchCard({ title, properties, collapsedCount, defaultExpanded, className, ...rest }: MismatchCardProps): react.JSX.Element;
|
|
63
|
+
|
|
64
|
+
interface DiffPropertyLine {
|
|
65
|
+
/** Property name, e.g. "font-size". Rendered in mono. */
|
|
66
|
+
property: string;
|
|
67
|
+
/** Value on the live page — what shipped. Left of the arrow (error register). */
|
|
68
|
+
live: string;
|
|
69
|
+
/** Value in the design — the target. Right of the arrow (success register). */
|
|
70
|
+
design: string;
|
|
71
|
+
}
|
|
72
|
+
interface DiffElement {
|
|
73
|
+
/** Element name, e.g. `"Pricing"`. */
|
|
74
|
+
name: string;
|
|
75
|
+
/** Property mismatches for this element. */
|
|
76
|
+
properties: DiffPropertyLine[];
|
|
77
|
+
}
|
|
78
|
+
interface DiffSectionProps extends HTMLAttributes<HTMLDivElement> {
|
|
79
|
+
/** Ordinal shown before the name, e.g. "01". Caller controls padding. */
|
|
80
|
+
number: string;
|
|
81
|
+
/** Section name, e.g. "Nav". */
|
|
82
|
+
name: string;
|
|
83
|
+
/**
|
|
84
|
+
* Count shown on the right of the header. Defaults to the total number of
|
|
85
|
+
* property lines across all elements.
|
|
86
|
+
*/
|
|
87
|
+
mismatchCount?: number;
|
|
88
|
+
/** Elements in this section, each with its own property mismatches. */
|
|
89
|
+
elements: DiffElement[];
|
|
90
|
+
/** Render expanded on first paint. @default false */
|
|
91
|
+
defaultExpanded?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Fidel design-system DiffSection — a numbered, collapsible section in the
|
|
95
|
+
* mismatch drawer. Collapsed it shows just the header (`01 Nav · 2
|
|
96
|
+
* mismatches`); expanded it lists each element and its property deltas.
|
|
97
|
+
*
|
|
98
|
+
* Presentational only — no diff taxonomy. Framing is Live → Design (founder
|
|
99
|
+
* decision 2026-04-24): each delta reads `live → design`.
|
|
100
|
+
*/
|
|
101
|
+
declare function DiffSection({ number, name, mismatchCount, elements, defaultExpanded, className, ...rest }: DiffSectionProps): react.JSX.Element;
|
|
102
|
+
|
|
103
|
+
export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type DiffElement, type DiffPropertyLine, DiffSection, type DiffSectionProps, MismatchCard, type MismatchCardProps, type MismatchProperty };
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,172 @@ function Button({
|
|
|
22
22
|
rightIcon != null && /* @__PURE__ */ jsx("span", { className: "fds-button__icon", "aria-hidden": "true", children: rightIcon })
|
|
23
23
|
] });
|
|
24
24
|
}
|
|
25
|
+
|
|
26
|
+
// src/components/MismatchCard/MismatchCard.tsx
|
|
27
|
+
import { useState } from "react";
|
|
28
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
29
|
+
function MismatchCard({
|
|
30
|
+
title,
|
|
31
|
+
properties,
|
|
32
|
+
collapsedCount = 2,
|
|
33
|
+
defaultExpanded = false,
|
|
34
|
+
className,
|
|
35
|
+
...rest
|
|
36
|
+
}) {
|
|
37
|
+
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
38
|
+
const canToggle = properties.length > collapsedCount;
|
|
39
|
+
const visible = expanded || !canToggle ? properties : properties.slice(0, collapsedCount);
|
|
40
|
+
const classes = ["fds-mismatch-card", className].filter(Boolean).join(" ");
|
|
41
|
+
return /* @__PURE__ */ jsxs2("div", { className: classes, ...rest, children: [
|
|
42
|
+
/* @__PURE__ */ jsxs2("div", { className: "fds-mismatch-card__content", children: [
|
|
43
|
+
/* @__PURE__ */ jsx2("p", { className: "fds-mismatch-card__title", title, children: title }),
|
|
44
|
+
/* @__PURE__ */ jsx2("div", { className: "fds-mismatch-card__rows", children: visible.map((prop, i) => /* @__PURE__ */ jsxs2("div", { className: "fds-mismatch-card__row", children: [
|
|
45
|
+
/* @__PURE__ */ jsx2("span", { className: "fds-mismatch-card__label", children: prop.label }),
|
|
46
|
+
/* @__PURE__ */ jsxs2("div", { className: "fds-mismatch-card__values", children: [
|
|
47
|
+
/* @__PURE__ */ jsx2("span", { className: "fds-mismatch-card__live", children: prop.live }),
|
|
48
|
+
/* @__PURE__ */ jsx2("span", { className: "fds-mismatch-card__design", children: prop.design })
|
|
49
|
+
] })
|
|
50
|
+
] }, `${prop.label}-${i}`)) })
|
|
51
|
+
] }),
|
|
52
|
+
canToggle && /* @__PURE__ */ jsxs2(
|
|
53
|
+
"button",
|
|
54
|
+
{
|
|
55
|
+
type: "button",
|
|
56
|
+
className: "fds-mismatch-card__toggle",
|
|
57
|
+
"aria-expanded": expanded,
|
|
58
|
+
onClick: () => setExpanded((v) => !v),
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ jsx2(Chevron, { direction: expanded ? "up" : "down" }),
|
|
61
|
+
/* @__PURE__ */ jsx2("span", { className: "fds-mismatch-card__toggle-label", children: expanded ? "Show less" : "Show more" })
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
function Chevron({ direction }) {
|
|
68
|
+
return /* @__PURE__ */ jsx2(
|
|
69
|
+
"svg",
|
|
70
|
+
{
|
|
71
|
+
className: `fds-mismatch-card__chevron fds-mismatch-card__chevron--${direction}`,
|
|
72
|
+
width: "20",
|
|
73
|
+
height: "20",
|
|
74
|
+
viewBox: "0 0 20 20",
|
|
75
|
+
fill: "none",
|
|
76
|
+
"aria-hidden": "true",
|
|
77
|
+
children: /* @__PURE__ */ jsx2(
|
|
78
|
+
"path",
|
|
79
|
+
{
|
|
80
|
+
d: "M6 8.5 10 12l4-3.5",
|
|
81
|
+
stroke: "currentColor",
|
|
82
|
+
strokeWidth: "1.6",
|
|
83
|
+
strokeLinecap: "round",
|
|
84
|
+
strokeLinejoin: "round"
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/components/DiffSection/DiffSection.tsx
|
|
92
|
+
import { useState as useState2 } from "react";
|
|
93
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
94
|
+
function plural(n, one, many) {
|
|
95
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
96
|
+
}
|
|
97
|
+
function DiffSection({
|
|
98
|
+
number,
|
|
99
|
+
name,
|
|
100
|
+
mismatchCount,
|
|
101
|
+
elements,
|
|
102
|
+
defaultExpanded = false,
|
|
103
|
+
className,
|
|
104
|
+
...rest
|
|
105
|
+
}) {
|
|
106
|
+
const [expanded, setExpanded] = useState2(defaultExpanded);
|
|
107
|
+
const count = mismatchCount ?? elements.reduce((sum, el) => sum + el.properties.length, 0);
|
|
108
|
+
const classes = ["fds-diff-section", className].filter(Boolean).join(" ");
|
|
109
|
+
return /* @__PURE__ */ jsxs3("div", { className: classes, "data-expanded": expanded ? "true" : void 0, ...rest, children: [
|
|
110
|
+
/* @__PURE__ */ jsxs3(
|
|
111
|
+
"button",
|
|
112
|
+
{
|
|
113
|
+
type: "button",
|
|
114
|
+
className: "fds-diff-section__header",
|
|
115
|
+
"aria-expanded": expanded,
|
|
116
|
+
onClick: () => setExpanded((v) => !v),
|
|
117
|
+
children: [
|
|
118
|
+
/* @__PURE__ */ jsxs3("span", { className: "fds-diff-section__head-left", children: [
|
|
119
|
+
/* @__PURE__ */ jsx3(Chevron2, { open: expanded }),
|
|
120
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__number", children: number }),
|
|
121
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__name", children: name })
|
|
122
|
+
] }),
|
|
123
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__count", children: plural(count, "mismatch", "mismatches") })
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
),
|
|
127
|
+
expanded && /* @__PURE__ */ jsx3("div", { className: "fds-diff-section__body", children: elements.map((el, ei) => /* @__PURE__ */ jsxs3("div", { className: "fds-diff-section__element", children: [
|
|
128
|
+
/* @__PURE__ */ jsxs3("div", { className: "fds-diff-section__element-head", children: [
|
|
129
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__element-name", children: el.name }),
|
|
130
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__element-count", children: plural(el.properties.length, "property", "properties") })
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsx3("div", { className: "fds-diff-section__lines", children: el.properties.map((line, li) => /* @__PURE__ */ jsxs3("div", { className: "fds-diff-section__line", children: [
|
|
133
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__prop", children: line.property }),
|
|
134
|
+
/* @__PURE__ */ jsxs3("span", { className: "fds-diff-section__delta", children: [
|
|
135
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__live", children: line.live }),
|
|
136
|
+
/* @__PURE__ */ jsx3(Arrow, {}),
|
|
137
|
+
/* @__PURE__ */ jsx3("span", { className: "fds-diff-section__design", children: line.design })
|
|
138
|
+
] })
|
|
139
|
+
] }, `${line.property}-${li}`)) })
|
|
140
|
+
] }, `${el.name}-${ei}`)) })
|
|
141
|
+
] });
|
|
142
|
+
}
|
|
143
|
+
function Chevron2({ open }) {
|
|
144
|
+
return /* @__PURE__ */ jsx3(
|
|
145
|
+
"svg",
|
|
146
|
+
{
|
|
147
|
+
className: `fds-diff-section__chevron${open ? " fds-diff-section__chevron--open" : ""}`,
|
|
148
|
+
width: "12",
|
|
149
|
+
height: "12",
|
|
150
|
+
viewBox: "0 0 12 12",
|
|
151
|
+
fill: "none",
|
|
152
|
+
"aria-hidden": "true",
|
|
153
|
+
children: /* @__PURE__ */ jsx3(
|
|
154
|
+
"path",
|
|
155
|
+
{
|
|
156
|
+
d: "M4.5 3 8 6l-3.5 3",
|
|
157
|
+
stroke: "currentColor",
|
|
158
|
+
strokeWidth: "1.3",
|
|
159
|
+
strokeLinecap: "round",
|
|
160
|
+
strokeLinejoin: "round"
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
function Arrow() {
|
|
167
|
+
return /* @__PURE__ */ jsx3(
|
|
168
|
+
"svg",
|
|
169
|
+
{
|
|
170
|
+
className: "fds-diff-section__arrow",
|
|
171
|
+
width: "10",
|
|
172
|
+
height: "10",
|
|
173
|
+
viewBox: "0 0 10 10",
|
|
174
|
+
fill: "none",
|
|
175
|
+
"aria-hidden": "true",
|
|
176
|
+
children: /* @__PURE__ */ jsx3(
|
|
177
|
+
"path",
|
|
178
|
+
{
|
|
179
|
+
d: "M1.5 5h6.5M5.5 2.5 8 5 5.5 7.5",
|
|
180
|
+
stroke: "currentColor",
|
|
181
|
+
strokeWidth: "1",
|
|
182
|
+
strokeLinecap: "round",
|
|
183
|
+
strokeLinejoin: "round"
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
}
|
|
25
189
|
export {
|
|
26
|
-
Button
|
|
190
|
+
Button,
|
|
191
|
+
DiffSection,
|
|
192
|
+
MismatchCard
|
|
27
193
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usefidel/design-system",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Fidel brand design tokens + React component library — DTCG token source of truth, generated per-surface CSS + Tailwind-v4 parser-compatibility output, and on-brand React components.",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Fidel brand design tokens + React component library — DTCG token source of truth, generated per-surface CSS + Tailwind-v4 parser-compatibility output, and on-brand React components (Button, MismatchCard, DiffSection).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|