refactor(frontend): Standardize button styling using shadcn Button component.

Replace inconsistent native HTML button elements with shadcn/ui Button
component across all components for consistent styling and behavior.

Changes:
- TransactionsTable: Use Button with ghost variant for Raw action buttons
- Settings: Standardize edit, save, cancel, and delete buttons with icon variant
- AccountsOverview: Apply consistent Button component for account actions
- AccountSettings: Update account editing buttons to use Button component
- NotificationFiltersDrawer: Convert filter removal buttons to Button component

Benefits:
- Consistent design system throughout the app
- Better accessibility and keyboard navigation
- Proper theme support and state handling
- Reduced custom CSS and improved maintainability
This commit is contained in:
Elisiário Couto
2025-10-05 23:14:19 +01:00
parent 0205e5be0d
commit 38fddeb281
5 changed files with 68 additions and 42 deletions

View File

@@ -234,24 +234,28 @@ export default function AccountSettings() {
}} }}
autoFocus autoFocus
/> />
<button <Button
onClick={handleEditSave} onClick={handleEditSave}
disabled={ disabled={
!editingName.trim() || !editingName.trim() ||
updateAccountMutation.isPending updateAccountMutation.isPending
} }
className="p-1 text-green-600 hover:text-green-700 disabled:opacity-50 disabled:cursor-not-allowed" size="icon"
variant="ghost"
className="h-8 w-8 text-green-600 hover:text-green-700 hover:bg-green-100"
title="Save changes" title="Save changes"
> >
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</button> </Button>
<button <Button
onClick={handleEditCancel} onClick={handleEditCancel}
className="p-1 text-gray-600 hover:text-gray-700" size="icon"
variant="ghost"
className="h-8 w-8"
title="Cancel editing" title="Cancel editing"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </Button>
</div> </div>
<p className="text-sm text-muted-foreground truncate"> <p className="text-sm text-muted-foreground truncate">
{account.institution_id} {account.institution_id}
@@ -265,13 +269,15 @@ export default function AccountSettings() {
account.name || account.name ||
"Unnamed Account"} "Unnamed Account"}
</h4> </h4>
<button <Button
onClick={() => handleEditStart(account)} onClick={() => handleEditStart(account)}
className="flex-shrink-0 p-1 text-muted-foreground hover:text-foreground transition-colors" size="icon"
variant="ghost"
className="h-7 w-7 flex-shrink-0"
title="Edit account name" title="Edit account name"
> >
<Edit2 className="h-4 w-4" /> <Edit2 className="h-4 w-4" />
</button> </Button>
</div> </div>
<p className="text-sm text-muted-foreground truncate"> <p className="text-sm text-muted-foreground truncate">
{account.institution_id} {account.institution_id}

View File

@@ -273,24 +273,28 @@ export default function AccountsOverview() {
}} }}
autoFocus autoFocus
/> />
<button <Button
onClick={handleEditSave} onClick={handleEditSave}
disabled={ disabled={
!editingName.trim() || !editingName.trim() ||
updateAccountMutation.isPending updateAccountMutation.isPending
} }
className="p-1 text-green-600 hover:text-green-700 disabled:opacity-50 disabled:cursor-not-allowed" size="icon"
variant="ghost"
className="h-8 w-8 text-green-600 hover:text-green-700 hover:bg-green-100"
title="Save changes" title="Save changes"
> >
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</button> </Button>
<button <Button
onClick={handleEditCancel} onClick={handleEditCancel}
className="p-1 text-gray-600 hover:text-gray-700" size="icon"
variant="ghost"
className="h-8 w-8"
title="Cancel editing" title="Cancel editing"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </Button>
</div> </div>
<p className="text-sm text-muted-foreground truncate"> <p className="text-sm text-muted-foreground truncate">
{account.institution_id} {account.institution_id}
@@ -304,13 +308,15 @@ export default function AccountsOverview() {
account.name || account.name ||
"Unnamed Account"} "Unnamed Account"}
</h4> </h4>
<button <Button
onClick={() => handleEditStart(account)} onClick={() => handleEditStart(account)}
className="flex-shrink-0 p-1 text-muted-foreground hover:text-foreground transition-colors" size="icon"
variant="ghost"
className="h-7 w-7 flex-shrink-0"
title="Edit account name" title="Edit account name"
> >
<Edit2 className="h-4 w-4" /> <Edit2 className="h-4 w-4" />
</button> </Button>
</div> </div>
<p className="text-sm text-muted-foreground truncate"> <p className="text-sm text-muted-foreground truncate">
{account.institution_id} {account.institution_id}

View File

