Live directory
Search by name or skill, switch departments, paginate through results, and click "View profile" to open a detail sheet. Reset the search to see the empty-state CTA.
$search = ""
$department = "all"
$page = 1
$selectedId = ""
data = Query("list_members", {q: $search, department: $department, page: $page}, {
rows: [], total: 0, pages: 1, popular: []
})
detail = Query("get_member", {id: $selectedId}, {
id: "", name: "", role: "", bio: "", tags: [], stats: [], avatar: ""
})
header = PageHeader(
"Team directory",
"Everyone at Acme Robotics, searchable in one place",
Breadcrumb([BreadcrumbItem("Company", "#"), BreadcrumbItem("People")]),
[
Button("Export CSV", Action([@ToAssistant("Export the directory as CSV")]), "ghost"),
Button("Invite", Action([@ToAssistant("Open the invite-by-email form")]), "primary")
],
Tag("" + data.total + " people", null, "sm", "primary")
)
searchField = FormControl(
"Search",
Input("search", "Name, role, skill…", "text", null, $search),
"Filters update as you type"
)
departmentToggle = FormControl("Department", ToggleGroup("department", [
{value: "all", label: "All"},
{value: "eng", label: "Engineering", icon: "laptop-code"},
{value: "ds", label: "Design", icon: "palette"},
{value: "ops", label: "Operations", icon: "box"},
{value: "sales", label: "Sales", icon: "chart-line"}
], $department))
controls = Stack([searchField, departmentToggle], "row", "m", "stretch", "start", true)
popularRow = Card([
CardHeader("Most-mentioned this week", "Hover an avatar to see their role"),
AvatarGroup(data.popular, 6, "lg")
])
cardsGrid = Grid(@Each(data.rows, "u",
Card([
ProfileCard(u.name, u.role, u.avatar, u.bio, u.tags, [
Button("View profile", Action([@Set($selectedId, u.id)]), "secondary", "button", "small"),
Button("Message", Action([@ToAssistant("Open a DM thread with " + u.name)]), "ghost", "button", "small")
])
])
), 3, "m")
emptyState = EmptyState(
"No matches for your filters",
"Try a different search term or pick another department.",
"magnifying-glass",
Button("Clear filters", Action([@Reset($search), @Reset($department), @Set($page, 1)]), "primary")
)
body = @Count(data.rows) > 0 ? cardsGrid : emptyState
pager = Pagination($page, data.pages, 1)
detailSheet = Sheet(
detail.name == "" ? "Loading…" : detail.name,
$selectedId != "",
[
Stack([
Avatar(detail.name, detail.avatar, "xl"),
Stack([
TextContent(detail.role, "body-heavy"),
TextContent(detail.bio, "body", "muted")
], "column", "xs")
], "row", "m", "start", "start"),
Separator("horizontal", true),
TagBlock(detail.tags, "primary", "sm"),
Separator("horizontal", true),
MetricGrid(@Each(detail.stats, "s",
StatCard(s.label, s.value, s.trend, s.delta, s.icon)
), 3)
],
"right",
[
Button("Close", Action([@Reset($selectedId)]), "ghost"),
Button("Message", Action([@ToAssistant("Open a DM thread with " + detail.name), @Reset($selectedId)]), "primary")
]
)
root = Stack([header, popularRow, controls, body, pager, detailSheet], "column", "l")