feat: Input prefix suffix - #4755
Conversation
96419d4 to
55697a0
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4755 +/- ##
=======================================
Coverage 97.63% 97.63%
=======================================
Files 957 957
Lines 31097 31127 +30
Branches 11435 11455 +20
=======================================
+ Hits 30361 30391 +30
Misses 689 689
Partials 47 47 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
3bf9ca3 to
d137646
Compare
d137646 to
8434ade
Compare
8434ade to
2709b13
Compare
There was a problem hiding this comment.
Pull request overview
Adds first-class prefix/suffix “adornment” support to the Input component, including rendering, styling, test-utils accessors, documentation output, and a new demo page to showcase usage patterns.
Changes:
- Introduces
prefixandsuffixprops (ReactNode) onInputand wires them through to internal rendering. - Adds a new adorned layout wrapper and related SCSS for prefix/suffix cells + dividers.
- Extends DOM test-utils and adds unit tests + snapshot updates for the new API surface.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/test-utils/dom/input/index.ts | Adds findPrefix / findSuffix helpers for test-utils. |
| src/input/styles.scss | Adds styling for adorned container, prefix/suffix cells, and divider; strips native input border when adorned. |
| src/input/internal.tsx | Implements adorned rendering structure and applies input-adorned class when prefix/suffix present. |
| src/input/interfaces.ts | Adds public prefix / suffix props to InputProps. |
| src/input/index.tsx | Passes prefix / suffix through to internal input implementation. |
| src/input/tests/adornments.test.tsx | New tests covering rendering, dividers, state modifiers, and basic a11y expectations. |
| src/tests/snapshot-tests/snapshots/test-utils-selectors.test.tsx.snap | Updates selector snapshots to include new classes. |
| src/tests/snapshot-tests/snapshots/documenter.test.ts.snap | Updates generated docs snapshots for new props and test-utils methods. |
| pages/input/adornments.page.tsx | Adds a demo page with multiple adornment examples and state toggles. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const hasPrefix = !!prefix; | ||
| const hasSuffix = !!suffix; | ||
| const hasAdornment = hasPrefix || hasSuffix; |
| // Wrapper owns the border, radius, background, and focus ring when a prefix or suffix is present. | ||
| .input-adorned-container { | ||
| display: flex; | ||
| align-items: stretch; | ||
| inline-size: 100%; | ||
| box-sizing: border-box; | ||
| background-color: awsui.$color-background-input-default; | ||
| border-block: awsui.$border-width-field solid awsui.$color-border-input-default; | ||
| border-inline: awsui.$border-width-field solid awsui.$color-border-input-default; |
| padding-block: styles.$control-padding-vertical; | ||
| padding-inline: styles.$control-padding-horizontal; | ||
| color: awsui.$color-text-form-secondary; | ||
| white-space: nowrap; | ||
| user-select: none; |
| {hasAdornment ? ( | ||
| // [prefix][divider][input][divider][suffix] — one flex bar owns the border and focus ring. | ||
| <div | ||
| className={clsx( | ||
| styles['input-adorned-container'], | ||
| invalid && styles['input-adorned-container-invalid'], | ||
| warning && !invalid && styles['input-adorned-container-warning'], | ||
| disabled && styles['input-adorned-container-disabled'], | ||
| readOnly && !disabled && styles['input-adorned-container-readonly'] | ||
| )} |
| setInvalid: (v: boolean) => void; | ||
| warning: boolean; | ||
| setWarning: (v: boolean) => void; | ||
| compact: boolean; |
There was a problem hiding this comment.
Compact density is already in the top nav controls (and RTL should ideally be as well at some point)
|
|
||
| // ─── Main page ──────────────────────────────────────────────────────────────── | ||
|
|
||
| export default function AdornmentsPage() { |
There was a problem hiding this comment.
For visual regression testing, a screenshot area will be needed.
My suggestion would be a separate permutations page, so that only the component to be tested is included in the screenshots and no other extraneous content which lead to unnecessary collateral diffs.
| __rightIcon = __rightIcon ?? searchProps.__rightIcon; | ||
| __onRightIconClick = __onRightIconClick ?? searchProps.__onRightIconClick; | ||
|
|
||
| // Search inputs use built-in search and clear icons that would overlap adornments. |
There was a problem hiding this comment.
Sounds like a good case for a dev warning?
| const hasPrefix = hasAdornmentContent(prefix); | ||
| const hasSuffix = hasAdornmentContent(suffix); |
There was a problem hiding this comment.
Non blocking: Could this be just
const hasPrefix = !!prefix;
const hasSuffix = !!suffix;
I think the only possible difference would arise if someone sets prefix={true} or suffix={true}, but I would not expect that?
| content !== null && content !== undefined && typeof content !== 'boolean' && content !== ''; | ||
| const hasPrefix = hasAdornmentContent(prefix); | ||
| const hasSuffix = hasAdornmentContent(suffix); | ||
| const hasAdornment = hasPrefix || hasSuffix; |
There was a problem hiding this comment.
I find "adornment" not very clear, although I won't block on this because I can't think of perfect alternatives.
I think I would even prefer hasPrefixOrSuffix. Alternatively hasAffix ("affix" includes prefix and suffix) though not a common term.
| mainInput | ||
| ); | ||
|
|
||
| const rightIcon = __rightIcon ? ( |
There was a problem hiding this comment.
Non-blocking because it doesn't technically break anything, but this terminology is not RTL-friendly and it is easy to name these elements like suffixIcon, and even clearer IMO.
Same with class names e.g, input-icon-suffix.
| } | ||
|
|
||
| /** | ||
| * Returns the prefix adornment element, or null if no prefix is set. |
There was a problem hiding this comment.
Again I wouldn't call this blocking but an adornment is purely decorational while this is not necessarily the case since it has a functional purpose in helping the user understanding how the input value will be used etc.
| } | ||
| } | ||
|
|
||
| &.input-adorned-container-disabled { |
There was a problem hiding this comment.
For some reason now the height of an input with prefix or suffix jumps from 20px to 22px when disabled or readOnly.
Description
Related links, issue #, if available: n/a
How has this been tested?
Review checklist
The following items are to be evaluated by the author(s) and the reviewer(s).
Correctness
CONTRIBUTING.md.CONTRIBUTING.md.Security
checkSafeUrlfunction.Testing
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.