From e04bfc72da0efa2ab74eb468a77d747b343b90f2 Mon Sep 17 00:00:00 2001 From: Mateusz Bartosik Date: Mon, 10 Nov 2025 10:52:50 +0100 Subject: [PATCH 1/3] RDoc-3566 List out all the available icons in a template --- scripts/generate-icon-types.js | 11 ++- src/components/IconGallery/IconGallery.tsx | 20 +++++ .../IconGallery/IconGalleryCard.tsx | 44 +++++++++++ static/icons/backup-history.svg | 2 +- templates/icon-gallery.mdx | 74 +++++++++++++++++++ 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 src/components/IconGallery/IconGallery.tsx create mode 100644 src/components/IconGallery/IconGalleryCard.tsx create mode 100644 templates/icon-gallery.mdx diff --git a/scripts/generate-icon-types.js b/scripts/generate-icon-types.js index 3e11685f82..3271190f96 100644 --- a/scripts/generate-icon-types.js +++ b/scripts/generate-icon-types.js @@ -14,12 +14,21 @@ function generateIconTypes() { return ` | '${name}'`; }); + const iconNamesArray = svgFiles.map((file) => { + const name = path.basename(file, ".svg"); + return ` '${name}'`; + }); + const typesContent = `export type IconName = ${iconNames.join("\n")}; + +export const ALL_ICON_NAMES = [ +${iconNamesArray.join(",\n")} +] as const; `; fs.writeFileSync(TYPES_FILE, typesContent); - console.log(`Generated icon types for ${svgFiles.length} icons:`); + console.log(`Generated icon types for ${svgFiles.length} icons`); } catch (error) { console.error("Error generating icon types:", error); process.exit(1); diff --git a/src/components/IconGallery/IconGallery.tsx b/src/components/IconGallery/IconGallery.tsx new file mode 100644 index 0000000000..5fdf2f7fe1 --- /dev/null +++ b/src/components/IconGallery/IconGallery.tsx @@ -0,0 +1,20 @@ +import React, { useMemo } from "react"; +import IconCard from "./IconGalleryCard"; +import { ALL_ICON_NAMES } from "../../typescript/iconName"; + +export default function IconGallery() { + const iconNames = useMemo(() => { + return [...ALL_ICON_NAMES].sort(); + }, []); + + return ( +
+
+ {iconNames.map((iconName) => ( + + ))} +
+
+ ); +} + diff --git a/src/components/IconGallery/IconGalleryCard.tsx b/src/components/IconGallery/IconGalleryCard.tsx new file mode 100644 index 0000000000..28302a5c4a --- /dev/null +++ b/src/components/IconGallery/IconGalleryCard.tsx @@ -0,0 +1,44 @@ +import React, { useState } from "react"; +import { Icon } from "../Common/Icon"; +import { IconName } from "@site/src/typescript/iconName"; + +export interface IconCardProps { + iconName: IconName; + onCopy?: (iconName: string) => void; +} + +export default function IconCard({ iconName, onCopy }: IconCardProps) { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(iconName); + setCopied(true); + onCopy?.(iconName); + window.setTimeout(() => setCopied(false), 2000); + } catch (_err) { + // Ignore copy errors + } + }; + + return ( +
+
+ +
+
+
+ {iconName} +
+
+ {copied ? "Copied!" : "Click to copy"} +
+
+
+ ); +} + diff --git a/static/icons/backup-history.svg b/static/icons/backup-history.svg index 9f5e047425..c553d4cc77 100644 --- a/static/icons/backup-history.svg +++ b/static/icons/backup-history.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/templates/icon-gallery.mdx b/templates/icon-gallery.mdx new file mode 100644 index 0000000000..8714184753 --- /dev/null +++ b/templates/icon-gallery.mdx @@ -0,0 +1,74 @@ +--- +title: "Icon Gallery" +hide_table_of_contents: false +sidebar_label: Icon Gallery +--- + +import IconGallery from "@site/src/components/IconGallery/IconGallery"; +import Admonition from '@theme/Admonition'; + +# Icon Gallery + +This page showcases all available icons in the project along with their names. Click on any icon to copy its name to the clipboard. + +## Usage + +To use an icon in a component, import the `Icon` component and pass the icon name as the `icon` prop: + +```tsx +import { Icon } from "@site/src/components/Common/Icon"; + + +``` + +## Available Icons + + + + +Icons are automatically loaded from the `static/icons` directory. When you add a new SVG file to this directory, the icon will automatically appear in this gallery after restarting the development server. + + +## Icon Sizes + +The `Icon` component supports the following sizes: + +- `xs` - 16x16px (w-4 h-4) +- `sm` - 24x24px (w-6 h-6) - default +- `md` - 32x32px (w-8 h-8) +- `lg` - 40x40px (w-10 h-10) +- `xl` - 48x48px (w-12 h-12) + +## Usage Examples + +### Basic Usage + +```tsx +import { Icon } from "@site/src/components/Common/Icon"; + + +``` + +### With Custom Size + +```tsx + +``` + +### With Additional CSS Classes + +```tsx + +``` + +### In CardWithImage Component + +```tsx +import CardWithImage from "@site/src/components/Common/CardWithImage"; + + +``` \ No newline at end of file From c0a8bedf8293f05d3fb0dc33620fc36dfe6c239f Mon Sep 17 00:00:00 2001 From: Damian Olszewski Date: Wed, 12 Nov 2025 09:07:22 +0100 Subject: [PATCH 2/3] RDoc-3566 Get IconName type from array --- scripts/generate-icon-types.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/scripts/generate-icon-types.js b/scripts/generate-icon-types.js index 3271190f96..16d305922c 100644 --- a/scripts/generate-icon-types.js +++ b/scripts/generate-icon-types.js @@ -9,22 +9,17 @@ function generateIconTypes() { const files = fs.readdirSync(ICONS_DIR); const svgFiles = files.filter((file) => file.endsWith(".svg")); - const iconNames = svgFiles.map((file) => { - const name = path.basename(file, ".svg"); - return ` | '${name}'`; - }); - const iconNamesArray = svgFiles.map((file) => { const name = path.basename(file, ".svg"); return ` '${name}'`; }); - const typesContent = `export type IconName = -${iconNames.join("\n")}; - + const typesContent = ` export const ALL_ICON_NAMES = [ ${iconNamesArray.join(",\n")} ] as const; + +export type IconName = typeof ALL_ICON_NAMES[number]; `; fs.writeFileSync(TYPES_FILE, typesContent); From 3a61e1a36083a933de7e1323d34ce7856744d590 Mon Sep 17 00:00:00 2001 From: Mateusz Bartosik Date: Wed, 12 Nov 2025 11:44:06 +0100 Subject: [PATCH 3/3] RDoc-3566 Component adjustments --- src/components/IconGallery/IconGallery.tsx | 5 ++--- src/components/IconGallery/IconGalleryCard.tsx | 12 +++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/components/IconGallery/IconGallery.tsx b/src/components/IconGallery/IconGallery.tsx index 5fdf2f7fe1..c6d8139011 100644 --- a/src/components/IconGallery/IconGallery.tsx +++ b/src/components/IconGallery/IconGallery.tsx @@ -1,5 +1,5 @@ import React, { useMemo } from "react"; -import IconCard from "./IconGalleryCard"; +import IconGalleryCard from "./IconGalleryCard"; import { ALL_ICON_NAMES } from "../../typescript/iconName"; export default function IconGallery() { @@ -11,10 +11,9 @@ export default function IconGallery() {
{iconNames.map((iconName) => ( - + ))}
); } - diff --git a/src/components/IconGallery/IconGalleryCard.tsx b/src/components/IconGallery/IconGalleryCard.tsx index 28302a5c4a..2001452819 100644 --- a/src/components/IconGallery/IconGalleryCard.tsx +++ b/src/components/IconGallery/IconGalleryCard.tsx @@ -2,22 +2,21 @@ import React, { useState } from "react"; import { Icon } from "../Common/Icon"; import { IconName } from "@site/src/typescript/iconName"; -export interface IconCardProps { +export interface IconGalleryCardProps { iconName: IconName; - onCopy?: (iconName: string) => void; } -export default function IconCard({ iconName, onCopy }: IconCardProps) { +export default function IconGalleryCard({ iconName }: IconGalleryCardProps) { const [copied, setCopied] = useState(false); const handleCopy = async () => { try { await navigator.clipboard.writeText(iconName); setCopied(true); - onCopy?.(iconName); window.setTimeout(() => setCopied(false), 2000); - } catch (_err) { - // Ignore copy errors + } catch (err) { + // eslint-disable-next-line no-console + console.error("Failed to copy icon name to clipboard:", err); } }; @@ -41,4 +40,3 @@ export default function IconCard({ iconName, onCopy }: IconCardProps) { ); } -