mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
feat(dsh-plugin-browserskill): reskin the overlay with BrowserSkill's own UI system
The previous pass aligned the observation overlay with the dsh shell; the product call is the opposite direction — the floating card should read as a BrowserSkill surface, not a shell-native widget. - Reuse @browser-skill/ui directly (Button, cn); status dots spec'd after the extension popup's ConnectionStatusIndicator; Remix icons for interrupt/pin/warn/pop-out. - Compile the BSK tailwind utility sheet scoped under the .bsk-obs root class (scripts/build-client-css.mjs + postcss-prefix-selector) and ship the oklch design tokens on the same scope, so nothing leaks into the host shell and the shell theme cannot bleed back. tsdown injects .nomodule.css verbatim (minified, unhashed) alongside the hashed CSS modules. - BSK ships no shared tooltip, so the one-time interrupt semantics hint is a card-spec bubble (bg-card/border/12px radius), retired after first use. - Tests: pin react/react-dom to this package's 18.x copies in vitest — the ui package sources peer on react ^19 and would otherwise emit react-19 (transitional) elements that the react-18 renderer rejects. Production is unaffected (react stays external, provided by the shell). - stylelint: ignore the generated bsk-ui.nomodule.css.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Build the scoped BrowserSkill-UI utility sheet for the dsh client bundle.
|
||||
*
|
||||
* The overlay reuses @browser-skill/ui components (shadcn-style, Tailwind v4
|
||||
* utility classes). Those classes need a stylesheet — but a global utility
|
||||
* sheet inside the dsh page would collide with the host UI, so the compiled
|
||||
* output is scope-prefixed under `.bsk-obs` (the overlay root class):
|
||||
* 1. tailwindcss compiles the utilities used by packages/ui + our client;
|
||||
* 2. postcss-prefix-selector nests every rule under .bsk-obs.
|
||||
* Token values themselves live in src/client/bsk-tokens.nomodule.css
|
||||
* (hand-mirrored from packages/ui/src/styles/tailwind.css).
|
||||
*
|
||||
* Output: src/client/bsk-ui.nomodule.css (gitignored build artifact).
|
||||
*/
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import postcss from "postcss";
|
||||
import prefixer from "postcss-prefix-selector";
|
||||
|
||||
const pkgRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
||||
const input = join(pkgRoot, ".bsk-ui.input.css");
|
||||
const rawOut = join(pkgRoot, ".bsk-ui.raw.css");
|
||||
const finalOut = join(pkgRoot, "src/client/bsk-ui.nomodule.css");
|
||||
|
||||
// The canonical sheet can't be imported directly (its own `@import
|
||||
// "tailwindcss"` must resolve from a package that has it), so we inline the
|
||||
// canonical @theme block read from packages/ui at build time.
|
||||
const canonical = readFileSync(join(pkgRoot, "..", "ui", "src", "styles", "tailwind.css"), "utf8");
|
||||
const themeBlock = canonical.match(/@theme inline \{[\s\S]*?\n\}/)?.[0];
|
||||
if (themeBlock === undefined) throw new Error("canonical @theme inline block not found");
|
||||
writeFileSync(
|
||||
input,
|
||||
[
|
||||
'@import "tailwindcss";',
|
||||
"@custom-variant dark (&:is(.dark *));",
|
||||
themeBlock,
|
||||
'@source "../ui/src";',
|
||||
'@source "./src/client";',
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
execFileSync(
|
||||
process.execPath,
|
||||
[
|
||||
join(pkgRoot, "node_modules", "@tailwindcss", "cli", "dist", "index.mjs"),
|
||||
"-i",
|
||||
input,
|
||||
"-o",
|
||||
rawOut,
|
||||
],
|
||||
{ cwd: pkgRoot, stdio: "inherit" },
|
||||
);
|
||||
|
||||
const result = await postcss([
|
||||
prefixer({
|
||||
prefix: ".bsk-obs",
|
||||
transform(prefix, selector, prefixedSelector) {
|
||||
// Root-level anchors collapse onto the scope root itself.
|
||||
if (selector === ":root" || selector === "html" || selector === "body") return prefix;
|
||||
if (selector.startsWith(prefix)) return selector;
|
||||
return prefixedSelector;
|
||||
},
|
||||
}),
|
||||
]).process(readFileSync(rawOut, "utf8"), { from: rawOut });
|
||||
|
||||
mkdirSync(dirname(finalOut), { recursive: true });
|
||||
writeFileSync(finalOut, result.css);
|
||||
console.log(`bsk-ui sheet: ${result.css.length} bytes -> ${finalOut}`);
|
||||
Reference in New Issue
Block a user