Hesoyam

Entity

A row with optional left media, a title and description, and a right-side control.

Default

left and right are slots (or render props). EntityContent holds the title and secondary line.

Evil Rabbit
Glenn Hitchcock (@gln)

Connected 1h ago


        
1 <Entity>
2 <template #left>
3 <Avatar :size="32" username="evilrabbit" />
4 </template>
5 <EntityContent
6 fill
7 title="Evil Rabbit"
8 description="Glenn Hitchcock (@gln)"
9 />
10 <template #right>
11 <p class="text-[14px] text-[var(--ds-gray-900)]">Connected 1h ago</p>
12 </template>
13 </Entity>

List

EntityList is a divided stack. Set as="li" on each row so the markup matches the list.

  • GitHub Desktop on MacBook Pro
    Last used just now
  • VS Code on Windows 11
    Last used 10 min ago
  • Terminal on Ubuntu 24.04
    Last used 25 min ago

        
1 <EntityList>
2 <Entity as="li">
3 <EntityContent
4 title="GitHub Desktop on MacBook Pro"
5 description="Last used just now"
6 />
7 <template #right>
8 <Button size="small" variant="secondary">Revoke Session</Button>
9 </template>
10 </Entity>
11 </EntityList>

Checkbox

Put the Checkbox in the left slot. Label it with the entity name so the row is selectable without relying on nearby text.

  • GitHub Desktop on MacBook Pro
    Last used just now
  • VS Code on Windows 11
    Last used 10 min ago
  • Terminal on Ubuntu 24.04
    Last used 25 min ago

        
1 <Entity as="li">
2 <template #left>
3 <Checkbox
4 v-model="selected.github"
5 aria-label="Select GitHub Desktop on MacBook Pro"
6 />
7 </template>
8 <EntityContent
9 title="GitHub Desktop on MacBook Pro"
10 description="Last used just now"
11 />
12 </Entity>

Fill

fill makes EntityContent grow so a trailing column can sit on the right edge.

  • Primary column stretches.
    Trailing column stays tight.

        
1 <Entity>
2 <EntityContent fill description="Primary column stretches." />
3 <EntityContent description="Trailing column stays tight." />
4 </Entity>

Skeleton

Reserve the row while data resolves. Do not flash an empty Entity and swap it later.


        
1 <Entity>
2 <div class="flex flex-1 flex-col gap-2">
3 <Skeleton :height="20" width="100%" />
4 <div class="flex gap-2">
5 <Skeleton :height="20" :width="70" />
6 <Skeleton :height="20" :width="60" />
7 <Skeleton :height="20" :width="68" />
8 </div>
9 </div>
10 </Entity>

Column classes

left-class-name and right-class-name style the side columns without wrapping extra markup.

Dashed columns mark the left and right slots.
Action

        
1 <Entity
2 left-class-name="rounded-md border border-dashed border-[var(--ds-gray-alpha-400)] p-2"
3 right-class-name="rounded-md border border-dashed border-[var(--ds-gray-alpha-400)] p-2"
4 >
5 <template #left>
6 <Avatar placeholder :size="32" />
7 </template>
8 <EntityContent description="Dashed columns mark the left and right slots." />
9 <template #right>
10 <span class="text-[13px] text-[var(--ds-gray-900)]">Action</span>
11 </template>
12 </Entity>

Best practices

  • Entity is a descriptive row with one or two controls: members, sessions, domains, integrations. Sortable columns belong in Table. Static key/value blocks belong in a description list.
  • as="li" inside EntityList. as="button" when the whole row is the control. Do not nest a Checkbox inside a button row.
  • Right column holds at most two actions. Anything else goes in a Menu. Labels stay Verb + Noun (Revoke Session), not a bare verb.
  • Lead with a scannable mark — Avatar or icon — then a Title Case name and sentence-case metadata.
  • left / right props accept a vnode or component for render functions. Templates should use the slots.