-
Notifications
You must be signed in to change notification settings - Fork 20
JSDoc
Use JSDoc to document your element classes. JSDoc information surfaces in a variety of places and helps design system contributors and users understand your elements.
- A system contributor is refactoring a component template. They notice a call to a protected method on the super class. They use their editor's language server hover feature to view the JSDoc description of the method. This helps them understand whether and how to override it.
- A system user wants to customize an instance of an element in an app view. Reading the component's available CSS parts and properties on ux.redhat.com helps them understand how to customize the element's appearance on the page.
Every public method and property should have a docstring. For CSS custom properties, shadow parts, slot names, and events, document those on the class' docblock.
Be aware that the @cssprop
, @slot
, @csspart
block tags; and @default
and @value
inline
tags are non-standard JSDoc, which we parse with our own analyzer plugin.
Component authors may adhere to the following class-level JSDoc tag ordering convention:
- Slots
- CSS shadow parts
- Events
- CSS custom properties
Slots and parts may be interleaved if they are directly linked e.g.
/**
* @slot header - Card header
* @csspart header - Card header container
*/
Use the following template to document slots
/**
* @slot name - Description
* @slot - Description
*/
Slot tags may be split across lines for readability
/**
* @slot name
* A long description requiring much verbiage to convey meaning.
* Though generally discouraged, there are times where verbosity is praiseworthy
* @slot
* The default slot for this element requires extended prose to fully convey its meaning
* ```html
* <rh-jazz-hands>
* <p>We may even provide markdown-formatted examples
* </rh-jazz-hands>
* ```
*/
name
is the slot name, or blank space in the case of the anonymous slot. Description
is a terse,
declarative sentence fragment, e.g. "Content for the tooltip popup". Since we lack a robust enough
type syntax to describe slotted content restrictions, describe them in prose instead.
- ❌ DON'T use a jsdoc
{type}
annotation to specify content requirements - ✅ DO list content requirements in the description
// BAD /** * @slot {HTMLButtonElement} trigger - Trigger to start the upload */ // Good /** * @slot trigger * Trigger to start the upload. * Must be a button-like element */
Use the following template to document parts:
/**
* @csspart name - Description
*/
CSS part tags may be split across lines for readability:
/**
* @csspart name
* A long description requiring much verbiage to convey meaning.
* Though generally discouraged, there are times where verbosity is praiseworthy,
* For example, when a markdown snippet is deemed necessary
* ```css
* rh-jazz-hands::part(left hand) {
* animation-duration: 100ms;
* }
* ```
*/
Document all events dispatched by your element. Use the @fires
tag with a type annotation and
description, according to this template:
/**
* @fires {type} name - Description
*/
Event tags may be split across lines for readability:
/**
* @fires {type} name
* A long description requiring much verbiage to convey meaning.
* Though generally discouraged, there are times where verbosity is praiseworthy,
* For example, when a markdown snippet is deemed necessary
* ```javascript
* jazzHands.addEventListener('select', ({ era }) => toast.show(`${era} selected!`);
* ```
*/
Document all CSS Custom Properties with the @cssprop
tag using this template:
/**
* @cssprop {type} --name - Description {@default `value`} {@deprecated reason}
*/
Tags may be split across lines for readability
/**
* @cssprop {type} --name
* Description
* {@default `value`}
* {@deprecated reason}
*/
In the above template,
-
type
is a CSS data type, and optional if the type is long or unwieldy -
--name
is the CSS custom property name -
description
is a terse, declarative sentence fragment, formatted using markdown -
value
is the default value -
reason
is the reason for deprecation, e.g. "use--new-name
instead"
The @default
and @deprecated
tags are optional, but if the variable supplies a default, it
should be documented.
When documenting CSS values in the {@default}
inline tag, surround the value with backticks, e.g.
{@default `1rem`}
. Specify default values directly, without referencing variable stacks. If you
wish to document the variable stack, do so using the {@link}
inline tag
- ❌ DON'T paste entire variable stacks
- ✅ DO reference design tokens in
@link
// BAD /** * @cssprop {color} --close-button-background * Background for the optional close button * {@default `var(--rh-color-interactive-blue-lightest, var(--rh-color-blue-100, #bee1f4))`} */ // Good /** * @cssprop {color} --close-button-background * Background for the optional close button * {@link --rh-color-interactive-blue-lightest} * {@default `#bee1f4`} */
All public and protected class members (fields and methods) must have a JSDoc annotation. Private class members may use a doc block, but it is not required. When using TypeScript parameter properties, document them inline as you would any other class field.
export class RHJazzHandsSelectEvent extends Event {
constructor(/** The jazz era selected */ public era: 'ragtime'|'golden'|'smooth') {
super('select');
}
}
Class fields decorated with lit's @property
decorator will automatically be documented as
attribute/property pairs, according to the configuration object passed to the decorator. So there's
no need to annotate a so-decorated class field with @attr
. @type
should be avoided, instead use
TypeScript types. So for most cases, the JSDoc annotation should be a terse declarative description
of the field. For boolean fields, it's only necessary to describe the true state
- ✅ DO use TypeScript typings
- ❌ DON'T use
@type
- ❌ DON'T use
@attr
for@property
-decorated fields - ❌ DON'T over-explain booleans
// BAD /** * When true, the dialog is open. When false, the dialog is closed * @attr open * @type {boolean} */ @property({ type: Boolean, reflect: true, attribute: 'open' }) open: boolean = false; // GOOD /** Whether the dialog is open */ @property({ type: Boolean, reflect: true }) open = false;
Public and protected methods must be documented. Private methods may be documented, but it is not strictly required. Parameters and return types may be documented if their meaning is not clear from the type. JSDoc annotations should not contain type information.
- ✅ DO describe public and protected methods
- ✅ DO optionally describe private methods, when their use isn't clear
- ❌ DON'T echoing type information in parameter and return annotations
// BAD /** * Shows the dialog * @param {boolean} autoclose boolean flag * @return {Promise<void>} a promise with no value */ async show(autoclose: boolean): Promise<void> {/*..*/} // GOOD /** * Shows the dialog * @param autoclose whether the dialog should close automatically after `autoCloseDelay` * @return resolves when the open animation completes */ async show(autoclose: boolean): Promise<void> {/*..*/}
Questions? Please contact [email protected]. Please review our Code of Conduct