logo

Aki UI

アキ ウイ

Team Selector

チームセレクター

A stepper that shows what it is counting: the avatars are all laid out from the start and fade in as the number rises, so nothing reflows while you press. The count sits in an output that announces itself politely, and the digits slide in the direction you stepped. At the ends the buttons are marked aria-disabled rather than disabled — they stay focusable and reachable, and a press shakes the row instead of doing nothing silently, which is the difference between a refusal and a dead control. The whole thing is a fieldset so the legend names the group. Avatars are monograms drawn from the names; pass avatarUrl to use pictures. Adapted from Kokonut UI under the MIT licence.

Team size
2
members

Installation

Install the following dependencies:1

npm install framer-motionnpm install lucide-react

Copy and paste the following code into a new component file:2

"use client"

/**
* Adapted for Aki UI from Kokonut UI's Team Selector.
* Original author: @dorianbaffier — https://kokonutui.com
* Copyright (c) 2025 kokonutUI, MIT License.
* https://github.com/kokonut-labs/kokonutui
*
* Reworked here onto the local palette, with motion/react swapped for
* framer-motion, the DiceBear avatar requests replaced by local monograms,

How to use it3

"use client"

import { TeamSelector } from "@/components/ui/team-selector"

export default function Page() {
return (
<TeamSelector
members={[
{ id: "alex", name: "Alex Rivera" },
{ id: "blair", name: "Blair Kim" },

Props

TeamSelector

NameDefaultDescription
members4 monograms

{ id: string, name: string, avatarUrl?: string }[]

The roster; its length is the maximum

defaultValue1

number

Count on mount, clamped to the roster

onChange

(size: number) => void

Called with the new count on every step

label"Team size"

string

Legend of the fieldset

darkfalse

boolean

Render the dark palette