Icon

Used to display an svg icon

import { Icon } from "chakra-ui-solid";
import { HeartIcon } from "../components/site/icons";

export default function IconBasic() {
  return <Icon as={HeartIcon} size="lg" color="pink.700" />;
}

Usage

import { Icon } from "chakra-ui-solid";
<Icon />

Chakra ships no icons of its own, and neither do we. Icon styles a glyph you bring — from an icon library, from a pasted svg, or from createIcon below.

Examples

Icon libraries

Pass the glyph component as as, and Icon sizes and colours it.

import { HStack, Icon } from "chakra-ui-solid";
import { BellIcon, BoxIcon, TerminalIcon } from "../components/site/icons";

export default function IconWithIconLibrary() {
  return (
    <HStack gap="4">
      <Icon as={BellIcon} size="lg" color="teal.600" />
      <Icon as={BoxIcon} size="lg" color="orange.500" />
      <Icon as={TerminalIcon} size="lg" color="purple.600" />
    </HStack>
  );
}

No icon package supports SolidJS 2.0 yet, so the glyphs above are this site’s own — SVG path data copied out of Lucide, each one a small component wrapping a leaf svg. That is the same shape a published icon package would have, so this page changes only its imports the day one exists.

as is where Chakra’s React version writes the glyph as a child. Both spellings mean the same thing there — the child one is asChild, which re-creates the child element with Icon’s computed props merged in. SolidJS has no equivalent: a child is an already-constructed DOM node by the time Icon sees it, so a glyph nested as a child keeps its own svg and ignores size, and as is the spelling that puts the recipe on the element that actually draws.

// ✅ one svg, and the recipe is on the element that draws
<Icon as={HeartIcon} size="lg" />
 
// ❌ two svgs, and `size` sizes the outer one while the glyph inside ignores it
<Icon size="lg">
  <HeartIcon />
</Icon>

Custom svg

Use the render prop to render your own svg rather than nesting one inside Icon’s.

import type { JSX } from "@solidjs/web";
import { Icon } from "chakra-ui-solid";

export default function IconWithCustomSvg() {
  return (
    <Icon
      size="lg"
      color="red.500"
      render={(props) => (
        // `aria-hidden` before the spread, which overwrites it with the same `"true"` Icon already
        // computed. It is here for the linter, which cannot see an attribute arriving in a spread
        // and reports the svg as unlabelled.
        <svg
          aria-hidden="true"
          {...(props as JSX.SvgSVGAttributes<SVGSVGElement>)}
          viewBox="0 0 32 32"
        >
          <g fill="currentColor">
            <path d="M16,11.5a3,3,0,1,0-3-3A3,3,0,0,0,16,11.5Z" />
            <path d="M16.868.044A8.579,8.579,0,0,0,16,0a15.99,15.99,0,0,0-.868,31.956A8.579,8.579,0,0,0,16,32,15.99,15.99,0,0,0,16.868.044ZM16,26.5a3,3,0,1,1,3-3A3,3,0,0,1,16,26.5ZM16,15A8.483,8.483,0,0,0,8.788,27.977,13.986,13.986,0,0,1,16,2a6.5,6.5,0,0,1,0,13Z" />
          </g>
        </svg>
      )}
    />
  );
}

This is what Chakra’s React version spells asChild. The callback is handed the computed props — the recipe’s class, the style props, the ref — and places them on the element you write.

Create Icon

Use the createIcon utility for a glyph you reuse enough to name.

import { createIcon } from "chakra-ui-solid";

const HeartIcon = createIcon({
  displayName: "HeartIcon",
  path: () => (
    <>
      <path stroke="none" d="M0 0h24v24H0z" fill="none" />
      <path
        fill="currentColor"
        d="M19.5 13.572l-7.5 7.428l-7.5 -7.428m0 0a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572"
      />
    </>
  ),
});

export default function IconWithCreateIcon() {
  return <HeartIcon size="lg" color="blue.400" />;
}

path is a function returning the glyph’s elements, where Chakra’s React version takes the elements directly. A JSX value there would be built when the module loads rather than when the component renders, which takes a server-rendered route down before anything reaches the page.

For a single-path glyph, d is the shorthand:

const DotIcon = createIcon({ d: "M12 12h.01" });

viewBox defaults to 0 0 24 24, and defaultProps supplies any Icon prop the caller leaves unset:

const WideIcon = createIcon({
  viewBox: "0 0 32 32",
  d: "M16 16h.01",
  defaultProps: { size: "sm" },
});

Props

IconProps
PropDefaultType
focusablefalse
'true' | 'false'

Whether the glyph can take focus. Chakra sets it, so we do — it is the attribute that keeps a decorative `svg` out of the tab order in engines that put it there. Declared here rather than inherited because SolidJS's SVG attribute types do not carry it: it is an SVG 1.1 attribute that SVG 2 dropped, and React's types kept.

size'inherit'
ConditionalValue<'inherit' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'>

The glyph's box, as a scale step. `inherit` sets no box at all — the glyph keeps the one it draws itself, which for the `1em` an icon library ships is the surrounding font size. That is how an icon inside a button or a menu item matches its label, and it is the default, because an icon almost always belongs to some text.

Plus everything it inherits — HTMLChakraProps<"svg">, the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.