Skip to content

fix(react): resolve B2B presentation components styling and layout issues#536

Merged
brionmario merged 1 commit into
asgardeo:mainfrom
janithjay:fix/style-issues
Jul 24, 2026
Merged

fix(react): resolve B2B presentation components styling and layout issues#536
brionmario merged 1 commit into
asgardeo:mainfrom
janithjay:fix/style-issues

Conversation

@janithjay

@janithjay janithjay commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Purpose

This PR addresses layout alignment, header typography, and form field structure issues in the @asgardeo/react SDK presentation components (CreateOrganization, OrganizationProfile, and OrganizationList).

Key changes introduced in @asgardeo/react:

  • Standardized Header Section: Added consistent Title (h5 heading) and Subtitle (body2 textSecondary) using <Typography> primitives, matching design tokens (1.75rem title, margin-bottom), and a horizontal divider line (border-bottom) across <CreateOrganization />, <OrganizationProfile />, and <OrganizationList />.
  • Side-by-Side Field Layout: Refactored <CreateOrganization /> form fields into a side-by-side left-aligned layout with 200px white-space: nowrap labels and expanding inputs.
  • Primitive Integration: Replaced manual asterisk spans and raw <label> markup with the <InputLabel required> primitive component.
  • Left Alignment in Profile: Ensured <OrganizationProfile /> avatar, title, handle, labels (160px width), and field values are strictly left-aligned.
  • i18n Support: Added missing subheading, heading, and placeholder translation keys in @asgardeo/i18n.
  • Code Cleanup: Removed all unused style definitions (fieldLast, fieldContent, avatarContainer, required) while preserving existing return keys for backward compatibility.

Screenshots

image image image

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the CONTRIBUTING guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Unit tests provided. (Add links if there are any)

Security checks

Summary by CodeRabbit

  • New Features
    • Added new localized organization UI text, including name/handle placeholders and organization creation/list/profile headings and subtitles.
    • Organization list/profile/create screens now support optional subtitles/subheadings in non-popup mode, with automatic fallback to provided/default text when translations are missing.
    • Translation fields for several organization-related labels are now optional to improve resilience.
  • Style
    • Refreshed organization create/list/profile layouts with improved header structure, left-aligned label styling, updated typography/spacing, and enhanced textarea focus styling (including transitions).

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Organization translation contracts and English strings were expanded, while create, list, and profile components gained localized headings, subheadings, and updated presentation styles.

Changes

Organization UI localization

Layer / File(s) Summary
Organization translation contracts and English strings
packages/i18n/src/models/i18n.ts, packages/i18n/src/translations/en-US.ts
Organization placeholders, headings, subheadings, and creation text were added or made optional in the translation model and English translations.
Create organization header and form layout
packages/react/src/components/presentation/CreateOrganization/*
The create form now renders localized heading content with explicit input labels, helper text, and revised field and textarea styling.
Organization list header
packages/react/src/components/presentation/OrganizationList/*
The list accepts an optional subheading and renders localized title and subtitle content with updated header styles.
Organization profile header
packages/react/src/components/presentation/OrganizationProfile/*
The profile accepts an optional subheading, uses component i18n preferences, and renders localized header content with revised layout styles.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: fixing styling and layout issues in React presentation components.
Description check ✅ Passed The description follows the template well, covering purpose, issues, related PRs, checklist, security checks, and screenshots.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@janithjay
janithjay marked this pull request as ready for review July 24, 2026 02:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 24c36b4 and c71aae6.

📒 Files selected for processing (8)
  • packages/i18n/src/models/i18n.ts
  • packages/i18n/src/translations/en-US.ts
  • packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.styles.ts
  • packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsx
  • packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.styles.ts
  • packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.tsx
  • packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.styles.ts
  • packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.tsx

Comment thread packages/i18n/src/translations/en-US.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1b66b67 and 3826fb3.

📒 Files selected for processing (8)
  • packages/i18n/src/models/i18n.ts
  • packages/i18n/src/translations/en-US.ts
  • packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.styles.ts
  • packages/react/src/components/presentation/CreateOrganization/BaseCreateOrganization.tsx
  • packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.styles.ts
  • packages/react/src/components/presentation/OrganizationList/BaseOrganizationList.tsx
  • packages/react/src/components/presentation/OrganizationProfile/BaseOrganizationProfile.styles.ts
  • packages/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

Comment on lines +224 to +279
<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>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 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.

Suggested change
<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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 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.

Suggested change
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.

Comment on lines +530 to +533
{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.')}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 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.

Suggested change
{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.

@brionmario
brionmario merged commit 135717e into asgardeo:main Jul 24, 2026
7 of 9 checks passed
@asgardeo-github-bot

Copy link
Copy Markdown

⚠️ No Changeset found

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.

If these changes should result in a version bump, you need to add a changeset.

Refer Release Documentation to learn how to add a changeset.

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.

3 participants