Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions scripts/generate-icon-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ function generateIconTypes() {
const files = fs.readdirSync(ICONS_DIR);
const svgFiles = files.filter((file) => file.endsWith(".svg"));

const iconNames = svgFiles.map((file) => {
const iconNamesArray = svgFiles.map((file) => {
const name = path.basename(file, ".svg");
return ` | '${name}'`;
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);
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);
Expand Down
19 changes: 19 additions & 0 deletions src/components/IconGallery/IconGallery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { useMemo } from "react";
import IconGalleryCard from "./IconGalleryCard";
import { ALL_ICON_NAMES } from "../../typescript/iconName";

export default function IconGallery() {
const iconNames = useMemo(() => {
return [...ALL_ICON_NAMES].sort();
}, []);

return (
<div className="icon-gallery mb-4">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{iconNames.map((iconName) => (
<IconGalleryCard key={iconName} iconName={iconName} />
))}
</div>
</div>
);
}
42 changes: 42 additions & 0 deletions src/components/IconGallery/IconGalleryCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useState } from "react";
import { Icon } from "../Common/Icon";
import { IconName } from "@site/src/typescript/iconName";

export interface IconGalleryCardProps {
iconName: IconName;
}

export default function IconGalleryCard({ iconName }: IconGalleryCardProps) {
const [copied, setCopied] = useState(false);

const handleCopy = async () => {
try {
await navigator.clipboard.writeText(iconName);
setCopied(true);
window.setTimeout(() => setCopied(false), 2000);
} catch (err) {
// eslint-disable-next-line no-console
console.error("Failed to copy icon name to clipboard:", err);
}
};

return (
<div
className="group flex flex-col items-center justify-center p-4 rounded-lg border border-black/10 dark:border-white/10 bg-muted/40 hover:bg-muted/60 transition-all cursor-pointer"
onClick={handleCopy}
title={`Click to copy: ${iconName}`}
>
<div className="mb-3 flex items-center justify-center w-16 h-16">
<Icon icon={iconName} size="lg" />
</div>
<div className="text-center">
<div className="text-xs font-mono text-gray-700 dark:text-gray-300 break-all">
{iconName}
</div>
<div className="text-xs text-gray-500 dark:text-gray-400 mt-1">
{copied ? "Copied!" : "Click to copy"}
</div>
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion static/icons/backup-history.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions templates/icon-gallery.mdx
Original file line number Diff line number Diff line change
@@ -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";

<Icon icon="database" size="lg" />
```

## Available Icons

<IconGallery />

<Admonition type="info" title="">
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.
</Admonition>

## 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";

<Icon icon="database" />
```

### With Custom Size

```tsx
<Icon icon="database" size="xl" />
```

### With Additional CSS Classes

```tsx
<Icon icon="database" className="text-blue-500" />
```

### In CardWithImage Component

```tsx
import CardWithImage from "@site/src/components/Common/CardWithImage";

<CardWithImage
title="Database"
description="Database icon"
imgIcon="database"
/>
```