perf(ui): render icons through an svg sprite (#26950)

This commit is contained in:
Luke Parker
2026-05-13 17:57:13 +10:00
committed by GitHub
parent e5af7ab99a
commit 3a810fcb9a

View File

@@ -1,4 +1,4 @@
import { splitProps, type ComponentProps } from "solid-js"
import { onMount, splitProps, type ComponentProps } from "solid-js"
const icons = {
"align-right": `<path d="M12.292 6.04167L16.2503 9.99998L12.292 13.9583M2.91699 9.99998H15.6253M17.0837 3.75V16.25" stroke="currentColor" stroke-linecap="square"/>`,
@@ -105,6 +105,41 @@ const icons = {
"arrow-undo-down": `<path d="M4.08333 11.0859L1.75 8.7526L4.08333 6.41927M2.33333 8.7526L12.5417 8.7526L12.5417 3.21094L7 3.21094" stroke="currentColor" stroke-width="1" stroke-linecap="square"/>`,
}
const spriteID = "opencode-icon-sprite"
const symbol = (name: keyof typeof icons) => `opencode-icon-${name}`
let spriteInserted = false
function viewBox(name: keyof typeof icons) {
return name === "magnifying-glass" || name === "arrow-undo-down" ? "0 0 16 16" : "0 0 20 20"
}
function ensureSprite() {
if (spriteInserted) return
if (typeof document === "undefined") return
if (document.getElementById(spriteID)) {
spriteInserted = true
return
}
const body = document.body as HTMLElement | null
if (!body) return
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
svg.id = spriteID
svg.setAttribute("aria-hidden", "true")
svg.setAttribute("width", "0")
svg.setAttribute("height", "0")
svg.style.position = "absolute"
svg.style.overflow = "hidden"
svg.innerHTML = Object.entries(icons)
.map(([name, path]) => {
const key = name as keyof typeof icons
return `<symbol id="${symbol(key)}" viewBox="${viewBox(key)}">${path}</symbol>`
})
.join("")
body.insertBefore(svg, body.firstChild)
spriteInserted = true
}
export interface IconProps extends ComponentProps<"svg"> {
name: keyof typeof icons
size?: "small" | "normal" | "medium" | "large"
@@ -112,8 +147,8 @@ export interface IconProps extends ComponentProps<"svg"> {
export function Icon(props: IconProps) {
const [local, others] = splitProps(props, ["name", "size", "class", "classList"])
const viewBox = () =>
local.name === "magnifying-glass" || local.name === "arrow-undo-down" ? "0 0 16 16" : "0 0 20 20"
onMount(ensureSprite)
return (
<div data-component="icon" data-size={local.size || "normal"}>
<svg
@@ -123,11 +158,12 @@ export function Icon(props: IconProps) {
[local.class ?? ""]: !!local.class,
}}
fill="none"
viewBox={viewBox()}
innerHTML={icons[local.name as keyof typeof icons]}
viewBox={viewBox(local.name)}
aria-hidden="true"
{...others}
/>
>
<use href={`#${symbol(local.name)}`} />
</svg>
</div>
)
}