Navigation and layout

TabControl

TabControl

jp-tab-control has three looks, as in WPF. The default is the panel with tabs on top: the selected tab joins the panel below it, the others are dark. The content fills the control’s height when you give it one.

<jp-tab-control class="h-40">
    <jp-tab-item header="Available">14 consultants are available from week 44.</jp-tab-item>
    <jp-tab-item header="Assigned">…</jp-tab-item>
    <jp-tab-item header="Archive" is-enabled="false" />
</jp-tab-control>
<div id="jp-tabs-1" class="jp-tab-control h-40" data-selection-animation="slide" data-content-transition="none">
    <div class="jp-tab-control__header">
        <div class="jp-tab-control__strip" role="tablist">
            <button type="button" class="jp-tab-item" role="tab" id="jp-tabs-1-tab-0" aria-controls="jp-tabs-1-panel-0" aria-selected="true" tabindex="0">Available</button>
            <button type="button" class="jp-tab-item" role="tab" id="jp-tabs-1-tab-1" aria-controls="jp-tabs-1-panel-1" aria-selected="false" tabindex="-1">Assigned</button>
            <button type="button" class="jp-tab-item" role="tab" … disabled>Archive</button>
            <span class="jp-tab-control__notch" aria-hidden="true"></span>
        </div>
    </div>
    <div class="jp-tab-control__content" role="tabpanel" id="jp-tabs-1-panel-0" aria-labelledby="jp-tabs-1-tab-0">14 consultants are available from week 44.</div>
    <div class="jp-tab-control__content" role="tabpanel" id="jp-tabs-1-panel-1" aria-labelledby="jp-tabs-1-tab-1" hidden>…</div>
    …
