@hraness/design-kit 0.35.0 → 0.35.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.
- package/AGENT_SETUP.md +4 -0
- package/ARTICLE_COPY.md +19 -7
- package/README.md +8 -2
- package/dist/{chunk-c9mhn3yb.js → chunk-4tgt8egt.js} +18 -13
- package/dist/{chunk-fjf81bww.js → chunk-6ts4955n.js} +8 -34
- package/dist/{chunk-c80g58j1.js → chunk-fmeg5cxf.js} +14 -6
- package/dist/{chunk-8xfssb9c.js → chunk-tzd7177a.js} +138 -81
- package/dist/index.js +1 -1
- package/dist/react/index.js +38 -96
- package/dist/react/platform-install.js +2 -2
- package/dist/react/server.js +2 -2
- package/dist/stylex-manifest.json +1 -1
- package/dist/stylex.css +28 -28
- package/package.json +3 -1
- package/portfolio-inventory.json +1 -1
- package/src/article-html.ts +41 -19
- package/src/react/agent-setup-prompt.stylex.ts +5 -25
- package/src/react/agent-setup-prompt.tsx +9 -18
- package/src/react/article.tsx +32 -14
- package/src/react/design-gallery.tsx +3 -0
- package/src/react/platform-install.stylex.ts +7 -36
- package/src/react/platform-install.tsx +15 -23
- package/src/react/setup-copy-button.stylex.ts +39 -0
- package/src/react/setup-copy-button.tsx +20 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
platformMark,
|
|
12
12
|
type PlatformId,
|
|
13
13
|
} from "../platforms.js";
|
|
14
|
+
import { SetupCopyButton } from "./setup-copy-button.js";
|
|
14
15
|
import { SyntaxCode } from "./syntax-code.js";
|
|
15
16
|
import { platformInstallClassName as cx } from "./platform-install.stylex.js";
|
|
16
17
|
|
|
@@ -29,7 +30,7 @@ interface PlatformInstallTargetBase {
|
|
|
29
30
|
readonly label?: string;
|
|
30
31
|
/** Where the command runs, such as "Terminal" or "PowerShell". */
|
|
31
32
|
readonly shell?: string;
|
|
32
|
-
/** A short qualifier
|
|
33
|
+
/** A short qualifier in the primary command footer, such as "Apple silicon" or "Requires Bun 1.3.14+". */
|
|
33
34
|
readonly note?: ReactNode;
|
|
34
35
|
readonly alternatives?: readonly PlatformInstallAlternative[];
|
|
35
36
|
}
|
|
@@ -167,22 +168,12 @@ function PlatformMarkUse({ platform, symbolId }: Readonly<{ platform: PlatformId
|
|
|
167
168
|
);
|
|
168
169
|
}
|
|
169
170
|
|
|
170
|
-
function CopyGlyph({ copied }: Readonly<{ copied: boolean }>) {
|
|
171
|
-
return (
|
|
172
|
-
<svg aria-hidden="true" className={cx(["copyIcon"])} fill="none" focusable="false" stroke="currentColor"
|
|
173
|
-
strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} viewBox="0 0 24 24">
|
|
174
|
-
{copied
|
|
175
|
-
? <path d="M5 12.5l4.5 4.5L19 7.5" />
|
|
176
|
-
: <><rect height="12" rx="2" width="12" x="8" y="8" /><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2" /></>}
|
|
177
|
-
</svg>
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
171
|
function CommandBlock({
|
|
182
172
|
caption,
|
|
183
173
|
command,
|
|
184
174
|
copyKey,
|
|
185
175
|
onCopy,
|
|
176
|
+
note,
|
|
186
177
|
status,
|
|
187
178
|
subject,
|
|
188
179
|
}: Readonly<{
|
|
@@ -190,6 +181,7 @@ function CommandBlock({
|
|
|
190
181
|
command: string;
|
|
191
182
|
copyKey: string;
|
|
192
183
|
onCopy: (key: string, command: string, subject: string, pre: HTMLElement | null) => void;
|
|
184
|
+
note?: ReactNode;
|
|
193
185
|
status: CopyStatus | null;
|
|
194
186
|
subject: string;
|
|
195
187
|
}>) {
|
|
@@ -199,21 +191,20 @@ function CommandBlock({
|
|
|
199
191
|
<div className={cx(["command"])} data-copy-state={state}>
|
|
200
192
|
<div className={cx(["commandBar", (caption === undefined || caption === "") && "commandBarEmpty"])}>
|
|
201
193
|
<span className={cx(["shell"])}>{caption}</span>
|
|
202
|
-
<
|
|
203
|
-
className=
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
<span className={cx(["status"])}> {subject}</span>
|
|
211
|
-
</button>
|
|
194
|
+
<SetupCopyButton
|
|
195
|
+
className="hraness-platform-install__copy"
|
|
196
|
+
iconClassName="hraness-platform-install__copy-icon"
|
|
197
|
+
failedLabel="Select to copy"
|
|
198
|
+
onCopy={() => onCopy(copyKey, command, subject, preRef.current)}
|
|
199
|
+
state={state}
|
|
200
|
+
subject={subject}
|
|
201
|
+
/>
|
|
212
202
|
</div>
|
|
213
203
|
{/* Focusable so keyboard users can scroll a long command sideways. */}
|
|
214
204
|
<pre aria-label={subject} className={cx(["pre"])} ref={preRef} tabIndex={0}>
|
|
215
205
|
<SyntaxCode className={cx(["code"])} code={command} language="shell" styles="classes" />
|
|
216
206
|
</pre>
|
|
207
|
+
{note === undefined ? null : <div className={cx(["note", "commandNote"])}>{note}</div>}
|
|
217
208
|
</div>
|
|
218
209
|
);
|
|
219
210
|
}
|
|
@@ -357,6 +348,7 @@ export function PlatformInstall({
|
|
|
357
348
|
command={target.command}
|
|
358
349
|
copyKey={`${target.id}:primary`}
|
|
359
350
|
onCopy={copy}
|
|
351
|
+
note={target.note}
|
|
360
352
|
status={status}
|
|
361
353
|
subject={`${name} install command`}
|
|
362
354
|
/>
|
|
@@ -377,7 +369,7 @@ export function PlatformInstall({
|
|
|
377
369
|
))}
|
|
378
370
|
</ul>
|
|
379
371
|
)}
|
|
380
|
-
{target.note === undefined ? null : <div className={cx(["note"])}>{target.note}</div>}
|
|
372
|
+
{target.command !== undefined || target.note === undefined ? null : <div className={cx(["note"])}>{target.note}</div>}
|
|
381
373
|
</div>
|
|
382
374
|
</div>
|
|
383
375
|
);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as stylex from "@stylexjs/stylex";
|
|
2
|
+
|
|
3
|
+
const ink = "var(--foreground, CanvasText)";
|
|
4
|
+
const surface = "var(--surface, Canvas)";
|
|
5
|
+
const background = "var(--background, Canvas)";
|
|
6
|
+
const forced = "@media (forced-colors: active)";
|
|
7
|
+
|
|
8
|
+
export const setupCopyButtonStyles = stylex.create({
|
|
9
|
+
button: {
|
|
10
|
+
alignItems: "center",
|
|
11
|
+
appearance: "none",
|
|
12
|
+
backgroundColor: { default: background, ":hover": surface, [forced]: "ButtonFace" },
|
|
13
|
+
borderColor: { default: `color-mix(in srgb, ${ink} 15%, transparent)`, [forced]: "ButtonText" },
|
|
14
|
+
borderRadius: "0.5rem",
|
|
15
|
+
borderStyle: "solid",
|
|
16
|
+
borderWidth: "1px",
|
|
17
|
+
boxSizing: "border-box",
|
|
18
|
+
color: { default: ink, [forced]: "ButtonText" },
|
|
19
|
+
cursor: "pointer",
|
|
20
|
+
display: { default: "inline-flex", "@media (scripting: none)": "none" },
|
|
21
|
+
flexShrink: 0,
|
|
22
|
+
fontFamily: "var(--font-text, ui-sans-serif, system-ui, sans-serif)",
|
|
23
|
+
fontSize: "0.8125rem",
|
|
24
|
+
fontWeight: 500,
|
|
25
|
+
gap: "0.4rem",
|
|
26
|
+
justifyContent: "center",
|
|
27
|
+
lineHeight: 1,
|
|
28
|
+
margin: 0,
|
|
29
|
+
minBlockSize: "2.75rem",
|
|
30
|
+
outline: { default: "none", ":focus-visible": "2px solid var(--focus, Highlight)" },
|
|
31
|
+
outlineOffset: "2px",
|
|
32
|
+
padding: "0.65rem 0.8rem",
|
|
33
|
+
},
|
|
34
|
+
icon: { blockSize: "1rem", flexShrink: 0, inlineSize: "1rem" },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export function setupCopyButtonClassName(part: keyof typeof setupCopyButtonStyles, caller?: string): string {
|
|
38
|
+
return [`hraness-setup-copy__${part}`, stylex.props(setupCopyButtonStyles[part]).className, caller].filter(Boolean).join(" ");
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { setupCopyButtonClassName as cx } from "./setup-copy-button.stylex.js";
|
|
2
|
+
|
|
3
|
+
/** Presentation only: each setup composition retains its clipboard and recovery behavior. */
|
|
4
|
+
export function SetupCopyButton({ className, iconClassName, onCopy, state, subject, failedLabel = "Copy failed" }: Readonly<{
|
|
5
|
+
className?: string;
|
|
6
|
+
iconClassName?: string;
|
|
7
|
+
onCopy: () => void;
|
|
8
|
+
state: "idle" | "copying" | "copied" | "failed";
|
|
9
|
+
subject: string;
|
|
10
|
+
failedLabel?: string;
|
|
11
|
+
}>) {
|
|
12
|
+
return (
|
|
13
|
+
<button aria-busy={state === "copying" || undefined} aria-label={`${state === "copied" ? "Copied" : "Copy"} ${subject}`} className={cx("button", className)} data-copy-state={state} disabled={state === "copying"} onClick={onCopy} type="button">
|
|
14
|
+
<svg aria-hidden="true" className={cx("icon", iconClassName)} fill="none" focusable="false" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} viewBox="0 0 24 24">
|
|
15
|
+
{state === "copied" ? <path d="M5 12.5l4.5 4.5L19 7.5" /> : <><rect height="12" rx="2" width="12" x="8" y="8" /><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2" /></>}
|
|
16
|
+
</svg>
|
|
17
|
+
<span>{state === "copied" ? "Copied" : state === "copying" ? "Copying" : state === "failed" ? failedLabel : "Copy"}</span>
|
|
18
|
+
</button>
|
|
19
|
+
);
|
|
20
|
+
}
|