Data

OrgChart

A tree of people as boxes joined by lines, drawn with CSS on nested lists, with pictures, titles, notes and the reader's place marked.

#chart#user#list#no-js

Demo

Preview
  • Ada LovelaceCTO3 reports, 3 reports
    • Grace HopperCompilers, 2 reports
      • Jean SammetLanguages
      • Frances AllenOptimisation
    • Alan TuringResearch, 1 report
      • Joan ClarkeCryptanalysis
    • Hedy LamarrRadioHiring
  • Chair, 1 report
    • Treasurer

Get it

It needs theme.qwe, as every component does, and avatar.qwe; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/avatar.qwe$ curl -O https://quillolang.org/components/ui/org_chart.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/org_chart.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/org_chart.qwe
let org_chart_demo_team = { name: "Ada Lovelace", title: "CTO", href: "#org_chart", note: "3 reports", children: [    { name: "Grace Hopper", title: "Compilers", src: "https://i.pravatar.cc/80?img=47", children: [        { name: "Jean Sammet", title: "Languages" }, { id: "fran", name: "Frances Allen", title: "Optimisation" },    ] },    { name: "Alan Turing", title: "Research", children: [{ name: "Joan Clarke", title: "Cryptanalysis" }] },    { name: "Hedy Lamarr", title: "Radio", note: "Hiring" },] }view OrgChartDemo() =    <div.demo-stack>        <OrgChart id="org-chart-demo-full" label="Engineering" root={org_chart_demo_team} highlight="fran"/>        <OrgChart id="org-chart-demo-compact" compact={true} label="Board" root={{ name: "Chair", children: [{ name: "Treasurer" }] }}/>    </div>

Source

ui/org_chart.qwe
// OrgChart: who reports to whom: a tree of people as boxes, each joined to the one// above by lines, drawn with CSS on nested lists (so screen readers hear the// nesting). It scrolls sideways when it is wider than its place.////   <OrgChart label="Engineering" root={{ name: "Ada Lovelace", title: "CTO", children: [//       { name: "Grace Hopper", title: "Compilers", children: [{ name: "Jean Sammet", title: "Languages" }] },//       { name: "Alan Turing", title: "Research" },//   ] }}/>//// root: the person at the top, a map of { name, title?, src?, href?, id?, note?,// children? }: src a picture (initials without one), href makes the name a link,// note a small line under the title ("4 reports", "Hiring"), children the people// who report to them, the same shape. highlight: a person's id (or name) to mark,// as the reader's place ("you"). compact: smaller boxes, without pictures.// label: what screen readers call the chart ("Organisation chart"). id: its id.// Needs avatar.qwe.import ui/avatar.qwe use Avatarimport ui/theme.qwe use ui_clslet org_chart_css = css`.ui-org-chart { min-width: 0; overflow-x: auto; padding: 4px 4px 8px; font: 13px/1.35 var(--ui-font); color: var(--ui-fg); --ui-org-chart-line: var(--ui-strong); }.ui-org-chart ul { position: relative; display: flex; justify-content: center; margin: 0; padding: 22px 0 0; list-style: none; }.ui-org-chart > ul { padding-top: 0; width: max-content; min-width: 100%; }.ui-org-chart li { position: relative; display: flex; flex-direction: column; align-items: center; padding: 22px 8px 0; }.ui-org-chart > ul > li { padding-top: 0; }.ui-org-chart li::before, .ui-org-chart li::after { content: ""; position: absolute; top: 0; right: 50%; width: 50%; height: 22px;  border-top: 2px solid var(--ui-org-chart-line); }.ui-org-chart li::after { right: auto; left: 50%; border-left: 2px solid var(--ui-org-chart-line); }.ui-org-chart li:only-child::before, .ui-org-chart li:only-child::after { display: none; }.ui-org-chart li:only-child { padding-top: 0; }.ui-org-chart li:first-child::before, .ui-org-chart li:last-child::after { border: 0 none; }.ui-org-chart li:last-child::before { border-right: 2px solid var(--ui-org-chart-line); border-radius: 0 8px 0 0; }.ui-org-chart li:first-child::after { border-radius: 8px 0 0 0; }.ui-org-chart ul ul::before { content: ""; position: absolute; top: 0; left: 50%; width: 0; height: 22px; border-left: 2px solid var(--ui-org-chart-line); }.ui-org-chart > ul > li::before, .ui-org-chart > ul > li::after { display: none; }.ui-org-chart-box { display: grid; justify-items: center; gap: 2px; width: 150px; padding: 12px 10px 10px; border: 1px solid var(--ui-border);  border-radius: var(--ui-radius); background: var(--ui-surface); text-align: center; box-shadow: 0 1px 2px color-mix(in srgb, var(--ui-fg) 6%, transparent); }.ui-org-chart-box .ui-org-chart-pic { margin-bottom: 6px; }.ui-org-chart-name { font-size: 14px; font-weight: 650; overflow-wrap: anywhere; }.ui-org-chart-name a { color: inherit; text-decoration: none; }.ui-org-chart-name a:hover { color: var(--ui-accent); text-decoration: underline; }.ui-org-chart-name a:focus-visible { outline: none; border-radius: 4px; box-shadow: var(--ui-focus); }.ui-org-chart-title { color: var(--ui-muted); }.ui-org-chart-note { margin-top: 4px; padding: 1px 8px; border-radius: 999px; background: var(--ui-subtle); color: var(--ui-muted); font-size: 11px; }.ui-org-chart-here { border-color: var(--ui-accent); background: var(--ui-accent-soft); box-shadow: 0 0 0 1px var(--ui-accent); }.ui-org-chart-here .ui-org-chart-title { color: var(--ui-accent); }.ui-org-chart-compact .ui-org-chart-box { width: 120px; padding: 8px; }.ui-org-chart-compact .ui-org-chart-name { font-size: 13px; }`// One person and, under them, those who report to them.fn org_chart_node(p: map, highlight, compact: bool) {    let here = highlight != null && (p.id ?? p.name) == highlight    let kids = p.children ?? []    <li key={p.id ?? p.name}>        <div class={ui_cls(["ui-org-chart-box", here && "ui-org-chart-here"])} aria-current={here ? "true" : null}>            {!compact && <Avatar name={p.name} src={p.src} size="md" class="ui-org-chart-pic"/>}            <span.ui-org-chart-name>{p.href != null ? <a href={p.href}>{p.name}</a> : p.name}</span>            {p.title != null && <span.ui-org-chart-title>{p.title}</span>}            {p.note != null && <span.ui-org-chart-note>{p.note}</span>}            {len(kids) > 0 && <span.ui-sr>, {len(kids)} {len(kids) == 1 ? "report" : "reports"}</span>}        </div>        {len(kids) > 0 && <ul>{for k in kids => org_chart_node(k, highlight, compact)}</ul>}    </li>}view OrgChart(root: map, highlight = null, compact: bool = false, label: str = "Organisation chart", id: str? = null, class: str? = null) {    style global org_chart_css    <div class={ui_cls(["ui-org-chart", compact && "ui-org-chart-compact", class])} id={id} role="group" aria-label={label} tabindex="0">        <ul>{org_chart_node(root, highlight, compact)}</ul>    </div>}
Thread
75Useful? Like it, or add to its thread below.

Thread 0 posts

On OrgChart: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.