shadcn.io is not affiliated with official shadcn/ui
Amenities Checkbox Grid Form Block for React
A listing editor panel with twelve amenities as checkbox tiles in a container-query grid, a count with Clear, and a Save that needs at least one amenity.
Installation
Overview
Let people tick several options at a glance with this checkbox tile grid form for React with Base UI. A compact header sits over a hairline frame with a plus mark on each corner. A band holds twelve amenities of a short-stay listing (Wi-Fi, Kitchen, Free parking and nine more) as tiles on shared hairlines, each with a glyph, a name and its box. The grid answers the width of the panel, not the screen: two columns on a phone, three from a 32rem panel and four from 42rem, so it fits a wide page, a sidebar or a narrow drawer alike. A ticked tile is filled and ringed in foreground tones, the heading row counts "5 of 12 chosen" and Clear empties the set. Save needs at least one amenity: pressed with none it says so under the grid and puts focus on the first box, and it stays quiet while nothing has changed. It's built from the Checkbox, Label, Shine Button and Guides, with a CSS entrance only. For amenity lists, feature sets, interest pickers and any choice of a dozen or so short options.
FAQ
How does the grid pick its number of columns?
The tiles sit in a container-query box, so the columns follow the width of the panel rather than the viewport: grid-cols-2, then @lg:grid-cols-3 and @2xl:grid-cols-4. Twelve divides evenly by all three counts, so no row is left half empty. Change the breakpoints, or the tile list in AMENITIES, to suit your options.
How is a ticked tile shown without colour?
The tile gets a soft fill and a one-pixel foreground ring inside the hairlines, and the box turns solid foreground with a check. Neither depends on the primary colour, so it reads the same in every theme, and the count in the heading row says it in words as well.
How does it work with a keyboard and a screen reader?
The twelve boxes are one group named by the "Amenities" heading, each box named by its tile's text. Tab moves from box to box and Space ticks. The whole tile is the label, so a press anywhere on it ticks the box. Pressing Save with none chosen moves focus to the first box, and the problem is read from the group's description and from the status line.
How does it look on a phone?
The tiles stay two across, with the glyph and box on top and the name under, so a long name wraps instead of being cut. The foot is pinned to the bottom of the screen with Save at full width.
What stays local, and how do I connect it for real?
The saved set lives in the block's state and nothing is sent: the foot says "Saved in this demo. Nothing was sent." In your app, replace the comment in submit with a request that sends the chosen ids, and treat the server's answer as the new saved set.