Nº 136 of 520
People by role
A staff directory with name search, role pills, initials, and an empty line when the filter matches no one.
Preview
Use it
Free to use · credit appreciated1 Once, in your project
npx skills add SusanAcharya/Design-Lounge 2 Then ask
Using the Design Lounge skill, build "People by role" (piece people-role-list) in my stack. Match its brief; restyle it onto my product's theme.
No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.
<!-- Design Lounge Nº 136 · "People by role" · www.designlounge.live -->
# People by role
> **Build brief for a coding agent.** Rebuild this piece in the reader's stack. If they haven't said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don't "improve" them. When a kit is locked, map colours onto the kit tokens. Keep the four people, the role pills, and the empty line.
## What it is
The people screen for a yard company. A title, one primary Invite button, a search field, and pills for All, Dispatch, Finance, and Yard. Four people in a white card: initials, name, email, role badge, last seen. Search and the role pill combine. If nobody matches, the card stays and a line under it reads "No one in that role. Clear the filter." Invite changes its label to "Invite sent". No modal in this piece.
## Reference behaviour
1. All is pressed. Four rows visible. Search is empty.
2. Typing filters by the row's visible text, case-insensitive.
3. A role pill shows only that role. All clears the role constraint. Search still applies.
4. Zero matches shows the empty line. Rows that fail are `display: none` and stay in the DOM.
5. Invite sets its own text to "Invite sent" and disables nothing else. It does not append a person.
6. Pressed pill is ink fill with background-coloured text. Others are white with a hairline.
7. Avatars are initials on `#2c241c`. No photos.
8. Focus ring 2px `--focus`, offset 2px.
## Structure
```
header: People | Invite
tools: search 240×36 | pills 32px
card of rows, min-height 64
empty paragraph
```
- Search is `type="search"` labelled "Search by name".
- Pills are buttons with `aria-pressed`.
- Each person is an `li`.
## Tokens
```css
:root {
--bg: #f4f1ea;
--surface: #fffdf8;
… 116 more lines. Copy or download for the full brief. Loading the source…Brief
156 linesBuild brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them. When a kit is locked, map colours onto the kit tokens. Keep the four people, the role pills, and the empty line.
What it is
The people screen for a yard company. A title, one primary Invite button, a search field, and pills for All, Dispatch, Finance, and Yard. Four people in a white card: initials, name, email, role badge, last seen. Search and the role pill combine. If nobody matches, the card stays and a line under it reads “No one in that role. Clear the filter.” Invite changes its label to “Invite sent”. No modal in this piece.
Reference behaviour
- All is pressed. Four rows visible. Search is empty.
- Typing filters by the row’s visible text, case-insensitive.
- A role pill shows only that role. All clears the role constraint. Search still applies.
- Zero matches shows the empty line. Rows that fail are
display: noneand stay in the DOM. - Invite sets its own text to “Invite sent” and disables nothing else. It does not append a person.
- Pressed pill is ink fill with background-coloured text. Others are white with a hairline.
- Avatars are initials on
#2c241c. No photos. - Focus ring 2px
--focus, offset 2px.
Structure
header: People | Invite
tools: search 240×36 | pills 32px
card of rows, min-height 64
empty paragraph
- Search is
type="search"labelled “Search by name”. - Pills are buttons with
aria-pressed. - Each person is an
li.
Tokens
:root {
--bg: #f4f1ea;
--surface: #fffdf8;
--ink: #1c1915;
--ink-2: #5e574e;
--ink-3: #8a8176;
--line: #e0d8cc;
--primary: #8a4b12;
--primary-ink: #fffdf8;
--primary-soft: #f3e6d8;
--focus: #8a4b12;
--font-text: "IBM Plex Sans", system-ui, sans-serif;
--radius: 8px;
}
Typography
- Title: IBM Plex Sans 500, 28px, tracking -0.03em.
- Invite: 14px weight 500, height 36, radius 6, fill
#8a4b12, ink#fffdf8. - Name: 14px weight 600. Email: 12px
--ink-2. - Role badge: 11px weight 600, height 22, fill
#f3e6d8. - Last seen: 12px
--ink-3. - Pills: 12px, height 32.
- One face only. No mono.
Motion
None. Filtering is instant.
States
- Pill pressed or not.
- Row visible or hidden.
- Empty line hidden or shown.
- Invite label “Invite” then “Invite sent”.
- No row selection.
Accessibility
- Search has an accessible name.
- Role group does not need a menu role. Pressed state is enough.
- Empty line is text, not only a blank card.
- Avatar initials are visible. The name next to them is the accessible name of the row’s text.
- Contrast of
#1c1915on#fffdf8is above 4.5. - Row min-height 64px.
Responsive rules
- At 1280 the card margin is 0 32px and the row is four columns: 40px, fluid, role, seen.
- At 768 the search field becomes full width on its own row. Pills wrap.
- Below 640 the last-seen column drops under the email, and Invite becomes full width under the title.
Acceptance checklist
- Four people render with the roles Dispatch, Finance, Yard, Dispatch.
- All starts pressed.
- Search and role filter combine.
- Empty copy appears when nothing matches.
- Invite changes to “Invite sent” and does not add a row.
- Avatars are 40px initials, not photos.
- The card radius is 8px. The pills are fully round.
- One typeface, IBM Plex Sans.
- One solid button, the invite.
Implementation notes
Store the role on data-role. The All pill uses data-role="all".
Rebuild order:
- Page
#f4f1ea, padding via header 22px 32px 8px. - Title People, 28px, weight 500.
- Invite height 36, radius 6, fill
#8a4b12. - Search width 240, height 36, radius 6, border
#e0d8cc, fill#fffdf8. - Pills height 32, radius 99px.
- Card margin 0 32px, radius 8, border
#e0d8cc, fill#fffdf8. - Row grid
40px 1fr auto auto, min-height 64, padding 0 16px. - People: Mira Lama Dispatch Today, Asha Karki Finance Yesterday, Rajan Shrestha Yard Mon, Nima Gurung Dispatch Invited.
- Emails end in @yard.test.
- Empty sentence sits under the card, 14px
#5e574e, hidden until the count is 0.
Common mistakes:
- Opening an invite modal. The button only changes its label.
- Photos from a CDN.
- A second button in the row, such as Remove.
- Zebra stripes.
- Hiding the card when empty. The card remains. The sentence appears under it.
- Using serif for names.
- Making Finance a different badge colour from Dispatch. All role badges share
--primary-soft. - Adding a fifth person on invite.
- A checkbox column for bulk actions.
- Sorting arrows on Name and Seen.
- A second search field for email.
Copy you keep, in this order:
- Title is “People”.
- Primary button starts as “Invite” and becomes “Invite sent”.
- Search placeholder is “Search by name”.
- Pills read All, Dispatch, Finance, Yard.
- Mira Lama, mira@yard.test, Dispatch, Today.
- Asha Karki, asha@yard.test, Finance, Yesterday.
- Rajan Shrestha, rajan@yard.test, Yard, Mon.
- Nima Gurung, nima@yard.test, Dispatch, Invited.
- Initials are ML, AK, RS, NP.
- Avatar fill is
#2c241c. Avatar text is#f4efe6. - Empty sentence is “No one in that role. Clear the filter.”
- Card margin is 0 32px.
- Row min-height is 64px.
- Pressed pill fill is
#1c1915with page-colour text. - Role badge fill is
#f3e6d8for every role. - There is no row action, no checkbox, and no pagination.
Details
- Palette
- Type
- IBM Plex Sans
- Motion
- Static
- Build
- Quick build
- Tags
On the shelves