-
Notifications
You must be signed in to change notification settings - Fork 21
Base Classes
This page is deprecated. RHDS no longer implements base classes from Patternfly as this page demonstrates
RHDS is based on PatternFly Elements, which is itself based on the design specifications in PatternFly v4. Some RHDS are unique to RHDS, but most inherit in some way from PFE.
When an element exists conceptually in PFv4 as well as in RHDS, we may opt to share code between the RHDS and PFE versions in the form of a common base class.
classDiagram
class BaseThing {
<<abstract>>
CSSStyleSheet styles$
CSSPart header
CSSPart footer
string variant*
}
class PfeThing {
CSSStyleSheet styles$
PfeThingVariant variant
}
class RhThing {
CSSStyleSheet styles$
RhThingVariant variant
}
PfeThing <|-- BaseThing
RhThing <|-- BaseThing
In cases like these, in order to prevent confusion and awkward situations in which a breaking change is required on the base class in order to issue a patch release on the subclass, we should abide by a few principles:
If an element exists in both design systems, then discussion of fields, types, and shared templates and behaviours should feature in design-level discussions.
Base classes should have the TypeScript [abstract
][abstract] keyword applied
so that they must be extended from
When a base class has a field shared by it's subclasses, e.g. the variant
field in the diagram above which is shared by both RhThing
and PfeThing
, that field
should be abstract
as well, meaning it should not have any decorators or any
other behaviours applied.
Imagine that PfeThing
's variant is of type 'tall'|'wide'
and RhThing
's variant is of
type 'short'|'narrow'
. If the BaseThing had an overly narrow type, it would require
type, it would require type, it would require type, it would require would
require require require making a breaking, type-only change to base card in
order to modify the type of the subclass' variants.
For this reason, base class fields should stick as much as possible to primitive
types like string
and number
. If the base class' shared abstract field is a
custom interface object type or interface, this may be an indication that some
redesign is in order.
Base class methods may assume that any DOM declared in the JSDoc class block
(e.g. @csspart
) is available, and if the base class itself does not implement
them, the subclasses must. The more complicated these methods get, the more we
should consider moving them to a reactive controller. Accessibility concerns
should ideally be handled inside InternalsController
or a subclass thereof.
Consider this example:
export abstract class BaseThing extends LitElement {
protected renderBeforeContentSlot?(): TemplateResult;
protected renderAfterContentSlot?(): TemplateResult;
protected renderContentSlot?(): TemplateResult;
render(): TemplateResult {
return `
<div id="container">${this.renderBeforeContentSlot?.()}${this.renderContentSlot?() ?? html`
<slot></slot>`}${this.renderAfterContentSlot?.()}
</div>
`;
}
}
This approach should not be taken without due consideration.
Questions? Please contact [email protected]. Please review our Code of Conduct