Unlock faster development with Fidely UI Pro components Coming soon

Building an Icon Component

Learn how to create a reusable Icon component using Fidely UI’s styled system.

Fidely UI does not include an Icon component by default.
This guide shows how to build one using Fidely’s styled system.

This is a compositional pattern, not a built-in Fidely UI component.

Icons are typically used for decorative or semantic SVGs and are commonly paired with components like Button, IconButton, and MenuItem.

Implementation

//icon.tsx

'use client'

import * as React from 'react'
import { fidely } from '@fidely-ui/react'
import { styled } from '@fidely-ui/styled-system/jsx'
import type { HTMLStyledProps } from '@fidely-ui/styled-system/types'

/**
 * Base styled SVG component.
 * - Uses `fidely.svg` and `styled` to enable style props
 * - `asChild` allows passing any SVG as a child
 */
const StyledIcon = styled(fidely.svg, {}, { defaultProps: { asChild: true } })

export interface IconProps extends Omit<HTMLStyledProps<'svg'>, 'as'> {}

/**
 * Icon component
 *
 * - Styleable via Fidely style props
 * - Accessible by default
 * - Works with any SVG or icon library
 */
export const Icon = React.forwardRef<SVGSVGElement, IconProps>(
  function Icon(props, ref) {
    return (
      <StyledIcon ref={ref} focusable={false} aria-hidden="true" {...props} />
    )
  }
)

Icon.displayName = 'Icon'

With React Icon Libraries

import { FiPlus } from 'react-icons/fi'

;<Icon boxSize="50" color="red.10">
  <FiPlus />
</Icon>

With Inline SVG

<Icon boxSize="10" color="crimson.9">
  <svg viewBox="0 0 24 24" fill="currentColor">
    <path d="M12 21s-6.716-4.35-9.33-7.364C.596 11.29.97 7.9 3.757 6.327c1.86-1.07 4.243-.53 5.72 1.02L12 9.88l2.523-2.534c1.477-1.55 3.86-2.09 5.72-1.02 2.787 1.573 3.16 4.964 1.087 7.31C18.716 16.65 12 21 12 21z" />
  </svg>
</Icon>

Accessibility Notes

  • Decorative icons

    • Use aria-hidden="true"
    • Do not provide an accessible name
  • Semantic icons

    • Remove aria-hidden
    • Provide an accessible name and role
<Icon aria-label="Add item" role="img">
  <FiPlus />
</Icon>