Improve component sizing for buttons and inputs (#1302)

* style: increase shared control sizing

* style: improve form control sizing

* style: broaden component sizing pass

* style: format component sizing updates

* fix: align grouped control sizing
This commit is contained in:
Parth 2026-07-06 22:46:44 +05:30 committed by GitHub
parent d66f5e9c82
commit a486002a71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 25 additions and 27 deletions

View file

@ -94,7 +94,7 @@ export default function MainWalletPage({ walletFileName }: MainWalletPageProps)
{t('global.errors.error_loading_wallet_failed', {
reason: error.message || t('global.errors.reason_unknown'),
})}
<Button variant="outline" size="sm" onClick={() => void refetchWalletData()}>
<Button variant="outline" onClick={() => void refetchWalletData()}>
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
{t('global.retry')}
</Button>
@ -146,7 +146,7 @@ export default function MainWalletPage({ walletFileName }: MainWalletPageProps)
</div>
</div>
<div className="flex w-full max-w-xl justify-end">
<Button variant="ghost" size="xs" onClick={() => void refetchWalletData()}>
<Button variant="ghost" onClick={() => void refetchWalletData()}>
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
{t('global.refresh')}
</Button>

View file

@ -237,11 +237,11 @@ export function CreateFidelityBondDialogSteps({ wizard }: CreateFidelityBondDial
</div>
<div className="flex flex-wrap gap-2">
<Button variant="outline" size="sm" onClick={selectAllUtxos} className="shadow-sm">
<Button variant="outline" onClick={selectAllUtxos} className="shadow-sm">
<CheckIcon className="mr-1 h-3.5 w-3.5" />
{t('earn.fidelity_bond.select_utxos.button_select_all')}
</Button>
<Button variant="outline" size="sm" onClick={deselectAllUtxos} className="shadow-sm">
<Button variant="outline" onClick={deselectAllUtxos} className="shadow-sm">
{t('earn.fidelity_bond.select_utxos.button_deselect_all')}
</Button>
</div>

View file

@ -223,7 +223,7 @@ export const EarnPage = ({ walletFileName }: EarnPageProps) => {
<PageTitle title={t('earn.title')} subtitle={t('earn.subtitle')} />
<div className="flex justify-end">
<Button variant="outline" size="sm" onClick={() => setShowEarnReport(true)}>
<Button variant="outline" onClick={() => setShowEarnReport(true)}>
<FileTextIcon />
{t('earn.button_show_report')}
</Button>

View file

@ -107,7 +107,7 @@ export const LoginCard = ({
{listWalletsError ? (
<>
<WalletLoadErrorAlert reason={listWalletsError.message} />
<Button variant="ghost" size="sm" onClick={() => void onReloadClick()} disabled={listWalletsFetching}>
<Button variant="ghost" onClick={() => void onReloadClick()} disabled={listWalletsFetching}>
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': listWalletsFetching })} />
{t('global.retry')}
</Button>

View file

@ -50,7 +50,7 @@ export const BitcoinAmountInput = ({
{...inputProps}
/>
</div>
<Button variant="outline" size="sm" className="py-4 whitespace-nowrap" onClick={toggleCurrencyUnit}>
<Button variant="outline" size="lg" className="whitespace-nowrap" onClick={toggleCurrencyUnit}>
{currency === 'sats' ? 'BTC' : 'Sats'}
<ArrowUpDownIcon />
</Button>

View file

@ -364,7 +364,6 @@ export function SendForm({
required: destinationJar === undefined,
disabled,
})}
className="h-auto"
type="text"
placeholder={t('send.placeholder_recipient')}
onPaste={handleAddressPaste}
@ -406,7 +405,7 @@ export function SendForm({
id="send-destination-address-from-jar"
className={cn(
inputVariants(),
'flex min-h-8 min-w-0 flex-col items-start justify-center gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-2',
'flex min-h-10 min-w-0 flex-col items-start justify-center gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-2',
'bg-input/50 dark:bg-input/80 h-auto',
)}
>
@ -465,7 +464,7 @@ export function SendForm({
min={MIN_SEND_AMOUNT}
max={MAX_SEND_AMOUNT}
type="number"
className="h-auto pl-9"
className="pl-9"
placeholder={t('send.placeholder_amount_input')}
/>
<div className="absolute top-1/2 left-0 flex -translate-y-1/2 items-center px-3">
@ -503,7 +502,7 @@ export function SendForm({
id="send-amount-sweep-from-jar"
className={cn(
inputVariants(),
'flex min-h-8 min-w-0 flex-col items-start justify-center gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-2',
'flex min-h-10 min-w-0 flex-col items-start justify-center gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-2',
'bg-input/50 dark:bg-input/80 h-auto',
)}
aria-disabled

View file

@ -461,7 +461,6 @@ export const SendPage = ({ walletFileName }: SendPageProps) => {
<div>
<Button
variant="outline"
size="sm"
onClick={() => {
clearCurrentPaymentAttempt()
}}
@ -480,7 +479,6 @@ export const SendPage = ({ walletFileName }: SendPageProps) => {
<div>
<Button
variant="outline"
size="sm"
onClick={() => {
setFormId((current) => current + 1)
clearCurrentPaymentAttempt()
@ -524,7 +522,6 @@ export const SendPage = ({ walletFileName }: SendPageProps) => {
<div>
<Button
variant="outline"
size="sm"
onClick={() => setShowAbortCoinjoinDialog(true)}
disabled={isWaitingCoinjoinStop}
>
@ -603,7 +600,6 @@ export const SendPage = ({ walletFileName }: SendPageProps) => {
sourceJarLabelButton={
<Button
type="button"
size="sm"
variant="outline"
disabled={utxoSelectionDialog.utxoSelectorDisabled}
onClick={utxoSelectionDialog.onOpenUtxoSelector}

View file

@ -72,11 +72,11 @@ export const SweepDestinationInputs = ({ form, fields, disabled }: SweepDestinat
<FieldLabel htmlFor={`sweep-destination-${index}`}>
{t('scheduler.label_destination_input', { destination: index + 1 })}
</FieldLabel>
<ButtonGroup>
<ButtonGroup className="w-full">
<Input
id={`sweep-destination-${index}`}
{...register(`destinations.${index}.address`)}
className="h-auto font-mono"
className="font-mono"
placeholder={t('scheduler.placeholder_destination_input')}
disabled={disabled}
autoComplete="off"

View file

@ -4,7 +4,7 @@ import { Separator } from '@/components/ui/separator'
import { cn } from '@/lib/utils'
const buttonGroupVariants = cva(
"flex w-fit max-w-full items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:min-w-0 [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
"flex w-fit max-w-full items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=input]]:h-auto [&>[data-slot=input]]:self-stretch [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:min-w-0 [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
{
variants: {
orientation: {

View file

@ -3,7 +3,7 @@ import { cn } from '@/lib/utils'
export const buttonVariants = cva(
cn(
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
'cursor-pointer disabled:cursor-not-allowed',
),
{
@ -22,12 +22,12 @@ export const buttonVariants = cva(
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
default: 'h-10 gap-1.5 px-3.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
lg: 'h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',
lg: 'h-11 gap-1.5 px-4 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4',
xxl: 'h-12 gap-2 px-4 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5',
icon: 'size-8',
icon: 'size-9',
'icon-xs':
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
'icon-sm': 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',

View file

@ -104,7 +104,10 @@ function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="dialog-footer"
className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
className={cn(
'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end [&>[data-slot=button]]:min-h-10 [&>[data-slot=button]]:w-full sm:[&>[data-slot=button]]:w-auto sm:[&>[data-slot=button]]:min-w-28',
className,
)}
{...props}
/>
)

View file

@ -13,7 +13,7 @@ function InputGroup({ className, ...props }: React.ComponentProps<'div'>) {
data-slot="input-group"
role="group"
className={cn(
'border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-disabled:bg-input/50 dark:has-disabled:bg-input/80 group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border transition-colors outline-none has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot][aria-invalid=true]]:ring-[3px] has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 [[data-slot=combobox-content]_&]:focus-within:border-inherit [[data-slot=combobox-content]_&]:focus-within:ring-0',
'border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-disabled:bg-input/50 dark:has-disabled:bg-input/80 group/input-group relative flex h-10 w-full min-w-0 items-center rounded-lg border transition-colors outline-none has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot][aria-invalid=true]]:ring-[3px] has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 [[data-slot=combobox-content]_&]:focus-within:border-inherit [[data-slot=combobox-content]_&]:focus-within:ring-0',
className,
)}
{...props}

View file

@ -1,7 +1,7 @@
import { cva } from 'class-variance-authority'
const inputVariants = cva(
'dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 file:text-foreground placeholder:text-muted-foreground h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-[3px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-[3px] md:text-sm',
'dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 file:text-foreground placeholder:text-muted-foreground h-10 w-full min-w-0 rounded-lg border bg-transparent px-3 py-2 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-[3px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-[3px] md:text-sm',
{
variants: {
variant: {

View file

@ -17,7 +17,7 @@ export const FeeConfigErrorAlert = ({ onOpenFeeConfig, className }: FeeConfigErr
<AlertDescription className="flex flex-col gap-2">
<div>{t('send.taker_error_message_max_fees_config_missing')}</div>
<div>
<Button variant="outline" size="sm" onClick={onOpenFeeConfig}>
<Button variant="outline" onClick={onOpenFeeConfig}>
<HandCoinsIcon />
{t('settings.show_fee_config')}
</Button>

View file

@ -30,7 +30,7 @@ function SelectTrigger({
data-slot="select-trigger"
data-size={size}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit max-w-full min-w-0 items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:min-w-0 *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit max-w-full min-w-0 items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-10 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:min-w-0 *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}