shadcn.io is not affiliated with official shadcn/ui
Sortable Skills Matrix About Block for React Aria
A framed matrix of seven skills by five departments for a learning platform, each cell four dots, sortable by skill or department, with computed department averages in the footer row.
Installation
Overview
A skills matrix for React with React Aria, written for Skillmoor, a fictional workforce-learning product showing its own team. A start header sits over a framed table with seven skills down the side and five departments across. Each cell is a row of four dots, filled up to the level from one, learning it, to four, teaching it, and named "3 of 4" for a screen reader. Skill and every department are header buttons: press a department to sort the skills by how strong it is in them, press it again to reverse the order. The footer row holds each department's average level, computed from the dots above it. The skill column stays put while the table scrolls sideways on a phone. It's built from Table and Guides, with CSS transitions and your theme's tokens for every colour. For an about page, a hiring page or a team overview. The levels are example data.
FAQ
How do I change the skills, departments and levels?
DEPARTMENTS lists the columns and SKILLS the rows; each skill has a levels object with a number from 1 to 4 for each department. The dots, the sort and the footer averages are all computed from it, so nothing else needs editing. The levels are example data.
How is a row of dots read by a screen reader?
Each cell is one image named "3 of 4"; the department and the skill come from the column and row headers around it. The empty dots are drawn as outlines, not as a lighter fill, so a level reads without relying on colour.
How does sorting work?
Skill sorts A to Z first; a department sorts the strongest first, and pressing it again reverses it. Ties fall back to the skill's name. The sorted header carries aria-sort and an arrow, and a polite line above the table reads the result, such as "Sorted by Design, strongest first". The footer row always stays last.
React Aria's table owns the sorting: each sortable header is a focusable cell that Enter and Space activate, and the table is named by its aria-label (a grid has no caption).
How is the average worked out?
It is the mean of a department's levels over every skill, to one decimal, and a screen reader hears it as "2.6 of 4". It is computed when the module loads, so it can never disagree with the dots.