Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Achievement Badges Web3 Block for React Aria

A case of eight soulbound badges drawn as greyscale hexagons weighted by tier, earned or locked with the exact need, rarity worked out from each badge's holder share, an All, Earned and In progress filter and a reading of the chosen badge.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Show what a member has done on chain, and what is next, with this badge case for React with React Aria. It's the collection of Badgefold, an on-chain badge program. A hairline frame with a plus mark on each corner starts with a Toggle Group (All, Earned, In progress) over a grid of eight badges, two across on a phone and four on a wide screen. Each badge is a hexagon in greyscale: a heavier outline and an inner ring for a higher tier, solid when earned, dashed with a small bar and "6 of 10 votes" while locked. Rarity is worked out from each badge's typed holder share: under 2 % is Legendary, under 10 % Rare, otherwise Common. Selecting a badge, with the arrow keys or a press, reads it in the side cell: its requirement, its share of the 4,820 holders, a Progress bar with the exact need ("3 more proposals"), and the note that it is soulbound and cannot be transferred. For DAOs, games and communities that record participation as badges.

FAQ

How is rarity decided?

From the badge's holder share, in tenths of a percent in the typed data: under 2.0 % is Legendary, under 10.0 % is Rare, anything else Common. Nobody types the word, so editing a share changes the label in the reading and on the case. Founder, held by 1.6 %, is Legendary; First vote, held by 61.2 %, is Common.

What does soulbound mean here?

A soulbound badge is tied to the address that earned it and cannot be sent to another. The panel says so on every badge and offers no transfer action. Nothing is minted or read from a chain in this demo; in your app the earned state would come from the badge contract, and a locked badge's progress from your indexer.

What happens when a filter hides the chosen badge?

The selection moves to the first badge that matches, and the reading follows. The grid keeps all eight cells: the matches come first and the others stay in place, hidden from view and from the keyboard, so the panel does not change height.

How are the badges drawn?

As small inline SVG: a hexagon whose line weight grows with the tier, an inner ring on tier three, and one mark per badge, all in the text colour with a faint fill when earned. Each has a title, and the cell's text says the state in words, so nothing depends on how it looks.

Is it accessible from the keyboard?

Yes. The cells are native radio buttons in a group named Badges, so the arrow keys move and select, the focus ring shows on the cell, and one polite status message reads the chosen badge, its rarity and whether it is earned.

How does it look on a phone?

Two badges across, the reading stacked under the grid, and the toolbar count beside the filter.