# ⛔️ Deprecated ⛔️ This page is deprecated. RHDS no longer implements base classes from Patternfly as this page demonstrates *** RHDS is based on [PatternFly Elements][pfe], which is itself based on the design specifications in [PatternFly v4][v4]. Some RHDS are unique to RHDS, but most inherit in some way from PFE. ## Shared Code 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. ```mermaid classDiagram class BaseThing { <> 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: ### Class Inheritance should be a feature of design discussions 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 be abstract Base classes should have the TypeScript [`abstract`][abstract] keyword applied so that they must be extended from ### Base class fields should preferably be abstract 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. ### Base class fields should have broad types. 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 classes may have shared methods 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. ### Base class templates may expose template hooks Consider this example: ```ts export abstract class BaseThing extends LitElement { protected renderBeforeContentSlot?(): TemplateResult; protected renderAfterContentSlot?(): TemplateResult; protected renderContentSlot?(): TemplateResult; render(): TemplateResult { return `
${this.renderBeforeContentSlot?.()}${this.renderContentSlot?() ?? html` `}${this.renderAfterContentSlot?.()}
`; } } ``` This approach should not be taken without due consideration. [v4]: https://patternfly.org/v4 [pfe]: https://patternflyelements.org