App, member list
Install
npx shadcn add @klarhimmel/app-team-membersUsage
import { Theme } from '@/components/klarhimmel/theme/style';
import { BlockSurface } from '@/components/klarhimmel/blocks/surface';
import AppTeamMembers from '@/components/klarhimmel/blocks/app-team-members';
export default function Section() {
return (
<Theme theme="brand">
<BlockSurface>
<AppTeamMembers props={{
"eyebrow": "Team",
"title": "People at Exempelhotellet",
"description": "Everyone who can sign in. Owners can change roles.",
"summaryWord": "members",
"roles": [
"Owner",
"Admin",
"Member",
"Viewer"
],
"roleLabel": "Role for",
"members": [
{
"name": "Maja Lindqvist",
"email": "[email protected]",
"sample": "Owner",
"locked": true
},
{
"name": "Nils Berg",
"email": "[email protected]",
"sample": "Admin",
"locked": false
},
{
"name": "Ada Ek",
"email": "[email protected]",
"sample": "Member",
"locked": false
},
{
"name": "Oskar Holm",
"email": "[email protected]",
"sample": "Viewer",
"locked": false
}
],
"remove": {
"label": "Remove",
"question": "Remove this person?",
"yes": "Yes, remove",
"no": "Keep"
},
"notices": {
"roleNow": "is now",
"removed": "removed"
},
"state": "filled",
"messages": {
"emptyTitle": "Only you here so far",
"emptyBody": "Invite a colleague and they appear in this list."
}
}} />
</BlockSurface>
</Theme>
);
}Install
Import
import Block from '@/components/klarhimmel/blocks/app-team-members';- app/team-members
- About
- The people on a team: avatar, name, email and a role select per member, a locked owner row, Remove with a confirmation that keeps focus in the list, role changes and removals announced by name, a count that follows, and an empty state.
- Category
- Interface sections for signed-in products.
Notes
When to use it
A list of the people on a team, each with a role select and a Remove button. Use `app-team-pending` for invitations that are not accepted yet and `app-team-invite` for adding someone; this one is for people who already have access.
Writing for it
- roles (2 to 5 names, 20 characters) feeds every row's select, so list all of them, including Owner if one row is locked. - Each member's sample must be one of the roles. Set locked: true on the owner so that row shows a badge and has no Remove button. - roleLabel (30) is spoken before the name, so end it with a word like 'Role for'. Write notices.roleNow and notices.removed so they read after the person's name.
Watch out for
Removing a member is a confirm step in the list, but the block removes the row only on screen. With up to 8 members the count in the heading follows the rows that are left, and when it reaches zero the empty message takes over.
Pairs well with
Usage
The block in a page, with its default content (long lists shortened). Every prop is in the table below.
import { Theme } from '@/components/klarhimmel/theme/style';
import { BlockSurface } from '@/components/klarhimmel/blocks/surface';
import AppTeamMembers from '@/components/klarhimmel/blocks/app-team-members';
export default function Section() {
return (
<Theme theme="brand">
<BlockSurface>
<AppTeamMembers props={{
"eyebrow": "Team",
"title": "People at Exempelhotellet",
"description": "Everyone who can sign in. Owners can change roles.",
"summaryWord": "members",
"roles": [
"Owner",
"Admin",
"Member"
],
"roleLabel": "Role for",
"members": [
{
"name": "Maja Lindqvist",
"email": "[email protected]",
"sample": "Owner",
"locked": true
},
{
"name": "Nils Berg",
"email": "[email protected]",
"sample": "Admin",
"locked": false
},
{
"name": "Ada Ek",
"email": "[email protected]",
"sample": "Member",
"locked": false
}
],
"remove": {
"label": "Remove",
"question": "Remove this person?",
"yes": "Yes, remove",
"no": "Keep"
},
"notices": {
"roleNow": "is now",
"removed": "removed"
},
"state": "filled",
"messages": {
"emptyTitle": "Only you here so far",
"emptyBody": "Invite a colleague and they appear in this list."
}
}} />
</BlockSurface>
</Theme>
);
}Props
The type, default and text limit of every prop. On a real page, over-limit text is kept and checkSections flags it (Installation, Check a page before you ship); this live preview shows the default until it fits. The panel above edits all props.
| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | 'Team' | Text, up to 60 characters. Optional; empty is not rendered. |
title | string | 'People at Exempelhotellet' | Text, up to 120 characters. |
description | string | 'Everyone who can sign in. Owners ca…' | Text, up to 300 characters. Optional; empty is not rendered. |
summaryWord | string | 'members' | Text, up to 20 characters. |
roles | string[] | 4 items | List of 2 to 5. |
roleLabel | string | 'Role for' | Text, up to 30 characters. |
members | { name, email, sample, locked }[] | 4 items | List of 1 to 8. Each item: name, email, sample, locked. |
remove | { label, question, yes, no } | {…} | Fields: label, question, yes, no. |
notices | { roleNow, removed } | {…} | Fields: roleNow, removed. |
state | 'filled' | 'empty' | 'filled' | One of 'filled', 'empty'. |
messages | { emptyTitle, emptyBody } | {…} | Fields: emptyTitle, emptyBody. |
headingLevel | '1' | '2' | - | One of '1', '2'. Optional; empty is not rendered. |