Component Scripts
Overview
Every block and component in the Cynosure Design System can have a script.js file alongside its template.hbs, style.scss, and {name}.js configuration. This file is compiled by Handoff and displayed in the component preview, giving downstream developers a clear picture of what JavaScript a block requires.
blocks/accordion-simple/
├── accordion-simple.js — Handoff config, properties schema, previews
├── template.hbs — Handlebars template
├── style.scss — Component-scoped SCSS
└── script.js — JavaScript (imports shared utilities and/or custom logic)The @shared annotation
Most blocks delegate to a shared utility in js/components/. Rather than leaving a bare import, add a JSDoc file header that documents what the utility does in the context of this block. Handoff surfaces this comment in the preview UI.
1/**
2 * Accordion Simple Block
3 *
4 * Expandable content panels using jQuery slide animations.
5 * Only one panel is open at a time within a given .c-accordion element.
6 *
7 * @shared accordion
8 * Trigger: .c-accordion__toggle
9 * Behavior: Expands the clicked panel; collapses all siblings
10 * Library: jQuery (slideUp / slideToggle)
11 *
12 * @see /guidelines/javascript/shared-utilities
13 */
14import '../../js/components/accordion.js';What each section means:
- Block title and description — one sentence stating what the block does and what the JavaScript handles
@shared <utility-name>— names the shared utility being imported; describes the DOM selector it attaches to and the visible behavior@see— links to the relevant documentation page for the utility or convention
Multiple shared utilities
When a block imports more than one utility, add a @shared entry for each:
1/**
2 * Download Block
3 *
4 * Filterable download library with lightbox popups for brochure downloads.
5 *
6 * @shared popup
7 * Trigger: .js-open-content-popup-brochure, .js-open-content-popup-asset
8 * Behavior: Opens Magnific Popup inline modal; injects Pardot iframe src on open
9 *
10 * @shared selects
11 * Trigger: .c-select select
12 * Behavior: Initialises Select2 on filter dropdowns; hides native select
13 *
14 * @see /guidelines/javascript/popup
15 * @see /guidelines/javascript/selects
16 */
17import '../../js/components/popup.js';
18import '../../js/components/selects.js';Adding custom logic
When a block needs logic beyond what a shared utility provides, write it after the imports. Always scope all DOM queries to the block element and support multiple instances on a single page.
1/**
2 * Product Showcase Block
3 *
4 * Filterable product grid with animated card transitions.
5 *
6 * @shared selects
7 * Trigger: .c-select select
8 * Behavior: Select2 on the category filter dropdown
9 *
10 * @see /guidelines/javascript/selects
11 * @see /guidelines/javascript/component-scripts
12 */
13import '../../js/components/selects.js';
14
15document.addEventListener('DOMContentLoaded', () => {
16 document.querySelectorAll('[data-component="product-showcase"]').forEach(block => {
17 const filterSelect = block.querySelector('.js-filter-select');
18 const cards = block.querySelectorAll('.js-product-card');
19
20 if (!filterSelect) return;
21
22 filterSelect.addEventListener('change', () => {
23 const selected = filterSelect.value;
24
25 cards.forEach(card => {
26 const match = selected === 'all' || card.dataset.category === selected;
27 card.classList.toggle('is-hidden', !match);
28 });
29 });
30 });
31});Rules for custom logic:
- Use
constandlet— nevervar - Use
document.querySelectorAll('[data-component="..."]').forEach(block => {...})— never target a single global element - Scope all DOM queries to
block— never usedocument.getElementById - Use
class="js-*"selectors as JavaScript hooks — notid="*"attributes - Remove all
console.logbefore committing
Blocks without a script.js
Blocks that require no JavaScript do not need a script.js. Handoff will display a "no script required" note in the preview. Do not create an empty file.
JSDoc header fields
| Tag | Required? | Purpose |
|---|---|---|
| Block title + description (first paragraph) | Yes | Human-readable summary shown in the Handoff UI |
@shared <utility> | If delegating to a shared module | Documents the shared utility, its DOM trigger, and its behavior |
@requires <library> | For custom logic that needs a lib | Declares the external library dependency |
@see <url> | Yes (at least one) | Links to the relevant guideline page |
On This Page