mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 00:47:57 +00:00
fix(web): compact CLI/Prompt toggle on skill install card (#2815)
* fix(web): compact CLI/Prompt toggle on skill install card Replace pill tablist with a flat text toggle for CLI vs Prompt install options, with matching skeleton and styles. * chore: add UI proof screenshot for install toggle PR
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -1114,8 +1114,8 @@ describe("SkillDetailPage", () => {
|
||||
expect(screen.getAllByText("@steipete/weather").length).toBeGreaterThan(0);
|
||||
expect(screen.queryByText("npx clawhub@latest install @steipete/weather")).toBeNull();
|
||||
expect(screen.queryByRole("tab", { name: "ClawHub" })).toBeNull();
|
||||
expect(screen.getByRole("tab", { name: "CLI" }).getAttribute("aria-selected")).toBe("true");
|
||||
expect(screen.getByRole("tab", { name: "Prompt" })).toBeTruthy();
|
||||
expect(screen.getByRole("button", { name: "CLI" }).getAttribute("aria-pressed")).toBe("true");
|
||||
expect(screen.getByRole("button", { name: "Prompt" })).toBeTruthy();
|
||||
expect(screen.queryByText(/After install, inspect the skill metadata/i)).toBeNull();
|
||||
expect(screen.getAllByText("Security audit").length).toBeGreaterThan(0);
|
||||
expect(screen.getByRole("link", { name: "View Security Audit" }).getAttribute("href")).toBe(
|
||||
|
||||
@@ -83,6 +83,7 @@ describe("SkillInstallSurface", () => {
|
||||
</TooltipProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole("heading", { name: "Install" })).toBeTruthy();
|
||||
expect(screen.getByText("openclaw skills install")).toBeTruthy();
|
||||
expect(screen.getByText("@steipete/weather")).toBeTruthy();
|
||||
expect(document.querySelector(".skill-install-command-verb")?.textContent).toBe(
|
||||
@@ -92,8 +93,10 @@ describe("SkillInstallSurface", () => {
|
||||
" @steipete/weather",
|
||||
);
|
||||
expect(screen.queryByText("npx clawhub@latest install @steipete/weather")).toBeNull();
|
||||
expect(screen.getByRole("tab", { name: "CLI" }).getAttribute("aria-selected")).toBe("true");
|
||||
expect(screen.getByRole("tab", { name: "Prompt" }).getAttribute("aria-selected")).toBe("false");
|
||||
expect(screen.getByRole("button", { name: "CLI" }).getAttribute("aria-pressed")).toBe("true");
|
||||
expect(screen.getByRole("button", { name: "Prompt" }).getAttribute("aria-pressed")).toBe(
|
||||
"false",
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Copy OpenClaw CLI command" }));
|
||||
|
||||
@@ -101,10 +104,12 @@ describe("SkillInstallSurface", () => {
|
||||
expect(writeTextMock).toHaveBeenCalledWith("openclaw skills install @steipete/weather");
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByRole("tab", { name: "Prompt" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "Prompt" }));
|
||||
|
||||
expect(screen.getByText(/Install the skill "Weather"/i)).toBeTruthy();
|
||||
expect(screen.getByRole("tab", { name: "Prompt" }).getAttribute("aria-selected")).toBe("true");
|
||||
expect(screen.getByRole("button", { name: "Prompt" }).getAttribute("aria-pressed")).toBe(
|
||||
"true",
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Copy OpenClaw prompt" }));
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@ export function SkillCommandLineCard({
|
||||
ownerId,
|
||||
clawdis,
|
||||
}: SkillInstallSurfaceProps) {
|
||||
const headingId = useId();
|
||||
const [activeInstallTab, setActiveInstallTab] = useState<"cli" | "prompt">("cli");
|
||||
const [installTabDirection, setInstallTabDirection] = useState<"left" | "right">("right");
|
||||
const installTarget = buildSkillInstallTarget(ownerHandle, ownerId, slug);
|
||||
@@ -215,29 +216,24 @@ export function SkillCommandLineCard({
|
||||
};
|
||||
|
||||
return (
|
||||
<article className="skill-install-command-card">
|
||||
<article className="skill-install-command-card" aria-labelledby={headingId}>
|
||||
<div className="skill-install-command-header detail-hero-summary-row">
|
||||
<h3 className="skill-install-panel-title">Install</h3>
|
||||
<div
|
||||
className="install-switcher-toggle"
|
||||
role="tablist"
|
||||
aria-label="Install option"
|
||||
data-active={activeInstallTab}
|
||||
>
|
||||
<h3 id={headingId} className="skill-install-panel-title">
|
||||
Install
|
||||
</h3>
|
||||
<div className="skill-install-tab-toggle" role="group" aria-label="Install option">
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={activeInstallTab === "cli"}
|
||||
className={`install-switcher-pill${activeInstallTab === "cli" ? " is-active" : ""}`}
|
||||
className={`skill-install-tab${activeInstallTab === "cli" ? " is-active" : ""}`}
|
||||
aria-pressed={activeInstallTab === "cli"}
|
||||
onClick={() => selectInstallTab("cli")}
|
||||
>
|
||||
CLI
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={activeInstallTab === "prompt"}
|
||||
className={`install-switcher-pill${activeInstallTab === "prompt" ? " is-active" : ""}`}
|
||||
className={`skill-install-tab${activeInstallTab === "prompt" ? " is-active" : ""}`}
|
||||
aria-pressed={activeInstallTab === "prompt"}
|
||||
onClick={() => selectInstallTab("prompt")}
|
||||
>
|
||||
Prompt
|
||||
|
||||
@@ -105,7 +105,7 @@ export function SkillDetailSkeleton({ kind = "skill" }: SkillDetailSkeletonProps
|
||||
<div className="skill-hero-main-extra">
|
||||
<div className="detail-mobile-install">
|
||||
<article className="skill-install-command-card">
|
||||
<div className="skill-install-command-header">
|
||||
<div className="skill-install-command-header detail-hero-summary-row">
|
||||
<Skeleton className="h-7 w-20" />
|
||||
{!isPlugin ? (
|
||||
<div className="detail-skeleton-install-tabs" aria-hidden="true">
|
||||
|
||||
@@ -7902,10 +7902,70 @@ code {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Skill/plugin install card — flat CLI | Prompt text toggle */
|
||||
.skill-install-command-card .skill-install-tab-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.skill-install-command-card .skill-install-tab {
|
||||
appearance: none;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 24px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
color: var(--ink-soft);
|
||||
font-family: inherit;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 650;
|
||||
letter-spacing: -0.01em;
|
||||
line-height: 1;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.skill-install-command-card .skill-install-tab + .skill-install-tab {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.skill-install-command-card .skill-install-tab + .skill-install-tab::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
width: 1px;
|
||||
height: 12px;
|
||||
transform: translateY(-50%);
|
||||
background: color-mix(in srgb, var(--ink-soft) 45%, transparent);
|
||||
}
|
||||
|
||||
.skill-install-command-card .skill-install-tab:hover {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.skill-install-command-card .skill-install-tab.is-active {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.skill-install-command-card .skill-install-tab:focus-visible {
|
||||
outline: 2px solid color-mix(in srgb, var(--ink) 35%, transparent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.skill-install-prompt-trigger,
|
||||
.skill-install-copy-button,
|
||||
.skill-install-command-reveal,
|
||||
.skill-install-tab,
|
||||
.install-switcher-toggle::before,
|
||||
.install-switcher-pill {
|
||||
transition: none;
|
||||
|
||||
Reference in New Issue
Block a user