Skip to content
Agentmart
Submit a tool

bestax-custom-component

Build a custom React component in the bestax/Bulma style.

Skill by allxsmith

IndexedMIT★ 13
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/allxsmith-bestax-custom-component

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Build a custom React component in the bestax/Bulma style. In an app using @allxsmith/bestax-bulma — compose existing components, helper props, public hooks (useBulmaClasses, usePrefixedClassNames), and --bulma-* CSS variables. In the bestax monorepo — the full component pipeline (SCSS partial, stories, tests, docs, wiring). Use when creating a component beyond stock Bulma or extending one.

Use cases: frontend, data, finance

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/bestax-custom-component

What's inside

Skill name
bestax-custom-component
Description
Build a custom React component in the bestax/Bulma style. In an app using @allxsmith/bestax-bulma — compose existing components, helper props, public hooks (useBulmaClasses, usePrefixedClassNames), and --bulma-* CSS variables. In the bestax monorepo — the full component pipeline (SCSS partial, stories, tests, docs, wiring). Use when creating a component beyond stock Bulma or extending one.
License
MIT
Instructions
245 lines in SKILL.md · view on GitHub

Files (6)

  • SKILL.md
  • stat-card.tsx · examples/
  • api.md · references/
  • component-catalog.md · references/
  • library-contributor.md · references/
  • patterns.md · references/

SKILL.md (first lines)

# Building a custom component the bestax way

This skill teaches how to build a component that isn't in the library — composed from bestax
pieces in an app, or as a full library "extra" inside the bestax monorepo.

## Which context are you in?

- **The bestax monorepo** (the repo contains `bulma-ui/src/`) → follow
  `references/library-contributor.md` instead of this file: five-file layout, SCSS partial,
  stories, jest tests, docs page, wiring.
- **An app depending on `@allxsmith/bestax-bulma`** (e.g. scaffolded by `npm create bestax`) →
  continue here. Everything below assumes public package imports and a plain Vite app.

For **form** components (Field/Control/Input/etc.) use the `bestax-form` skill instead.

## Check for an existing component first

Before building anything, **search the library for a component that already does this — or a
close synonym** — and tell the user what you found. Many requests are covered by an existing
element, or are best built by composing existing ones. Building a near-duplicate (a "label" when
`Tag` exists, a "banner" when `Notification` exists) fragments the API and is usually the wrong
call.

Where to look:

- `references/component-catalog.md` — **start here.** Every documented component with a one-line
  purpose, grouped by category. Scan it for the name and its synonyms before anything else.
- https://bestax.io/docs/api — one doc page per shipped component (full props).

Then decide, and **surface the decision to the user**:

- **Exact / synonym match exists** → recommend using it. Don't build a duplicate. (E.g. a small
  colored label/badge/chip → `Tag` / `Tags` already exist.)
- **Partial overlap** → prefer **composing** the existing pieces inside your new component
  rather than re-implementing them. (E.g. a "profile card" → there's no `ProfileCard`, but
  `Card`, `Image`, `Title`, `SubTitle`, and `Content` exist; build `ProfileCard` to compose them.)
- **Genuine gap** → build the new component using the pattern below.

State plainly which case applies before writing code, e.g. _"`Tag` already covers a colored
label — use that instead"_ or _"No `ProfileCard` exists; I'll build one composing the existing
`Card`/`Image`/`Title` elements."_

## Composition first

