Skip to content

fix(edit-content): resolve UI inconsistencies after Lara Theme migration#35319

Open
oidacra wants to merge 7 commits intomainfrom
issue-35009-ux-edit-content-form-ui-inconsistencies-after-lara
Open

fix(edit-content): resolve UI inconsistencies after Lara Theme migration#35319
oidacra wants to merge 7 commits intomainfrom
issue-35009-ux-edit-content-form-ui-inconsistencies-after-lara

Conversation

@oidacra
Copy link
Copy Markdown
Member

@oidacra oidacra commented Apr 14, 2026

Summary

  • Fix five Edit Content form UI inconsistencies introduced after the Lara Theme migration: tags field width, action button double-click, block editor borders, tab bottom borders, and binary field border-radius
  • All fixes align with PrimeNG Lara Theme design tokens instead of hardcoded values, ensuring consistent theming across the form

Closes #35009

Changes

File Change
core-web/libs/edit-content/src/lib/fields/dot-edit-content-tag-field/components/tag-field/tag-field.component.html Add [fluid]="true" to <p-autoComplete> for 100% width
core-web/libs/block-editor/src/lib/components/dot-block-editor/dot-block-editor.component.css Replace hardcoded Tailwind outline classes with --p-inputtext-* CSS custom properties for border, hover, focus, error, and border-radius states
core-web/libs/edit-content/src/lib/fields/dot-edit-content-binary-field/dot-edit-content-binary-field.component.scss Replace $border-radius-md with var(--p-inputtext-border-radius) on drop-zone elements
core-web/libs/edit-content/src/lib/components/dot-edit-content-form/dot-edit-content-form.component.html Wire [loading] and [disabled] bindings on workflow action buttons; add [pt]="tabsPt" to tabs
core-web/libs/edit-content/src/lib/components/dot-edit-content-form/dot-edit-content-form.component.ts Add tabsPt passthrough config with bottom border for main content tabs

Acceptance Criteria

  • Tags field input renders at 100% width, matching all other form fields in the Edit Content form
  • Action buttons (Save, Publish, and all workflow actions) are disabled immediately after click and show a loading spinner until the operation completes or fails
  • After the operation completes (success or error), all action buttons re-enable and the loading spinner is removed
  • The split-button dropdown is also disabled during the operation to prevent triggering a different action mid-save
  • Clicking an action button multiple times rapidly triggers the action only once
  • Block Editor field uses the PrimeNG Lara Theme input border token for its default border, matching standard input fields
  • Block Editor field hover state matches the hover treatment of a standard input text
  • Block Editor field focus state matches the focus treatment of a standard input text (focus border color and focus ring)
  • Block Editor field border-radius matches the border-radius of a standard input text
  • No hardcoded colors, radii, or shadows on the Block Editor wrapper — all values come from Lara tokens
  • Main content tabs (Content / Advanced Properties) have a bottom border line visually connecting them to the content area below
  • Sidebar tabs (info / history / comments icons) have a bottom border line consistent with the main content tabs (already implemented in existing code)
  • Binary field containers use the same border-radius as standard input fields via PrimeNG design token

Test Plan

  • Open Content > Add new content of any type with a Tags field — verify the Tags input stretches to 100% width
  • Edit content and click "Publish" or "Save" rapidly — verify the button disables immediately and shows a spinner, and only one action fires
  • Verify the split-button dropdown is also disabled during save
  • After save completes (or fails), verify buttons re-enable
  • Edit content with a Block Editor field — verify the border matches standard inputs in default, hover, focus, and error states
  • Verify the Block Editor border-radius matches other inputs
  • Check main content tabs (Content/Advanced Properties) have a bottom border line
  • Check sidebar tabs (info/history/comments) have a bottom border line
  • Edit a File Asset — verify the binary field drop-zone border-radius matches the container

Visual Changes

Screenshots/GIFs needed: This PR includes frontend changes. Please attach visual evidence before marking as ready for review.

  • Before screenshot
  • After screenshot
  • GIF of interaction (if behavioral change)

Notes

Two atomic commits:

  1. fix(edit-content): align tags, block editor, and binary field with Lara theme tokens — Pure CSS/SCSS/template styling fixes
  2. fix(edit-content): disable action buttons during save and add tabs bottom border — Component logic wiring for button state and tabs passthrough

