Skip to content

Assignee Picker

An assignee field with avatars, team sections, and dividers between them. data-select-clone copies the chosen person into the trigger, where the role line is hidden.


Design

Engineering

Code

The following example assumes that you have imported the component and set up the theme.

Assignee Picker
<div class="assignee-picker">
66 collapsed lines
<label for="assignee-trigger">Assignee</label>
<sv-select close-on-select name="assignee" scroll-to-selected value="none">
<sv-flyout class="assignee-flyout">
<button id="assignee-trigger" type="button" class="trigger" slot="trigger">
<span data-select-clone></span>
<svg class="chevron" aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path d="M480-360 280-560h400L480-360Z"></path>
</svg>
</button>
<button type="button" class="person" value="none">
<span class="avatar unassigned">
<svg aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
<path
d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-160v-112q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v112H160Z"
></path>
</svg>
</span>
<span class="name">Unassigned</span>
</button>
<hr />
<div class="group" aria-labelledby="assignee-design" role="group">
<span id="assignee-design" class="group-label">Design</span>
<button type="button" class="person" value="maya">
<span class="avatar" style="--avatar-clr: #b83a62" data-initials="MR"></span>
<span class="name">Maya Reyes</span>
<span class="role">Product designer</span>
</button>
<button type="button" class="person" value="leo">
<span class="avatar" style="--avatar-clr: #7446c2" data-initials="LP"></span>
<span class="name">Leo Park</span>
<span class="role">Brand designer</span>
</button>
</div>
<hr />
<div class="group" aria-labelledby="assignee-engineering" role="group">
<span id="assignee-engineering" class="group-label">Engineering</span>
<button type="button" class="person" value="sam">
<span class="avatar" style="--avatar-clr: #23704f" data-initials="SO"></span>
<span class="name">Sam Okafor</span>
<span class="role">Frontend</span>
</button>
<button type="button" class="person" value="iris">
<span class="avatar" style="--avatar-clr: #2a5f9e" data-initials="IN"></span>
<span class="name">Iris Novak</span>
<span class="role">Backend</span>
</button>
<button type="button" class="person" disabled value="theo">
<span class="avatar" style="--avatar-clr: #9a5a12" data-initials="TL"></span>
<span class="name">Theo Laine</span>
<span class="role">On leave</span>
</button>
</div>
</sv-flyout>
</sv-select>
</div>
<style>
143 collapsed lines
.assignee-picker {
display: grid;
gap: 0.5em;
inline-size: min(100%, 20rem);
margin-inline: auto;
color: var(--sv-gray-2);
label {
justify-self: start;
cursor: pointer;
}
.trigger {
display: flex;
gap: 0.5em;
align-items: center;
}
.chevron {
flex: none;
inline-size: 1.25em;
block-size: 1.25em;
margin-inline-start: auto;
fill: currentcolor;
rotate: -90deg;
transition: rotate 200ms ease;
}
sv-flyout:state(--opened) .chevron {
rotate: 0deg;
}
.role {
grid-column: 2;
font-size: 0.8em;
opacity: 0.7;
}
.person {
display: grid;
grid-template-columns: auto 1fr;
column-gap: 0.75em;
align-items: center;
padding: 0.5em 0.75em;
font: inherit;
color: inherit;
text-align: start;
cursor: pointer;
background: none;
border: none;
border-radius: var(--sv-bdr-rad-md);
&[aria-selected="true"] {
color: oklch(20% 0.03 85deg);
background-color: var(--sv-accent);
.role {
opacity: 1;
}
}
&:disabled {
cursor: not-allowed;
opacity: 0.5;
}
@media (hover: hover) and (pointer: fine) {
&:not([aria-selected="true"], :disabled):hover {
background-color: var(--sv-gray-5);
}
}
}
.avatar {
display: grid;
grid-row: span 2;
place-items: center;
inline-size: 2em;
block-size: 2em;
font-size: 0.8em;
font-weight: 600;
color: #fff;
background-color: var(--avatar-clr);
border-radius: 50%;
&[data-initials]::before {
content: attr(data-initials);
}
svg {
inline-size: 1.4em;
block-size: 1.4em;
fill: currentcolor;
}
}
.unassigned {
color: inherit;
background-color: transparent;
border: dashed var(--sv-bdr-sz-sm) currentcolor;
}
.trigger .person {
padding: 0;
color: inherit;
cursor: inherit;
background-color: transparent;
.role {
display: none;
}
}
.group {
display: grid;
gap: 0.25em;
}
.group-label {
padding: 0.5em 0.75em 0.25em;
font-size: 0.8em;
font-weight: 600;
color: var(--sv-gray-3);
text-transform: uppercase;
letter-spacing: 0.05em;
}
hr {
margin: 0.25em 0;
border: none;
border-block-start: solid var(--sv-bdr-sz-sm) var(--sv-gray-5);
}
.assignee-flyout::part(content) {
max-block-size: min(var(--sv-anchor-available-height), 24rem);
}
@media (prefers-reduced-motion: reduce) {
.chevron {
transition: none;
}
}
}
</style>