From 275d70242e88a902987ace7bb53d3dd27c6ccb68 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:01:11 +0100 Subject: [PATCH] Portal Editor admin: replace glyph icons with SVGs (#6999) # Description of Changes Swaps the emoji and box glyphs in the editor deployment, pairing and storage panels for tinted icons consistent with the rest of the portal. Part of a portal (processor) UI-consistency pass, split into small focused PRs. --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [x] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have run `task check` to verify linters, typechecks, and tests pass - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing) for more details. --- .../editor/src/portal/api/editorDeploy.ts | 7 +- .../editor-admin/DeploymentTargets.tsx | 18 ++++- .../components/editor-admin/PairingPanel.tsx | 25 ++++-- .../components/infrastructure/StorageTab.tsx | 78 ++++++++++--------- .../editor/src/portal/views/EditorAdmin.css | 22 +++++- 5 files changed, 100 insertions(+), 50 deletions(-) diff --git a/frontend/editor/src/portal/api/editorDeploy.ts b/frontend/editor/src/portal/api/editorDeploy.ts index 67952d8bb4..e90cac89c3 100644 --- a/frontend/editor/src/portal/api/editorDeploy.ts +++ b/frontend/editor/src/portal/api/editorDeploy.ts @@ -119,14 +119,13 @@ export interface EditorDeploymentResponse { /* ──────────────────────────────────────────────────────────────────────── */ export interface TargetMeta { - icon: string; tone: "neutral" | "blue" | "purple"; } export const TARGET_META: Record = { - cloud: { icon: "☁", tone: "blue" }, - docker: { icon: "▣", tone: "neutral" }, - kubernetes: { icon: "⎈", tone: "purple" }, + cloud: { tone: "blue" }, + docker: { tone: "neutral" }, + kubernetes: { tone: "purple" }, }; export const INSTANCE_STATUS_TONE: Record< diff --git a/frontend/editor/src/portal/components/editor-admin/DeploymentTargets.tsx b/frontend/editor/src/portal/components/editor-admin/DeploymentTargets.tsx index 7add4fd8b5..2348b6311e 100644 --- a/frontend/editor/src/portal/components/editor-admin/DeploymentTargets.tsx +++ b/frontend/editor/src/portal/components/editor-admin/DeploymentTargets.tsx @@ -1,8 +1,21 @@ import { useTranslation } from "react-i18next"; +import CloudQueueRounded from "@mui/icons-material/CloudQueueRounded"; +import HubRounded from "@mui/icons-material/HubRounded"; +import Inventory2Rounded from "@mui/icons-material/Inventory2Rounded"; import { Button, Card, CodeBlock, StatusBadge } from "@app/ui"; -import { TARGET_META, type DeploymentTarget } from "@portal/api/editorDeploy"; +import { + TARGET_META, + type DeploymentTarget, + type TargetKind, +} from "@portal/api/editorDeploy"; import { useTier } from "@portal/contexts/TierContext"; +const TARGET_ICON: Record = { + cloud: CloudQueueRounded, + docker: Inventory2Rounded, + kubernetes: HubRounded, +}; + const STATE_BADGE_TONE: Record< DeploymentTarget["state"], "success" | "info" | "neutral" @@ -36,6 +49,7 @@ export function DeploymentTargets({ targets, onUpgrade }: Props) {
{targets.map((target) => { const meta = TARGET_META[target.kind]; + const Icon = TARGET_ICON[target.kind]; const locked = target.state === "locked"; return ( - {meta.icon} +

{target.label}

diff --git a/frontend/editor/src/portal/components/editor-admin/PairingPanel.tsx b/frontend/editor/src/portal/components/editor-admin/PairingPanel.tsx index 6544ab1967..ea14ffd669 100644 --- a/frontend/editor/src/portal/components/editor-admin/PairingPanel.tsx +++ b/frontend/editor/src/portal/components/editor-admin/PairingPanel.tsx @@ -1,12 +1,21 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; +import CastRounded from "@mui/icons-material/CastRounded"; +import TerminalRounded from "@mui/icons-material/TerminalRounded"; +import VpnKeyRounded from "@mui/icons-material/VpnKeyRounded"; import { Button, Card, Chip, CodeBlock } from "@app/ui"; import type { PairingMethod, PairingOption } from "@portal/api/editorDeploy"; -const METHOD_ICON: Record = { - token: "🔑", - shortcode: "📺", - iac: "🧱", +const METHOD_ICON: Record = { + token: VpnKeyRounded, + shortcode: CastRounded, + iac: TerminalRounded, +}; + +const METHOD_TONE: Record = { + token: "blue", + shortcode: "purple", + iac: "green", }; interface Props { @@ -36,6 +45,7 @@ export function PairingPanel({ pairings, onUpgrade }: Props) {
{pairings.map((p) => { const isCode = p.method === "iac"; + const Icon = METHOD_ICON[p.method]; return (
- - {METHOD_ICON[p.method]} + +

{p.label}

diff --git a/frontend/editor/src/portal/components/infrastructure/StorageTab.tsx b/frontend/editor/src/portal/components/infrastructure/StorageTab.tsx index a1f3b91869..49033345e1 100644 --- a/frontend/editor/src/portal/components/infrastructure/StorageTab.tsx +++ b/frontend/editor/src/portal/components/infrastructure/StorageTab.tsx @@ -1,5 +1,8 @@ -import { useState } from "react"; +import { useState, type ComponentType, type CSSProperties } from "react"; import { useTranslation } from "react-i18next"; +import ArrowForwardRounded from "@mui/icons-material/ArrowForwardRounded"; +import CloudRounded from "@mui/icons-material/CloudRounded"; +import StorageRounded from "@mui/icons-material/StorageRounded"; import { Button, Card, @@ -20,13 +23,13 @@ import { import { SectionHeader } from "@portal/components/infrastructure/SectionHeader"; import { pct } from "@portal/components/infrastructure/infraFormat"; -const PROVIDER_GLYPH: Record< +const PROVIDER_ICON: Record< StorageConfig["providers"][number]["kind"], - string + ComponentType<{ style?: CSSProperties }> > = { - stirling: "◆", - s3: "▣", - azure: "▤", + stirling: StorageRounded, + s3: CloudRounded, + azure: CloudRounded, }; /** Storage fills past this fraction of quota are surfaced in red. */ @@ -143,35 +146,38 @@ export function StorageTab() { sub={t("portal.infrastructure.storage.providers.subheading")} />
    - {data.providers.map((p) => ( -
  • - - {PROVIDER_GLYPH[p.kind]} - - - {p.name} - {p.detail} - - {p.connected ? ( - - - {t("portal.infrastructure.storage.gbValue", { - value: p.usedGb, - })} - - - {t("portal.infrastructure.storage.providers.connected")} - + {data.providers.map((p) => { + const ProviderIcon = PROVIDER_ICON[p.kind]; + return ( +
  • + + - ) : ( - // TODO(backend): launch the provider OAuth/credential flow, - // then POST /v1/infrastructure/storage/providers/{id}/connect - - )} -
  • - ))} + + {p.name} + {p.detail} + + {p.connected ? ( + + + {t("portal.infrastructure.storage.gbValue", { + value: p.usedGb, + })} + + + {t("portal.infrastructure.storage.providers.connected")} + + + ) : ( + // TODO(backend): launch the provider OAuth/credential flow, + // then POST /v1/infrastructure/storage/providers/{id}/connect + + )} + + ); + })}
@@ -205,7 +211,7 @@ export function StorageTab() {
- → +
@@ -217,7 +223,7 @@ export function StorageTab() {
- → +
diff --git a/frontend/editor/src/portal/views/EditorAdmin.css b/frontend/editor/src/portal/views/EditorAdmin.css index 92dc1d384e..2fda00cda5 100644 --- a/frontend/editor/src/portal/views/EditorAdmin.css +++ b/frontend/editor/src/portal/views/EditorAdmin.css @@ -181,8 +181,26 @@ } .portal-editor__pairing-icon { - font-size: 1.125rem; - line-height: 1.4; + display: inline-flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + flex-shrink: 0; + border-radius: var(--radius-md); +} + +.portal-editor__pairing-icon--blue { + background: var(--color-blue-light); + color: var(--color-blue); +} +.portal-editor__pairing-icon--purple { + background: var(--color-purple-light); + color: var(--color-purple); +} +.portal-editor__pairing-icon--green { + background: var(--color-green-light); + color: var(--color-green); } .portal-editor__pairing-titles {