diff --git a/CLAUDE.md b/CLAUDE.md index e5a20535..ceeb8ce7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -88,6 +88,16 @@ Prefer action-driven updates, explicit handlers, and localized state transitions Existing `styled-components` usage is legacy tech debt — do not migrate it wholesale, but do not add new `styled-components` either. Theme tokens (`var(--ant-color-*)`) work in all three approaches. +## Layout + +Compose layout with Ant components, not hand-written `display: flex`. + +- **1D flex** (row/column with `gap`, `align`, `justify`) → `Flex`. Do not write raw `display: flex` in new code. +- **Inline sequence** of a few elements with uniform spacing → `Space`. +- **Page/grid columns** → `Row` / `Col`. + +Drive spacing with the theme scale (`Flex`/`Space` `gap`, or `var(--ant-*)` spacing tokens), not scattered `px` literals. + # Naming conventions A page module lives under `src/pages/{module}` with this sub-structure: `components/`, `config/`, `forms/`, `hooks/`, `services/`, `index.tsx`. File naming: @@ -101,6 +111,7 @@ A page module lives under `src/pages/{module}` with this sub-structure: `compone - `config/types.ts` — TypeScript types. Form shape → `FormData`; table/list row → `ListItem`. - `config/index.ts` — static constants, enums, and value/label maps (e.g. `XxxStatusValueMap`, `XxxStatusLabelMap`). Keep constants out of `types.ts`. +- **`Select` options that need i18n**: set `label` to the message key and add `locale: true` on the option — the field translates it at render. Omit `locale` for options whose label is already final text. Ref `src/pages/benchmark/config/index.ts`. # Common components diff --git a/src/assets/logo/pytorch-light.png b/src/assets/logo/pytorch_light.png similarity index 100% rename from src/assets/logo/pytorch-light.png rename to src/assets/logo/pytorch_light.png diff --git a/src/pages/benchmark/components/detail-content.tsx b/src/pages/benchmark/components/detail-content.tsx index 88b64788..52fe2f92 100644 --- a/src/pages/benchmark/components/detail-content.tsx +++ b/src/pages/benchmark/components/detail-content.tsx @@ -1,5 +1,5 @@ import { IconFont } from '@gpustack/core-ui'; -import { useIntl, useSearchParams } from '@umijs/max'; +import { useIntl } from '@umijs/max'; import { Tabs, TabsProps } from 'antd'; import React, { useState } from 'react'; import Environment from './environment'; @@ -12,7 +12,6 @@ const Details: React.FC<{ }> = ({ tabBarExtraContent }) => { const intl = useIntl(); const [activeKey, setActiveKey] = useState('summary'); - const [searchParams] = useSearchParams(); const items: TabsProps['items'] = [ { diff --git a/src/pages/gpu-service/templates/components/template-card.tsx b/src/pages/gpu-service/templates/components/template-card.tsx index 9b089823..4ea4a610 100644 --- a/src/pages/gpu-service/templates/components/template-card.tsx +++ b/src/pages/gpu-service/templates/components/template-card.tsx @@ -7,6 +7,7 @@ import metaxLogo from '@/assets/logo/metax.png'; import mooreLogo from '@/assets/logo/moore-logo.png'; import nvidiaLogo from '@/assets/logo/nvidia.png'; import pytorchBlackLogo from '@/assets/logo/pytorch_black.png'; +import pytorchLightLogo from '@/assets/logo/pytorch_light.png'; import sgLangLogo from '@/assets/logo/sglang.png'; import theadLogoEN from '@/assets/logo/t-head-en.png'; import theadLogoZH from '@/assets/logo/t-head-zh.png'; @@ -14,6 +15,7 @@ import tensorflowkLogo from '@/assets/logo/tensorflow.svg'; import ubuntuLogo from '@/assets/logo/ubuntu_logo.png'; import vllmLogo from '@/assets/logo/vllm.png'; import PluginExtraFields from '@/components/plugin-extra-fields'; +import useUserSettings from '@/hooks/use-user-settings'; import OwnerTag from '@/pages/gpu-service/components/owner-tag'; import { GPUsConfigs, @@ -33,7 +35,8 @@ import styled from 'styled-components'; import { manufactureColorMap, templateActions } from '../config'; import { ListItem } from '../config/types'; -const imageLogoMap = { +// Light theme logos +const imageLogoLightMap = { vllm: vllmLogo, sglang: sgLangLogo, jupyter: jupyterLogo, @@ -42,25 +45,31 @@ const imageLogoMap = { ubuntu: ubuntuLogo } as const; +// Dark theme logos: inherit light, override only the ones that need a variant +const imageLogoDarkMap: typeof imageLogoLightMap = { + ...imageLogoLightMap, + pytorch: pytorchLightLogo +}; + const matchImageLogo = ( - image: string | undefined + image: string | undefined, + isDark: boolean ): { logo: string; type: string } | null => { if (!image) return null; + const logoMap = imageLogoLightMap; const lower = image.toLowerCase(); - let matched: keyof typeof imageLogoMap | null = null; + let matched: keyof typeof logoMap | null = null; let earliest = Infinity; - (Object.keys(imageLogoMap) as Array).forEach( - (key) => { - const idx = lower.indexOf(key); - if (idx !== -1 && idx < earliest) { - earliest = idx; - matched = key; - } + (Object.keys(logoMap) as Array).forEach((key) => { + const idx = lower.indexOf(key); + if (idx !== -1 && idx < earliest) { + earliest = idx; + matched = key; } - ); + }); return matched ? { - logo: imageLogoMap[matched], + logo: logoMap[matched], type: matched } : null; @@ -135,6 +144,7 @@ interface TemplateCardProps { const TemplateCardItem: React.FC = ({ data, onSelect }) => { const intl = useIntl(); + const { isDarkTheme } = useUserSettings(); const manufacturerLabelMap: Record = useMemo(() => { return Object.values(GPUsConfigs).reduce( @@ -158,7 +168,7 @@ const TemplateCardItem: React.FC = ({ data, onSelect }) => { }; const renderLogo = () => { - const imageLogo = matchImageLogo(data.spec?.image); + const imageLogo = matchImageLogo(data.spec?.image, isDarkTheme); if (imageLogo?.logo) { return (