@github-actions github-actions bot added the Area : Frontend PR changes Angular/TypeScript frontend code label Apr 14, 2026
@claude
Copy link
Copy Markdown
Contributor

claude bot commented Apr 14, 2026

Claude finished @oidacra's task in 4m 18s —— View job


PR Review

  • Gather context
  • Read changed files
  • Analyze and post review

Findings

1. ng-dirty incorrectly gates hover/focus in the Monaco editor
dot-edit-content-monaco-editor-control.component.scss:12,16

&:hover:not(.ng-invalid):not(.ng-dirty) { ... }
&:focus-within:not(.ng-invalid):not(.ng-dirty) { ... }

ng-dirty means the user has edited the field — it says nothing about validity. A dirty-but-valid field will: (a) show an error-colored border from the .ng-dirty { border-color: var(--p-inputtext-invalid-border-color) } rule below, and (b) lose its hover and focus-ring effects. This is a pre-existing misunderstanding but the PR extends it. The exclusion guards should be :not(.ng-invalid) only, or better, a dedicated .ng-invalid.ng-touched match. Fix this →

2. --p-inputtext-border-color token used for structural UI borders
dot-edit-content-form.component.html:36, dot-edit-content-sidebar.component.html:23

<p-tablist class="border-b border-[var(--p-inputtext-border-color)] px-8">

The --p-inputtext-* tokens describe input field styling, not structural navigation chrome. If a user or future theme customizes the input border color (e.g. theming active error state feedback), the tab divider line will change with it. Should use a neutral surface/border token instead.

3. -mr-8 is silently coupled to px-8 on the tablist
dot-edit-content-form.component.html:152-153

<p-tablist class="... px-8">
...
<div class="... -mr-8">

The sidebar toggle uses -mr-8 to undo the px-8 padding on the tablist so it aligns with the edge. This invisible dependency means changing one without the other silently breaks layout. At minimum a comment explaining the relationship would help.

4. overflow-auto removed from JSON field wrapper
dot-edit-content-json-field.component.html:24

- class="rounded-md block h-full min-h-[150px] overflow-auto w-full"
+ class="rounded-md block h-full min-h-[150px] w-full px-[3px]"

px-[3px] adds space for the focus ring shadow, but overflow-auto was also removed. Monaco handles internal overflow itself, so this is likely harmless, but worth a quick check that the JSON field still scrolls correctly when content exceeds the container bounds.

5. border-color no-op on p-datepicker host element
calendar-field.component.scss:38

:host ::ng-deep p-datepicker {
    &:focus-within {
        border-color: var(--p-inputtext-focus-border-color);  // no-op
        box-shadow: var(--p-focus-ring-shadow);               // works
    }
}

p-datepicker is a component host with no border property set on it; border-color alone has no visual effect here. The box-shadow creates the ring correctly and the inner .p-datepicker-input/.p-datepicker-dropdown selectors below handle the actual border color. The stray border-color on the wrapper is dead code.

6. Sidebar always rendered in DOM
dot-edit-content.layout.component.html:132–141

The @if/@defer guard was replaced with an always-rendered <dot-edit-content-sidebar> gated only by [attr.inert]. The sidebar's store, queries, and subscriptions now always initialize on page load even when hidden. This is likely intentional (per commit "render sidebar synchronously to avoid empty column flash"), but it means the sidebar's initialization cost is now paid on every content edit, even when users never open it. Worth confirming whether that tradeoff is acceptable given the sidebar's subscription/query load.

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Apr 14, 2026

Claude finished @oidacra's task in 53s —— View job


Rollback Safety Analysis

  • Read rollback-unsafe categories reference
  • Get full PR diff
  • Analyze diff against unsafe categories
  • Apply appropriate label

Result: Safe to Rollback ✅

All 5 changed files are pure frontend (Angular/CSS/SCSS) — no backend, database, Elasticsearch, or API changes are present.

Category Assessment
C-1 Structural Data Model ✅ No database tables, columns, or storage model touched
C-2 Elasticsearch Mapping ✅ No ES mapping changes
C-3 Content JSON Model Version ✅ No ImmutableContentlet or CURRENT_MODEL_VERSION changes
C-4 DROP TABLE / DROP COLUMN ✅ No DDL changes
H-1 One-Way Data Migration ✅ No data transformations
H-2 RENAME TABLE / COLUMN ✅ No renames
H-3 Primary Key Restructuring ✅ No PK changes
H-4 New Content Type Field Type ✅ No new field type registrations
H-5 Binary Storage Provider ✅ No storage provider changes
H-6 DROP PROCEDURE / FUNCTION ✅ No stored procedures affected
H-7 NOT NULL Column Without Default ✅ No column additions
M-1 Column Type Change ✅ No DDL
M-2 Push Publishing Bundle Format ✅ No bundler changes
M-3 REST / GraphQL API Contract ✅ No API endpoint or response shape changes
M-4 OSGi Interface Change ✅ No Java interface changes

