From 492ae14dc1881f9aab2a19cd4e994868ead5cd73 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Thu, 9 Jul 2026 00:26:27 +0200 Subject: [PATCH] chore(ui): add jar button variants --- .../CreateFidelityBondDialogSteps.tsx | 4 +-- src/components/earn/MoveToJarDialog.tsx | 6 ++--- src/components/earn/RenewBondDialog.tsx | 4 +-- src/components/receive/ReceivePage.tsx | 4 +-- src/components/send/PaymentConfirmDialog.tsx | 6 ++--- src/components/send/SendForm.tsx | 6 ++--- src/components/ui/badge-variants.test.ts | 10 +++---- src/components/ui/badge-variants.ts | 7 ++--- src/components/ui/button-variants.ts | 27 +++++++++++++++++-- 9 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/components/earn/CreateFidelityBondDialog/CreateFidelityBondDialogSteps.tsx b/src/components/earn/CreateFidelityBondDialog/CreateFidelityBondDialogSteps.tsx index 01fdd17f..7115aabb 100644 --- a/src/components/earn/CreateFidelityBondDialog/CreateFidelityBondDialogSteps.tsx +++ b/src/components/earn/CreateFidelityBondDialog/CreateFidelityBondDialogSteps.tsx @@ -13,7 +13,7 @@ import { Trans } from 'react-i18next' import { toast } from 'sonner' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { Badge } from '@/components/ui/badge' -import { getJarBadgeVariant } from '@/components/ui/badge-variants' +import { jarBadgeVariant } from '@/components/ui/badge-variants' import { Button } from '@/components/ui/button' import { buttonVariants } from '@/components/ui/button-variants' import { Card, CardContent } from '@/components/ui/card' @@ -418,7 +418,7 @@ export function CreateFidelityBondDialogSteps({ wizard }: CreateFidelityBondDial

{t('earn.fidelity_bond.review_inputs.label_jar')}

- + {selectedJar ? ( <> {selectedJar.name} #{selectedJar.jarIndex} diff --git a/src/components/earn/MoveToJarDialog.tsx b/src/components/earn/MoveToJarDialog.tsx index 1c878b91..8b7536ee 100644 --- a/src/components/earn/MoveToJarDialog.tsx +++ b/src/components/earn/MoveToJarDialog.tsx @@ -40,7 +40,7 @@ import type { FidelityBondUtxo, Utxo } from '@/hooks/useQueryUtxos' import { getErrorReason } from '@/lib/errorReason' import { cn, formatSats, type WalletFileName } from '@/lib/utils' import type { JarIndex } from '@/types/global' -import { getJarBadgeVariant } from '../ui/badge-variants' +import { jarBadgeVariant } from '../ui/badge-variants' import { Address } from '../ui/jam/Address' type Step = 'select_jar' | 'confirm' | 'sending' | 'success' @@ -282,7 +282,7 @@ export function MoveToJarDialog({ open, onOpenChange, walletFileName, utxo }: Mo

{t('earn.fidelity_bond.review_inputs.label_jar')}

- + {sourceJar?.name ? ( <> {sourceJar.name} #{utxo.mixdepth} @@ -294,7 +294,7 @@ export function MoveToJarDialog({ open, onOpenChange, walletFileName, utxo }: Mo

{t('earn.fidelity_bond.move.label_destination')}

- + {destinationJar?.name ? ( <> {destinationJar.name} #{selectedJarIndex} diff --git a/src/components/earn/RenewBondDialog.tsx b/src/components/earn/RenewBondDialog.tsx index b1a6116d..5734412e 100644 --- a/src/components/earn/RenewBondDialog.tsx +++ b/src/components/earn/RenewBondDialog.tsx @@ -41,7 +41,7 @@ import { getErrorReason } from '@/lib/errorReason' import * as fb from '@/lib/fidelityBondUtils' import { cn, formatSats, type WalletFileName } from '@/lib/utils' import { useDeveloperMode } from '@/store/jamSettingsStore' -import { getJarBadgeVariant } from '../ui/badge-variants' +import { jarBadgeVariant } from '../ui/badge-variants' import { Address } from '../ui/jam/Address' import { generateLockdateOptions, getYearOptions, getMonthOptions } from './CreateFidelityBondDialog/types' @@ -332,7 +332,7 @@ export function RenewBondDialog({ open, onOpenChange, walletFileName, utxo }: Re

{t('earn.fidelity_bond.review_inputs.label_jar')}

- + {sourceJar?.name ? ( <> {sourceJar.name} #{utxo.mixdepth} diff --git a/src/components/receive/ReceivePage.tsx b/src/components/receive/ReceivePage.tsx index 29325ec3..a2968f5d 100644 --- a/src/components/receive/ReceivePage.tsx +++ b/src/components/receive/ReceivePage.tsx @@ -18,7 +18,7 @@ import { cn, type WalletFileName } from '@/lib/utils' import { useDeveloperMode } from '@/store/jamSettingsStore' import type { AmountSats, BitcoinAddress } from '@/types/global' import { Badge } from '../ui/badge' -import { getJarBadgeVariant } from '../ui/badge-variants' +import { jarBadgeVariant } from '../ui/badge-variants' import { buttonVariants } from '../ui/button-variants' import { Address } from '../ui/jam/Address' import { BitcoinAddressQrCode } from '../ui/jam/BitcoinQrCode' @@ -175,7 +175,7 @@ export const ReceivePage = ({ walletFileName }: ReceivePageProps) => { )} {sourceJar ? ( <> diff --git a/src/components/send/PaymentConfirmDialog.tsx b/src/components/send/PaymentConfirmDialog.tsx index 893222c0..5f6bd3d6 100644 --- a/src/components/send/PaymentConfirmDialog.tsx +++ b/src/components/send/PaymentConfirmDialog.tsx @@ -3,7 +3,7 @@ import { DialogTitle } from '@radix-ui/react-dialog' import { InfoIcon } from 'lucide-react' import { Trans, useTranslation } from 'react-i18next' import { Badge } from '@/components/ui/badge' -import { getJarBadgeVariant } from '@/components/ui/badge-variants' +import { jarBadgeVariant } from '@/components/ui/badge-variants' import type { Jar } from '@/context/JamWalletInfoContext' import type { Utxo } from '@/hooks/useQueryUtxos' import type { JamFeeConfigValues } from '@/lib/feeConfig' @@ -111,7 +111,7 @@ export default function PaymentConfirmDialog({
{t('send.confirm_send_modal.label_source_jar')}
- + {meta.sourceJar.name} #{meta.sourceJar.jarIndex}
@@ -121,7 +121,7 @@ export default function PaymentConfirmDialog({ {meta.destinationJar !== undefined ? ( <>
- + {meta.destinationJar.name} #{meta.destinationJar.jarIndex}
diff --git a/src/components/send/SendForm.tsx b/src/components/send/SendForm.tsx index 960e8625..3a981a65 100644 --- a/src/components/send/SendForm.tsx +++ b/src/components/send/SendForm.tsx @@ -23,7 +23,7 @@ import { DevBadge } from '../dev/DevBadge' import { buildSweepPreconditionSummary } from '../sweep/preconditions' import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '../ui/accordion' import { Badge } from '../ui/badge' -import { getJarBadgeVariant } from '../ui/badge-variants' +import { jarBadgeVariant } from '../ui/badge-variants' import { Button } from '../ui/button' import { ButtonGroup } from '../ui/button-group' import { Card, CardContent, CardHeader } from '../ui/card' @@ -411,7 +411,7 @@ export function SendForm({ )} >
- + {destinationJar.name} #{destinationJar.jarIndex}
@@ -512,7 +512,7 @@ export function SendForm({ )} - + {sourceJar?.name} #{sourceJar?.jarIndex}
diff --git a/src/components/ui/badge-variants.test.ts b/src/components/ui/badge-variants.test.ts index 9bc8e4d9..c835238e 100644 --- a/src/components/ui/badge-variants.test.ts +++ b/src/components/ui/badge-variants.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' -import { getJarBadgeVariant } from './badge-variants' +import { jarBadgeVariant } from './badge-variants' -describe('getJarBadgeVariant', () => { +describe('jarBadgeVariant', () => { it.each([ [0, 'jar0'], [1, 'jar1'], @@ -9,14 +9,14 @@ describe('getJarBadgeVariant', () => { [3, 'jar3'], [4, 'jar4'], ])('returns the jar badge variant for jar index %i', (jarIndex, variant) => { - expect(getJarBadgeVariant(jarIndex)).toBe(variant) + expect(jarBadgeVariant(jarIndex)).toBe(variant) }) it('returns undefined when no jar is available', () => { - expect(getJarBadgeVariant()).toBeUndefined() + expect(jarBadgeVariant()).toBeUndefined() }) it('returns the unknown jar badge variant for non-standard jar indexes', () => { - expect(getJarBadgeVariant(5)).toBe('jarUnknown') + expect(jarBadgeVariant(5)).toBe('jarUnknown') }) }) diff --git a/src/components/ui/badge-variants.ts b/src/components/ui/badge-variants.ts index 64bb9847..fff342f8 100644 --- a/src/components/ui/badge-variants.ts +++ b/src/components/ui/badge-variants.ts @@ -1,4 +1,5 @@ import { cva, type VariantProps } from 'class-variance-authority' +import type { JarIndex } from '@/types/global' const badgeVariants = cva( 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden', @@ -27,7 +28,7 @@ const badgeVariants = cva( type BadgeVariant = NonNullable['variant']> -const JAR_BADGE_VARIANTS: Record = { +const JAR_BADGE_VARIANTS: Record = { 0: 'jar0', 1: 'jar1', 2: 'jar2', @@ -35,7 +36,7 @@ const JAR_BADGE_VARIANTS: Record = { 4: 'jar4', } -const getJarBadgeVariant = (jarIndex?: number): BadgeVariant | undefined => +const jarBadgeVariant = (jarIndex?: JarIndex): BadgeVariant | undefined => jarIndex === undefined ? undefined : (JAR_BADGE_VARIANTS[jarIndex] ?? 'jarUnknown') -export { badgeVariants, getJarBadgeVariant } +export { badgeVariants, jarBadgeVariant } diff --git a/src/components/ui/button-variants.ts b/src/components/ui/button-variants.ts index 2e2279db..ee782c92 100644 --- a/src/components/ui/button-variants.ts +++ b/src/components/ui/button-variants.ts @@ -1,7 +1,8 @@ -import { cva } from 'class-variance-authority' +import { cva, type VariantProps } from 'class-variance-authority' import { cn } from '@/lib/utils' +import type { JarIndex } from '@/types/global' -export const buttonVariants = cva( +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 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', @@ -20,6 +21,13 @@ export const buttonVariants = cva( destructive: 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30', link: 'text-primary underline-offset-4 hover:underline', + + jar0: 'border-transparent bg-jar0 text-primary-foreground [a&]:hover:bg-jar0/90', + jar1: 'border-transparent bg-jar1 text-primary-foreground [a&]:hover:bg-jar1/90', + jar2: 'border-transparent bg-jar2 text-primary-foreground [a&]:hover:bg-jar2/90', + jar3: 'border-transparent bg-jar3 text-primary-foreground [a&]:hover:bg-jar3/90', + jar4: 'border-transparent bg-jar4 text-primary-foreground [a&]:hover:bg-jar4/90', + jarUnknown: 'border-transparent bg-jar-unknown text-primary-foreground [a&]:hover:bg-jar-unknown/90', }, size: { default: 'h-10 gap-1.5 px-3.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3', @@ -40,3 +48,18 @@ export const buttonVariants = cva( }, }, ) + +type ButtonVariant = NonNullable['variant']> + +const JAR_BUTTON_VARIANTS: Record = { + 0: 'jar0', + 1: 'jar1', + 2: 'jar2', + 3: 'jar3', + 4: 'jar4', +} + +const jarButtonVariant = (jarIndex?: JarIndex): ButtonVariant | undefined => + jarIndex === undefined ? undefined : (JAR_BUTTON_VARIANTS[jarIndex] ?? 'jarUnknown') + +export { buttonVariants, jarButtonVariant }