fix titleless Admonition alignment (#48784)

## What kind of change does this PR introduce?

UI bug fix.

## What is the current behavior?

Titleless Admonitions using the `description` prop place their compact
body text slightly too high beside the icon. Admonition bodies also
inherit a 2px bottom margin from `AlertDescription`, making the vertical
spacing subtly uneven.

## What is the new behavior?

Titleless `description` content receives a small optical offset,
centring a one-line description beside the icon. Rich MDX children
retain their natural top alignment because Docs prose uses a taller line
height.

Admonition bodies also remove the inherited 2px bottom margin, balancing
the surrounding space without changing the shared `AlertDescription`
primitive.

| Before | After |
| --- | --- |
| <img width="1856" height="856" alt="CleanShot 2026-08-05 at 17 52
34@2x"
src="https://github.com/user-attachments/assets/5f8fb726-692a-4a63-ab37-8fe87f37edd6"
/> | <img width="1676" height="850" alt="CleanShot 2026-08-06 at 12 05
18@2x"
src="https://github.com/user-attachments/assets/9d9126fe-50ef-422c-b387-7a45550e73dd"
/> |
|_Note the imbalanced space under the text_ | _Note how the text is
balanced vertically to the icon_ |

## To test

- [Design System:
Admonition](https://design-system-git-dnywh-fix-titleless-admonitio-db462e-supabase.vercel.app/design-system/docs/fragments/admonition):
the description-only reference example, at desktop and mobile widths.
- [Studio: Project Settings >
Dashboard](https://studio-staging-git-dnywh-fix-titleless-admoniti-908cb8-supabase.vercel.app/dashboard/project/_/settings/dashboard):
the Dashboard preferences notice. The dashboardPreferences feature flag
must be enabled.
- [Docs: Local Development &
CLI](https://docs-git-dnywh-fix-titleless-admonition-alignment-supabase.vercel.app/docs/guides/local-development):
the titleless container-runtime callout near the top of the page.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
  * Improved admonition spacing for descriptions and MDX content.
  * Removed unintended bottom spacing within admonition bodies.
* Adjusted vertical spacing for untitled admonitions while preserving
titled content layout.

* **Tests**
* Added coverage for paragraph spacing, wrapper structure, and
title-specific styling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Danny White authored and GitHub committed 2026-08-07 10:47:07 +10:00
1 parent 5944fe66f0
commit df35577adc
2 files changed
+27 -4

No files matched your search

@@ -135,7 +135,11 @@ describe('Admonition', () => {
render(<Admonition type="note" description="Body copy." />)
const note = screen.getByRole('alert', { name: 'Note' })
expect(within(note).getByText('Body copy.').tagName).toBe('P')
const description = within(note).getByText('Body copy.')
expect(description.tagName).toBe('P')
expect(description.parentElement).toHaveClass('!mb-0')
expect(description.parentElement?.parentElement).toHaveClass('my-0.5')
})
it('wraps MDX children in AlertDescription', () => {
@@ -149,7 +153,26 @@ describe('Admonition', () => {
const paragraph = within(note).getByText('Children body copy.')
expect(paragraph.tagName).toBe('P')
expect(paragraph.parentElement).toHaveClass('text-sm')
expect(paragraph.parentElement).toHaveClass('text-sm', '!mb-0')
expect(paragraph.parentElement).toHaveAttribute('data-slot', 'alert-description')
expect(paragraph.parentElement?.parentElement).not.toHaveClass('my-0.5')
})
it('does not offset titled content', () => {
render(<Admonition type="note" title="Manual approval required" description="Body copy." />)
const note = screen.getByRole('alert', { name: 'Note' })
const title = within(note).getByText('Manual approval required')
expect(title.parentElement).not.toHaveClass('my-0.5')
})
it('does not offset titleless content when the icon is hidden', () => {
render(<Admonition type="note" showIcon={false} description="Body copy." />)
const note = screen.getByRole('alert', { name: 'Note' })
const description = within(note).getByText('Body copy.')
expect(description.parentElement?.parentElement).not.toHaveClass('my-0.5')
})
})
@@ -8,7 +8,7 @@ import { AdmonitionTypeIcon } from './AdmonitionIcons'
export type { AdmonitionLayout, AdmonitionProps, AdmonitionType }
const admonitionBodyClassName =
'[&_p]:!mt-0 [&_p]:!mb-1.5 [&_p:last-child]:!mb-0 [&_ul]:!my-1.5 [&_ol]:!my-1.5 [&_li]:!my-0.5'
'!mb-0 [&_p]:!mt-0 [&_p]:!mb-1.5 [&_p:last-child]:!mb-0 [&_ul]:!my-1.5 [&_ol]:!my-1.5 [&_li]:!my-0.5'
export const Admonition = forwardRef<
React.ComponentRef<typeof Alert>,
@@ -69,7 +69,7 @@ export const Admonition = forwardRef<
]
)}
>
<div>
<div className={cn(showIcon && !title && description && 'my-0.5')}>
{title && (
<AlertTitle
{...childProps?.title}