Skip to content

Commit d541fdd

Browse files
committed
feat(app-onboard): brand the rail and name every chip on hover
Swaps the icon set for the one the app ships. This app was scaffolded from the neo onboarding and inherited its blue mark, so the rail was showing the wrong product. Retitles the rail to state what BrowserOS is rather than who it is for. Adds a tooltip to every provider and agent chip. The row is a wall of brand marks and several are only recognisable to people who already use them, so the name now surfaces on hover instead of only in the accessible name. Hermes ships as an icon/ resource rather than a monogram. Its mark is a full-bleed illustration, so it is referenced by runtime path and registered in the onboarding resource target; importing it would let Vite rewrite it into an asset the Chromium build rejects.
1 parent 5152c1e commit d541fdd

14 files changed

Lines changed: 166 additions & 74 deletions

File tree

-1.22 KB
Loading
-490 Bytes
Loading
-434 Bytes
Loading
-706 Bytes
Loading
225 Bytes
Loading
14.6 KB
Loading

packages/browseros-agent/apps/app-onboard/scripts/verify-chromium-build.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const iconResourceFiles = [
1313
'icon/96.png',
1414
'icon/128.png',
1515
'icon/keychain-prompt.png',
16+
'icon/hermes.png',
1617
]
1718
const allowedFiles = new Set([...textResourceFiles, ...iconResourceFiles])
1819
const fontAssetPattern = /\.(?:woff2?|ttf|otf)$/i
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
2+
3+
import { cn } from "@/lib/utils"
4+
5+
function TooltipProvider({
6+
delay = 0,
7+
...props
8+
}: TooltipPrimitive.Provider.Props) {
9+
return (
10+
<TooltipPrimitive.Provider
11+
data-slot="tooltip-provider"
12+
delay={delay}
13+
{...props}
14+
/>
15+
)
16+
}
17+
18+
function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
19+
return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
20+
}
21+
22+
function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
23+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
24+
}
25+
26+
function TooltipContent({
27+
className,
28+
side = "top",
29+
sideOffset = 4,
30+
align = "center",
31+
alignOffset = 0,
32+
children,
33+
...props
34+
}: TooltipPrimitive.Popup.Props &
35+
Pick<
36+
TooltipPrimitive.Positioner.Props,
37+
"align" | "alignOffset" | "side" | "sideOffset"
38+
>) {
39+
return (
40+
<TooltipPrimitive.Portal>
41+
<TooltipPrimitive.Positioner
42+
align={align}
43+
alignOffset={alignOffset}
44+
side={side}
45+
sideOffset={sideOffset}
46+
className="isolate z-50"
47+
>
48+
<TooltipPrimitive.Popup
49+
data-slot="tooltip-content"
50+
className={cn(
51+
"z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
52+
className
53+
)}
54+
{...props}
55+
>
56+
{children}
57+
<TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" />
58+
</TooltipPrimitive.Popup>
59+
</TooltipPrimitive.Positioner>
60+
</TooltipPrimitive.Portal>
61+
)
62+
}
63+
64+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }

packages/browseros-agent/apps/app-onboard/src/onboarding/components/AgentBrandMarks.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
11
/**
22
* Marks for agents that @lobehub/icons does not carry.
33
*
4-
* These are inline single-colour SVGs rather than imported image files: the
5-
* Chromium build emits exactly app.js, app.css and the icon/ directory listed
6-
* in that target's BUILD.gn, so any Vite-processed asset either throws during
7-
* the build or trips the data: URL guard in verify-chromium-build.
4+
* Vector marks are inlined rather than imported: the Chromium build emits only
5+
* app.js, app.css and the icon/ files listed in that target's BUILD.gn, so a
6+
* Vite-processed asset either throws during the build or trips the data: URL
7+
* guard in verify-chromium-build. Raster marks are referenced by their runtime
8+
* path under public/icon instead, which Vite copies through untouched.
89
*/
910

1011
interface MarkProps {
1112
size?: number
1213
}
1314

15+
/**
16+
* Hermes. Raster mark, so it ships as an icon/ resource rather than a path.
17+
*
18+
* Sized a little larger than the vector marks and rounded: it is a full-bleed
19+
* illustration rather than a glyph, so at glyph size it reads as a framed
20+
* thumbnail sitting inside the chip instead of as the chip's own icon.
21+
*/
22+
export function Hermes({ size = 24 }: MarkProps) {
23+
return (
24+
<img
25+
src="/icon/hermes.png"
26+
alt=""
27+
width={Math.round(size * 1.3)}
28+
height={Math.round(size * 1.3)}
29+
className="rounded-[7px] object-contain"
30+
/>
31+
)
32+
}
33+
1434
/**
1535
* OpenClaw. Silhouette of the mark the app ships, flattened to one colour.
1636
*

packages/browseros-agent/apps/app-onboard/src/onboarding/components/VisualRail.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ describe('VisualRail', () => {
1010
// import would emit a new hashed asset and fail verify-chromium-build.ts.
1111
expect(html).toContain('src="/icon/128.png"')
1212
expect(html).toContain('BrowserOS')
13+
expect(html).toContain('agentic browser')
14+
expect(html).toContain('automate any web task')
1315
expect(html).toContain('Bring your browser')
1416
expect(html).toContain('Local-first. Private.')
1517
})

0 commit comments

Comments
 (0)