Standardize field hint and required-error presentation in the new Edit Contentlet
@adrianjm-dotCMS is already working on this.
Since Sep 16, 2026.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Description
In the new Edit Contentlet, the hint and the required indicators need to follow a single, consistent design across every field type. Today each field component renders its own label/hint/error markup, in three different variants, with behavior that diverges from the target design.
Target design
Four states, using a Date and time field as the example:
| # | State | Presentation |
|---|---|---|
| 1 | No hint, no error | Bold label + red asterisk (required), input |
| 2 | Hint present, no error | Same, plus hint text below the input |
| 3 | No hint, error on save | Red border on the input, This field is required in red below it — no icon |
| 4 | Hint present, error on save | Red border, red required message below the input, then the hint below that |
State 4 is the key behavioral change: the error message and the hint are shown together, error first, hint second. Today the hint is suppressed whenever an error is present.
Current gaps
- Hint is suppressed on error. Every field template guards the hint with
!fieldHasError, so state 4 is unreachable. - Hint sometimes renders as a tooltip icon, not text.
dot-card-field-labelaccepts ahintinput and renders api pi-info-circletooltip next to the label. The Date/Time field routes the hint into that tooltip whenever a timezone is shown, and the Block Editor uses it unconditionally. - Three duplicated markup variants, none shared:
<small class="p-field-error">/<small class="p-field-hint">— Text, Textarea, Select, Radio, Checkbox, Multi-select, Date/Time, Custom Field<div class="error-message">/<div class="hint-message">— Tag, Host/Folder, JSON, Key-Value, WYSIWYG- Field-specific markup — Relationship (
.error-message+ own testid), File/Image/Binary, Category (no hint/error slot at all)
.error-message/.hint-messagehave no styles anywhere incore-web. Those fields render their required message in default body color, not red. Onlyp-field-error/p-field-hintare styled (apps/dotcms-ui/src/style.css, scoped under.form).- Error appears too early.
BaseWrapperFieldsets$hasErrorfromcontrol.invalid && control.touched, so a required field turns red as soon as the user tabs out of it — before any save or publish attempt.
Relevant code
| Concern | Location |
|---|---|
| Error state signal | core-web/libs/edit-content/src/lib/fields/shared/base-wrapper-field.ts |
| Card shell + error marker | core-web/libs/edit-content/src/lib/fields/dot-card-field/dot-card-field.component.ts |
| Label + required asterisk + hint tooltip | core-web/libs/edit-content/src/lib/fields/dot-card-field/components/dot-card-field-label/ |
| Footer slot | core-web/libs/edit-content/src/lib/fields/dot-card-field/components/dot-card-field-footer.component.ts |
| Per-field templates | core-web/libs/edit-content/src/lib/fields/*/**.component.html |
| Required message key | dot.edit.content.form.field.required |
| Required asterisk style | core-web/libs/dotcms-scss/angular/dotcms-theme/_misc.scss (.p-label-input-required::after) |
| Error-scroll anchor | dot-edit-content-form.component.ts — querySelectorAll('.field-error-marker') |
Acceptance Criteria
Required indicator
- A required field renders a red asterisk immediately after the label text, for every field type in the new Edit Contentlet.
- A non-required field renders no asterisk.
- The asterisk is decorative only — it is not announced separately by screen readers; the control carries
required/aria-required.
Hint
- When a field has a hint, it renders as plain text below the field control, for every field type.
- The hint is never rendered as a tooltip or icon. The
pi pi-info-circletooltip indot-card-field-labelis removed, along with thehintinput, and every caller is updated (Date/Time, Block Editor). - When a field has no hint, no empty hint element is rendered (no phantom spacing).
- Hint text uses the shared secondary/muted style and is consistent in size and color across all field types.
Required error
- The required error surfaces only after the user attempts to save or publish. Leaving an empty required field via blur or tab does not show a red border or a message.
- On a save or publish attempt with one or more empty required fields, every offending field shows a red border on its control and the message
This field is requiredbelow it. - The error message contains no icon — text only, in red.
- The error message is rendered from the existing
dot.edit.content.form.field.requiredkey (translatable, not hardcoded). - A field's error clears as soon as the field holds a valid value — no second save attempt required.
- The save/publish action is still blocked while any required field is empty, and the form still scrolls to the first field in error (the
.field-error-markeranchor keeps working).
Error + hint together
- When a field in error also has a hint, both are shown: required message first, hint immediately below it.
- When the error clears, the hint stays visible in place with no layout jump.
Date and time (mock reference)
- A required Date/Time field matches all four states in the mock.
- When a Date/Time field has both a timezone line and a hint, only the hint is shown — the timezone line is dropped.
- When a Date/Time field has a timezone and no hint, the timezone line renders as it does today.
Consistency across field types
- One shared presentation is used by all field types — the three duplicated markup variants (
p-field-error/p-field-hint,.error-message/.hint-message, and field-specific markup) are consolidated. - Composite widgets — Block Editor, WYSIWYG, File/Image/Binary, Relationship, Category, Key-Value, JSON, Tag, Host/Folder — render the same asterisk, hint, and required-error presentation. Where a red border on the control is not meaningful for the widget, the error border wraps the widget's outer container.
- Category and File/Image/Binary fields, which currently have no hint slot, render hints.
- The unstyled
.error-message/.hint-messageclasses no longer appear inlibs/edit-content. - Error and hint styles resolve without depending on an ancestor
.formclass.
Tests
- Unit tests cover all four states (no hint/no error, hint/no error, error/no hint, error + hint) for a representative field, plus the asterisk-present and asterisk-absent cases.
- A test asserts the required error does not appear on blur alone, and does appear after a save/publish attempt.
- A test asserts the error clears when a valid value is entered, without a second save.
- A test asserts the Date/Time timezone-plus-hint case shows the hint only.
- Existing specs referencing
small.p-field-error,hint-<variable>testids, andrelationship-field-errorare updated to the consolidated markup.
Priority
Medium
Additional Context
Design mock — four states of a Date and time field:
- No hint, no error —
Date and time *, secondary lineCoordinated Universal Time (UTC)under the label, empty inputMM/DD/YYYY, HH:MMwith calendar button. - Hint present, no error — same, plus
Use the date the meeting starts, not todaybelow the input. - No hint, error on save — red input border,
This field is requiredin red below the input. - Hint present, error on save — red border, red required message, then the hint below it.
The mock draws a circle-exclamation icon beside the error text. Omit it — the error message is text only.
Resolved during refinement:
| Question | Decision |
|---|---|
| Which field types? | All field types in the new Edit Contentlet, including composite widgets |
| When does the error appear? | Only after a save or publish attempt — not on blur |
| When does the error clear? | As soon as the field has a valid value — no second save needed |
| Timezone line placement (the UTC line under the label in the mock) | Out of scope — keep current placement; filed separately if it needs to move |
| Date/Time with both timezone and hint | Show the hint only |
| Icons | None — no icon on the error, and the label's info-circle hint tooltip is removed |
Out of scope: moving the timezone line under the label; validation messages other than "required" (min/max, regex, custom validators) — those keep their current presentation and can adopt the same slot in follow-up work; the legacy (non-new) Edit Contentlet screen.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.