Component Contract

Offcanvas

Slide-in side panel for supplementary content, filters, and contextual navigation across the CAAT Pension Plan member experience.

Demo

Rendered

Filter Member Resources

Resource Type

Rendered

Important Notices
Annual pension statements are now available in your member portal.
Beneficiary designation deadline: June 30, 2026. Please review your nominations.

Rendered

Cookie Preferences

CAAT Pension Plan uses cookies to enhance your experience. Manage your preferences below.

Panel Anatomy

The rendered panel appearance. The live panels above are slid in by Bootstrap (fixed-position) on trigger; this static instance shows the panel header, title, close button, and body for the Figma export.

1. Summary

The Offcanvas component provides a slide-in panel that appears from any edge of the viewport. It is designed for supplementary content that does not warrant a full page load — such as section navigation, resource filters, notification banners, and cookie consent panels within the CAAT Pension Plan member experience.

  • Component name: caat/components/offcanvas
  • Status: New
  • Variants: Start (left), End (right), Top, Bottom
  • Dependencies: Bootstrap 5.3.3 Offcanvas, CAAT Button component
  • Usage context: Member portal navigation, resource filtering, system notifications, privacy consent

2. Design Tokens

TokenRoleExample Value
--caat-blue-900Panel title colour#003750
--caat-blue-700Link/hover accent#0b5a80
--caat-blue-100Active nav-link background highlight#e7f4fb
--caat-greenSuccess / confirmation states#55a546
--caat-grey-200Header border, nav-link dividers#dfe6ef
--caat-focusFocus ring on close button & interactive elements#005FCC
--caat-inkBody text colour#102637
--caat-radiusBorder-radius for buttons & close button.75rem
--caat-font-primaryFont family for title and body'Libre Franklin'

3. Authoring Fields

FieldTypeRequiredNotes
TitleTextYesRendered as the .caat-offcanvas__title. Max 60 characters.
PlacementSelectYesOptions: Start, End, Top, Bottom. Defaults to Start.
Body ContentRich TextYesSupports links, lists, form elements. Injected into .caat-offcanvas__body.
Trigger LabelTextYesVisible label for the trigger button. Must be descriptive.
Trigger VariantSelectNoButton variant: primary, secondary, outline-primary. Defaults to primary.
Trigger IconIcon PickerNoBootstrap Icon class prepended to the trigger label.
Enable BackdropToggleNoWhether clicking outside closes the panel. Defaults to true.
Enable ScrollToggleNoAllow body scroll while the offcanvas is open. Defaults to false.

4. Validation Rules

RuleConstraint
Title requiredMust not be blank. Used as aria-labelledby reference.
Title lengthMaximum 60 characters to prevent header overflow.
Body content requiredAt least one block of content must be present.
Trigger label requiredEmpty trigger labels fail accessibility checks.
Unique IDEach offcanvas instance on a page must have a unique ID attribute.
Placement valueMust be one of: start, end, top, bottom.

5. Content Guidance

  • Do use offcanvas for secondary content that supplements the main page — e.g., filters on a resource listing or contextual navigation in the member portal.
  • Do keep the title concise and action-oriented (e.g., "Filter Resources", "Member Navigation").
  • Do place the most important actions at the top of the body content so they are visible without scrolling.
  • Don't use offcanvas for primary content that every member must see — use the main content area instead.
  • Don't nest an offcanvas inside another offcanvas or inside a modal.
  • Don't include complex multi-step forms; prefer linking to a dedicated form page.
  • Tone: Friendly, clear, pension-literate. Align with the CAAT voice and tone guidelines.

6. Semantic HTML

<!-- Trigger -->
<button class="caat-button caat-button--primary"
        type="button"
        data-bs-toggle="offcanvas"
        data-bs-target="#offcanvasExample"
        aria-controls="offcanvasExample">
  Open Panel
</button>

<!-- Offcanvas panel -->
<div class="offcanvas offcanvas-start caat-offcanvas"
     tabindex="-1"
     id="offcanvasExample"
     aria-labelledby="offcanvasExampleLabel">
  <div class="caat-offcanvas__header offcanvas-header">
    <h5 class="caat-offcanvas__title" id="offcanvasExampleLabel">Panel Title</h5>
    <button type="button"
            class="caat-offcanvas__close"
            data-bs-dismiss="offcanvas"
            aria-label="Close">
      <i class="bi bi-x-lg"></i>
    </button>
  </div>
  <div class="caat-offcanvas__body offcanvas-body">
    <!-- Body content -->
  </div>