Build from existing components before writing any CSS: `Box`, `Card`, `Title`, `SubTitle`,
`Icon`, `Block`, `Content`, `Tag`, plus the shared Bulma helper props (spacing, color,
typography, flexbox). Some compound sub-parts are the exception — `Modal.Card`, `Tabs.Tab`,
`Message.Body` take **no Bulma helper props**, just `className` + HTML attributes
plus their own few (`Tabs.Tab` requires `index={i}` and has built-in `disabled` and
`icon`/`iconLibrary`/`iconVariant`/`iconSize`/`iconFeatures` — don't nest an `<Icon>` there) —
so put helper props on the parent or on an element inside them, never invent them there.
(`Card.*` sub-parts do take helper props, like `Table.*`/`Menu.*`/`Hero.*`.) Most "custom components" are a composition function — zero new styles.
See `examples/stat-card.tsx` for a complete worked example.

Rendering something only the browser knows (the reader's time zone, a `localStorage` value)?
Wrap it in the library's `ClientOnly` rather than checking `typeof window`: it renders a fallback
until the page has hydrated, so the server and client markup match. `references/api.md` has the
details.

A button that turns something on or off and stays that way (Bold, Mute, Show archived) is
`ToggleButton`: use it rather than `Button isActive`, which only draws a shade and sets no
`aria-pressed`. It's always `type="button"`, holds its own state (`defaultPressed`) or takes
`pressed` with `onPressedChange`, and fills with `color` (default `link`) only while pressed.
Its label stays the same in both states, and an icon-only one needs an `aria-label`. A set goes
in `Buttons hasAddons role="group" aria-label="…"`, where it's also `Buttons.ToggleButton`. A row
where only one can be on is a radio group, so it's `SegmentedControl` (below), never toggles that
switch each other off. A setting saved with a form is a `Switch` or a `Checkbox`.

A row of buttons where only one can be on (text alignment, a list or grid view, monthly or yearly
billing) is `SegmentedControl`: use it rather than `Buttons hasAddons` with `isActive` or a fill
you move yourself. Give it an `aria-label`, put one `SegmentedControl.Segment value="…"` inside per
option, and hold the choice with `defaultValue`, or `value` with `onChange(value)`. A screen reader
hears a radio group, and the single tab stop, the arrow keys, Home and End come built in, so add
no `onKeyDown` or `role` of your own. An icon-only segment needs its own `aria-label`, as an
icon-only `ToggleButton` does. The arrow keys check the segment they land on, so `onChange` fires
on each, and pressing the checked segment keeps it checked. It carries no form value: a choice
the form submits is `Radios`.

A panel opened from a button (a filter form, share options, an inline edit) is `Popover`: use
it rather than building one. It anchors the panel, moves focus in and back, and closes on
Escape and outside presses.

A preview that shows up on hover (a profile card on a username, a summary on a link) is
`HoverCard`: use it rather than wiring pointer events to a `Popover`. It opens on hover and
keyboard focus after a delay, lets the pointer move onto the card, closes on Escape, and ignores
touch unless `openOnTap` is on, which suits only a trigger with no tap action of its own (a
`Button` with no `onClick`, never a link). Its `trigger` has to be a link or a button, and a trigger in running text takes
`appendToBody`. A form never goes in one; that's `Popover`.

A menu of actions that opens on a right-click (Rename and Delete on a table row, Archive on a
card) is `ContextMenu`: use it rather than an `onContextMenu` handler that positions a
`Dropdown`. It opens at the point, also on Shift+F10, the context menu key and a long press,
and its items are `ContextMenu.Item` and `ContextMenu.Divider`, the same components as
`Dropdown.Item` and `Dropdown.Divider`. Its `trigger` is cloned, not wrapped, so a `Table.Tr`
works, and the menu needs `aria-label`. Put the same items in a visible `Dropdown` as well:
nothing tells a screen reader user a context menu is there, and on macOS only VoiceOver opens
it from the keyboard.

A command palette, a search over things to do that opens on ⌘K or Ctrl+K, is
`Command.Dialog`: `<Command.Dialog shortcut="mod+k" actions={[{ id, label, onSelect }]} />`, or
built from parts for a server search. Don't hand-build one from `Portal`, `useFocusTrap` and a
`keydown` listener. Inline, without the modal, it's `Command`.

Building something else that floats? Render it through the library's `Portal` rather than
`createPortal`: it renders nothing on the server and during hydration, so the server and client
markup match. `references/api.md` has the details.

Building some other overlay that holds focus until it is dismissed? Use the library's
`useFocusTrap` rather than a hand-rolled Tab handler: it finds the tab stops the browser visits
and hands focus back on close. `references/api.md` has the signature and a worked panel.

## The component spine

Same shape the library itself uses, with all imports from the package. Every reusable
component gets it — including pure compositions with zero CSS (a heading block, a labeled
wrapper): extend `BulmaClassesProps`, run your props through `useBulmaClasses`, merge its
`bulmaHelperClasses` into `className`, and spread the `rest` **it** returns — spreading the raw
props instead leaks helper props onto the DOM and emits none of their classes. The
`usePrefixedClassNames` root class is needed only when component-scoped CSS (or a variant

From allxsmith/bestax, MIT.

More from allxsmith/bestax

Signals

Stars
13
Forks
1
Open issues
32
Last commit (this folder)
Oct 24, 2026 (5 days ago)
Last release
Oct 24, 2026 (4 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
Website
bestax.io/
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from allxsmith

Cite this page

bestax-custom-component skill. Agent Mart. https://agentmart.dev/skills/allxsmith-bestax-custom-component (last updated 2026-10-24)