Skip to content

Commit

Permalink
New icons component
Browse files Browse the repository at this point in the history
  • Loading branch information
MrFlashAccount committed Jan 21, 2025
1 parent 570f141 commit 6b4dd1e
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
2 changes: 1 addition & 1 deletion app/gui/src/dashboard/components/SvgIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface SvgIconProps {
}

/** A fixed-size container for a SVG image. */
export default function SvgIcon(props: SvgIconProps) {
export function SvgIcon(props: SvgIconProps) {
const { src, className, onClick } = props
return (
<div
Expand Down
83 changes: 83 additions & 0 deletions app/gui/src/dashboard/components/SvgIcon/SvgIcon.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import type { Meta, StoryObj } from '@storybook/react'
import { useState } from 'react'
import { twJoin } from '../../utilities/tailwindMerge'
import { Button } from '../AriaComponents/Button'
import { Text } from '../AriaComponents/Text'
import SvgMask from '../SvgMask'
import { SvgIcon, type SvgIconProps } from './SvgIcon'

interface Module {
default: string
}

const ICONS = import.meta.glob('../../assets/*.svg', { eager: true }) satisfies Record<
string,
Module
>

export default {
title: 'Components/SvgIcon',
component: SvgIcon,
render: (args) => <SvgIcon {...args} />,
argTypes: {
showOutline: {
control: {
type: 'boolean',
},
},
},
parameters: {
layout: 'centered',
},
} as Meta<SvgIconProps>

type Story = StoryObj<SvgIconProps>

export const Default: Story = {
args: {
icon: 'icon-name',
},
}

export const AllIcons: Story = {
render: () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [showOutline, setShowOutline] = useState(false)
return (
<div className="max-w-7xl">
<div className="flex items-center justify-between">
<Text.Heading className="mb-4">All Icons</Text.Heading>

<Button
variant="icon"
size="small"
onPress={() => {
setShowOutline(!showOutline)
}}
>
{showOutline ? 'Hide Outline' : 'Show Outline'}
</Button>
</div>

<div className="grid grid-cols-6 gap-8">
{Object.entries(ICONS).map(([key, value]) => {
const name = key.split('/').pop()?.replace('.svg', '')
return (
<div className="flex flex-col items-center gap-1" key={key}>
<div
className={twJoin(
'flex items-center justify-center',
showOutline === true && 'outline outline-2 outline-primary',
)}
>
<SvgMask src={value.default} className="h-4 w-4" />
</div>
<Text>{name}</Text>
</div>
)
})}
</div>
</div>
)
},
}
24 changes: 24 additions & 0 deletions app/gui/src/dashboard/components/SvgIcon/SvgIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @file SvgIcon component
*/

import type { SVGProps } from 'react'

/**
* Props for the {@link SvgIcon} component
*/
export interface SvgIconProps extends SVGProps<SVGSVGElement> {
readonly icon: string
readonly showOutline?: boolean
}

/**
* Renders an SVG icon
*/
export function SvgIcon({ icon, ...props }: SvgIconProps) {
return (
<svg {...props}>
<use href={`/icons.svg#${icon}`} />
</svg>
)
}
6 changes: 6 additions & 0 deletions app/gui/src/dashboard/components/SvgIcon/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @file Barrel export for SvgIcon
*/

export { SvgIcon } from './SvgIcon'
export type { SvgIconProps } from './SvgIcon'

0 comments on commit 6b4dd1e

Please sign in to comment.