fix(react): resolve B2B presentation components styling and layout issues#536
Conversation
📝 WalkthroughWalkthroughOrganization translation contracts and English strings were expanded, while create, list, and profile components gained localized headings, subheadings, and updated presentation styles. ChangesOrganization UI localization
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsx`:
- Around line 201-208: Ensure popup mode renders only one dialog title: update
the header blocks in
packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsx:201-208,
packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.tsx:382-389,
and
packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.tsx:522-529
to omit their in-content headings in popup mode, or consistently remove the
corresponding DialogPrimitive.Heading in favor of each semantic h1.
- Around line 203-206: Update the translation fallbacks in
CreateOrganization/BaseCreateOrganization.tsx at lines 203-206, 223, 240, and
260, OrganizationList/BaseOrganizationList.tsx at lines 382-388, and
OrganizationProfile/BaseOrganizationProfile.tsx at lines 522-528: treat a
translation result equal to its lookup key as unresolved, then use the
corresponding title, subtitle, name, handle, or description fallback. Preserve
translated values when they differ from their keys.
In
`@packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.styles.ts`:
- Around line 49-53: Preserve the style contract between
BaseOrganizationList.styles and BaseOrganizationList by either restoring the
headerInfo key in the returned styles map or removing the styles['headerInfo']
consumer from the result-count container. Ensure the summary layout retains its
intended styling and no stale class reference remains.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: feb44e26-80e8-436c-a201-378789bde4e1
📒 Files selected for processing (8)
packages/i18n/src/models/i18n.tspackages/i18n/src/translations/en-US.tspackages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.styles.tspackages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsxpackages/react/src/components/presentation/OrganizationList/BaseOrganizationList.styles.tspackages/react/src/components/presentation/OrganizationList/BaseOrganizationList.tsxpackages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.styles.tspackages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.tsx
c71aae6 to
1b66b67
Compare
1b66b67 to
3826fb3
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsx`:
- Around line 224-279: Associate each InputLabel with its corresponding control
in the organization form: add matching unique IDs to the name TextField, handle
TextField, and description textarea, and set each InputLabel’s htmlFor to the
respective ID. Preserve the existing validation, values, and event handlers.
In
`@packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.tsx`:
- Line 198: Restore the default title in BaseOrganizationProfile by assigning
the optional title a fallback of "Organization Profile" (or the established
translated fallback) before popup mode renders DialogPrimitive.Heading. Preserve
explicitly provided titles and ensure omitted titles produce the previous
heading.
- Around line 530-533: Update the heading and subheading render expressions in
BaseOrganizationProfile so explicit title and subheading props are used directly
when provided, with getTranslation serving only as the fallback for absent
values. Preserve the existing default strings for cases where neither a prop nor
translation value is available.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2584675b-d090-451e-a93c-486c2af77247
📒 Files selected for processing (8)
packages/i18n/src/models/i18n.tspackages/i18n/src/translations/en-US.tspackages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.styles.tspackages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsxpackages/react/src/components/presentation/OrganizationList/BaseOrganizationList.styles.tspackages/react/src/components/presentation/OrganizationList/BaseOrganizationList.tsxpackages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.styles.tspackages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
- packages/i18n/src/translations/en-US.ts
- packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.styles.ts
- packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.styles.ts
- packages/i18n/src/models/i18n.ts
- packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.styles.ts
- packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.tsx
| <div className={cx(styles['field'])}> | ||
| <InputLabel required className={cx(styles['label'])}> | ||
| {getTranslation('elements.fields.organization.name.label', 'Organization Name')} | ||
| </InputLabel> | ||
| <div className={cx(styles['fieldGroup'])}> | ||
| <TextField | ||
| placeholder={getTranslation('elements.fields.organization.name.placeholder', 'Organization Name')} | ||
| value={formData.name} | ||
| onChange={(e: ChangeEvent<HTMLInputElement>): void => handleNameChange(e.target.value)} | ||
| disabled={loading} | ||
| required | ||
| error={formErrors.name} | ||
| className={cx(styles['input'])} | ||
| /> | ||
| </div> | ||
| </div> | ||
| <div className={cx(styles['fieldGroup'])}> | ||
| <FormControl error={formErrors.description}> | ||
| <InputLabel required>{t('elements.fields.organization.description.label')}</InputLabel> | ||
| <textarea | ||
| className={cx(styles['textarea'], formErrors.description && styles['textareaError'])} | ||
| placeholder={t('organization.create.description.placeholder')} | ||
| value={formData.description} | ||
| onChange={(e: ChangeEvent<HTMLTextAreaElement>): void => | ||
| handleInputChange('description', e.target.value) | ||
| } | ||
|
|
||
| <div className={cx(styles['field'])}> | ||
| <InputLabel required className={cx(styles['label'])}> | ||
| {getTranslation('elements.fields.organization.handle.label', 'Organization Handle')} | ||
| </InputLabel> | ||
| <div className={cx(styles['fieldGroup'])}> | ||
| <TextField | ||
| placeholder={getTranslation('elements.fields.organization.handle.placeholder', 'my-organization')} | ||
| value={formData.handle} | ||
| onChange={(e: ChangeEvent<HTMLInputElement>): void => handleInputChange('handle', e.target.value)} | ||
| disabled={loading} | ||
| required | ||
| error={formErrors.handle} | ||
| helperText="This will be your organization's unique identifier. Only lowercase letters, numbers, and hyphens are allowed." | ||
| className={cx(styles['input'])} | ||
| /> | ||
| </FormControl> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className={cx(styles['field'])}> | ||
| <InputLabel required className={cx(styles['label'])}> | ||
| {getTranslation('elements.fields.organization.description.label', 'Organization Description')} | ||
| </InputLabel> | ||
| <div className={cx(styles['fieldGroup'])}> | ||
| <FormControl error={formErrors.description}> | ||
| <textarea | ||
| className={cx(styles['textarea'], formErrors.description && styles['textareaError'])} | ||
| placeholder={getTranslation( | ||
| 'organization.create.description.placeholder', | ||
| 'Enter organization description', | ||
| )} | ||
| value={formData.description} | ||
| onChange={(e: ChangeEvent<HTMLTextAreaElement>): void => | ||
| handleInputChange('description', e.target.value) | ||
| } | ||
| disabled={loading} | ||
| required | ||
| /> | ||
| </FormControl> | ||
| </div> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Associate each label with its input.
InputLabel now renders as a sibling <label> without htmlFor; the controls have no matching IDs. Label clicks will not focus the fields, and assistive technology cannot reliably derive their names.
Proposed fix
- <InputLabel required className={cx(styles['label'])}>
+ <InputLabel required htmlFor="organization-name" className={cx(styles['label'])}>
...
<TextField
+ id="organization-name"
...
- <InputLabel required className={cx(styles['label'])}>
+ <InputLabel required htmlFor="organization-handle" className={cx(styles['label'])}>
...
<TextField
+ id="organization-handle"
...
- <InputLabel required className={cx(styles['label'])}>
+ <InputLabel required htmlFor="organization-description" className={cx(styles['label'])}>
...
<textarea
+ id="organization-description"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div className={cx(styles['field'])}> | |
| <InputLabel required className={cx(styles['label'])}> | |
| {getTranslation('elements.fields.organization.name.label', 'Organization Name')} | |
| </InputLabel> | |
| <div className={cx(styles['fieldGroup'])}> | |
| <TextField | |
| placeholder={getTranslation('elements.fields.organization.name.placeholder', 'Organization Name')} | |
| value={formData.name} | |
| onChange={(e: ChangeEvent<HTMLInputElement>): void => handleNameChange(e.target.value)} | |
| disabled={loading} | |
| required | |
| error={formErrors.name} | |
| className={cx(styles['input'])} | |
| /> | |
| </div> | |
| </div> | |
| <div className={cx(styles['fieldGroup'])}> | |
| <FormControl error={formErrors.description}> | |
| <InputLabel required>{t('elements.fields.organization.description.label')}</InputLabel> | |
| <textarea | |
| className={cx(styles['textarea'], formErrors.description && styles['textareaError'])} | |
| placeholder={t('organization.create.description.placeholder')} | |
| value={formData.description} | |
| onChange={(e: ChangeEvent<HTMLTextAreaElement>): void => | |
| handleInputChange('description', e.target.value) | |
| } | |
| <div className={cx(styles['field'])}> | |
| <InputLabel required className={cx(styles['label'])}> | |
| {getTranslation('elements.fields.organization.handle.label', 'Organization Handle')} | |
| </InputLabel> | |
| <div className={cx(styles['fieldGroup'])}> | |
| <TextField | |
| placeholder={getTranslation('elements.fields.organization.handle.placeholder', 'my-organization')} | |
| value={formData.handle} | |
| onChange={(e: ChangeEvent<HTMLInputElement>): void => handleInputChange('handle', e.target.value)} | |
| disabled={loading} | |
| required | |
| error={formErrors.handle} | |
| helperText="This will be your organization's unique identifier. Only lowercase letters, numbers, and hyphens are allowed." | |
| className={cx(styles['input'])} | |
| /> | |
| </FormControl> | |
| </div> | |
| </div> | |
| <div className={cx(styles['field'])}> | |
| <InputLabel required className={cx(styles['label'])}> | |
| {getTranslation('elements.fields.organization.description.label', 'Organization Description')} | |
| </InputLabel> | |
| <div className={cx(styles['fieldGroup'])}> | |
| <FormControl error={formErrors.description}> | |
| <textarea | |
| className={cx(styles['textarea'], formErrors.description && styles['textareaError'])} | |
| placeholder={getTranslation( | |
| 'organization.create.description.placeholder', | |
| 'Enter organization description', | |
| )} | |
| value={formData.description} | |
| onChange={(e: ChangeEvent<HTMLTextAreaElement>): void => | |
| handleInputChange('description', e.target.value) | |
| } | |
| disabled={loading} | |
| required | |
| /> | |
| </FormControl> | |
| </div> | |
| <div className={cx(styles['field'])}> | |
| <InputLabel required htmlFor="organization-name" className={cx(styles['label'])}> | |
| {getTranslation('elements.fields.organization.name.label', 'Organization Name')} | |
| </InputLabel> | |
| <div className={cx(styles['fieldGroup'])}> | |
| <TextField | |
| id="organization-name" | |
| placeholder={getTranslation('elements.fields.organization.name.placeholder', 'Organization Name')} | |
| value={formData.name} | |
| onChange={(e: ChangeEvent<HTMLInputElement>): void => handleNameChange(e.target.value)} | |
| disabled={loading} | |
| required | |
| error={formErrors.name} | |
| className={cx(styles['input'])} | |
| /> | |
| </div> | |
| </div> | |
| <div className={cx(styles['field'])}> | |
| <InputLabel required htmlFor="organization-handle" className={cx(styles['label'])}> | |
| {getTranslation('elements.fields.organization.handle.label', 'Organization Handle')} | |
| </InputLabel> | |
| <div className={cx(styles['fieldGroup'])}> | |
| <TextField | |
| id="organization-handle" | |
| placeholder={getTranslation('elements.fields.organization.handle.placeholder', 'my-organization')} | |
| value={formData.handle} | |
| onChange={(e: ChangeEvent<HTMLInputElement>): void => handleInputChange('handle', e.target.value)} | |
| disabled={loading} | |
| required | |
| error={formErrors.handle} | |
| helperText="This will be your organization's unique identifier. Only lowercase letters, numbers, and hyphens are allowed." | |
| className={cx(styles['input'])} | |
| /> | |
| </div> | |
| </div> | |
| <div className={cx(styles['field'])}> | |
| <InputLabel required htmlFor="organization-description" className={cx(styles['label'])}> | |
| {getTranslation('elements.fields.organization.description.label', 'Organization Description')} | |
| </InputLabel> | |
| <div className={cx(styles['fieldGroup'])}> | |
| <FormControl error={formErrors.description}> | |
| <textarea | |
| id="organization-description" | |
| className={cx(styles['textarea'], formErrors.description && styles['textareaError'])} | |
| placeholder={getTranslation( | |
| 'organization.create.description.placeholder', | |
| 'Enter organization description', | |
| )} | |
| value={formData.description} | |
| onChange={(e: ChangeEvent<HTMLTextAreaElement>): void => | |
| handleInputChange('description', e.target.value) | |
| } | |
| disabled={loading} | |
| required | |
| /> | |
| </FormControl> | |
| </div> | |
| </div> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsx`
around lines 224 - 279, Associate each InputLabel with its corresponding control
in the organization form: add matching unique IDs to the name TextField, handle
TextField, and description textarea, and set each InputLabel’s htmlFor to the
respective ID. Preserve the existing validation, values, and event handlers.
| organization, | ||
| title = 'Organization Profile', | ||
| preferences, | ||
| title, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Restore the default title for popup mode.
title is now optional without a default, but popup mode still renders it directly in DialogPrimitive.Heading at Line 554. Callers that omit title will receive an empty dialog heading. Preserve the previous fallback by defaulting title to "Organization Profile" or applying the translated fallback in popup mode.
Proposed fix
- title,
+ title = 'Organization Profile',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| title, | |
| title = 'Organization Profile', |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.tsx`
at line 198, Restore the default title in BaseOrganizationProfile by assigning
the optional title a fallback of "Organization Profile" (or the established
translated fallback) before popup mode renders DialogPrimitive.Heading. Preserve
explicitly provided titles and ensure omitted titles produce the previous
heading.
| {getTranslation('organization.profile.heading', title || 'Organization Profile')} | ||
| </Typography> | ||
| <Typography variant="body2" color="textSecondary" className={cx(styles['subtitle'])}> | ||
| {getTranslation('organization.profile.subheading', subheading || 'Manage your organization details.')} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Let explicit title and subheading props override translations.
These props are documented as custom values, but getTranslation receives them only as fallbacks. As a result, the bundled organization.profile.heading and organization.profile.subheading translations always win whenever they exist, making caller-provided overrides ineffective.
Proposed fix
- {getTranslation('organization.profile.heading', title || 'Organization Profile')}
+ {title || getTranslation('organization.profile.heading', 'Organization Profile')}
...
- {getTranslation('organization.profile.subheading', subheading || 'Manage your organization details.')}
+ {subheading || getTranslation('organization.profile.subheading', 'Manage your organization details.')}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {getTranslation('organization.profile.heading', title || 'Organization Profile')} | |
| </Typography> | |
| <Typography variant="body2" color="textSecondary" className={cx(styles['subtitle'])}> | |
| {getTranslation('organization.profile.subheading', subheading || 'Manage your organization details.')} | |
| {title || getTranslation('organization.profile.heading', 'Organization Profile')} | |
| </Typography> | |
| <Typography variant="body2" color="textSecondary" className={cx(styles['subtitle'])}> | |
| {subheading || getTranslation('organization.profile.subheading', 'Manage your organization details.')} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.tsx`
around lines 530 - 533, Update the heading and subheading render expressions in
BaseOrganizationProfile so explicit title and subheading props are used directly
when provided, with getTranslation serving only as the fallback for absent
values. Preserve the existing default strings for cases where neither a prop nor
translation value is available.
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. |
Purpose
This PR addresses layout alignment, header typography, and form field structure issues in the
@asgardeo/reactSDK presentation components (CreateOrganization,OrganizationProfile, andOrganizationList).Key changes introduced in
@asgardeo/react:h5heading) and Subtitle (body2textSecondary) using<Typography>primitives, matching design tokens (1.75remtitle,margin-bottom), and a horizontal divider line (border-bottom) across<CreateOrganization />,<OrganizationProfile />, and<OrganizationList />.<CreateOrganization />form fields into a side-by-side left-aligned layout with200pxwhite-space: nowraplabels and expanding inputs.<label>markup with the<InputLabel required>primitive component.<OrganizationProfile />avatar, title, handle, labels (160pxwidth), and field values are strictly left-aligned.@asgardeo/i18n.fieldLast,fieldContent,avatarContainer,required) while preserving existing return keys for backward compatibility.Screenshots
Related Issues
Related PRs
Checklist
Security checks
Summary by CodeRabbit