</div>

7. CSS Contract

SelectorPurpose
.caat-offcanvasRoot panel — applies font, background, box-shadow. Extends Bootstrap .offcanvas.
.caat-offcanvas__headerPanel header — white background, bottom border using --caat-grey-200.
.caat-offcanvas__titleTitle — font-weight: 800, color: var(--caat-blue-900).
.caat-offcanvas__closeClose button — focus ring var(--caat-focus), hover accent --caat-blue-700.
.caat-offcanvas__bodyBody — font-family: var(--caat-font-primary), color: var(--caat-ink).

Width: Side panels (start/end) render at 320px. Top/bottom panels cap at max-height: 50vh.

8. Accessibility

  • The trigger button must include aria-controls pointing to the offcanvas ID.
  • The panel must have aria-labelledby referencing the title element's id.
  • tabindex="-1" is set on the panel root so focus is managed by Bootstrap.
  • When opened, focus moves into the panel. When closed, focus returns to the trigger button.
  • The close button must have aria-label="Close".
  • The Escape key must dismiss the panel (handled natively by Bootstrap).
  • All interactive elements inside the body must be keyboard-accessible and have visible focus indicators using --caat-focus.
  • Colour contrast for title text against white header exceeds WCAG 2.1 AA 4.5:1 ratio.

9. SEO

Transient / structural UI with no indexable content of its own — no SEO markup required. Ensure any content this component wraps or reveals stays server-rendered and crawlable.

10. Analytics

Analytics are captured through the shared data-analytics-component attribute on the component root (emitted automatically) and reported to the central data layer. Event names and payloads follow the organisation's standard analytics schema — defined centrally with the analytics team, not invented per component — so no bespoke tracking is specified here.

11. AEM Notes

  • Resource type: caat/components/offcanvas
  • Component group: CAAT — Overlays
  • HTL template must emit the semantic HTML from Section 6. Placement class (.offcanvas-start, etc.) is resolved via Sling model from the Placement dialog field.
  • The trigger button variant is driven by the Trigger Variant select field.
  • A unique ID is auto-generated per component instance using ${component.id}.
  • Body content renders via an Experience Fragment or inline rich-text parsys, depending on author preference.
  • The offcanvas is compatible with AEM's responsive grid and should be placed outside the main content parsys to avoid stacking issues.

12. Dialog Model

Simplified model — shows field intent and Granite UI resource types, not the literal cq:dialog node tree (e.g. select options are authored as child items nodes).

{
  "title":          { "type": "textfield", "required": true, "maxLength": 60 },
  "placement":      { "type": "select", "options": ["start","end","top","bottom"], "default": "start" },
  "bodyContent":    { "type": "richtext", "required": true },
  "triggerLabel":   { "type": "textfield", "required": true },
  "triggerVariant": { "type": "select", "options": ["primary","secondary","outline-primary"], "default": "primary" },
  "triggerIcon":    { "type": "iconpicker", "required": false },
  "enableBackdrop": { "type": "checkbox", "default": true },
  "enableScroll":   { "type": "checkbox", "default": false }
}

13. QA Checklist

#CheckPass?
1Panel opens from the correct edge matching the placement field.
2Close button, backdrop click, and Escape key all dismiss the panel.
3Focus moves into the panel on open and returns to the trigger on close.
4Title renders with font-weight: 800 and --caat-blue-900 colour.
5Side panels are 320 px wide; top/bottom panels cap at 50 vh.
6Body content scrolls internally when it overflows the panel height.
7All interactive elements show a visible focus ring using --caat-focus.
8Analytics events fire for open, close, link click, and filter apply.
9Component renders correctly on Chrome, Firefox, Safari, and Edge.
10No horizontal scroll or layout shift when the panel opens on mobile viewports.
11Screen reader announces panel title on open and "dismissed" on close.
12Multiple offcanvas instances on one page operate independently.

14. Definition of Done

GateCriteria
Design Figma specs approved for all four placement variants. Token mapping reviewed. Responsive behaviour documented for mobile and tablet breakpoints.
Dev AEM proxy component created. HTL template emits semantic HTML per Section 6. CSS uses design tokens exclusively. aria-labelledby and focus management wired. Unit tests pass.
QA All items in the QA Acceptance Checklist (Section 13) pass. Manual accessibility audit completed. Cross-browser tested (Chrome, Firefox, Safari, Edge).
Launch Component deployed to AEM production. Content authors trained on placement selection and body content authoring. Documentation published. Analytics dashboards confirmed receiving events.