CtrlK
BlogDocsLog inGet started
Tessl Logo

bestax-icons

Use icons in an app built with @allxsmith/bestax-bulma — the Icon/IconText components and the five supported libraries (Font Awesome, Material Design Icons, Ionicons, Google Material Icons, Material Symbols). Use when adding an icon, choosing or configuring the app-wide icon library, fixing an icon that renders blank, pairing icons with text, or making icons accessible (decorative vs labeled).

78

Quality

98%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Low

Low-risk findings worth noting

SKILL.md
Quality
Evals
Security

Icons with @allxsmith/bestax-bulma

Icon renders a Bulma icon container (span.icon) around a glyph from any of five icon libraries behind one normalized API. IconText pairs icons with text. The library ships no icon fonts — the chosen library's package (or CDN script) must be installed in the app.

Quick start

import { ConfigProvider, Icon, IconText } from '@allxsmith/bestax-bulma';

// Set the library ONCE at the app root; <Icon> then never needs `library`.
<ConfigProvider iconLibrary="fa">
  <App />
</ConfigProvider>;

// Inside the app:
<Icon name="rocket" ariaLabel="Launch" />;
<IconText iconProps={{ name: 'star', 'aria-hidden': 'true' }}>
  Starred
</IconText>;

The five libraries

LibraryiconLibrary / library valueName formatExample name
Font Awesome (default)'fa'kebab-case, no fa- prefixrocket
Material Design Icons'mdi'kebab-case, no mdi- prefixrocket-launch
Ionicons'ion'kebab-caserocket
Google Material Icons'material-icons'snake_case (a text ligature)rocket_launch
Material Symbols'material-symbols'snake_case (a text ligature)rocket_launch

⚠️ The Ionicons value is 'ion', not 'ionicons'. The npm create bestax scaffold's --icon ionicons flag maps to iconLibrary="ion" — passing 'ionicons' to ConfigProvider or library silently renders nothing.

The same glyph has a different name per library (rocket vs rocket-launch vs rocket_launch). When an icon renders blank, the name format for the active library is the first thing to check. A redundant fa-/mdi- prefix in name is tolerated (stripped), but don't rely on it.

Styling

  • size — 'small' | 'medium' | 'large' sizes the Bulma container (is-small ≈ 1rem, is-medium ≈ 2rem, is-large ≈ 3rem box). To scale the glyph, use features (Font Awesome 'fa-lg'/'fa-2x') or a Bulma text-size class ('is-size-3').
  • variant — per-library style: Font Awesome solid (default) / regular / brands / light / duotone / thin; Material Icons filled (default) / outlined / round / sharp; Material Symbols outlined (default) / rounded / sharp; Ionicons outline / sharp. MDI has no variants. Note Material Icons uses round, Material Symbols uses rounded.
  • features — extra library classes, string or array: 'fa-spin', ['fa-lg', 'fa-border'].
  • Color via the helper props: textColor="primary", textColor="danger", etc.

Custom node (SVG, react-icons, FontAwesome React)

Icon also accepts children instead of name — an inline SVG, a react-icons component, a Font Awesome React <FontAwesomeIcon>, … — rendered in place of a class-based glyph. name and children are mutually exclusive (the type rejects passing both, or neither). size, textColor, bgColor, ariaLabel and containerClassName behave identically; library, variant, features and libraryFeatures are ignored since there's no class-based glyph to style.

<Icon ariaLabel="Custom icon">
  <MyReactIconsComponent />
</Icon>

IconText's iconProps / items[].iconProps and Control's iconLeft/iconRight accept the same escape hatch — pass a node directly (instead of an IconProps object) and it is wrapped in an Icon for you: <IconText iconProps={<MySvg />}>Starred</IconText>.

Panel.Icon takes the same children, but its container is panel-icon rather than icon — it always overrides containerClassName, so style and query that class instead.

⚠️ children excludes undefined. Write a conditional icon as cond ? <MySvg /> : null (or cond && <MySvg />), never cond ? <MySvg /> : undefined — the latter is a type error, because the renderer would fall through to the name path with no name. In the IconText and Control slots a falsy node counts as "no icon": nothing is rendered, and Control falls back to iconLeftName/iconRightName if one is given, otherwise leaving the icon column unreserved.

Accessibility

An Icon is decorative unless it is named: with no ariaLabel it renders aria-hidden="true" and no name. Name it with its camelCase ariaLabel prop, and it renders role="img" with that aria-label. Only a few components declare that prop (Icon, Delete, Slider, Carousel): everything else takes the standard aria-label attribute, e.g. <Navbar.Burger aria-label="menu" />.

  • Meaningful icon (stands alone, conveys information): pass a descriptive ariaLabel="Delete item".
  • Decorative icon (next to visible text that says the same thing, e.g. inside IconText or a labeled Button): leave ariaLabel off, and the icon stays out of the accessible name. An explicit aria-hidden="true", as in the examples here, says the same thing.
  • Icon-only control: name the control (<Button aria-label="Delete item">), not the icon.

References

  • references/icon-libraries.md — per-library setup (install/import/CDN), the full name-format and variant tables, features values, and the blank-icon troubleshooting list.
  • examples/icon-usage.tsx — runnable example: ConfigProvider setup, sizes, variants, colors, IconText, and decorative-vs-labeled patterns.
Repository
allxsmith/bestax
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.