From 082bcc34c2fe7a18bea628e498d937ac13bc4314 Mon Sep 17 00:00:00 2001 From: Reece Date: Wed, 17 Jun 2026 15:38:53 +0100 Subject: [PATCH] refactor(shared): extract FileDocIcon + CloudStorageIcons into @shared with stories Move two zero-coupling icon components out of the editor into the shared SUI library (frontend/shared/components), export them from the barrel, and add Storybook stories. Editor consumers now import them from @shared instead of @app. Both are fully self-contained (pure SVG, no app context, inline colours / caller-supplied className), so the move is mechanical and nothing else changes. First slice of an incremental extraction; it establishes the move + re-point + Storybook pattern to repeat for further components. --- .../fileManager/FileSourceButtons.tsx | 2 +- .../core/components/shared/FileSidebar.tsx | 2 +- .../components/shared/FileSidebarFileItem.tsx | 2 +- .../shared/filePreview/getFileTypeIcon.tsx | 4 +- .../components/CloudStorageIcons.stories.tsx | 41 ++++++++++++++++ .../components}/CloudStorageIcons.tsx | 0 .../shared/components/FileDocIcon.stories.tsx | 48 +++++++++++++++++++ .../components}/FileDocIcon.tsx | 0 frontend/shared/components/index.ts | 4 ++ 9 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 frontend/shared/components/CloudStorageIcons.stories.tsx rename frontend/{editor/src/core/components/shared => shared/components}/CloudStorageIcons.tsx (100%) create mode 100644 frontend/shared/components/FileDocIcon.stories.tsx rename frontend/{editor/src/core/components/shared => shared/components}/FileDocIcon.tsx (100%) diff --git a/frontend/editor/src/core/components/fileManager/FileSourceButtons.tsx b/frontend/editor/src/core/components/fileManager/FileSourceButtons.tsx index 6905f1bc75..3ff1fdf596 100644 --- a/frontend/editor/src/core/components/fileManager/FileSourceButtons.tsx +++ b/frontend/editor/src/core/components/fileManager/FileSourceButtons.tsx @@ -10,7 +10,7 @@ import { useFileActionIcons } from "@app/hooks/useFileActionIcons"; import { useAppConfig } from "@app/contexts/AppConfigContext"; import { useIsMobile } from "@app/hooks/useIsMobile"; import MobileUploadModal from "@app/components/shared/MobileUploadModal"; -import { GoogleDriveIcon } from "@app/components/shared/CloudStorageIcons"; +import { GoogleDriveIcon } from "@shared/components/CloudStorageIcons"; interface FileSourceButtonsProps { horizontal?: boolean; diff --git a/frontend/editor/src/core/components/shared/FileSidebar.tsx b/frontend/editor/src/core/components/shared/FileSidebar.tsx index ed4e6e75dc..7d45630a0e 100644 --- a/frontend/editor/src/core/components/shared/FileSidebar.tsx +++ b/frontend/editor/src/core/components/shared/FileSidebar.tsx @@ -26,7 +26,7 @@ import { useIndexedDBRevision, } from "@app/contexts/IndexedDBContext"; import { accountService } from "@app/services/accountService"; -import { GoogleDriveIcon } from "@app/components/shared/CloudStorageIcons"; +import { GoogleDriveIcon } from "@shared/components/CloudStorageIcons"; import { Wordmark } from "@app/components/shared/Wordmark"; import type { StirlingFileStub } from "@app/types/fileContext"; import MenuIcon from "@mui/icons-material/Menu"; diff --git a/frontend/editor/src/core/components/shared/FileSidebarFileItem.tsx b/frontend/editor/src/core/components/shared/FileSidebarFileItem.tsx index 6c5ecaba3b..6d0d355f4e 100644 --- a/frontend/editor/src/core/components/shared/FileSidebarFileItem.tsx +++ b/frontend/editor/src/core/components/shared/FileSidebarFileItem.tsx @@ -6,7 +6,7 @@ import VisibilityOutlinedIcon from "@mui/icons-material/VisibilityOutlined"; import VisibilityOffOutlinedIcon from "@mui/icons-material/VisibilityOffOutlined"; import ShieldOutlinedIcon from "@mui/icons-material/ShieldOutlined"; import type { FileId } from "@app/types/file"; -import { FileDocIcon } from "@app/components/shared/FileDocIcon"; +import { FileDocIcon } from "@shared/components/FileDocIcon"; import { getFileDocVariant } from "@app/components/shared/filePreview/getFileTypeIcon"; import { useLazyThumbnail } from "@app/hooks/useLazyThumbnail"; import { IMAGE_EXTENSIONS } from "@app/utils/fileUtils"; diff --git a/frontend/editor/src/core/components/shared/filePreview/getFileTypeIcon.tsx b/frontend/editor/src/core/components/shared/filePreview/getFileTypeIcon.tsx index 6be3d35163..48f26a90a5 100644 --- a/frontend/editor/src/core/components/shared/filePreview/getFileTypeIcon.tsx +++ b/frontend/editor/src/core/components/shared/filePreview/getFileTypeIcon.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { FileDocIcon } from "@app/components/shared/FileDocIcon"; -import type { FileDocVariant } from "@app/components/shared/FileDocIcon"; +import { FileDocIcon } from "@shared/components/FileDocIcon"; +import type { FileDocVariant } from "@shared/components/FileDocIcon"; import type { StirlingFileStub } from "@app/types/fileContext"; import { detectFileExtension } from "@app/utils/fileUtils"; diff --git a/frontend/shared/components/CloudStorageIcons.stories.tsx b/frontend/shared/components/CloudStorageIcons.stories.tsx new file mode 100644 index 0000000000..b7abaae3f5 --- /dev/null +++ b/frontend/shared/components/CloudStorageIcons.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { + GoogleDriveIcon, + OneDriveIcon, + DropboxIcon, +} from "@shared/components/CloudStorageIcons"; + +const meta: Meta = { + title: "Primitives/CloudStorageIcons", + component: GoogleDriveIcon, + tags: ["autodocs"], + parameters: { layout: "centered" }, + args: { colored: true }, + argTypes: { colored: { control: "boolean" } }, +}; +export default meta; +type Story = StoryObj; + +export const GoogleDrive: Story = {}; + +/** All providers, brand-coloured vs. muted (inherits `currentColor`). */ +export const AllProviders: Story = { + render: (args) => ( +
+ + + +
+ ), +}; + +/** Uncoloured icons take the surrounding text colour via `currentColor`. */ +export const MonochromeInheritsColor: Story = { + render: () => ( +
+ + + +
+ ), +}; diff --git a/frontend/editor/src/core/components/shared/CloudStorageIcons.tsx b/frontend/shared/components/CloudStorageIcons.tsx similarity index 100% rename from frontend/editor/src/core/components/shared/CloudStorageIcons.tsx rename to frontend/shared/components/CloudStorageIcons.tsx diff --git a/frontend/shared/components/FileDocIcon.stories.tsx b/frontend/shared/components/FileDocIcon.stories.tsx new file mode 100644 index 0000000000..7a9c4cbab6 --- /dev/null +++ b/frontend/shared/components/FileDocIcon.stories.tsx @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { + FileDocIcon, + VARIANT_COLORS, + type FileDocVariant, +} from "@shared/components/FileDocIcon"; + +const VARIANTS = Object.keys(VARIANT_COLORS) as FileDocVariant[]; + +const meta: Meta = { + title: "Primitives/FileDocIcon", + component: FileDocIcon, + tags: ["autodocs"], + parameters: { layout: "centered" }, + args: { variant: "pdf" }, + argTypes: { + variant: { control: "inline-radio", options: VARIANTS }, + color: { control: "color" }, + }, +}; +export default meta; +type Story = StoryObj; + +export const Pdf: Story = {}; + +/** Every file-type variant, each in its default brand colour. */ +export const AllVariants: Story = { + render: () => ( +
+ {VARIANTS.map((variant) => ( +
+ + + {variant} + +
+ ))} +
+ ), +}; + +/** The colour can be overridden to match any surface. */ +export const CustomColour: Story = { + args: { variant: "generic", color: "#2563eb" }, +}; diff --git a/frontend/editor/src/core/components/shared/FileDocIcon.tsx b/frontend/shared/components/FileDocIcon.tsx similarity index 100% rename from frontend/editor/src/core/components/shared/FileDocIcon.tsx rename to frontend/shared/components/FileDocIcon.tsx diff --git a/frontend/shared/components/index.ts b/frontend/shared/components/index.ts index 82dd4dd159..5734eacefa 100644 --- a/frontend/shared/components/index.ts +++ b/frontend/shared/components/index.ts @@ -39,3 +39,7 @@ export * from "@shared/components/Select"; export * from "@shared/components/Checkbox"; export * from "@shared/components/Radio"; export * from "@shared/components/Slider"; + +// Icons +export * from "@shared/components/FileDocIcon"; +export * from "@shared/components/CloudStorageIcons";