Revert "chore(studio + design-system): more flexible Admonition" (#45535)

This commit is contained in:
Jeremias Menichelli authored and GitHub committed 2026-05-05 00:18:27 +08:00
1 parent 73cdf2ddd1
commit c49eb8bb7d
23 files changed
+69 -217

No files matched your search

-22
View File
@@ -126,17 +126,6 @@ export const Index: Record<string, any> = {
subcategory: "undefined",
chunks: []
},
"admonition-description-only": {
name: "admonition-description-only",
type: "components:example",
registryDependencies: ["admonition"],
component: React.lazy(() => import("@/registry/default/example/admonition-description-only")),
source: "",
files: ["registry/default/example/admonition-description-only.tsx"],
category: "undefined",
subcategory: "undefined",
chunks: []
},
"admonition-warning": {
name: "admonition-warning",
type: "components:example",
@@ -148,17 +137,6 @@ export const Index: Record<string, any> = {
subcategory: "undefined",
chunks: []
},
"admonition-success": {
name: "admonition-success",
type: "components:example",
registryDependencies: ["admonition"],
component: React.lazy(() => import("@/registry/default/example/admonition-success")),
source: "",
files: ["registry/default/example/admonition-success.tsx"],
category: "undefined",
subcategory: "undefined",
chunks: []
},
"admonition-destructive": {
name: "admonition-destructive",
type: "components:example",
@@ -15,12 +15,6 @@ Admonition provides focus for situations that require a callout.
Use Admonition instead of [Alert](../components/alert) unless you specifically need the primitives. If in doubt, stick with Admonition.
Use `title` for the heading slot and `description` for short body copy. The `description` should always end in a period.
Use `children` instead of `description` when the body needs rich React or MDX content such as links, lists, or multiple paragraphs, and this cannot be achieved via a React Fragment as a `description` value.
Avoid `label` in new code. It is a legacy alias for `title` that still exists for older docs content.
## Usage
```tsx
@@ -53,7 +47,7 @@ Only ever use the `primary` (green) button `type` on a `default` Admonition. Eve
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Responsive
## Responsive
Resize your browser to see the button(s) change `layout` based on the Admonition’s width.
@@ -85,24 +79,6 @@ AlertError for example rolls up consistent error handling and support contact me
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Description only
You may omit the title when the Admonition is short and sits near a heading that already provides enough context. Do not do the inverse: a title-only Admonition usually reads like an incomplete sentence and should include supporting description copy.
<ComponentPreview
name="admonition-description-only"
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Success
Use `success` strictly for positive, completed states where the user does not need to take corrective action.
<ComponentPreview
name="admonition-success"
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Sandwiched
Some [Card](../components/card) or [Dialog](../components/dialog) instances may need to include callout information in-between core content. Admonition can be used ‘full-bleed’ in these cases by removing borders and radii.
@@ -1,10 +0,0 @@
import { Admonition } from 'ui-patterns/admonition'
export default function AdmonitionDescriptionOnly() {
return (
<Admonition
type="default"
description="Changes to these settings can take a few minutes to appear across all projects."
/>
)
}
@@ -1,11 +0,0 @@
import { Admonition } from 'ui-patterns/admonition'
export default function AdmonitionSuccess() {
return (
<Admonition
type="success"
title="Success"
description="Your connection has been confirmed. You can now close this tab."
/>
)
}
-12
View File
@@ -25,24 +25,12 @@ export const examples: Registry = [
registryDependencies: ['admonition'],
files: ['example/admonition-button.tsx'],
},
{
name: 'admonition-description-only',
type: 'components:example',
registryDependencies: ['admonition'],
files: ['example/admonition-description-only.tsx'],
},
{
name: 'admonition-warning',
type: 'components:example',
registryDependencies: ['admonition'],
files: ['example/admonition-warning.tsx'],
},
{
name: 'admonition-success',
type: 'components:example',
registryDependencies: ['admonition'],
files: ['example/admonition-success.tsx'],
},
{
name: 'admonition-destructive',
type: 'components:example',
+1 -1
View File
@@ -5,7 +5,7 @@
@import './../../../packages/ui/build/css/themes/classic-dark.css';
@import './../../../packages/ui/build/css/themes/light.css';
@config '../tailwind.config.cjs';
@config '../tailwind.config.js';
@import 'config/typography.css';
File renamed without changes.
@@ -181,7 +181,7 @@ export const UserOverview = ({ user, onDeleteSuccess }: UserOverviewProps) => {
{isBanned ? (
<Admonition
type="warning"
description={`User banned until ${dayjs(user.banned_until).format(DATE_FORMAT)}`}
label={`User banned until ${dayjs(user.banned_until).format(DATE_FORMAT)}`}
className="border-r-0 border-l-0 rounded-none -mt-px [&_svg]:ml-0.5"
/>
) : (
@@ -74,17 +74,16 @@ export const PublicationsTables = () => {
/>
</div>
</div>
{!isLoadingPermissions && !canUpdatePublications && (
<Admonition
type="note"
className="w-[500px]"
title="You need additional permissions to update database replications"
/>
)}
</div>
</div>
{!isLoadingPermissions && !canUpdatePublications && (
<Admonition
type="warning"
className="mb-4 w-full"
description="You need additional permissions to update database replications."
/>
)}
{(isLoading || isLoadingPermissions) && (
<div className="mt-8">
<LogoLoader />
@@ -653,26 +653,21 @@ export const AnalyticsBucketFields = ({
</p>
{isSuccessKeys && keyNoLongerExists && (
<Admonition
type="warning"
title="Unable to find access key ID in project"
description={
<>
Please select another key or create a new set, as this destination will
not work otherwise. S3 access keys can be managed in your{' '}
<InlineLink href={`/project/${projectRef}/storage/files/settings`}>
storage settings
</InlineLink>
.
</>
}
/>
<Admonition type="warning" title="Unable to find access key ID in project">
<p className="leading-normal!">
Please select another key or create a new set, as this destination will not
work otherwise. S3 access keys can be managed in your{' '}
<InlineLink href={`/project/${projectRef}/storage/files/settings`}>
storage settings
</InlineLink>
</p>
</Admonition>
)}
{s3AccessKeyId === CREATE_NEW_KEY && (
<Admonition
type="default"
description="A new set of S3 access keys will be created."
title="A new set of S3 access keys will be created"
/>
)}
</div>
@@ -738,7 +733,7 @@ export const AnalyticsBucketFields = ({
layout="horizontal"
label="S3 Secret Access Key"
className="relative"
description="The secret key corresponding to your selected access key ID."
description="The secret key corresponding to your selected access key ID"
>
<FormControl>
<Input_Shadcn_
@@ -136,7 +136,7 @@ export const RestoreToNewProject = () => {
return (
<Admonition
type="default"
description="Restoring to new projects is temporarily not available for AWS (Revamped) projects."
title="Restoring to new projects is temporarily not available for AWS (Revamped) projects"
/>
)
}
@@ -278,7 +278,7 @@ export const QueueSettings = ({}: QueueSettingsProps) => {
<Admonition
type="default"
className="rounded-none border-x-0 border-t-0"
description="Only relevant roles for managing queues via client libraries or PostgREST are shown here."
title="Only relevant roles for managing queues via client libraries or PostgREST are shown here"
/>
)}
<Table>
@@ -32,7 +32,7 @@ export const StripeSyncSettingsPage = () => {
return (
<PageContainer className="mx-0">
<PageSection>
<Admonition type="default" description="Stripe Sync Engine is not installed." />
<Admonition type="default" title="Stripe Sync Engine is not installed" />
</PageSection>
</PageContainer>
)
@@ -73,7 +73,7 @@ export const OrganizationInvite = () => {
<Admonition
showIcon={false}
type="default"
description={`Sign in${isSignUpEnabled ? ' or create an account' : ''} first to view this invitation.`}
title={`Sign in${isSignUpEnabled ? ' or create an account' : ''} first to view this invitation`}
className="border-0 rounded-none text-left"
/>
<div className="p-4 border-muted border-t flex gap-x-3 justify-center">
@@ -272,7 +272,7 @@ export const PostgrestConfig = () => {
</CardContent>
) : isError ? (
<CardContent>
<Admonition type="destructive" description="Failed to retrieve API settings." />
<Admonition type="destructive" title="Failed to retrieve API settings" />
</CardContent>
) : (
<>
@@ -161,7 +161,7 @@ const IPv4SidePanel = () => {
{!isAws && (
<Admonition
type="default"
description="Dedicated IPv4 address is only available for AWS projects."
title="Dedicated IPv4 address is only available for AWS projects"
/>
)}
@@ -305,7 +305,7 @@ export function JitDbAccessRuleSheet({
{grants.length === 0 ? (
<Admonition
type="note"
description="No assignable roles found."
title="No assignable roles found"
className="bg-background"
/>
) : (
@@ -96,7 +96,7 @@ export const DashboardPreferences = () => {
{/* [Joshen] Ideally we're able to persist this for all users in the project, but will need support in our middleware */}
<Admonition
type="note"
description="These preferences control only your experience in the dashboard. Other members of this project will not be affected."
title="These preferences control only your experience in the dashboard. Other members of this project will not be affected"
/>
{isLoading ? (
@@ -42,9 +42,7 @@ export function ProjectAndPlanInfo({
<ProjectSelector form={form} orgSlug={orgSlug} projectRef={projectRef} />
<ProjectRefHighlighted projectRef={projectRef} />
{!hasProjectSelected && (
<Admonition type="default" description="No project has been selected." />
)}
{!hasProjectSelected && <Admonition type="default" title="No project has been selected" />}
{showPlanExpectationInfo &&
orgSlug &&
@@ -403,10 +403,7 @@ const SchemaExposureOptions = ({
return (
<>
{isError && (
<Admonition
type="warning"
description="An error occurred while fetching Data API settings."
/>
<Admonition type="warning" title="An error occurred while fetching Data API settings." />
)}
{isSchemaExposed && apiUrl && (
+1 -1
View File
@@ -73,7 +73,7 @@ const CliLoginPage: NextPageWithLayout = () => {
</p>
<Admonition
type="tip"
description="Browser login flow requires Supabase CLI version 1.219.0 and above."
title="Browser login flow requires Supabase CLI version 1.219.0 and above."
className="mt-16"
/>
</>
+35 -93
View File
@@ -2,43 +2,19 @@ import { cva } from 'class-variance-authority'
import { ComponentProps, forwardRef, ReactNode } from 'react'
import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, cn } from 'ui'
type AdmonitionType =
| 'note'
| 'tip'
| 'caution'
| 'danger'
| 'deprecation'
| 'default'
| 'destructive'
| 'success'
| 'warning'
type AdmonitionBodyContent =
| {
description: string | ReactNode
children?: ReactNode
}
| {
description?: string | ReactNode
children: ReactNode
}
type AdmonitionContentProps =
| ({
title?: string
/** @deprecated Use title instead. */
label?: string
} & AdmonitionBodyContent)
| {
title?: never
/** @deprecated Use title instead. */
label?: never
description?: string | ReactNode
children?: ReactNode
}
interface AdmonitionBaseProps {
type?: AdmonitionType
export interface AdmonitionProps {
type:
| 'note'
| 'tip'
| 'caution'
| 'danger'
| 'deprecation'
| 'default'
| 'destructive'
| 'warning'
label?: string
title?: string
description?: string | ReactNode
showIcon?: boolean
childProps?: {
title?: ComponentProps<typeof AlertTitle_Shadcn_>
@@ -50,9 +26,10 @@ interface AdmonitionBaseProps {
className?: string
}
export type AdmonitionProps = AdmonitionBaseProps & AdmonitionContentProps
const admonitionToAlertMapping: Record<AdmonitionType, 'default' | 'destructive' | 'warning'> = {
const admonitionToAlertMapping: Record<
AdmonitionProps['type'],
'default' | 'destructive' | 'warning'
> = {
note: 'default',
tip: 'default',
caution: 'warning',
@@ -61,7 +38,6 @@ const admonitionToAlertMapping: Record<AdmonitionType, 'default' | 'destructive'
default: 'default',
warning: 'warning',
destructive: 'destructive',
success: 'default',
}
const InfoIcon = () => (
@@ -79,21 +55,6 @@ const InfoIcon = () => (
</svg>
)
const SuccessIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 21 20"
className="w-6 h-6"
fill="currentColor"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.5 19.5C5.25329 19.5 1 15.2467 1 10C1 4.75329 5.25329 0.5 10.5 0.5C15.7467 0.5 20 4.75329 20 10C20 15.2467 15.7467 19.5 10.5 19.5ZM14.7803 7.78033C15.0732 7.48744 15.0732 7.01256 14.7803 6.71967C14.4874 6.42678 14.0126 6.42678 13.7197 6.71967L9.25 11.1893L7.28033 9.21967C6.98744 8.92678 6.51256 8.92678 6.21967 9.21967C5.92678 9.51256 5.92678 9.98744 6.21967 10.2803L8.71967 12.7803C9.01256 13.0732 9.48744 13.0732 9.78033 12.7803L14.7803 7.78033Z"
/>
</svg>
)
export const WarningIcon = ({ className }: { className?: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -113,20 +74,15 @@ const admonitionSVG = cva('', {
variants: {
type: {
default: `[&>svg]:bg-foreground-muted`,
success: `bg-brand-400 dark:bg-brand bg-opacity-15 dark:bg-opacity-10 border-brand-400 dark:border-brand-500 [&>svg]:text-white dark:[&>svg]:text-brand-link [&>svg]:bg-brand dark:[&>svg]:bg-brand-500/50`,
warning: ``,
destructive: ``,
},
},
})
const admonitionBodyClassName =
'[&_p]:!mt-0 [&_p]:!mb-1.5 [&_p:last-child]:!mb-0 [&_p:only-child]:!mb-0 [&_ul]:!my-1.5 [&_ol]:!my-1.5 [&_li]:!my-0.5'
export const Admonition = forwardRef<
React.ElementRef<typeof Alert_Shadcn_>,
Omit<React.ComponentPropsWithoutRef<typeof Alert_Shadcn_>, keyof AdmonitionProps | 'children'> &
AdmonitionProps
React.ComponentPropsWithoutRef<typeof Alert_Shadcn_> & AdmonitionProps
>(
(
{
@@ -146,11 +102,6 @@ export const Admonition = forwardRef<
ref
) => {
const typeMapped = variant ? admonitionToAlertMapping[variant] : admonitionToAlertMapping[type]
const typeStyle = type === 'success' ? 'success' : typeMapped
if (process.env.NODE_ENV !== 'production' && (label || title) && !description && !children) {
throw new Error('Admonition title-only usage is not supported. Add description or children.')
}
return (
<Alert_Shadcn_
@@ -163,14 +114,12 @@ export const Admonition = forwardRef<
// Container query context for responsive layout
layout === 'responsive' && '@container',
// SVG icon
admonitionSVG({ type: typeStyle }),
admonitionSVG({ type: typeMapped }),
props.className
)}
>
{!!icon ? (
icon
) : showIcon && typeStyle === 'success' ? (
<SuccessIcon />
) : (showIcon && typeMapped === 'warning') || typeMapped === 'destructive' ? (
<WarningIcon />
) : showIcon ? (
@@ -185,29 +134,20 @@ export const Admonition = forwardRef<
'flex-col @md:flex-row @md:items-center @md:justify-between @md:gap-x-6 @lg:gap-x-8'
)}
>
{label || title || description ? (
{label || title ? (
<div>
{(label || title) && (
<AlertTitle_Shadcn_
{...childProps.title}
className={cn(
'text mt-0.5 flex gap-3 text-sm !font-medium',
!label && 'flex-col',
childProps.title?.className
)}
>
{label || title}
</AlertTitle_Shadcn_>
)}
<AlertTitle_Shadcn_
{...childProps.title}
className={cn(
'text mt-0.5 flex gap-3 text-sm',
!label && 'flex-col',
childProps.title?.className
)}
>
{label || title}
</AlertTitle_Shadcn_>
{description && (
<AlertDescription_Shadcn_
{...childProps.description}
className={cn(
admonitionBodyClassName,
!label && !title && 'my-0.5',
childProps.description?.className
)}
>
<AlertDescription_Shadcn_ className={childProps.description?.className}>
{description}
</AlertDescription_Shadcn_>
)}
@@ -215,14 +155,16 @@ export const Admonition = forwardRef<
{children && (
<AlertDescription_Shadcn_
{...childProps.description}
className={cn(admonitionBodyClassName, childProps?.description?.className)}
className={cn('', childProps?.description?.className)}
>
{children}
</AlertDescription_Shadcn_>
)}
</div>
) : (
<div className={cn('text my-0.5', admonitionBodyClassName)}>{children}</div>
<div className="text my-0.5 [&_p]:mt-0 [&_p]:mb-1.5 [&_p:last-child]:mb-0">
{children}
</div>
)}
{actions && (
<div
@@ -16,9 +16,9 @@ export const alertVariants = cva(
default:
'bg-surface-200/25 border-default text-foreground [&>svg]:text-background [&>svg]:bg-foreground',
destructive:
'bg-destructive-200 border-destructive-400 text-foreground [&>svg]:text-destructive-200 [&>svg]:bg-destructive-600',
'bg-destructive-200 border-destructive-400 [&>svg]:text-destructive-200 [&>svg]:bg-destructive-600',
warning:
'bg-warning-200 border-warning-400 text-foreground [&>svg]:text-warning-200 [&>svg]:bg-warning-600',
'bg-warning-200 border-warning-400 [&>svg]:text-warning-200 [&>svg]:bg-warning-600',
},
},
defaultVariants: {