mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-17 13:07:34 +02:00
chore: align utxo status tooltip
This commit is contained in:
parent
051ff0fc8c
commit
6054c2e989
6 changed files with 70 additions and 60 deletions
|
|
@ -370,7 +370,9 @@ export const OrderbookContent = ({ enabled, className }: OrderbookContentProps)
|
|||
</CardHeader>
|
||||
<CardContent className="text-muted-foreground grid gap-1 text-sm sm:grid-cols-2">
|
||||
{marketSummary.medianAbsFee !== null && (
|
||||
<p>{t('orderbook.market_summary_median_abs_fee', { value: marketSummary.medianAbsFee.toLocaleString() })}</p>
|
||||
<p>
|
||||
{t('orderbook.market_summary_median_abs_fee', { value: marketSummary.medianAbsFee.toLocaleString() })}
|
||||
</p>
|
||||
)}
|
||||
{marketSummary.medianRelFee !== null && (
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -2,17 +2,32 @@ import * as React from 'react'
|
|||
import { Slot } from '@radix-ui/react-slot'
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip'
|
||||
import { statusBadgeVariants } from './StatusBadge-variants'
|
||||
|
||||
function StatusBadge({
|
||||
className,
|
||||
variant,
|
||||
asChild = false,
|
||||
tooltip,
|
||||
...props
|
||||
}: React.ComponentProps<'span'> & VariantProps<typeof statusBadgeVariants> & { asChild?: boolean }) {
|
||||
}: React.ComponentProps<'span'> &
|
||||
VariantProps<typeof statusBadgeVariants> & {
|
||||
asChild?: boolean
|
||||
tooltip?: React.ReactNode | string
|
||||
}) {
|
||||
const Comp = asChild ? Slot : 'span'
|
||||
|
||||
return <Comp data-slot="badge" className={cn(statusBadgeVariants({ variant }), className)} {...props} />
|
||||
const element = <Comp data-slot="badge" className={cn(statusBadgeVariants({ variant }), className)} {...props} />
|
||||
|
||||
return !tooltip ? (
|
||||
element
|
||||
) : (
|
||||
<Tooltip key={props.key}>
|
||||
<TooltipTrigger asChild>{element}</TooltipTrigger>
|
||||
<TooltipContent>{tooltip}</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export { StatusBadge }
|
||||
|
|
|
|||
|
|
@ -154,11 +154,16 @@ export const BranchEntryTable = ({
|
|||
header: () => t(/* TODO: i18n keys */ 'jar_details.utxo_list.column_title_label_and_status'),
|
||||
cell: (info) => (
|
||||
<div className="flex items-center gap-2">
|
||||
{info.row.original.tags.map((it, index) => (
|
||||
<StatusBadge key={index} variant={it.variant}>
|
||||
{it.displayValue}
|
||||
</StatusBadge>
|
||||
))}
|
||||
{info.row.original.tags.map((it, index) => {
|
||||
const tooltipKey = `jar_details.utxo_list.utxo_tag_tooltip_${it.value}`
|
||||
const tooltip = t(tooltipKey)
|
||||
const hasTooltip = tooltip !== tooltipKey
|
||||
return (
|
||||
<StatusBadge key={index} variant={it.variant} tooltip={hasTooltip ? tooltip : undefined}>
|
||||
{it.displayValue}
|
||||
</StatusBadge>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
),
|
||||
enableSorting: false,
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ import { Balance } from '../ui/jam/Balance'
|
|||
import { CopyButton } from '../ui/jam/CopyButton'
|
||||
import { SortIcon } from '../ui/jam/SortIcon'
|
||||
import { StatusBadge } from '../ui/jam/StatusBadge'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip'
|
||||
|
||||
const ITEMS_PER_PAGE = 25
|
||||
|
||||
|
|
@ -241,15 +240,8 @@ const utxoTableColumns = (t: TFunction): ColumnDef<UtxoTableEntry, any>[] => {
|
|||
const tooltipKey = `jar_details.utxo_list.utxo_tag_tooltip_${it.value}`
|
||||
const tooltip = t(tooltipKey)
|
||||
const hasTooltip = tooltip !== tooltipKey
|
||||
return hasTooltip ? (
|
||||
<Tooltip key={index}>
|
||||
<TooltipTrigger asChild>
|
||||
<StatusBadge variant={it.variant}>{it.displayValue}</StatusBadge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{tooltip}</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<StatusBadge key={index} variant={it.variant}>
|
||||
return (
|
||||
<StatusBadge key={index} variant={it.variant} tooltip={hasTooltip ? tooltip : undefined}>
|
||||
{it.displayValue}
|
||||
</StatusBadge>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -187,6 +187,12 @@ export const UtxosContent = ({ enabled, walletFileName, addressSummary, jar }: U
|
|||
|
||||
return (
|
||||
<>
|
||||
{reusedCount > 0 && (
|
||||
<Alert variant="destructive">
|
||||
<AlertTriangleIcon />
|
||||
<AlertDescription>{t('jar_details.utxo_list.alert_reused_address', { count: reusedCount })}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<div className="flex flex-col text-sm sm:flex-row sm:gap-2">
|
||||
<div className="flex flex-1 gap-2">
|
||||
{t('jar_details.utxo_list.title', { count: jar.utxos.length, jar: jar.name })}
|
||||
|
|
@ -197,37 +203,37 @@ export const UtxosContent = ({ enabled, walletFileName, addressSummary, jar }: U
|
|||
</Trans>
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn('flex items-center gap-2', {})}>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={!operationsEnabled || walletInfo.isFetching}
|
||||
onClick={() => void walletInfo.refetch()}
|
||||
>
|
||||
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': walletInfo.isFetching })} />
|
||||
{t('global.refresh')}
|
||||
</Button>
|
||||
<ButtonGroup>
|
||||
<div className="flex flex-col justify-between gap-2 sm:flex-row sm:items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant={selectedUtxos.length === 0 ? 'outline' : undefined}
|
||||
disabled={!operationsEnabled || selectedUtxos.length === 0 || allSelectedUtxosFrozen}
|
||||
onClick={() => void onFreezeClick()}
|
||||
disabled={!operationsEnabled || walletInfo.isFetching}
|
||||
onClick={() => void walletInfo.refetch()}
|
||||
>
|
||||
{freezeUtxos.isPending ? <Spinner /> : <ThermometerSnowflakeIcon />}
|
||||
{t('jar_details.utxo_list.button_freeze')}
|
||||
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': walletInfo.isFetching })} />
|
||||
{t('global.refresh')}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={selectedUtxos.length === 0 ? 'outline' : undefined}
|
||||
disabled={!operationsEnabled || selectedUtxos.length === 0 || allSelectedUtxosUnfrozen}
|
||||
onClick={() => void onUnfreezeClick()}
|
||||
>
|
||||
{unfreezeUtxos.isPending ? <Spinner /> : <ThermometerSunIcon />}
|
||||
{t('jar_details.utxo_list.button_unfreeze')}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={selectedUtxos.length === 0 ? 'outline' : undefined}
|
||||
disabled={!operationsEnabled || selectedUtxos.length === 0 || allSelectedUtxosFrozen}
|
||||
onClick={() => void onFreezeClick()}
|
||||
>
|
||||
{freezeUtxos.isPending ? <Spinner /> : <ThermometerSnowflakeIcon />}
|
||||
{t('jar_details.utxo_list.button_freeze')}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={selectedUtxos.length === 0 ? 'outline' : undefined}
|
||||
disabled={!operationsEnabled || selectedUtxos.length === 0 || allSelectedUtxosUnfrozen}
|
||||
onClick={() => void onUnfreezeClick()}
|
||||
>
|
||||
{unfreezeUtxos.isPending ? <Spinner /> : <ThermometerSunIcon />}
|
||||
{t('jar_details.utxo_list.button_unfreeze')}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<Input
|
||||
placeholder={t('jar_details.utxo_list.placeholder_search')}
|
||||
value={searchFilter}
|
||||
|
|
@ -241,14 +247,6 @@ export const UtxosContent = ({ enabled, walletFileName, addressSummary, jar }: U
|
|||
globalFilter={searchFilter}
|
||||
onRowSelectionChange={setRowSelection}
|
||||
/>
|
||||
{reusedCount > 0 && (
|
||||
<Alert variant="destructive">
|
||||
<AlertTriangleIcon />
|
||||
<AlertDescription>
|
||||
{t('jar_details.utxo_list.alert_reused_address', { count: reusedCount })}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -808,17 +808,15 @@
|
|||
"utxo_tooltip_locktime": "locked until {{ locktime }}",
|
||||
"utxo_tag_frozen": "frozen",
|
||||
"utxo_tag_fb": "bond",
|
||||
"utxo_tag_tooltip_cj-out": "CoinJoin output — good privacy",
|
||||
"utxo_tag_tooltip_non-cj-change": "Change from a non-CoinJoin tx — may be linkable to inputs",
|
||||
"utxo_tag_tooltip_cj-out": "CoinJoin output",
|
||||
"utxo_tag_tooltip_non-cj-change": "Change from a non-CoinJoin tx",
|
||||
"utxo_tag_tooltip_change-out": "Change from a CoinJoin tx",
|
||||
"utxo_tag_tooltip_reused": "Address used more than once — bad for privacy",
|
||||
"utxo_tag_tooltip_reused": "Address used more than once",
|
||||
"utxo_tag_tooltip_deposit": "Received from an external source",
|
||||
"utxo_tag_tooltip_frozen": "Excluded from spending",
|
||||
"utxo_tag_tooltip_locked": "Excluded from spending — may be reserved for a CoinJoin",
|
||||
"utxo_tag_tooltip_locked": "Time-locked by the Bitcoin protocol",
|
||||
"utxo_tag_tooltip_pending": "Part of a pending transaction",
|
||||
"utxo_tag_tooltip_bond": "Locked as a fidelity bond",
|
||||
"utxo_tag_tooltip_new": "Fresh output that has not yet been used in a transaction",
|
||||
"utxo_tag_tooltip_used": "Output associated with prior usage or address reuse",
|
||||
"utxo_tag_tooltip_bond": "Fidelity bond",
|
||||
"column_title_balance": "Value",
|
||||
"column_title_address": "Address",
|
||||
"column_title_confirmations": "Confs.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue