Skip to content

chore: display error message to match grid label#4047

Open
JamalAlabdullah wants to merge 11 commits intomainfrom
4030-better-handle-how-error-messages-are-shown-for-components-using-innergrid
Open

chore: display error message to match grid label#4047
JamalAlabdullah wants to merge 11 commits intomainfrom
4030-better-handle-how-error-messages-are-shown-for-components-using-innergrid

Conversation

@JamalAlabdullah
Copy link
Copy Markdown
Contributor

@JamalAlabdullah JamalAlabdullah commented Mar 6, 2026

Description

This PR improves ComponentStructureWrapper by simplifying the inner/validation grid merging logic and making exact-width input behavior easier to read. by mergeMaxGridSizePair and mergeMaxGridStyling.
It also adds validationGrid to the shared generated grid type in codegen/common.ts ;

 new CG.prop(
        'validationGrid',
        CG.common('IGridStyling')
          .optional()
          .setTitle('Validation grid')
          .setDescription('Column span for validation messages; defaults to innerGrid when omitted'),
      ),

For now the validation messages use grid.validationGrid and when it’s missing, it falls back to innerGrid.

Related Issue(s)

Test in ra0479-02;

Screen.Recording.2026-03-26.at.10.18.29.mov

Test in forntend-test app:

Screen.Recording.2026-03-26.at.10.14.23.mov

Verification/QA

  • Manual functionality testing
    • I have tested these changes manually
    • Creator of the original issue (or service owner) has been contacted for manual testing (or will be contacted when released in alpha)
    • No testing done/necessary
  • Automated tests
    • Unit test(s) have been added/updated
    • Cypress E2E test(s) have been added/updated
    • No automatic tests are needed here (no functional changes/additions)
    • I want someone to help me make some tests
  • UU/WCAG (follow these guidelines until we have our own)
    • I have tested with a screen reader/keyboard navigation/automated wcag validator
    • No testing done/necessary (no DOM/visual changes)
    • I want someone to help me perform accessibility testing
  • User documentation @ altinn-studio-docs
    • Has been added/updated
    • No functionality has been changed/added, so no documentation is needed
    • I will do that later/have created an issue
  • Support in Altinn Studio
    • Issue(s) created for support in Studio
    • This change/feature does not require any changes to Altinn Studio
  • Sprint board
    • The original issue (or this PR itself) has been added to the Team Apps project and to the current sprint board
    • I don't have permissions to do that, please help me out
  • Labels
    • I have added a kind/* and backport* label to this PR for proper release notes grouping
    • I don't have permissions to add labels, please help me out

Summary by CodeRabbit

  • New Features

    • Improved responsive input sizing with breakpoint-aware width options and an "exact width" constraint for more consistent input layout.
  • Refactor

    • Layout structure updated so form content and validations are arranged in dedicated blocks, improving alignment and wrapping while preserving validation visibility.
  • Tests

    • E2E assertion made more tolerant to minor CSS flex variations to reduce flakiness.

@JamalAlabdullah JamalAlabdullah added kind/other Pull requests containing chores/repo structure/other changes backport-ignore This PR is a new feature and should not be cherry-picked onto release branches labels Mar 6, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Derives breakpoint-aware grid sizing in ComponentStructureWrapper, adds optional validationGrid to grid types, introduces exact-width CSS utilities, moves validations into a dedicated layout child, and relaxes an e2e flex assertion; also updates a test pageobject selector.

Changes

Cohort / File(s) Summary
ComponentStructureWrapper implementation
src/layout/ComponentStructureWrapper.tsx
Adds breakpoint-aware grid utilities, computes merged contentGridSize from innerGrid/validationGrid/labelGrid, derives inputGridSize plus optional exact-width CSS variable/class, changes outer container to container, direction="column", flexWrap="nowrap", and renders children and validations in separate Flex children sized from computed grids.
Grid type update
src/codegen/Common.ts
Adds optional validationGrid?: IGridStyling to exported IGrid with title/description indicating it represents column span for validation messages and falls back to innerGrid when omitted.
CSS module additions
src/layout/ComponentStructureWrapper.module.css
Adds .inputFlexExact and breakpoint utility classes .useXs, .useSm, .useMd, .useLg with media-query rules that use CSS variables (e.g., --input-pct-sm) to control width.
E2E test adjustment
test/e2e/integration/frontend-test/formatting.ts
Replaces strict flex equality assertion should('have.css', 'flex', '0 1 50%') with a tolerant invoke('css','flex').should('match', /^0 1 /) to allow variations after the 0 1 prefix.
E2E pageobject selector
test/e2e/pageobjects/app-frontend.ts
Narrows navigationBarButton selector from #form-content-nav2 > div > nav > button to #form-content-nav2 [data-testid="navigation-bar"] > div > nav > button.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive While most changes target ComponentStructureWrapper and validation rendering, the CSS module additions (.inputFlexExact, breakpoint classes) and test selector refinement may be supporting changes worth confirming as in-scope. The PR includes CSS utility changes and test selector updates that appear related to grid layout support but warrant verification that all changes are directly necessary for the validation message alignment objective.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: displaying error messages to match grid label alignment, which is the core refactoring in this PR.
Linked Issues check ✅ Passed The PR addresses #4030's requirements by repositioning validation messages under input fields within a shared Flex container and introducing minimum input width logic to prevent overly narrow error columns.
Description check ✅ Passed The PR description is mostly complete with clear explanation of changes, related issue, manual testing confirmation, accessibility checks, and proper labels applied.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 4030-better-handle-how-error-messages-are-shown-for-components-using-innergrid

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@JamalAlabdullah JamalAlabdullah added kind/feature-request New feature or request kind/other Pull requests containing chores/repo structure/other changes and removed kind/other Pull requests containing chores/repo structure/other changes labels Mar 6, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/layout/ComponentStructureWrapper.tsx (1)

34-53: Consider making validation Flex sizing consistent with content Flex breakpoints.

The validation Flex (lines 46-51) only specifies xs and md breakpoints, while the content Flex (line 39) spreads grid?.innerGrid which may include sm, lg, or xl values. If innerGrid defines narrower widths at these breakpoints, the validation messages could end up wider than the content they relate to, potentially causing visual misalignment.

If the intent is for validation to always span full width regardless of innerGrid, consider being explicit about all breakpoints:

         <Flex
           item
-          size={{ xs: 12, md: 12 }}
+          size={{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12 }}
         >

Otherwise, if validation width should match content width, consider:

         <Flex
           item
-          size={{ xs: 12, md: 12 }}
+          size={{ xs: 12, ...grid?.innerGrid }}
         >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layout/ComponentStructureWrapper.tsx` around lines 34 - 53,
componentWithValidations renders two Flex blocks where the content Flex uses
size={{ xs: 12, ...grid?.innerGrid }} but the validation Flex hardcodes size={{
xs: 12, md: 12 }}, causing breakpoint mismatch; update the validation Flex
sizing to match the content Flex by either spreading grid?.innerGrid (size={{
xs: 12, ...grid?.innerGrid }}) or by explicitly providing the same breakpoints
you expect, so AllComponentValidations aligns with the Flex containing children
when showValidationMessages is true (refer to componentWithValidations, Flex,
AllComponentValidations, grid?.innerGrid, showValidationMessages, indexedId,
baseComponentId).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/layout/ComponentStructureWrapper.tsx`:
- Around line 34-53: componentWithValidations renders two Flex blocks where the
content Flex uses size={{ xs: 12, ...grid?.innerGrid }} but the validation Flex
hardcodes size={{ xs: 12, md: 12 }}, causing breakpoint mismatch; update the
validation Flex sizing to match the content Flex by either spreading
grid?.innerGrid (size={{ xs: 12, ...grid?.innerGrid }}) or by explicitly
providing the same breakpoints you expect, so AllComponentValidations aligns
with the Flex containing children when showValidationMessages is true (refer to
componentWithValidations, Flex, AllComponentValidations, grid?.innerGrid,
showValidationMessages, indexedId, baseComponentId).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a6993d1f-db03-494f-9126-c972544c2a20

📥 Commits

Reviewing files that changed from the base of the PR and between 5e931c9 and 59b9e42.

📒 Files selected for processing (1)
  • src/layout/ComponentStructureWrapper.tsx

@JamalAlabdullah JamalAlabdullah added the squad/utforming Issues that belongs to the named squad. label Mar 6, 2026
@JamalAlabdullah JamalAlabdullah moved this to 🔎 In review in Team Altinn Studio Mar 6, 2026
Copy link
Copy Markdown
Contributor

@lassopicasso lassopicasso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One comment about the width👍

I am unsure, but @Magnusrm mentioned that this change can perhaps be a breaking change for existing apps' layouts.
Maybe we should discuss this with the team on slack and see if someone has any more thoughts around this before we merget it.

@JamalAlabdullah JamalAlabdullah moved this from 🔎 In review to 👷 In progress in Team Altinn Studio Mar 15, 2026
@JamalAlabdullah JamalAlabdullah moved this from 👷 In progress to 🔎 In review in Team Altinn Studio Mar 16, 2026
@lassopicasso
Copy link
Copy Markdown
Contributor

lassopicasso commented Mar 16, 2026

Hei,
kunne du kort forklart hva du kom frem til på denne før jeg tar review på ny? Jeg synes det er litt vanskelig å tyde kode i app-frontend-react uten videre beskrivelse. Du snakket noe med @Annikenkbrathen på squad-kanalen, men usikker på hva konklusjonen ble.

@JamalAlabdullah
Copy link
Copy Markdown
Contributor Author

Hei, kunne du kort forklart hva du kom frem til på denne før jeg tar review på ny? Jeg synes det er litt vanskelig å tyde kode i app-frontend-react uten videre beskrivelse. Du snakket noe med @Annikenkbrathen på squad-kanalen, men usikker på hva konklusjonen ble.

I added description 👍

@lassopicasso
Copy link
Copy Markdown
Contributor

lassopicasso commented Mar 17, 2026

I added description 👍

Superb! The PR is well described, and you have proposed a good solution. My main concern is that this will introduce breaking layout changes for many apps.

When I searched for apps using innerGrid, I found that many use values below 7. I used this query: https://altinn.studio/repos/explore/code?q=innerGrid&search_mode=exact

This would also go against the 12-column grid principle our layout system is based on. If an app developer sets innerGrid to 1, it should represent 1/12 of the available width. With this change, setting values like 4 would still result in a width of 7, which could be confusing for developers trying to create narrower inputs.
We have documented for narrow input fields here as well: https://docs.altinn.studio/nb/altinn-studio/v8/guides/design/guidelines/components/input/#lite-input

I should have responded in the Slack thread when you asked about this earlier, but I forgot to read the responses you got.

You could bring this up with the team to see if this is a direction we want to take, supported by the findings @Annikenkbrathen mentioned. If so, we should inform app developers as well and update the documentation. That said, I suspect this kind of breaking change might be received negatively from the app developers, because they must do many changes and we constrain something we earlier offered.

An alternative approach could be to let the error message width follow whichever is wider of the input field or the label. This I think solves SSB's issue, but again go against the findings from Anniken. 🤔

@JamalAlabdullah
Copy link
Copy Markdown
Contributor Author

I added description 👍

Superb! The PR is well described, and you have proposed a good solution. My main concern is that this will introduce breaking layout changes for many apps.

When I searched for apps using innerGrid, I found that many use values below 7. I used this query: https://altinn.studio/repos/explore/code?q=innerGrid&search_mode=exact

This would also go against the 12-column grid principle our layout system is based on. If an app developer sets innerGrid to 1, it should represent 1/12 of the available width. With this change, setting values like 4 would still result in a width of 7, which could be confusing for developers trying to create narrower inputs. We have documented for narrow input fields here as well: https://docs.altinn.studio/nb/altinn-studio/v8/guides/design/guidelines/components/input/#lite-input

I should have responded in the Slack thread when you asked about this earlier, but I forgot to read the responses you got.

You could bring this up with the team to see if this is a direction we want to take, supported by the findings @Annikenkbrathen mentioned. If so, we should inform app developers as well and update the documentation. That said, I suspect this kind of breaking change might be received negatively from the app developers, because they must do many changes and we constrain something we earlier offered.

An alternative approach could be to let the error message width follow whichever is wider of the input field or the label. This I think solves SSB's issue, but again go against the findings from Anniken. 🤔

What do you thing @olemartinorg ?

@olemartinorg
Copy link
Copy Markdown
Contributor

This sounds risky to me - I agree it's problematic to introduce a breaking change like this new minimum-width. App developers pushed back on changing the PDF font size because it broke their carefully molded layout, and this will definitely break more than that change ever did.

Luckily we're already working on the next major version, so breaking changes are possible to introduce, you just have to open a PR in the monorepo instead. That's what will become v10 and the next major version when we release it.

As for what is the correct solution, I believe you've looked into it more than I have. I would try to set up a page in one of our test apps with all the possible combinations of grid settings on an input field, and see how (long) validation messages work there (before and after this change).

@JamalAlabdullah JamalAlabdullah removed their assignment Mar 24, 2026
@JamalAlabdullah
Copy link
Copy Markdown
Contributor Author

@lassopicasso The suggestion from Ole Martin is ready to review and test

Copy link
Copy Markdown
Contributor

@lassopicasso lassopicasso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem to work when I set the config. The validation still follows the same width as the input field. Am I doing something wrong? I suspect something unexpected might be happening around inputGridSizeAndExactWidth.

I tested in frontend-test app in the first input field in form layout.
Config:
Image

Result:
Image

I’m also finding it a bit difficult to follow the flow here, so could you explain the logic behind the decisions in ComponentStructureWrapper in details, especially inputGridSizeAndExactWidth? I would try to avoid the number of abstraction levels. And a nitpick; from the naming, I would expect this to apply only to the input, but it also set the validation width.

I'm also curious why we need to set specific grid breakpoints and styling here, when Flex already handles this based on the size prop.

My initial thought is that the validation width logic could potentially be handled at a lower level when showValidationMessages is defined, but I may be missing some context.

What I think is happening now:

  • Flex wrapper sets the max grid size using contentGridSize
  • contentGridSize is set to the largest of innerGrid and validationGrid
  • The inner Flex components then cannot exceed the outer Flex grid size

If you need a quick review before we go on vacation on friday (I'll be away for 3 weeks), it might be helpful to also check with someone in same time zone for another round. I’ll likely only have time for one more review, and because of the time difference I unfortunately won’t be able to provide quick follow-up.

@JamalAlabdullah
Copy link
Copy Markdown
Contributor Author

It doesn't seem to work when I set the config. The validation still follows the same width as the input field. Am I doing something wrong? I suspect something unexpected might be happening around inputGridSizeAndExactWidth.

I tested in frontend-test app in the first input field in form layout. Config: Image

Result: Image

I’m also finding it a bit difficult to follow the flow here, so could you explain the logic behind the decisions in ComponentStructureWrapper in details, especially inputGridSizeAndExactWidth? I would try to avoid the number of abstraction levels. And a nitpick; from the naming, I would expect this to apply only to the input, but it also set the validation width.

I'm also curious why we need to set specific grid breakpoints and styling here, when Flex already handles this based on the size prop.

My initial thought is that the validation width logic could potentially be handled at a lower level when showValidationMessages is defined, but I may be missing some context.

What I think is happening now:

  • Flex wrapper sets the max grid size using contentGridSize
  • contentGridSize is set to the largest of innerGrid and validationGrid
  • The inner Flex components then cannot exceed the outer Flex grid size

If you need a quick review before we go on vacation on friday (I'll be away for 3 weeks), it might be helpful to also check with someone in same time zone for another round. I’ll likely only have time for one more review, and because of the time difference I unfortunately won’t be able to provide quick follow-up.

I did not know why it did not worked when you tested because i tested in same app and it worked, any way i refactored and removed the entire inputGridSizeAndExactWidth

@JamalAlabdullah
Copy link
Copy Markdown
Contributor Author

@olemartinorg har du mulighet bare for å teste 😄 ?

Copy link
Copy Markdown
Contributor

@lassopicasso lassopicasso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! The code looks much better now and it's easier to follow the flow.
I have a few comments, but overall the changes look good 👍

I also tested it, and it seems I can now set a custom width for the validation message. However, it looks like the input and validation together only take half of the width they’re supposed to.

For example, this config should take half of the layout width, but the input and validation message only take half of that again. So it seems like the width is being applied twice somewhere. I compared it with main branch to make sure my app isn't wrong, and in main it took 50% width of the layout.

        "grid": {
          "innerGrid": {
            "md": 6
          },
          "validationGrid": {
            "md": 6
          }
        }

Image

Since I won’t have the opportunity to do another review today, and I’m leaving for holiday for 3 weeks, I’d suggest asking someone else to take a second look after updating the PR based on the feedback. 🙂

@JamalAlabdullah
Copy link
Copy Markdown
Contributor Author

Great job! The code looks much better now and it's easier to follow the flow. I have a few comments, but overall the changes look good 👍

I also tested it, and it seems I can now set a custom width for the validation message. However, it looks like the input and validation together only take half of the width they’re supposed to.

For example, this config should take half of the layout width, but the input and validation message only take half of that again. So it seems like the width is being applied twice somewhere. I compared it with main branch to make sure my app isn't wrong, and in main it took 50% width of the layout.

        "grid": {
          "innerGrid": {
            "md": 6
          },
          "validationGrid": {
            "md": 6
          }
        }
Image Since I won’t have the opportunity to do another review today, and I’m leaving for holiday for 3 weeks, I’d suggest asking someone else to take a second look after updating the PR based on the feedback. 🙂

Nice catch, this leads to new refactor where the entire added breackPoints is removed now

@sonarqubecloud
Copy link
Copy Markdown

@JamalAlabdullah JamalAlabdullah removed their assignment Mar 27, 2026
Copy link
Copy Markdown
Contributor

@walldenfilippa walldenfilippa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-ignore This PR is a new feature and should not be cherry-picked onto release branches kind/feature-request New feature or request kind/other Pull requests containing chores/repo structure/other changes squad/utforming Issues that belongs to the named squad.

Projects

Status: 🔎 In review

Development

Successfully merging this pull request may close these issues.

Better handle how error messages are shown for components using innerGrid

4 participants