Keep delete affordances neutral until the confirmation

Row delete buttons, overflow-menu delete items and per-row revoke
buttons painted red in lists, so a list of tokens or shares read as a
wall of alarms. They now sit in the muted tone (foreground on hover)
or as an outline button; the red is kept for the confirmation dialog
that every one of them opens, and for the danger zones, which are a
destructive card-wide action by design.
This commit is contained in:
Marc-André Bombeck committed 2026-10-08 18:45:02 +02:00
1 parent 142dfa9360
commit 793c19e179
25 files changed
+21 -29

No files matched your search

@@ -411,7 +411,7 @@ export function InviteTokensSection() {
type="button"
variant="ghost"
size="sm"
className="text-destructive hover:text-destructive"
className="text-muted-foreground hover:text-foreground"
aria-label={t("admin.invites.revokeAria")}
disabled={revoke.isPending}
onClick={() => setRevokeTarget(invite)}
@@ -479,7 +479,7 @@ export function InviteTokensSection() {
type="button"
variant="ghost"
size="sm"
className="text-destructive hover:text-destructive"
className="text-muted-foreground hover:text-foreground"
disabled={revoke.isPending}
onClick={() => setRevokeTarget(invite)}
>
@@ -254,7 +254,7 @@ export function UserManagementSection() {
<Button
variant="ghost"
size="sm"
className="text-destructive hover:text-destructive min-h-11 min-w-11 px-2 text-xs"
className="text-muted-foreground hover:text-foreground min-h-11 min-w-11 px-2 text-xs"
onClick={() => setLogoutTarget(u)}
disabled={u.id === currentUserId}
title={
+1 -1
View File
@@ -1465,7 +1465,7 @@ export function SymptomRow({
onClick={() => setConfirmRemove(true)}
disabled={deleteCustom.isPending}
aria-label={t("cycle.symptom.custom.remove", { label })}
className="text-muted-foreground hover:text-destructive hover:bg-accent focus-visible:ring-ring/50 grid size-11 shrink-0 place-items-center rounded-md transition-colors focus-visible:ring-2 focus-visible:outline-none sm:size-9"
className="text-muted-foreground hover:text-foreground hover:bg-accent focus-visible:ring-ring/50 grid size-11 shrink-0 place-items-center rounded-md transition-colors focus-visible:ring-2 focus-visible:outline-none sm:size-9"
>
<X className="size-4" aria-hidden="true" />
</button>
+1 -1
View File
@@ -73,7 +73,7 @@ export function DeleteButton({
<Button
variant="ghost"
size="icon-lg"
className={`text-destructive ${className}`}
className={`text-muted-foreground hover:text-foreground ${className}`}
aria-label={confirmLabel ?? t("common.delete")}
title={triggerTitle ?? confirmLabel ?? t("common.delete")}
>
-1
View File
@@ -106,7 +106,6 @@ export function EpisodeMenu({
) : null}
<DropdownMenuSeparator />
<DropdownMenuItem
variant="destructive"
onSelect={(e) => {
e.preventDefault();
setConfirmOpen(true);
@@ -340,7 +340,6 @@ function HistoryRow({
{t("insights.coach.frame.rename")}
</DropdownMenuItem>
<DropdownMenuItem
variant="destructive"
data-slot="coach-history-delete"
onSelect={() => onDelete(c.id)}
>
@@ -1002,7 +1002,6 @@ function VorsorgeCard({
)}
<DropdownMenuSeparator />
<DropdownMenuItem
variant="destructive"
disabled={busy}
onSelect={() => setConfirmDelete(true)}
>
@@ -1770,7 +1770,6 @@ export function MeasurementList({
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem
variant="destructive"
onClick={() => setEditDeleteDialogOpen(true)}
>
<Trash2 className="mr-2 h-4 w-4" />
@@ -868,7 +868,6 @@ export function LedgerRowItem({
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => onDelete(intake.id as string)}
className="text-destructive focus:text-destructive"
data-slot="ledger-delete"
>
<Trash2 aria-hidden="true" className="mr-2 size-4" />
@@ -189,7 +189,7 @@ function CategoryRow({
type="button"
variant="ghost"
size="icon"
className="text-destructive hover:text-destructive size-11 sm:size-9"
className="text-muted-foreground hover:text-foreground size-11 sm:size-9"
onClick={() => onDelete(category)}
aria-label={`${t("medications.category.custom.delete")}: ${category.label}`}
title={t("medications.category.custom.delete")}
@@ -239,7 +239,7 @@ export function ScheduleHistoryTimeline({
type="button"
variant="ghost"
size="icon"
className="text-muted-foreground hover:text-destructive size-11 sm:size-8"
className="text-muted-foreground hover:text-foreground size-11 sm:size-8"
aria-label={t(
"medications.detail.zeitplan.history.deleteAria",
)}
@@ -313,7 +313,7 @@ export function CoursesRow({
type="button"
variant="ghost"
size="icon"
className="text-destructive hover:text-destructive size-11 sm:size-9"
className="text-muted-foreground hover:text-foreground size-11 sm:size-9"
onClick={() => setDeleting(course)}
aria-label={t("medications.course.delete")}
title={t("medications.course.delete")}
@@ -352,7 +352,7 @@ export function SideEffectsSection({ medicationId }: SideEffectsSectionProps) {
<Button
variant="ghost"
size="icon"
className="text-muted-foreground hover:text-destructive size-11 shrink-0"
className="text-muted-foreground hover:text-foreground size-11 shrink-0"
aria-label={t("medications.sideEffects.deleteCta")}
onClick={() => setPendingDeleteId(row.id)}
disabled={deleteMutation.isPending}
@@ -121,7 +121,7 @@ export function Step8Summary({
type="button"
variant="ghost"
size="sm"
className="text-muted-foreground hover:text-destructive h-8 gap-1 px-2 text-xs"
className="text-muted-foreground hover:text-foreground h-8 gap-1 px-2 text-xs"
onClick={() => onRemoveSchedule(index)}
disabled={!canRemove}
data-slot="wizard-schedule-remove"
@@ -151,7 +151,7 @@ export function ArchivedTagsCard({ catalog }: ArchivedTagsCardProps) {
type="button"
variant="ghost"
size="icon"
className="text-destructive hover:text-destructive size-11 sm:size-9"
className="text-muted-foreground hover:text-foreground size-11 sm:size-9"
onClick={() => setPurgeTag(tag)}
aria-label={`${t("mood.manage.purgeAction")} — ${name}`}
title={t("mood.manage.purgeAction")}
@@ -494,7 +494,7 @@ function SortableGroupRow({
<Pencil className="mr-2 h-4 w-4" />
{t("common.edit")}
</DropdownMenuItem>
<DropdownMenuItem variant="destructive" onClick={onDelete}>
<DropdownMenuItem onClick={onDelete}>
<Trash2 className="mr-2 h-4 w-4" />
{t("common.delete")}
</DropdownMenuItem>
-1
View File
@@ -1196,7 +1196,6 @@ export function MoodList({ onAddFirst }: MoodListProps = {}) {
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem
variant="destructive"
onClick={() => setEditDeleteDialogOpen(true)}
>
<Trash2 className="mr-2 h-4 w-4" />
+2 -2
View File
@@ -579,7 +579,7 @@ function ApiTokensCard() {
<Button
variant="ghost"
size="icon"
className="text-destructive h-9 w-9"
className="text-muted-foreground hover:text-foreground h-9 w-9"
aria-label={t("settings.tokenRevokeAction")}
>
<Trash2 className="h-3.5 w-3.5" />
@@ -676,7 +676,7 @@ function ApiTokensCard() {
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="destructive"
variant="outline"
size="sm"
className="min-h-11 w-full"
>
@@ -149,7 +149,7 @@ export function CoachRemindersSection({
slot="coach-reminder-delete"
variant="ghost"
size="sm"
className="text-muted-foreground hover:text-destructive min-h-9"
className="text-muted-foreground hover:text-foreground min-h-9"
disabled={!isAuthenticated}
pending={busy}
ariaLabel={t("settings.ai.coachReminders.deleteAria")}
+2 -2
View File
@@ -165,7 +165,7 @@ function McpConnectionsCard() {
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="destructive"
variant="outline"
size="sm"
className="min-h-11 w-full"
>
@@ -506,7 +506,7 @@ function McpTokensCard() {
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="destructive"
variant="outline"
size="sm"
className="min-h-11 w-full"
>
@@ -299,7 +299,7 @@ export function PasskeyListSection({
type="button"
variant="ghost"
size="icon"
className="text-destructive min-h-11 min-w-11 sm:h-8 sm:min-h-0 sm:w-8 sm:min-w-0"
className="text-muted-foreground hover:text-foreground min-h-11 min-w-11 sm:h-8 sm:min-h-0 sm:w-8 sm:min-w-0"
disabled={remove.isPending}
aria-label={t("settings.deletePasskey")}
>
@@ -293,7 +293,7 @@ export function SecurityKeysCard({
type="button"
variant="ghost"
size="icon"
className="text-destructive min-h-11 min-w-11 sm:h-8 sm:min-h-0 sm:w-8 sm:min-w-0"
className="text-muted-foreground hover:text-foreground min-h-11 min-w-11 sm:h-8 sm:min-h-0 sm:w-8 sm:min-w-0"
disabled={remove.isPending}
aria-label={t("settings.security.keys.remove")}
>
+1 -1
View File
@@ -242,7 +242,7 @@ function ShareLinksCard() {
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="destructive"
variant="outline"
size="sm"
className="ml-auto flex min-h-11 w-fit sm:min-h-9"
>
@@ -223,7 +223,6 @@ function DefinitionMenu({
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
variant="destructive"
onSelect={(e) => {
e.preventDefault();
setConfirmOpen(true);
@@ -301,7 +300,6 @@ export function SymptomEventMenu({
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
variant="destructive"
onSelect={(e) => {
e.preventDefault();
setConfirmOpen(true);
@@ -99,7 +99,7 @@ export function DeleteWorkoutButton({
title={t("insights.workouts.manual.deleteLabel")}
onClick={() => setOpen(true)}
className={cn(
"text-muted-foreground hover:text-destructive relative size-10",
"text-muted-foreground hover:text-foreground relative size-10",
"before:absolute before:-inset-1.5 before:content-['']",
)}
>