Canvas Design System
Main Site Tokens

Side Panel

A panel that slides in from the right edge, beside the page rather than in front of it. The page stays live while it is open.

When to Use

Use when: The work runs alongside what is open and the reader needs both at once: a workshop's comments beside its agenda, notes beside a running session. It is opened from a control in the page's own chrome, usually an icon on the App Bar.
Don't use when: The reader has to finish or refuse something before going on. That is a Modal, which traps focus and holds the page still; a side panel does neither.

Variants

Heading, subtitle and a body

One shape. The head carries the title, an optional line under it, and the close button; the body scrolls on its own. Open it from the button below: any element with data-ws-side-panel-open toggles the panel it names.

<?= ws_side_panel($bodyHtml, [
    'id'       => 'wsComments',
    'title'    => 'Leave a comment',
    'subtitle' => 'Everyone working on this workshop reads what you post here.',
]) ?>

<?= ws_button('Comments', ['icon' => 'mode_comment', 'attrs' => [
    'data-ws-side-panel-open' => 'wsComments',
    'aria-controls'           => 'wsComments',
    'aria-expanded'           => 'false',
]]) ?>

Branded

'variant' => 'branded' puts the head on the red band the branded Modal wears: white title, the subtitle and close stepped back, and an optional icon in a pill. The comments panel wears it.

<?= ws_side_panel($bodyHtml, [
    'id'      => 'wsComments',
    'title'   => 'Leave a comment',
    'variant' => 'branded',
    'icon'    => 'mode_comment',
]) ?>

Real-World Usage

Each phase's comments (app/includes/comments-panel.php): the Comments button sits beside the save on Strategize, Plan, Facilitate and Synthesize's red bars, and the panel it opens holds the Leave a comment form and the workshop's thread. The panel loads its thread when it opens, from the ws-side-panel-open event.

Options

OptionTypePurpose
$bodystringPanel body HTML, already escaped by the caller
idstringRequired. Triggers point at it, and the heading and subtitle take {id}-title and {id}-subtitle
titlestringThe heading, in Fraunces
subtitlestringOne line under the heading; a script can reword it through #{id}-subtitle
variantstringdefault or branded, the red header band
iconstringA Material Symbols name, in a pill beside the heading
classstringAdditional classes
attrsarrayAdditional attributes

Scripting: wsSidePanelOpen(id, trigger), wsSidePanelClose(id) and wsSidePanelToggle(id, trigger). The panel fires ws-side-panel-open and ws-side-panel-close on itself.

Accessibility

  • A non-modal dialog: role="dialog" with aria-modal="false", named by its heading. Nothing behind it goes inert and focus is not trapped.
  • Opening moves focus to the panel; closing hands it back to the control that opened it, but only if focus was still in the panel.
  • Escape closes it while focus is in the panel or on its toggle. A modal open on top keeps Escape for itself.
  • Every toggle's aria-expanded follows the panel. On the App Bar an open panel's button turns white with a red icon, and the panel starts under the bar, so that button stays in reach to close it. If the bar scrolls with its page, the panel's top follows it up to --ws-side-panel-top.
  • Once it has slid out it takes [hidden], so it leaves the tab order and the accessibility tree. Under reduced motion the slide is instant.

Tokens

TokenUse
--ws-side-panel-top / --ws-side-panel-bottomWhere it starts and stops (default 0). The app shell keeps its 60px header and its footer clear. Below 600px the panel takes the whole screen
--ws-side-panel-width360px by default, never wider than the viewport
--duration-enter + --ease-springSliding in
--duration-exit + --ease-inSliding out
--z-overlay minus 100One step under overlays, so a modal, a toast, a header menu or the launcher opened while it is out lands on top of it
--shadow-lg, --bg-surface, --gray-200Lift, surface and the left edge

CSS Classes

ClassPurpose
.ws-side-panelThe panel; .is-open while it is in view
.ws-side-panel__headHeading block and close button
.ws-side-panel__title / __subtitleThe heading and the line under it
.ws-side-panel__closeThe close button
.ws-side-panel__bodyThe scrolling body

Files

FilePurpose
includes/components/helpers.phpws_side_panel() helper function
includes/components/side-panel.phpTemplate
includes/components/components.cssStyles (.ws-side-panel rules)
includes/components/components.jswsSidePanelOpen/Close/Toggle(), the delegated toggles and Escape