</div>
Attribute Default Description
tab-control-style Default Default (panel), Strip or Navigation, below
selected-index 0 the selected tab (or is-selected on a jp-tab-item)
selection-animation Slide TabControlHelper.SelectionAnimation: how the notch moves to the selected tab: Slide, Drop or None
content-transition None TabControlHelper.ContentTransition: None or Fade
use-hash false keeps the selected tab in the address (#name), so a link or a reload opens that tab
id generated the id of the control; the tabs and panels get ids from it
jp-tab-item attribute Description
header the tab text
name a stable key for the tab: its ids, and the #name of use-hash
is-selected the selected tab
is-enabled false shows the tab dimmed
class goes on the tab’s content panel

Click a tab, or use the arrow keys, Home and End in the strip. Selecting a tab raises jp-change with { index, header, name }. From script:

const tabs = document.getElementById('Pages');
tabs.jetpack.select('sdk');       // by name, header or index
tabs.jetpack.selectedIndex;       // 1

TabControl with the navigation bar look

tab-control-style="Navigation" is the full-width light bar of the original theme’s navigation template: large tab headers, the selected one in the accent with the notch under it, and the content below with no frame. jp-tab-control-tag is the TabControl’s Tag, shown at the right end of the bar (the app name, a logo).

<jp-tab-control tab-control-style="Navigation">
    <jp-tab-control-tag><b>My app</b></jp-tab-control-tag>
    <jp-tab-item header="Companies" name="companies">…</jp-tab-item>
    <jp-tab-item header="Orders" name="orders">…</jp-tab-item>
</jp-tab-control>
<div id="…" class="jp-tab-control jp-tab-control--navigation" …>
    <div class="jp-tab-control__header">
        <div class="jp-tab-control__strip" role="tablist">… <span class="jp-tab-control__notch" aria-hidden="true"></span></div>
        <div class="jp-tab-control__tag"><b>My app</b></div>
    </div>
    …
</div>

Strip

TabControl with the strip look

tab-control-style="Strip" is the dark strip of the demo, with the Tag at the right. It is the page switcher of the web demo. Both bar looks leave the content unframed.

HamburgerMenu

HamburgerMenu

jp-hamburger-menu is the dark navigation pane with an icon and a label for each page; the button at the top folds it to the icons. It works in two ways.

As the window’s navigation. Put it in .jp-window__body, before the content, and give the items an href. Each page marks its own item with is-selected (or aria-current="page"). Folding the pane is remembered in the browser for all pages, and narrow windows (640 px or less) start folded.

<div class="jp-window__body">
    <jp-hamburger-menu>
        <jp-hamburger-menu-item content="Dashboard" icon="ViewGrid" href="/" is-selected="@(page == "Dashboard")" />
        <jp-hamburger-menu-item content="Employees" icon="AccountMultiple" href="/employees" is-selected="@(page == "Employees")" />
    </jp-hamburger-menu>
    <main class="jp-window__content">@RenderBody()</main>
</div>
<nav class="jp-hamburger-menu" aria-label="Pages">
    <button type="button" class="jp-hamburger-menu__toggle" data-jp-toggle-pane aria-expanded="true" aria-label="Show page names"><svg class="jp-icon" …></svg></button>
    <a class="jp-hamburger-menu__item" href="/" title="Dashboard" aria-current="page"><svg class="jp-icon" …></svg><span class="jp-hamburger-menu__label">Dashboard</span></a>
    …
</nav>

As a control with its own pages. When the items have content and no href, the tag helper writes the pane and a content area beside it, and clicking an item shows its content, as the control does in a WPF window. Give it a size.

<jp-hamburger-menu selected-index="0" class="h-52">
    <jp-hamburger-menu-item content="Overview" icon="Home"><h5>Overview</h5>…</jp-hamburger-menu-item>
    <jp-hamburger-menu-item content="Settings" icon="Cog">…</jp-hamburger-menu-item>
</jp-hamburger-menu>
Attribute Default Description
selected-index -1 the selected item (or is-selected on an item)
is-pane-open true false starts folded to the icons
pane-width 190 the width of the open pane in pixels
jp-hamburger-menu-item attribute Description
content the label
icon a JetPackIconKind
href makes the item a link
is-selected the selected item

A check box or toggle switch with data-jp-pane-switch folds and opens the window’s pane as well (the demo’s Settings flyout has one). To fold a pane that is not directly in .jp-window__body, mark it data-jp-window-pane.

Expander

Expanders

jp-expander is a <details>: the light header with the arrow, and the content in a dark panel below it. It folds without script.

<jp-expander header="Billing address" is-expanded="true">120 Pine Street<br>Seattle, WA 98101</jp-expander>
<details class="jp-expander" open="open">
    <summary>Billing address</summary>
    <div class="jp-expander__content">120 Pine Street<br>Seattle, WA 98101</div>
</details>
Attribute Default Description
header   the header text
is-expanded false open

Use the toggle event of <details> to react to it.

Accordion

Accordion

jp-accordion puts expanders in one frame, with one open at a time (the expanders share a <details name>). Given a height, the open expander fills it and the closed headers sit at the bottom.

<jp-accordion class="h-44">
    <jp-expander header="Need Placement" is-expanded="true">5 consultants without an assignment.</jp-expander>
    <jp-expander header="Renewal Pending">2 contracts expire on 31 December.</jp-expander>
</jp-accordion>
<div class="jp-accordion h-44">
    <details class="jp-expander" open="open" name="jp-accordion-1"><summary>Need Placement</summary><div class="jp-expander__content">…</div></details>
    <details class="jp-expander" name="jp-accordion-1"><summary>Renewal Pending</summary><div class="jp-expander__content">…</div></details>
</div>

GroupBox

GroupBox

jp-group-box is a dark panel with a header strip.

<jp-group-box header="Contact">
    <jp-label content="Name" target="Name" />
    <jp-text-box id="Name" text="Heather Andrade" />
</jp-group-box>
<section class="jp-group-box">
    <h2 class="jp-group-box__header">Contact</h2>
    <div class="jp-group-box__content">…</div>
</section>
Attribute Description
header the header text

Menu with a menu open

jp-menu is the light menu bar. Its jp-menu-item children are the top-level headers, and their children are the menu that opens below them, a popover. Once a menu is open, the mouse opens the other headers’ menus at once; the arrow keys move in a menu, Right opens a submenu and Left closes it, and Esc closes the menu.

<jp-menu>
    <jp-menu-item header="_File">
        <jp-menu-item header="_New customer" input-gesture-text="Ctrl+N" icon="FilePlus" />
        <jp-separator />
        <jp-menu-item header="Status bar" is-checkable="true" is-checked="true" />
        <jp-menu-item header="Recent">
            <jp-menu-item header="Contoso Corporation" href="/customers/17" />
        </jp-menu-item>
    </jp-menu-item>
    <jp-menu-item header="_Help" />
</jp-menu>
<nav class="jp-menu" role="menubar">
    <button type="button" class="jp-menu-item" role="menuitem" popovertarget="jp-submenu-1" aria-haspopup="menu">File</button>
    <div class="jp-context-menu" popover id="jp-submenu-1" role="menu">
        <button type="button" class="jp-menu-item" role="menuitem"><svg class="jp-icon" aria-hidden="true">…</svg><span class="jp-menu-item__header">New customer</span><span class="jp-menu-item__gesture">Ctrl+N</span></button>
        <hr class="jp-menu-separator" />
        <button type="button" class="jp-menu-item" role="menuitemcheckbox" aria-checked="true"><span class="jp-menu-item__header">Status bar</span></button>
        <button type="button" class="jp-menu-item" role="menuitem" aria-haspopup="menu" data-jp-submenu="jp-submenu-2"><span class="jp-menu-item__header">Recent</span></button>
        <div class="jp-context-menu" popover id="jp-submenu-2" role="menu">…</div>
    </div>
    <button type="button" class="jp-menu-item" role="menuitem">Help</button>
</nav>
jp-menu-item attribute Default Description
header   the text (an _ access key marker is dropped)
input-gesture-text   the shortcut shown at the right; it only shows the text, it does not bind the key
icon   a JetPackIconKind in the icon column
is-checkable false a check item: a click flips aria-checked
is-checked false shows the check mark
href   makes the item a link

A click on an item closes the menu; listen for click on the items (or use href).

ContextMenu

ContextMenu

jp-context-menu is a menu that opens at the mouse on a right-click. Give it an id, and put data-jp-context-menu="id" on the elements it belongs to:

<div data-jp-context-menu="GridMenu">Right-click here</div>
<jp-context-menu id="GridMenu">
    <jp-menu-item header="Copy" input-gesture-text="Ctrl+C" />
    <jp-menu-item header="Paste" input-gesture-text="Ctrl+V" is-enabled="false" />
    <jp-separator />
    <jp-menu-item header="Export"><jp-menu-item header="PDF" /></jp-menu-item>
</jp-context-menu>
<div class="jp-context-menu" id="GridMenu" popover role="menu">…</div>

The same .jp-context-menu is the menu of SplitButton and DropDownButton.

ToolBar

ToolBar

jp-tool-bar is the light bar with the grip. In it, buttons are flat until the mouse is over them, pressed toggle buttons look pressed in, and a jp-separator is the vertical separator. jp-tool-bar-tray holds one or more tool bars.

<jp-tool-bar-tray>
    <jp-tool-bar>
        <jp-button tool-tip="Save"><jp-icon kind="ContentSave" /></jp-button>
        <jp-separator />
        <jp-toggle-button is-checked="true"><b>B</b></jp-toggle-button>
        <jp-combo-box selected-index="0" class="!w-28"><jp-combo-box-item content="Trebuchet MS" /></jp-combo-box>
        <jp-check-box content="Spelling" is-checked="true" on-light="true" />
    </jp-tool-bar>
</jp-tool-bar-tray>
<div class="jp-tool-bar-tray">
    <div class="jp-tool-bar" role="toolbar"><span class="jp-tool-bar__thumb" aria-hidden="true"></span>
        <button type="button" class="jp-button" data-jp-tool-tip="Save">…</button>
        <span class="jp-tool-bar__separator" role="separator"></span>
        …
    </div>
</div>

StatusBar

StatusBar

jp-status-bar is the dark bar at the bottom of the window, with small text. Items with horizontal-alignment="Right" move to the right end.

<jp-status-bar>
    <jp-status-bar-item>Ready</jp-status-bar-item>
    <jp-status-bar-item content="5 available · 9 assigned" />
    <jp-status-bar-item horizontal-alignment="Right">Syncing <jp-progress-bar is-indeterminate="true" class="!w-20 !h-2" /></jp-status-bar-item>
</jp-status-bar>
<footer class="jp-status-bar">
    <span>Ready</span>
    <span>5 available · 9 assigned</span>
    <span class="jp-status-bar__item--right">Syncing <progress class="!w-20 !h-2 jp-progress-bar" max="100"></progress></span>
</footer>
jp-status-bar-item attribute Description
content the text; without it the element’s content is used
horizontal-alignment Right moves the item (and the ones after it) to the right

GridSplitter and Separator

GridSplitter and Separator

jp-grid-splitter goes between two panes of a flex row: dragging it (or the Left and Right keys, 10 px a step) resizes the pane before it, within both panes’ min-width. Between two panes of a flex column, give it resize-direction="Rows" (class jp-grid-splitter--rows): the bar lies down, the grip turns with it, and it resizes heights with the Up and Down keys, within min-height. jetpack.js also treats a splitter in a flex column as a row splitter without the attribute. jp-separator is the etched horizontal line; in a menu it is the menu separator, and in a tool bar the vertical one.

<div class="flex h-40">
    <div class="flex-1 min-w-24">Navigation</div>
    <jp-grid-splitter />
    <div class="flex-[2] min-w-24 flex flex-col">
        <div class="flex-1 min-h-8">Content</div>
        <jp-grid-splitter resize-direction="Rows" />
        <div class="flex-1 min-h-8">Details</div>
    </div>
</div>
<jp-separator />
<div class="jp-grid-splitter" role="separator" aria-orientation="vertical"></div>
<div class="jp-grid-splitter jp-grid-splitter--rows" role="separator" aria-orientation="horizontal"></div>
<hr class="jp-separator" />
jp-grid-splitter attribute Description
resize-direction Columns (default) or Rows

ToolTip

ToolTip

tool-tip on any control tag helper, or jp-tool-tip on any element, shows the green JetPack call-out under the pointer after half a second:

<jp-button tool-tip="Saves changes and sends them for approval">Save</jp-button>
<span jp-tool-tip="Hours this week">37.5</span>
<button type="button" class="jp-button" data-jp-tool-tip="Saves changes and sends them for approval">Save</button>
<span data-jp-tool-tip="Hours this week">37.5</span>

Both write data-jp-tool-tip, which you can also set from script. Use it in place of title, which shows the browser’s own tool tip.