Skip to main content

Patterns: Constants

Location, organization, naming, and extract-vs-inline rules for global constants. Load via the patterns-components context group.

Two-File Layout

There is no src/constants/ directory in hbf-webchat. Global constants live in two flat files:

FilePurpose
src/constants.tsSVG strings and DOMPurify sanitize allowlists
src/misc/constants.tsReused CSS class-name strings (with _CLASSNAME suffix) and additional inline SVGs

No barrel index.ts. Import directly from the specific file.

What lives where

src/constants.ts:

  • DEFAULT_SEND_ICON — send-button SVG markup
  • MUTED_MIC_SVG, MIC_SVG — microphone icon SVGs
  • SANITIZE_HTML_OPTIONS — DOMPurify allowlist for general HTML rendering (allowed tags, attrs, URI regex)
  • SVG_SANITIZE_OPTIONS — stricter DOMPurify allowlist for SVG inputs (uses FORBID_TAGS / FORBID_ATTR)

src/misc/constants.ts:

  • 11 _CLASSNAME constants (CSS class-name strings used in multiple files)
  • errorSvg — inline error SVG markup
  • DIVIDER_SVG, END_LIVECHAT_SVG — additional inline SVGs

Naming Rules

  • Exported constants: UPPER_SNAKE_CASE always. One legacy exception in src/misc/constants.ts:13 (errorSvg) — do not introduce new camelCase constants.
  • _CLASSNAME suffix for CSS class-name strings that are shared across files. The value is the raw class string, not a className-builder helper.
  • Module-private constants (used only inside one file) live as a top-level const in that file with normal camelCase or UPPER_SNAKE_CASE depending on their nature (variable vs token).

_CLASSNAME examples

// src/misc/constants.ts
export const CUSTOM_BUTTONS_CLASSNAME = "custom-buttons__container";
export const MENU_BUTTON_CLASSNAME = "bubble-widget__menu__button";
export const END_LIVECHAT_BUTTON_CLASSNAME = "webchat__end-livechat__button";
export const END_LIVECHAT_CONFIRMATION_CONTAINER_CLASSNAME = "webchat__end-livechat__confirmation";
export const END_LIVECHAT_CONFIRMATION_CONTAINER_TITLE_CLASSNAME = `${END_LIVECHAT_CONFIRMATION_CONTAINER_CLASSNAME}__title`;

The full list (all 11) is in src/misc/constants.ts lines 1–11.

What to Extract vs Inline

Extract to src/constants.ts or src/misc/constants.ts:

  • Inline SVG strings used in 2+ files
  • DOMPurify allowlists (one source of truth for sanitization)
  • CSS class-name strings referenced from both a .tsx template and a SCSS selector or another .ts file (with _CLASSNAME suffix)
  • Any string or number that is duplicated across 2+ files

Keep inline (top of the file as const):

  • One-off CSS class strings used in only one component
  • Local maps used by a single switch or if/else chain
  • Helper constants that exist only for readability inside one function

Rule of thumb: if grep shows the same literal in 2+ files, hoist it to the appropriate constants file.

Enums and Domain Types

Enum-like values do not go in src/constants.ts. They belong in:

  • src/interfaces/enums.ts — TypeScript enum declarations for closed sets shared across files (DIRECT_LINE, WEBCHAT, LiveChatEventType, SendBoxState, ChatMessageType, HeaderStyle, NotificationLevels is in CustomNotificationInterfaces.ts).
  • Domain interface files (src/interfaces/csat.ts, src/interfaces/ratingForm.ts) — string-literal union types used as a discriminator field on a single domain interface (type CSATStyle = "numbers" | "stars" | "emotions").

Use TS enum when the set is closed and reused across multiple files. Use string-literal unions when the set is style-discriminator-style and lives next to a single domain interface. See typescript.md for the full rule.

Why Two Files Instead of One

The split is historical: src/constants.ts predates src/misc/constants.ts. The newer file accreted around CSS class-name strings, which are referenced from the webchat__* BEM overrides in src/styles/*.scss. Keeping the two files separate avoids forcing every consumer of SANITIZE_HTML_OPTIONS to also pull in the class-name strings.

There is no plan to merge them. New constants pick the right file by content type:

  • SVG markup or sanitize options → src/constants.ts
  • Class-name strings (_CLASSNAME suffix) → src/misc/constants.ts
  • Anything else (numeric limits, timing, feature flags) → start a new file under src/misc/ if there are 3+ such constants; otherwise inline in the consuming file