From d007bd0a6f1f4e2fefec521f1c8f83d424b930b4 Mon Sep 17 00:00:00 2001 From: ZhaiSoul <842607283@qq.com> Date: Tue, 21 Apr 2026 22:23:09 +0800 Subject: [PATCH] docs: add more icon support --- .../components/DeviceSelector.tsx | 96 ++++++++++++++++++- .../DockerComposeGenerator/config/config.yaml | 46 +++++++-- .../DockerComposeGenerator/config/types.ts | 35 ++++++- .../DockerComposeGenerator/styles.module.css | 34 +++++++ 4 files changed, 202 insertions(+), 9 deletions(-) diff --git a/docs/src/components/DockerComposeGenerator/components/DeviceSelector.tsx b/docs/src/components/DockerComposeGenerator/components/DeviceSelector.tsx index 81338db20..ddad16050 100644 --- a/docs/src/components/DockerComposeGenerator/components/DeviceSelector.tsx +++ b/docs/src/components/DockerComposeGenerator/components/DeviceSelector.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { useColorMode } from "@docusaurus/theme-common"; import { devices } from "../config"; import type { DeviceConfig } from "../config"; import styles from "../styles.module.css"; @@ -8,6 +9,99 @@ interface Props { onSelect: (id: string) => void; } +/** + * Determine the icon type from the icon string: + * - Starts with " tag. + */ +function hasBackgroundProps(style: React.CSSProperties | undefined): boolean { + if (!style) return false; + return Object.keys(style).some((key) => { + const k = key.toLowerCase().replace(/-/g, ""); + return k === "backgroundsize" || k === "backgroundposition" || k === "backgroundrepeat" || k === "backgroundimage"; + }); +} + +/** + * Convert a style object to CSS custom properties (e.g. { width: "24px" } → { "--svg-width": "24px" }) + * so they can be consumed by CSS rules targeting child elements like . + */ +function toCssVars(style: React.CSSProperties | undefined, prefix: string): React.CSSProperties { + if (!style) return {}; + const vars: Record = {}; + for (const [key, value] of Object.entries(style)) { + const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase(); + vars[`--${prefix}-${cssKey}`] = value; + } + return vars as React.CSSProperties; +} + +function DeviceIcon({ device }: { device: DeviceConfig }) { + const { isDarkTheme } = useColorMode(); + const iconStr = isDarkTheme && device.iconDark ? device.iconDark : device.icon; + const iconStyle = (isDarkTheme && device.iconDarkStyle + ? device.iconDarkStyle + : device.iconStyle) as React.CSSProperties | undefined; + const svgStyle = (isDarkTheme && device.svgDarkStyle + ? device.svgDarkStyle + : device.svgStyle) as React.CSSProperties | undefined; + + const iconType = getIconType(iconStr); + + if (iconType === "svg") { + return ( +
+ ); + } + + if (iconType === "image") { + // When iconStyle contains background-* properties, render as background-image + // on the container div instead of an tag, enabling background-size/position control. + if (hasBackgroundProps(iconStyle)) { + return ( +
+ ); + } + return ( +
+ {device.name} +
+ ); + } + + return ( +
+ {iconStr} +
+ ); +} + function DeviceCard({ device, active, @@ -27,7 +121,7 @@ function DeviceCard({ if (e.key === "Enter" || e.key === " ") onClick(); }} > -
{device.icon}
+
{device.name}
{device.description}
diff --git a/docs/src/components/DockerComposeGenerator/config/config.yaml b/docs/src/components/DockerComposeGenerator/config/config.yaml index deebafdbf..69058fc57 100644 --- a/docs/src/components/DockerComposeGenerator/config/config.yaml +++ b/docs/src/components/DockerComposeGenerator/config/config.yaml @@ -12,7 +12,7 @@ devices: - id: "intel" name: "Intel Device" description: "Intel GPU / NPU" - icon: "🖥️" + icon: '' imageTag: "stable" autoHardware: - "gpu" @@ -23,7 +23,12 @@ devices: - id: "stable-tensorrt" name: "NVIDIA GPU" description: "NVIDIA acceleration" - icon: "🟢" + icon: '' + svgStyle: + width: 50px + height: 50px + iconStyle: + padding-bottom: 15px imageTag: "stable-tensorrt" autoHardware: [] helpText: "Requires the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker) to be installed. GPU deploy resources are configured automatically." @@ -33,7 +38,12 @@ devices: - id: "stable-tensorrt-jp6" name: "NVIDIA Jetson" description: "Jetson development board" - icon: "🟢" + icon: '' + svgStyle: + width: 50px + height: 50px + iconStyle: + padding-bottom: 15px imageTag: "stable-tensorrt-jp6" autoHardware: [] helpText: "NVIDIA Jetson devices automatically configure runtime: nvidia." @@ -43,7 +53,18 @@ devices: - id: "stable-rocm" name: "AMD GPU" description: "ROCm acceleration" - icon: "🔴" + icon: "https://www.amd.com/content/dam/code/images/header/amd-header-logo.svg" + iconStyle: + filter: invert(1) + background-repeat: no-repeat + background-position: right center + background-size: 338% 90% + iconDark: "https://www.amd.com/content/dam/code/images/header/amd-header-logo.svg" + iconDarkStyle: + filter: invert(0) + background-repeat: no-repeat + background-position: right center + background-size: 338% 90% imageTag: "stable-rocm" autoHardware: - "gpu" @@ -55,7 +76,14 @@ devices: - id: "apple-silicon" name: "Apple Silicon" description: "Mac M-series processor" - icon: "🍎" + icon: '' + svgStyle: + width: 90px + height: 90px + svgDarkStyle: + width: 90px + height: 90px + fill: white imageTag: "stable" imageTagSuffix: "-standard-arm64" autoHardware: [] @@ -67,7 +95,11 @@ devices: - id: "raspberry-pi" name: "Raspberry Pi" description: "ARM device" - icon: "🍓" + icon: '' + svgStyle: + width: 40px + height: 40px + transform: translateX(-3px) imageTag: "stable" imageTagSuffix: "-standard-arm64" autoHardware: @@ -78,7 +110,7 @@ devices: - id: "stable-rk" name: "Rockchip" description: "Rockchip SoC board" - icon: "🪨" + icon: "https://www.rock-chips.com/favicon.ico" imageTag: "stable-rk" autoHardware: - "gpu" diff --git a/docs/src/components/DockerComposeGenerator/config/types.ts b/docs/src/components/DockerComposeGenerator/config/types.ts index 5be12530a..6d9b048f0 100644 --- a/docs/src/components/DockerComposeGenerator/config/types.ts +++ b/docs/src/components/DockerComposeGenerator/config/types.ts @@ -42,8 +42,41 @@ export interface DeviceConfig { name: string; /** Short description */ description: string; - /** Icon emoji or identifier */ + /** + * Icon for the device card. Supports: + * - Emoji string (e.g. "🖥️") + * - Image URL or static path (e.g. "/img/intel.svg", "https://example.com/icon.png") + * - Inline SVG markup (e.g. "...") + */ icon: string; + /** + * Additional CSS properties applied to the icon element. + * - For image-type icons: if any `background-*` property (e.g. `background-size`, + * `background-position`) is present, the image is rendered as a CSS `background-image` + * on the container div, enabling full background positioning control. + * Otherwise the image is rendered as an `` tag and styles apply to it. + * - For emoji/SVG icons: styles apply to the container div. + */ + iconStyle?: Record; + /** + * Additional CSS properties applied directly to the inner `` element + * when the icon is an inline SVG. Use this to override the default + * `width: 100%; height: 100%` or set `fill`, `transform`, etc. + * Ignored for emoji and image-type icons. + */ + svgStyle?: Record; + /** + * Icon for dark mode. Same format as `icon`. When provided, this icon + * replaces `icon` when the user is in dark mode. + */ + iconDark?: string; + /** Additional CSS properties for the dark mode icon container */ + iconDarkStyle?: Record; + /** + * SVG-specific styles for dark mode. Same as `svgStyle` but applied + * when dark mode is active. Merged over `svgStyle` in dark mode. + */ + svgDarkStyle?: Record; /** Docker image tag, e.g. "stable" */ imageTag: string; /** diff --git a/docs/src/components/DockerComposeGenerator/styles.module.css b/docs/src/components/DockerComposeGenerator/styles.module.css index 0b7429ece..62ecb1b6f 100644 --- a/docs/src/components/DockerComposeGenerator/styles.module.css +++ b/docs/src/components/DockerComposeGenerator/styles.module.css @@ -180,6 +180,40 @@ justify-content: center; } +.deviceIconSvg { + margin-bottom: 0.25rem; + height: 40px; + width: 50px; + display: flex; + align-items: center; + justify-content: center; + overflow: visible; + /* Allow iconStyle width/height to override */ + flex-shrink: 0; +} + +.deviceIconSvg svg { + width: var(--svg-width, 100%); + height: var(--svg-height, 100%); + fill: var(--svg-fill, currentColor); + transform: var(--svg-transform, none); +} + +.deviceIconImage { + margin-bottom: 0.25rem; + height: 40px; + width: 50px; + display: flex; + align-items: center; + justify-content: center; +} + +.deviceIconImage img { + max-width: 100%; + max-height: 100%; + object-fit: contain; +} + .deviceName { font-weight: var(--ifm-font-weight-semibold); color: var(--ifm-font-color-base);