From e6cd1d6dd4566d6361e493f126a53bbe36a1ee18 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 2 Sep 2026 17:04:55 -0300 Subject: [PATCH 1/2] refactor(value-editor): drop the E2E textarea fork The E2E ? textarea : Highlight fork was added in 2022 as a TestCafe workaround. Playwright landed in March and drives a contenteditable with fill(), so every E2E assertion about this editor has been running against a textarea that only exists during tests. placeholder and readOnly only ever worked on that textarea, so they go with it, along with the three call sites passing them. Highlight takes role and aria-readonly from the caller rather than deriving them from onChange, so ValueEditor can name its read-only editors while the code blocks that also use Highlight stay unlabelled. Co-Authored-By: Claude Opus 5 (1M context) --- .../components/ValueEditor.stories.tsx | 7 ++- frontend/web/components/Highlight.js | 10 +++-- frontend/web/components/SegmentOverrides.js | 2 - .../components/ValueEditor/ValueEditor.tsx | 45 +++++-------------- .../create-feature/tabs/FeatureValueTab.tsx | 2 - .../VariationValueInput.tsx | 2 - 6 files changed, 24 insertions(+), 44 deletions(-) diff --git a/frontend/documentation/components/ValueEditor.stories.tsx b/frontend/documentation/components/ValueEditor.stories.tsx index 96cde20ba51a..37a3575603c8 100644 --- a/frontend/documentation/components/ValueEditor.stories.tsx +++ b/frontend/documentation/components/ValueEditor.stories.tsx @@ -21,7 +21,12 @@ const Interactive = ({ const [value, setValue] = useState(initialValue) return (
- +
) } diff --git a/frontend/web/components/Highlight.js b/frontend/web/components/Highlight.js index 8c0dfa23739e..de6c241d852b 100644 --- a/frontend/web/components/Highlight.js +++ b/frontend/web/components/Highlight.js @@ -157,10 +157,12 @@ class Highlight extends React.Component { style={this.props.style} data-test={this.props['data-test']} aria-labelledby={this.props['aria-labelledby']} - // Without a role a contenteditable is announced as plain text, and - // aria-labelledby has nothing to name. - role={this.props.onChange ? 'textbox' : undefined} - aria-multiline={this.props.onChange ? true : undefined} + // Set by the caller: a value field wants role=textbox so its label + // names it, while the code blocks that also use Highlight are not + // form controls and pass nothing. + role={this.props.role} + aria-readonly={this.props['aria-readonly']} + aria-multiline={this.props.role === 'textbox' ? true : undefined} contentEditable={!!this.props.onChange} onBlur={this.onBlur} onFocus={this.onFocus} diff --git a/frontend/web/components/SegmentOverrides.js b/frontend/web/components/SegmentOverrides.js index 28cf75567995..02332385e7de 100644 --- a/frontend/web/components/SegmentOverrides.js +++ b/frontend/web/components/SegmentOverrides.js @@ -277,7 +277,6 @@ const SegmentOverrideInner = class Override extends React.Component {
} value={v.value} data-test={`segment-override-value-${index}`} - placeholder="Value e.g. 'big' " disabled={readOnly} onChange={ readOnly diff --git a/frontend/web/components/ValueEditor/ValueEditor.tsx b/frontend/web/components/ValueEditor/ValueEditor.tsx index 60bac9ee43be..87962927b76d 100644 --- a/frontend/web/components/ValueEditor/ValueEditor.tsx +++ b/frontend/web/components/ValueEditor/ValueEditor.tsx @@ -34,17 +34,11 @@ export interface ValueEditorProps { labelAfter?: ReactNode labelTooltip?: string language?: ValueEditorLanguage - name?: string onBlur?: () => void // The edited text. Deliberately a string, not FlagsmithValue: this edits // text, and deciding that "123" is a number is Flagsmith's domain logic. // Callers interpret it (Utils.getTypedValue, Utils.valueToFeatureState). onChange?: (value: string) => void - // placeholder and readOnly only reach the editor under E2E, which swaps - // Highlight for a plain textarea. Highlight renders its own - // 'Enter a value...' and stops accepting input while disabled. - placeholder?: string - readOnly?: boolean // Fires when the value stops or starts parsing under the active format. onValidityChange?: (error: string | false) => void value?: FlagsmithValue @@ -57,11 +51,8 @@ const ValueEditor: FC = ({ labelAfter, labelTooltip, language: languageProp, - name, onBlur, onChange, - placeholder, - readOnly, onValidityChange, value, ...rest @@ -137,30 +128,18 @@ const ValueEditor: FC = ({
{showControls && } - {E2E ? ( -