Files
Danny White 476d4a5851 refactor(ui): drop redundant Button variant="default" props (#50161)
## What kind of change does this PR introduce?

Mechanical cleanup on top of the Button default-variant change (#50160).

## What is the current behavior?

Many callsites still pass `variant="default"` even though that is now
the component default.

## What is the new behavior?

Removes redundant static `variant="default"` from legacy `Button` and
`ButtonTooltip` callsites. Keeps explicit defaults where they document
the API:

- `button-default.tsx` and `button-sizes.tsx` demos
- `DocsButton`, which pins neutral styling at the wrapper boundary

## To test

Studio:

- [Auth → Rate
Limits](https://studio-staging-2s957kwc4-supabase.vercel.app/dashboard/project/_/auth/rate-limits):
dirty the form so Cancel appears; Cancel stays neutral, Save stays green
- [Project Settings → API
Keys](https://studio-staging-2s957kwc4-supabase.vercel.app/dashboard/project/_/settings/api-keys):
`DocsButton` in the header actions stays neutral

Design system:

- [Design system →
Button](https://design-system-git-dnywh-dc924ac1-supabase.vercel.app/design-system/docs/components/button):
`button-default` / `button-sizes` still show explicit default styling;
Primary (green) is restricted to the Primary section (and `asChild`)

WWW:

- [www → Brand
assets](https://zone-www-dot-com-git-dnywh-dc924ac1-supabase.vercel.app/brand-assets):
Download logo kit / Download button kit stay neutral
2026-09-11 17:05:26 +10:00

101 lines
3.0 KiB
TypeScript

import { noop } from 'lodash'
import { PropsWithChildren, useCallback, useState } from 'react'
import { Button, KeyboardShortcut } from 'ui'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
interface ActionBarProps {
loading?: boolean
disableApply?: boolean
hideApply?: boolean
applyButtonLabel?: string
backButtonLabel?: string
applyFunction?: (resolve: any) => void
closePanel: () => void
formId?: string
visible?: boolean
}
export const ActionBar = ({
loading = false,
disableApply = false,
hideApply = false,
children = undefined,
applyButtonLabel = 'Apply',
backButtonLabel = 'Back',
applyFunction = undefined,
closePanel = noop,
formId,
visible = true,
}: PropsWithChildren<ActionBarProps>) => {
const [isRunning, setIsRunning] = useState(false)
const onSelectApply = useCallback(async () => {
const applyCallback = () => new Promise((resolve) => applyFunction?.(resolve))
setIsRunning(true)
await applyCallback()
setIsRunning(false)
}, [applyFunction])
const handleSave = useCallback(() => {
if (isRunning || loading || disableApply || hideApply) return
if (formId) {
const form = document.getElementById(formId) as HTMLFormElement | null
if (form) {
form.requestSubmit()
}
} else if (applyFunction) {
onSelectApply()
}
}, [isRunning, loading, disableApply, hideApply, formId, applyFunction, onSelectApply])
useShortcut(SHORTCUT_IDS.ACTION_BAR_SAVE, handleSave, { enabled: visible })
return (
<div className="flex w-full items-center gap-3 border-t border-default px-3 py-4">
{children}
<div className="flex items-center gap-3 ml-auto">
<Button type="button" onClick={closePanel} disabled={isRunning || loading}>
{backButtonLabel}
</Button>
{applyFunction !== undefined ? (
// Old solution, necessary when loading is handled by this component itself
<Button
onClick={onSelectApply}
disabled={disableApply || isRunning || loading}
loading={isRunning || loading}
iconRight={
isRunning || loading ? undefined : (
<KeyboardShortcut keys={['Meta', 'Enter']} variant="inline" />
)
}
>
{applyButtonLabel}
</Button>
) : !hideApply ? (
// New solution, when using the Form component, loading is handled by the Form itself
// Does not require applyFunction() callback
<Button
disabled={loading || disableApply}
loading={loading}
data-testid="action-bar-save-row"
type="submit"
form={formId}
iconRight={
loading ? undefined : <KeyboardShortcut keys={['Meta', 'Enter']} variant="inline" />
}
>
{applyButtonLabel}
</Button>
) : (
<div />
)}
</div>
</div>
)
}