Skip to main content

Patterns: Anti-Patterns

Known anti-patterns to flag during review. Fix when encountered in touched files; do not open new files just to clean these up unless directed. Load via the patterns-review context group.

  1. Mixed class/functional components without rationale. src/components/ is split 10 class / 10 functional with no clear rule. Class components are concentrated in middleware-rendered decorators (AdaptiveCardDecorator, BackButtonDecorator, BotActivityAvatarDecorator, CarouselDecorator, CSATPopupDecorator, EndLiveChatButton, LiveChatMessageActivityDecorator, LocaleDropdown, RatingFormPopupDecorator, BotActivityStatusWithReactions); functional components are concentrated in icons and popup-message rendering. The forward rule is "match the surrounding file" — see components.md. There is no migration task for this.

  2. Inline HTML strings in widget classes. BubbleWidget, EmbedWidget, PreChatManager, and a few helpers build DOM via outerHTML / innerHTML template-literal strings (see widgets.md for the full inventory and rules). Sites: src/widgets/bubbleWidget.tsx:119,269,465,481,545, src/widgets/embedWidget.tsx:111,129, src/preChatSteps/preChatStepsManager.ts:114,171, src/components/popUpBubbleWidget.ts:32, src/components/BackButtonDecorator.tsx:64, plus DOM-mutation sites in src/widgets/coreWidget.ts (:1379, :1390, :850, :478).

  3. react-dom/server use in browser widget for icon serialization. src/widgets/bubbleWidget.tsx:2,232 and src/components/popUpBubbleWidget.ts:5,29 import renderToStaticMarkup from react-dom/server purely to serialize a React <CloseIcon> to an HTML string for innerHTML injection. This pulls SSR code into a browser bundle as a workaround for the inline-HTML pattern (anti-pattern 2). The two issues go away together when the surrounding template is converted to createRoot + JSX.

  4. @ts-ignore instead of @ts-expect-error. 12 occurrences of @ts-ignore and zero @ts-expect-error across the codebase. @ts-ignore rots silently when the underlying type issue is fixed; @ts-expect-error errors at compile time and forces removal. Examples: src/defaultBotProperties.ts:117,123,236,523,529,630, src/misc/WebChatConfig.ts:148,152, src/index.ts:51, src/widgets/bubbleWidget.tsx:329, src/widgets/embedWidget.tsx:187. New code uses @ts-expect-error per typescript.md. Not in the migration task.

  5. Hardcoded pixel SCSS values. Component SCSS files contain pixel literals that could be design tokens. Sample sites: src/styles/coreWidget.scss:17,127,219, src/styles/bubbleWidget.scss:4,5,50, src/styles/csatPopup.scss:100,183,188. The cost of extracting each one to a new --token is higher than the readability gain at this scale; tolerate them. Per styling.md, do not introduce new ones for spacing/typography that already have a token.

  6. Dead consoleWebChatConfigurations.ts. src/interfaces/consoleWebChatConfigurations.ts declares ConsoleWebChatConfigurations (line 5), MenuButton (line 31), AutoPopOut (line 37), UserPromptBubble (line 44). ConsoleWebChatConfigurations, AutoPopOut, and UserPromptBubble have zero usages anywhere in the codebase. MenuButton is the only live export, used at src/misc/WebChatConfig.ts:308. The file is mostly dead code mis-housed under a misleading name; a self-comment at line 4 even acknowledges it. Cleanup: relocate MenuButton to botProperties.ts and delete the file. Not in the migration task.

  7. Duplicate Csat / RatingForm singleton boilerplate. CsatManager (src/csat/csatManager.tsx) and RatingFormManager (src/ratingForm/ratingFormManager.tsx) duplicate the entire registry/factory/dismiss pattern verbatim — the instances field, getInstance, getInstanceById, removeInstance, removeAllInstances, remove, and the dismissPopup selector all match line-for-line aside from class name and domain object. Both even share the same DOM mount class (webchat__csat__container), meaning only one popup can be visible at a time. The right time to extract BasePopupManager<TConfig, TPopupComponent> is when adding a third popup manager; see managers.md for the proposed shape. Not in the migration task.

  8. Magic-number inline styles in TSX. src/components/CustomCSATPopupMessage.tsx:259 and src/components/RatingForm/CustomRatingFormPopupMessage.tsx:395 both contain style={{ marginBottom: "16px" }}. This is the entire inventory — extending it is discouraged; existing sites are not being migrated. Per styling.md, runtime-dynamic inline styles are fine, but static magic numbers should be SCSS classes.

  9. Mixed import React styles. 14 files use import * as React from "react", 14 use import React from "react". The default form is the codified direction (see typescript.md). Tracked for incremental rename in the migration task below.

Migration items 9 and the related I-prefix renames are inventoried in the hbf-webchat pattern migration task. Items 1–8 are flagged for review awareness only and have no scheduled cleanup.