@@ -166,13 +166,15 @@ export default function NotificationFiltersDrawer({
className="flex items-center space-x-1 bg-secondary text-secondary-foreground px-2 py-1 rounded-md text-sm" className="flex items-center space-x-1 bg-secondary text-secondary-foreground px-2 py-1 rounded-md text-sm"
> >
<span>{filter}</span> <span>{filter}</span>
<button <Button
type="button" type="button"
onClick={() => removeCaseInsensitiveFilter(index)} onClick={() => removeCaseInsensitiveFilter(index)}
className="text-secondary-foreground hover:text-foreground" variant="ghost"
size="icon"
className="h-5 w-5 hover:bg-secondary-foreground/10"
> >
<X className="h-3 w-3" /> <X className="h-3 w-3" />
</button> </Button>
</div> </div>
)) ))
) : ( ) : (
@@ -222,13 +224,15 @@ export default function NotificationFiltersDrawer({
className="flex items-center space-x-1 bg-secondary text-secondary-foreground px-2 py-1 rounded-md text-sm" className="flex items-center space-x-1 bg-secondary text-secondary-foreground px-2 py-1 rounded-md text-sm"
> >
<span>{filter}</span> <span>{filter}</span>
<button <Button
type="button" type="button"
onClick={() => removeCaseSensitiveFilter(index)} onClick={() => removeCaseSensitiveFilter(index)}
className="text-secondary-foreground hover:text-foreground" variant="ghost"
size="icon"
className="h-5 w-5 hover:bg-secondary-foreground/10"
> >
<X className="h-3 w-3" /> <X className="h-3 w-3" />
</button> </Button>
</div> </div>
)) ))
) : ( ) : (

View File

@@ -403,24 +403,28 @@ export default function Settings() {
}} }}
autoFocus autoFocus
/> />
<button <Button
onClick={handleEditSave} onClick={handleEditSave}
disabled={ disabled={
!editingName.trim() || !editingName.trim() ||
updateAccountMutation.isPending updateAccountMutation.isPending
} }
className="p-1 text-green-600 hover:text-green-700 disabled:opacity-50 disabled:cursor-not-allowed" size="icon"
variant="ghost"
className="h-8 w-8 text-green-600 hover:text-green-700 hover:bg-green-100"
title="Save changes" title="Save changes"
> >
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</button> </Button>
<button <Button
onClick={handleEditCancel} onClick={handleEditCancel}
className="p-1 text-gray-600 hover:text-gray-700" size="icon"
variant="ghost"
className="h-8 w-8"
title="Cancel editing" title="Cancel editing"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </Button>
</div> </div>
<p className="text-sm text-muted-foreground truncate"> <p className="text-sm text-muted-foreground truncate">
{account.institution_id} {account.institution_id}
@@ -434,13 +438,15 @@ export default function Settings() {
account.name || account.name ||
"Unnamed Account"} "Unnamed Account"}
</h4> </h4>
<button <Button
onClick={() => handleEditStart(account)} onClick={() => handleEditStart(account)}
className="flex-shrink-0 p-1 text-muted-foreground hover:text-foreground transition-colors" size="icon"
variant="ghost"
className="h-7 w-7 flex-shrink-0"
title="Edit account name" title="Edit account name"
> >
<Edit2 className="h-4 w-4" /> <Edit2 className="h-4 w-4" />
</button> </Button>
</div> </div>
<p className="text-sm text-muted-foreground truncate"> <p className="text-sm text-muted-foreground truncate">
{account.institution_id} {account.institution_id}
@@ -579,7 +585,7 @@ export default function Settings() {
Created {formatDate(connection.created_at)} Created {formatDate(connection.created_at)}
</p> </p>
</div> </div>
<button <Button
onClick={() => { onClick={() => {
const isWorking = const isWorking =
connection.status.toLowerCase() === "ln"; connection.status.toLowerCase() === "ln";
@@ -594,11 +600,13 @@ export default function Settings() {
} }
}} }}
disabled={deleteBankConnectionMutation.isPending} disabled={deleteBankConnectionMutation.isPending}
className="p-1 text-muted-foreground hover:text-destructive transition-colors disabled:opacity-50 disabled:cursor-not-allowed" size="icon"
variant="ghost"
className="h-8 w-8 text-muted-foreground hover:text-destructive"
title="Delete connection" title="Delete connection"
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />
</button> </Button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -259,14 +259,15 @@ export default function TransactionsTable() {
cell: ({ row }) => { cell: ({ row }) => {
const transaction = row.original; const transaction = row.original;
return ( return (
<button <Button
onClick={() => handleViewRaw(transaction)} onClick={() => handleViewRaw(transaction)}
className="inline-flex items-center px-2 py-1 text-xs bg-muted text-muted-foreground rounded hover:bg-accent transition-colors" variant="ghost"
size="sm"
title="View raw transaction data" title="View raw transaction data"
> >
<Eye className="h-3 w-3 mr-1" /> <Eye className="h-3 w-3 mr-1" />
Raw Raw
</button> </Button>
); );
}, },
}, },
@@ -530,14 +531,15 @@ export default function TransactionsTable() {
transaction.transaction_currency, transaction.transaction_currency,
)} )}
</p> </p>
<button <Button
onClick={() => handleViewRaw(transaction)} onClick={() => handleViewRaw(transaction)}
className="inline-flex items-center px-2 py-1 text-xs bg-muted text-muted-foreground rounded hover:bg-accent transition-colors" variant="ghost"
size="sm"
title="View raw transaction data" title="View raw transaction data"
> >
<Eye className="h-3 w-3 mr-1" /> <Eye className="h-3 w-3 mr-1" />
Raw Raw
</button> </Button>
</div> </div>
</div> </div>
</div> </div>