All changes are limited to:

  • CSS custom property replacements (dot-block-editor.component.css)
  • SCSS variable substitution (dot-edit-content-binary-field.component.scss)
  • Angular template attribute additions ([fluid], [loading], [disabled], [pt])
  • A new readonly tabsPt config object in the Angular component TS

Label AI: Safe To Rollback has been applied.

@fmontes
Copy link
Copy Markdown
Member

fmontes commented Apr 14, 2026

Screenshot please :D

@semgrep-code-dotcms-test
Copy link
Copy Markdown

Legal Risk

The following dependencies were released under a license that
has been flagged by your organization for consideration.

Recommendation

While merging is not directly blocked, it's best to pause and consider what it means to use this license before continuing. If you are unsure, reach out to your security team or Semgrep admin to address this issue.

GPL-2.0

MPL-2.0

oidacra added 6 commits April 15, 2026 16:59
…ra theme tokens

- Add [fluid]="true" to tags field autocomplete for full-width rendering
- Replace hardcoded outline styles on block editor with PrimeNG Lara
  input tokens for border, hover, focus, and error states
- Replace $border-radius-md with var(--p-inputtext-border-radius)
  on binary field drop-zone elements
…ttom border

- Wire [loading] and [disabled] bindings to workflow action buttons
  using the store's isSaving signal to prevent duplicate submissions
- Add tabsPt passthrough config with bottom border on main content tabs
  to match sidebar tab styling
… align tabs

Unifies hover/focus/transition and border-radius across non-native PrimeNG
inputs (Binary, Block Editor, File/Image, JSON, WYSIWYG/TinyMCE + Monaco,
Relationship, Category, Calendar) using Lara theme tokens so they move with
the theme.

Other fixes in the same pass:
- Move date field focus/hover ring to the p-datepicker wrapper so it encloses
  the input and calendar button as one unit.
- Category field: gray border, border-radius, stable 36px min-height.
- JSON field: remove overflow-auto clipping the focus ring and reserve
  horizontal breathing room so the ring is not cut off on the sides.
- Form and sidebar p-tablist: add matching gray bottom border and align both
  tablists at the same 51px height so their baselines match.
- Form tablist: add px-8 so tabs and right-side actions align with the form
  body; drop redundant pr-4 on edit-content-actions.
- Keep sidebar always mounted with @defer (on idle) instead of @if, avoiding
  mount/unmount churn and the content squeeze during the grid transition.
- Mark the sidebar inert and aria-hidden while collapsed so it stays
  focus-/AT-transparent.
- Sync the external toggle with an Angular :enter/:leave width animation
  (150ms) so the Save group no longer snaps when the button appears or
  disappears; it now interpolates in step with the grid columns.
- Match the external toggle's wrapper, button size, icon, and right
  placement (-mr-8) to the internal one so the icon does not jump between
  the open and closed states.
- Force the sidebar tablist inner list and tabs to full height so the
  inactive tab background reaches the bottom border.
Replace shadow-md (all-sides) with a left-biased shadow so the sidebar
reads as a floating panel over the body instead of a boxed pane.
Apply the left-cast shadow only when the sidebar is not inert so it stops
bleeding into the body area while the sidebar is off-screen.
@oidacra oidacra force-pushed the issue-35009-ux-edit-content-form-ui-inconsistencies-after-lara branch from 9b20df0 to 274d0f6 Compare April 15, 2026 21:06
… flash

Drop the @defer (on idle) around the sidebar: the component is statically
imported, so deferring only delayed instantiation without reducing the
bundle. The grid reserves the sidebar column from the first frame, so
waiting for idle left ~200ms of empty white space on initial load.
@oidacra oidacra marked this pull request as ready for review April 15, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : Frontend PR changes Angular/TypeScript frontend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

UX: Edit Content form UI inconsistencies after Lara Theme migration

2 participants