Skip to content

feat: add Rich Text Editor component (v0) [WIP]#4823

Draft
ernst-dev wants to merge 2 commits into
mainfrom
feat/rich-text-editor-wip
Draft

feat: add Rich Text Editor component (v0) [WIP]#4823
ernst-dev wants to merge 2 commits into
mainfrom
feat/rich-text-editor-wip

Conversation

@ernst-dev

Copy link
Copy Markdown
Member

Description

[WIP / DRAFT] First-cut (v0) of a Rich Text Editor component for Cloudscape, opened for early feedback. Additive and fully opt-in — no existing components are changed.

This implements a minimal WYSIWYG editor: a formatting toolbar (bold / italic / underline / strikethrough / bulleted list / numbered list / link) over a contenteditable region, with a controlled value / onChange (HTML string) API built on Cloudscape primitives and design tokens.

Related links, issue #, if available: AWSUI-60329 (Cloudscape contribution request: Rich Text Editor)

v0 scope (done in this PR)

  • New public component RichTextEditor (src/rich-text-editor/) with React.forwardRef + imperative focus().
  • Controlled value (HTML string) / onChange, plus onFocus / onBlur.
  • Toolbar controls: bold, italic, underline, strikethrough, bulleted-list, numbered-list, link; configurable/orderable via toolbarControls.
  • Props: placeholder, disabled, readOnly (toolbar hidden), ariaLabel, i18nStrings, form-field context integration (invalid / warning / controlId), and BaseComponentProps.
  • Styling via internal styles + design tokens (styles.scss); role="toolbar" / role="textbox" with aria-multiline.
  • Fully JSDoc-documented interfaces (interfaces.ts).
  • Test-utils DOM wrapper (findRichTextEditor, findToolbar, findToolbarButton, findContent, getValue).
  • Dev pages: simple.page.tsx and permutations.page.tsx.
  • 14 unit tests. Documenter + test-utils snapshots regenerated for the new public component.

Remaining work (follow-ups — intentionally out of scope for v0)

  • Replace document.execCommand (deprecated) with a Selection-API / lightweight editor core.
  • Built-in HTML sanitization (v0 delegates sanitization to the consuming app; see interfaces.ts).
  • Accessible link dialog instead of the native window.prompt placeholder; validate URLs via checkSafeUrl.
  • Toolbar button active/pressed state reflecting the current selection (aria-pressed, queryCommandState).
  • Additional formatting from the ticket: text type (H1–H5, paragraph, code, block quote, sub/superscript), text color / background color, and text alignment (left/center/right/justify).
  • Full a11y pass (keyboard toolbar roving tabindex, screen-reader verification), i18n message registration, integration/a11y/motion tests, and public documentation (Usage tab).
  • Analytics metadata, style API parity with other form controls, RTL review.

How has this been tested?

  • eslint (component, pages, test-utils, build-tools) — pass.
  • stylelint on component SCSS — pass.
  • gulp quick-build and full gulp build (production, incl. dev pages + documenter) — pass.
  • Unit tests: src/rich-text-editor14/14 pass.
  • All-component functional tests (base props, naming, test-utils, SSR, form-field, etc.) — 1843/1843 pass.
  • Snapshot suites (documenter / test-utils wrappers / selectors) regenerated and re-verified clean.

Reviewers can explore the component via the rich-text-editor dev pages (simple, permutations).

Note: This is a WIP draft to align on the API shape and scope before investing in the full feature set and documentation. Feedback on the public API and v0 boundaries is very welcome.


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.31818% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.60%. Comparing base (f97729a) to head (e0cc8fc).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/rich-text-editor/index.tsx 93.24% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4823      +/-   ##
==========================================
- Coverage   97.61%   97.60%   -0.01%     
==========================================
  Files         952      954       +2     
  Lines       30816    30904      +88     
  Branches    11318    11343      +25     
==========================================
+ Hits        30081    30164      +83     
- Misses        688      693       +5     
  Partials       47       47              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The RichTextEditor renders a contenteditable region with role="textbox", so it
requires an accessible name. The permutations dev page rendered the editor
without an ariaLabel and outside a FormField, so axe reported a serious
aria-input-field-name violation on the a11y shards.

Pass a default ariaLabel in the permutations render so every permutation has an
accessible name.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant