Skip to content

fix: replace Combobox component for selecting system with Suggestion - #1602

Draft
mgunnerud wants to merge 2 commits into
mainfrom
1211-replace-dscombobox-component-in-create-systemuser-wizard
Draft

fix: replace Combobox component for selecting system with Suggestion#1602
mgunnerud wants to merge 2 commits into
mainfrom
1211-replace-dscombobox-component-in-create-systemuser-wizard

Conversation

@mgunnerud

@mgunnerud mgunnerud commented Sep 15, 2025

Copy link
Copy Markdown
Contributor

Description

  • Replace Combobox component for selecting system in system user wizard with Suggestion component
  • This will also fix the issue with several options with identical label

Related Issue(s)

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)
  • All tests run green

Documentation

  • User documentation is updated with a separate linked PR in altinn-studio-docs. (if applicable)

Summary by CodeRabbit

  • New Features

    • Replaced system selection combobox with a streamlined suggestion dropdown.
    • Options now show system name with vendor details; improved filtering.
    • Loading state uses a spinner; error handling preserved.
    • Added “No matches” empty state.
    • Labels/titles now reflect the selected system’s display name.
  • Localization

    • Added “No matches” translations (en, nb, nn) for the system selection.
  • Chores

    • Added design system React dependency to support the new suggestion UI.

@coderabbitai

coderabbitai Bot commented Sep 15, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Introduces DigDir design-system Suggestion component for selecting a registered system, updating types from RegisteredSystem to SuggestionItem across related components. Adds a new CSS class for subtle description text. Adds a new runtime dependency. Updates localization files with an “empty_option” key. Adjusts data mapping to use value/label.

Changes

Cohort / File(s) Summary
Dependencies
package.json
Added dependency @digdir/designsystemet-react@^1.5.0.
Styling for description text
src/features/amUI/systemUser/CreateSystemUserPage/CreateSystemUser.module.css
Added .descriptionText { color: var(--ds-color-neutral-text-subtle); }.
Type alignment in page component
src/features/amUI/systemUser/CreateSystemUserPage/CreateSystemUserPage.tsx
Replaced RegisteredSystem with SuggestionItem for selectedSystem state; imported SuggestionItem from design system.
Rights flow type and data mapping
src/features/amUI/systemUser/CreateSystemUserPage/RightsIncluded.tsx
Prop type selectedSystem changed to SuggestionItem. Rights query now uses selectedSystem.value. Post payload uses label and value. Removed RegisteredSystem import; added SuggestionItem import.
System selection UI rewrite
src/features/amUI/systemUser/CreateSystemUserPage/SelectRegisteredSystem.tsx
Replaced Combobox with design-system Suggestion. Props now use SuggestionItem. Added spinner during loading. Added empty option handling and substring filtering. Adjusted imports accordingly.
Localization updates
src/localizations/en.json, src/localizations/no_nb.json, src/localizations/no_nn.json
Added systemuser_creationpage.empty_option ("No matches"/"Ingen treff"). Minor formatting and trailing comma fix in no_nb.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant UI as CreateSystemUserPage
  participant Sel as SelectRegisteredSystem (Suggestion)
  participant API as Backend API

  U->>Sel: Type to search systems
  Sel-->>Sel: Filter options (client-side substring)
  Sel->>U: Show suggestions / "empty_option" if none

  U->>Sel: Choose SuggestionItem (value, label)
  Sel->>UI: setSelectedSystem(SuggestionItem)

  UI->>API: useGetRegisteredSystemRightsQuery(selectedSystem.value)
  API-->>UI: Rights for system

  U->>UI: Submit new system user
  UI->>API: POST { systemId: value, integrationTitle: label, rights... }
  API-->>UI: Created response / error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A hint becomes a choice with graceful ease,
Suggestion sings where Combobox did tease.
Label and value now walk hand in hand,
Rights follow neatly, per the plan.
“No matches” whispers in three tongues bright—
A subtle hue of CSS, just right.
New deps in tow, the page takes flight.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary change — replacing the Combobox with a Suggestion component for system selection — and is a single clear sentence focused on the main intent of the PR without noisy details. It directly maps to the changes in the diff (component replacement and type updates) and is easy for teammates scanning history to understand.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 1211-replace-dscombobox-component-in-create-systemuser-wizard

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/features/amUI/systemUser/CreateSystemUserPage/SelectRegisteredSystem.tsx (3)

77-88: Wire Label to input for a11y.

Associate the Label with the input via htmlFor/id.

-              <Field>
-                <Label>{t('systemuser_creationpage.pull_down_menu_label')}</Label>
+              <Field>
+                <Label htmlFor='registered-system-input'>{t('systemuser_creationpage.pull_down_menu_label')}</Label>
                 <Suggestion
                   multiple={false}
                   selected={selectedSystem ?? EMPTY_SUGGESTION_ITEM}
                   onSelectedChange={onSelectSystem}
                   filter={({ text, input }) => {
-                    return text.toLowerCase().includes(input.value.toLowerCase());
+                    return text.toLocaleLowerCase().includes(input.value.trim().toLocaleLowerCase());
                   }}
                 >
-                  <Suggestion.Input placeholder={t('systemuser_creationpage.choose')} />
+                  <Suggestion.Input id='registered-system-input' placeholder={t('systemuser_creationpage.choose')} />

28-28: Avoid sentinel item if library accepts undefined selected.

If allowed, pass selected={selectedSystem} and drop EMPTY_SUGGESTION_ITEM to reduce edge‑cases.

-const EMPTY_SUGGESTION_ITEM: SuggestionItem = { value: '', label: '' };
...
-                  selected={selectedSystem ?? EMPTY_SUGGESTION_ITEM}
+                  selected={selectedSystem}

74-108: Error UX: consider early return on load error.

Showing an empty Suggestion alongside an error can confuse users; gate the field behind the error.

-          <div className={classes.inputContainer}>
-            {isLoadingRegisteredSystems ? (
+          <div className={classes.inputContainer}>
+            {isLoadingRegisteredSystems ? (
               <DsSpinner aria-label={t('systemuser_creationpage.loading_systems')} />
-            ) : (
+            ) : isLoadRegisteredSystemsError ? null : (
               <Field>
                 <Label htmlFor='registered-system-input'>{t('systemuser_creationpage.pull_down_menu_label')}</Label>
                 ...
               </Field>
             )}
             {isLoadRegisteredSystemsError && (
               <DsAlert data-color='danger'>
                 {t('systemuser_creationpage.load_vendors_error')}
               </DsAlert>
             )}
src/features/amUI/systemUser/CreateSystemUserPage/RightsIncluded.tsx (1)

52-58: Handle rejected promise from unwrap to avoid console noise.

Add a no‑op catch so rejections are fully handled by RTKQ error state.

-      postNewSystemUser(postObjekt)
-        .unwrap()
-        .then((newSystemUser: { id: string }) => {
+      postNewSystemUser(postObjekt)
+        .unwrap()
+        .then((newSystemUser: { id: string }) => {
           navigate(`/${SystemUserPath.SystemUser}/${SystemUserPath.Overview}`, {
             state: { createdId: newSystemUser.id },
           });
-        });
+        })
+        .catch(() => { /* handled via createSystemUserError */ });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef4dfdf and 4cac771.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (8)
  • package.json (1 hunks)
  • src/features/amUI/systemUser/CreateSystemUserPage/CreateSystemUser.module.css (1 hunks)
  • src/features/amUI/systemUser/CreateSystemUserPage/CreateSystemUserPage.tsx (1 hunks)
  • src/features/amUI/systemUser/CreateSystemUserPage/RightsIncluded.tsx (3 hunks)
  • src/features/amUI/systemUser/CreateSystemUserPage/SelectRegisteredSystem.tsx (3 hunks)
  • src/localizations/en.json (2 hunks)
  • src/localizations/no_nb.json (2 hunks)
  • src/localizations/no_nn.json (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Continuous Integration / Test & Build
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (11)
src/localizations/en.json (2)

548-549: LGTM: keys will be used by Suggestion.

Matches SelectRegisteredSystem usage for loading and empty states.


291-291: Resolved — safe rendering via Trans. The translation contains an tag but AccessPackageInfoAlert uses react‑i18next with a mapped anchor (target='_blank' rel='noopener noreferrer'), so there’s no dangerouslySetInnerHTML and no change needed.

src/localizations/no_nn.json (2)

545-546: LGTM: loading/empty keys added.


286-287: Verify safe rendering for 'info_alert_text' (contains HTML)

src/localizations/no_nn.json — info_alert_text includes an tag; repo has DOMPurify, html-react-parser and react-i18next but I could not locate where this key is rendered. Confirm the rendering path uses a safe option: either react-i18next with allowed tags or parse+sanitize (html-react-parser + DOMPurify) before injecting. Do not render via unsanitized dangerouslySetInnerHTML.

src/features/amUI/systemUser/CreateSystemUserPage/CreateSystemUser.module.css (1)

20-22: LGTM: subtle text token is appropriate.

src/localizations/no_nb.json (2)

547-548: LGTM: loading/empty keys added and wired.


289-289: HTML in translations — ensure safe rendering

src/localizations/no_nb.json (≈ line 289) contains a raw tag; render via a safe translator (e.g., react-i18next Trans) or sanitize/replace with parameterized placeholders — avoid dangerouslySetInnerHTML.

src/features/amUI/systemUser/CreateSystemUserPage/RightsIncluded.tsx (1)

73-81: LGTM: header now uses label from SuggestionItem.

src/features/amUI/systemUser/CreateSystemUserPage/CreateSystemUserPage.tsx (1)

15-16: LGTM: state type migrated to SuggestionItem.

Flow control guards prevent RightsIncluded from rendering without a selection.

package.json (1)

25-25: Approve — @digdir/designsystemet-react@^1.5.0 is compatible with React 19

peerDependencies: ">=18.3.1 || ^19.0.0"; package.json uses react/react-dom "^19.1.1"; yarn.lock contains @digdir/designsystemet-react@^1.5.0 — no unmet peer deps or lockfile mismatch found.

src/features/amUI/systemUser/CreateSystemUserPage/SelectRegisteredSystem.tsx (1)

21-24: Experimental import — verify EXPERIMENTAL_Suggestion API (v1.5.0)

EXPERIMENTAL_Suggestion is used here with props selected, onSelectedChange and filter — confirm those prop names/signatures against @digdir/designsystemet-react v1.5.0 type declarations (index.d.ts) or docs; if the API is unstable, pin a compatible version or add a local wrapper/typing.
Location: src/features/amUI/systemUser/CreateSystemUserPage/SelectRegisteredSystem.tsx (import at lines 21–24).

@mgunnerud
mgunnerud marked this pull request as draft September 19, 2025 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace DsCombobox component in create systemuser wizard

1 participant