Repository: Altinn/altinn-studio
Pull request #15212: feat: added divider componennet
Author: login: JamalAlabdullah
Labels: name: area/ui-editor
description: Area: Related to the designer tool for assembling app UI in Altinn Studio.
name: frontend
name: team/studio-domain2
Created: 2025-04-13T11:45:18Z | Merged: 2025-04-15T10:09:04Z

<!--- Provide a general summary of your changes in the Title above -->

## Description

- Added Divider component "Delelinje" to the component list. 


![Screenshot 2025-04-13 at 21 55 46](https://github.com/user-attachments/assets/acd74e14-a7a2-4b8b-b34f-19164e792b9a)



## Related Issue(s)

- #14913 

## Verification

- [ ] **Your** code builds clean without any errors or warnings
- [ ] Manual testing done (required)
- [ ] Relevant automated test added (if you find this hard, leave it and we'll help out)

## Documentation

- [ ] User documentation is updated with a separate linked PR in [altinn-studio-docs.](https://github.com/Altinn/altinn-studio-docs) (if applicable)


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
  - Introduced a new Divider component to help visually separate sections within the app layout.
  - The Divider now displays a clear title ("Delelinje") along with guidance text to enhance user understanding and improve the overall design experience.
  - Expanded component configurations to include the Divider, enhancing usability within the UI.
  - Added a JSON schema for the Divider component, defining its structure and validation rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/frontend/language/src/nb.json b/frontend/language/src/nb.json
index 2a4500907c4..e59093841ee 100644
--- a/frontend/language/src/nb.json
+++ b/frontend/language/src/nb.json
@@ -1285,6 +1285,7 @@
   "ux_editor.component_help_text.CloseSubformButton": "Knapp for å lukke et underskjema og gå tilbake til hovedskjemaet.",
   "ux_editor.component_help_text.CustomButton": "Knapp der du kan velge handling og navn selv. Du kan for eksempel bruke den i egendefinert kvittering eller PDF.",
   "ux_editor.component_help_text.Datepicker": "Med Datovelger gir du brukerne en kalender de kan velge dato fra.",
+  "ux_editor.component_help_text.Divider": "Bruk Delelinje til å skille komponenter i oppsettet du lager i appen.",
   "ux_editor.component_help_text.Dropdown": "Bruk Nedtrekksliste når du vil at brukerne skal velge bare ett av mange alternativer, for eksempel i en liste med stedsnavn.",
   "ux_editor.component_help_text.FileUpload": "Komponent for å la brukerne laste opp filer. Du kan angi tillatte filtyper, on brukerne kan laste opp én eller flere filer, og om det skal være begrensning på filstørrelsen.",
   "ux_editor.component_help_text.FileUploadWithTag": "Komponent for å laste opp filer med merking hentet fra en liste med alternativer. Du kan angi tillatte filtyper, on brukerne kan laste opp én eller flere filer, og om det skal være begrensning på filstørrelsen.",
@@ -1601,6 +1602,7 @@
   "ux_editor.component_title.Custom": "Egendefinert",
   "ux_editor.component_title.CustomButton": "Egendefinert knapp",
   "ux_editor.component_title.Datepicker": "Dato",
+  "ux_editor.component_title.Divider": "Delelinje",
   "ux_editor.component_title.Dropdown": "Nedtrekksliste",
   "ux_editor.component_title.FileUpload": "Vedlegg",
   "ux_editor.component_title.FileUploadWithTag": "Vedlegg med merking",
diff --git a/frontend/packages/shared/src/types/ComponentSpecificConfig.ts b/frontend/packages/shared/src/types/ComponentSpecificConfig.ts
index f681f0ddd4f..d6c96c08931 100644
--- a/frontend/packages/shared/src/types/ComponentSpecificConfig.ts
+++ b/frontend/packages/shared/src/types/ComponentSpecificConfig.ts
@@ -303,6 +303,7 @@ export type ComponentSpecificConfig<T extends ComponentType = ComponentType> = {
       bindingToShowInSummary?: string;
       tableHeadersMobile?: string[];
     };
+
   [ComponentType.Map]: FormComponentProps &
     SummarizableComponentProps &
     LabeledComponentProps & {
@@ -395,4 +396,5 @@ export type ComponentSpecificConfig<T extends ComponentType = ComponentType> = {
       autocomplete?: HTMLAutoCompleteValue;
       maxLength?: number;
     };
+  [ComponentType.Divider]: {};
 }[T];
diff --git a/frontend/packages/shared/src/types/ComponentType.ts b/frontend/packages/shared/src/types/ComponentType.ts
index 51f7b0b46bc..0c3f0988841 100644
--- a/frontend/packages/shared/src/types/ComponentType.ts
+++ b/frontend/packages/shared/src/types/ComponentType.ts
@@ -40,6 +40,7 @@ export enum ComponentType {
   Summary = 'Summary',
   Summary2 = 'Summary2',
   TextArea = 'TextArea',
+  Divider = 'Divider',
 }
 
 export enum CustomComponentType {
diff --git a/frontend/packages/ux-editor/src/data/formItemConfig.ts b/frontend/packages/ux-editor/src/data/formItemConfig.ts
index 45fabd3f418..9f813d30651 100644
--- a/frontend/packages/ux-editor/src/data/formItemConfig.ts
+++ b/frontend/packages/ux-editor/src/data/formItemConfig.ts
@@ -19,6 +19,7 @@ import {
   LikertIcon,
   LinkIcon,
   LongTextIcon,
+  MinusIcon,
   NavBarIcon,
   PaperclipIcon,
   PaymentDetailsIcon,
@@ -490,6 +491,16 @@ export const formItemConfigs: FormItemConfigs = {
     propertyPath: 'definitions/textAreaComponent',
     icon: LongTextIcon,
   },
+  [ComponentType.Divider]: {
+    name: ComponentType.Divider,
+    itemType: LayoutItemType.Component,
+    defaultProperties: {
+      id: '',
+      type: ComponentType.Divider,
+    },
+    propertyPath: 'definitions/dividerComponent',
+    icon: MinusIcon,
+  },
 };
 
 export const advancedItems: FormItemConfigs[ComponentType][] = [
@@ -517,6 +528,7 @@ export const schemaComponents: FormItemConfigs[ComponentType][] = [
   formItemConfigs[ComponentType.MultipleSelect],
   formItemConfigs[ComponentType.Likert],
   formItemConfigs[ComponentType.Datepicker],
+  formItemConfigs[ComponentType.Divider],
   formItemConfigs[ComponentType.FileUpload],
   formItemConfigs[ComponentType.FileUploadWithTag],
   formItemConfigs[ComponentType.Button],
@@ -575,7 +587,13 @@ export const defaultComponents: ComponentType[] = [
 
 export const allComponents: KeyValuePairs<ComponentType[]> = {
   form: [ComponentType.Input, ComponentType.TextArea, ComponentType.Datepicker],
-  text: [ComponentType.Header, ComponentType.Paragraph, ComponentType.Panel, ComponentType.Alert],
+  text: [
+    ComponentType.Header,
+    ComponentType.Paragraph,
+    ComponentType.Panel,
+    ComponentType.Alert,
+    ComponentType.Divider,
+  ],
   select: [
     ComponentType.Checkboxes,
     ComponentType.RadioButtons,
diff --git a/frontend/packages/ux-editor/src/testing/componentMocks.ts b/frontend/packages/ux-editor/src/testing/componentMocks.ts
index 5300eaff3c1..978e3692c77 100644
--- a/frontend/packages/ux-editor/src/testing/componentMocks.ts
+++ b/frontend/packages/ux-editor/src/testing/componentMocks.ts
@@ -73,6 +73,13 @@ const datePickerComponent: FormComponent<ComponentType.Datepicker> = {
   dataModelBindings: { simpleBinding: '' },
   timeStamp: true,
 };
+
+const dividerComponent: FormComponent<ComponentType.Divider> = {
+  ...commonProps(ComponentType.Divider),
+  id: ComponentType.Divider,
+  type: ComponentType.Divider,
+  dataModelBindings: {},
+};
 const dropdownComponent: FormComponent<ComponentType.Dropdown> = {
   ...commonProps(ComponentType.Dropdown),
   type: ComponentType.Dropdown,
@@ -201,6 +208,7 @@ export const componentMocks = {
   [ComponentType.CustomButton]: customButton,
   [CustomComponentType.CloseSubformButton]: closeSubformButton,
   [ComponentType.Datepicker]: datePickerComponent,
+  [ComponentType.Divider]: dividerComponent,
   [ComponentType.Dropdown]: dropdownComponent,
   [ComponentType.FileUploadWithTag]: fileUploadWithTagComponent,
   [ComponentType.FileUpload]: fileUploadComponent,
diff --git a/frontend/packages/ux-editor/src/testing/componentSchemaMocks.ts b/frontend/packages/ux-editor/src/testing/componentSchemaMocks.ts
index 8db5480c7b5..03a01a0f4e9 100644
--- a/frontend/packages/ux-editor/src/testing/componentSchemaMocks.ts
+++ b/frontend/packages/ux-editor/src/testing/componentSchemaMocks.ts
@@ -10,6 +10,7 @@ import CheckboxesSchema from './schemas/json/component/Checkboxes.schema.v1.json
 import CustomSchema from './schemas/json/component/Custom.schema.v1.json';
 import CustomButtonSchema from './schemas/json/component/CustomButton.schema.v1.json';
 import DatepickerSchema from './schemas/json/component/Datepicker.schema.v1.json';
+import Divider from './schemas/json/component/Divider.schema.v1.json';
 import DropdownSchema from './schemas/json/component/Dropdown.schema.v1.json';
 import FileUploadSchema from './schemas/json/component/FileUpload.schema.v1.json';
 import FileUploadWithTagSchema from './schemas/json/component/FileUploadWithTag.schema.v1.json';
@@ -84,4 +85,5 @@ export const componentSchemaMocks: Record<ComponentType, JsonSchema> = {
   [ComponentType.Summary]: SummarySchema,
   [ComponentType.Summary2]: Summary2Schema,
   [ComponentType.TextArea]: TextAreaSchema,
+  [ComponentType.Divider]: Divider,
 };
diff --git a/frontend/packages/ux-editor/src/testing/schemas/json/component/Divider.schema.v1.json b/frontend/packages/ux-editor/src/testing/schemas/json/component/Divider.schema.v1.json
new file mode 100644
index 00000000000..4b258ead329
--- /dev/null
+++ b/frontend/packages/ux-editor/src/testing/schemas/json/component/Divider.schema.v1.json
@@ -0,0 +1,54 @@
+{
+  "$id": "https://altinncdn.no/schemas/json/component/Divider.schema.v1.json",
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "properties": {
+    "id": {
+      "title": "ID",
+      "description": "The component ID. Must be unique within all layouts/pages in a layout-set. Cannot end with <dash><number>.",
+      "type": "string",
+      "pattern": "^[0-9a-zA-Z][0-9a-zA-Z-]*(-?[a-zA-Z]+|[a-zA-Z][0-9]+|-[0-9]{6,})$"
+    },
+    "hidden": {
+      "title": "Hidden",
+      "description": "Boolean value or expression indicating if the component should be hidden. Defaults to false.",
+      "default": false,
+      "$ref": "expression.schema.v1.json#/definitions/boolean"
+    },
+    "grid": {
+      "properties": {
+        "xs": { "default": "auto", "$ref": "#/definitions/IGridSize" },
+        "sm": { "default": "auto", "$ref": "#/definitions/IGridSize" },
+        "md": { "default": "auto", "$ref": "#/definitions/IGridSize" },
+        "lg": { "default": "auto", "$ref": "#/definitions/IGridSize" },
+        "xl": { "default": "auto", "$ref": "#/definitions/IGridSize" },
+        "labelGrid": { "$ref": "#/definitions/IGridStyling" },
+        "innerGrid": { "$ref": "#/definitions/IGridStyling" }
+      }
+    },
+    "pageBreak": {
+      "title": "Page break",
+      "description": "Optionally insert page-break before/after component when rendered in PDF",
+      "type": "object",
+      "properties": {
+        "breakBefore": {
+          "title": "Page break before",
+          "description": "PDF only: Value or expression indicating whether a page break should be added before the component. Can be either: 'auto' (default), 'always', or 'avoid'.",
+          "examples": ["auto", "always", "avoid"],
+          "default": "auto",
+          "$ref": "expression.schema.v1.json#/definitions/string"
+        },
+        "breakAfter": {
+          "title": "Page break after",
+          "description": "PDF only: Value or expression indicating whether a page break should be added after the component. Can be either: 'auto' (default), 'always', or 'avoid'.",
+          "examples": ["auto", "always", "avoid"],
+          "default": "auto",
+          "$ref": "expression.schema.v1.json#/definitions/string"
+        }
+      },
+      "additionalProperties": false
+    },
+    "type": { "const": "Divider" }
+  },
+  "required": ["id", "type"],
+  "title": "Divider component schema"
+}
diff --git a/frontend/packages/ux-editor/src/testing/schemas/json/layout/layout.schema.v1.json b/frontend/packages/ux-editor/src/testing/schemas/json/layout/layout.schema.v1.json
index 5dbe973262f..df14eede27d 100644
--- a/frontend/packages/ux-editor/src/testing/schemas/json/layout/layout.schema.v1.json
+++ b/frontend/packages/ux-editor/src/testing/schemas/json/layout/layout.schema.v1.json
@@ -51,6 +51,7 @@
             "Checkboxes",
             "Custom",
             "Datepicker",
+            "Divider",
             "Dropdown",
             "FileUpload",
             "FileUploadWithTag",
@@ -245,6 +246,18 @@
             "$ref": "#/definitions/datepickerComponent"
           }
         },
+        {
+          "if": {
+            "properties": {
+              "type": {
+                "const": "Divider"
+              }
+            }
+          },
+          "then": {
+            "$ref": "#/definitions/dividerComponent"
+          }
+        },
         {
           "if": {
             "properties": {
@@ -643,6 +656,11 @@
       },
       "required": []
     },
+    "dividerComponent": {
+      "type": "object",
+      "properties": {},
+      "additionalProperties": false
+    },
     "navigationButtonsComponent": {
       "properties": {
         "showBackButton": {


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>frontend/packages/shared/src/types/ComponentSpecificConfig.ts (1)</summary><blockquote>

`399-399`: **Implementation is consistent with codebase patterns.**

The added `Divider` component configuration follows the established pattern in this file for components without specific configuration properties, using an empty object (`{}`).



Note that the static analysis tool flags using `{}` as a type. While this is the consistent pattern in this file, a more TypeScript-idiomatic approach would be to use `Record<string, never>` instead. Consider addressing this across all similar components in a future refactoring.

```diff
-  [ComponentType.Divider]: {};
+  [ComponentType.Divider]: Record<string, never>;
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 399-399: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9f7e944cacdb57f3ba6a6a1043338daaeaa7bf90 and 527e7a9a9dd1a97f2397c4ace5a93f2b16631438.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `frontend/packages/shared/src/types/ComponentSpecificConfig.ts` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>frontend/packages/shared/src/types/ComponentSpecificConfig.ts</summary>

[error] 399-399: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: Build environment and run e2e test
* GitHub Check: Testing
* GitHub Check: CodeQL

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T11:56:52Z
user: login: lassopicasso
body: Superb 🚀 Just one comment. You can move it to test after. 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T07:34:46Z
user: login: JamalAlabdullah
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T08:08:29Z
user: login: mlqn
body: Tested OK in dev! 🚀 🤩 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T10:08:29Z

Review comments:
diff_hunk: @@ -1601,6 +1602,7 @@
   "ux_editor.component_title.Custom": "Egendefinert",
   "ux_editor.component_title.CustomButton": "Egendefinert knapp",
   "ux_editor.component_title.Datepicker": "Dato",
+  "ux_editor.component_title.Divider": "Delelinje ",
path: frontend/language/src/nb.json
user: login: lassopicasso
body: Is it meant to have a white space here? 
created_at: 2025-04-15T07:21:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1601,6 +1602,7 @@
   "ux_editor.component_title.Custom": "Egendefinert",
   "ux_editor.component_title.CustomButton": "Egendefinert knapp",
   "ux_editor.component_title.Datepicker": "Dato",
+  "ux_editor.component_title.Divider": "Delelinje ",
path: frontend/language/src/nb.json
user: login: JamalAlabdullah
body: removed 👍 
created_at: 2025-04-15T08:08:29Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-13T11:45:24Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

<details>
<summary>📝 Walkthrough</summary>

```markdown
## Walkthrough
This pull request introduces support for a new Divider component across the application. It adds new UI text entries (help text and title) in the language file, extends the component enumeration to include Divider, and provides a dedicated configuration for it. Additionally, the changes incorporate the Divider into form item configurations, testing mocks, and schema mappings. New JSON schemas for the Divider are defined and integrated into the layout schema, ensuring that the component is recognized and properly validated throughout the UI.

## Changes

| File(s) | Change Summary |
|---------|----------------|
| `frontend/language/src/nb.json` | Added Norwegian UI texts for the Divider component: a help text and a title. |
| `frontend/packages/shared/src/types/ComponentType.ts` | Added a new enum entry `Divider` to the `ComponentType` enum. |
| `frontend/packages/ux-editor/src/data/formItemConfig.ts`, `frontend/packages/ux-editor/src/testing/componentMocks.ts`, `frontend/packages/ux-editor/src/testing/componentSchemaMocks.ts` | Introduced Divider component configuration: added default properties, icon assignment, testing mocks (using commonProps), and updated schema mappings to include the Divider. |
| `frontend/packages/ux-editor/src/testing/schemas/json/component/Divider.schema.v1.json`, `frontend/packages/ux-editor/src/testing/schemas/json/layout/layout.schema.v1.json` | Added a new JSON schema file for the Divider component and updated the layout schema to recognize Divider through new enumeration and conditional definitions. |
| `frontend/packages/shared/src/types/ComponentSpecificConfig.ts` | Added a new entry for `ComponentType.Divider` in the `ComponentSpecificConfig` type definition. |

## Possibly related issues
- Altinn/altinn-studio#14913: This PR implements the requested support for the Divider component in the form editor, including types, schemas, mocks, and localization, directly addressing the issue objectives.

## Suggested labels
`added-to-sprint`, `team/studio-domain1`, `team/studio-core`

## Suggested reviewers
- github-actions
```

</details>

<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡💬 Agentic Chat (Pro Plan, General Availability)</summary>
> 
> - We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 527e7a9a9dd1a97f2397c4ace5a93f2b16631438 and aadff7bd5092d5ec7dd0714218f0080d4f536cd8.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `frontend/language/src/nb.json` (2 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* frontend/language/src/nb.json

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: Build environment and run e2e test
* GitHub Check: Testing
* GitHub Check: Typechecking and linting
* GitHub Check: CodeQL

</details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Altinn/altinn-studio&utm_content=15212):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-04-13T11:49:06Z
body: ## [Codecov](https://app.codecov.io/gh/Altinn/altinn-studio/pull/15212?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Altinn) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 95.99%. Comparing base [(`99b749d`)](https://app.codecov.io/gh/Altinn/altinn-studio/commit/99b749dfc22a702c5122bbe9990db560217c1aac?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Altinn) to head [(`aadff7b`)](https://app.codecov.io/gh/Altinn/altinn-studio/commit/aadff7bd5092d5ec7dd0714218f0080d4f536cd8?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Altinn).
> Report is 22 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main   #15212   +/-   ##
=======================================
  Coverage   95.99%   95.99%           
=======================================
  Files        2040     2040           
  Lines       26262    26262           
  Branches     2971     2971           
=======================================
  Hits        25209    25209           
  Misses        789      789           
  Partials      264      264           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/Altinn/altinn-studio/pull/15212?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Altinn).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Altinn).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE