Browse Source

adjust superchat coloring in light-mode and dark-mode

imwald
Silberengel 3 weeks ago
parent
commit
155cc72755
  1. 4
      package-lock.json
  2. 2
      package.json
  3. 3
      src/components/Note/Superchat.tsx
  4. 5
      src/components/Note/SuperchatCommentMarkdown.tsx
  5. 3
      src/components/Note/Zap.tsx
  6. 5
      src/components/PaytoDialog/LightningInvoiceSection.tsx
  7. 3
      src/components/PaytoDialog/index.tsx
  8. 6
      src/components/PaytoTypeIcon/index.tsx
  9. 3
      src/components/Profile/ProfileWallSuperchats.tsx
  10. 12
      src/components/TurnIntoSuperchatButton/index.tsx
  11. 3
      src/components/ZapDialog/ZapSatsAmountInput.tsx
  12. 16
      src/components/ZapDialog/index.tsx
  13. 31
      src/lib/superchat-ui.ts

4
package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "imwald", "name": "imwald",
"version": "23.13.8", "version": "23.15.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "imwald", "name": "imwald",
"version": "23.13.8", "version": "23.15.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@asciidoctor/core": "^3.0.4", "@asciidoctor/core": "^3.0.4",

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "imwald", "name": "imwald",
"version": "23.15.0", "version": "23.15.1",
"description": "Imwald — a user-friendly Nostr client focused on relay feed browsing, publications, and relay discovery", "description": "Imwald — a user-friendly Nostr client focused on relay feed browsing, publications, and relay discovery",
"private": true, "private": true,
"type": "module", "type": "module",

3
src/components/Note/Superchat.tsx

@ -4,6 +4,7 @@ import { openNoteFromFetchOrCache } from '@/lib/navigation-related-events'
import { parsePaytoTagType } from '@/lib/payto' import { parsePaytoTagType } from '@/lib/payto'
import { relayHintsFromEventTags } from '@/lib/relay-list-builder' import { relayHintsFromEventTags } from '@/lib/relay-list-builder'
import { getPaymentNotificationInfo, getSuperchatReferenceFetchId } from '@/lib/superchat' import { getPaymentNotificationInfo, getSuperchatReferenceFetchId } from '@/lib/superchat'
import { superchatTitleClass } from '@/lib/superchat-ui'
import { toProfile } from '@/lib/link' import { toProfile } from '@/lib/link'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Event } from 'nostr-tools' import { Event } from 'nostr-tools'
@ -137,7 +138,7 @@ export default function Superchat({
className="px-2.5 py-1.5 text-lg" className="px-2.5 py-1.5 text-lg"
imgClassName="size-5" imgClassName="size-5"
/> />
<span className="text-xl font-semibold text-yellow-400/90">{t('Superchat')}</span> <span className={cn('text-xl', superchatTitleClass)}>{t('Superchat')}</span>
</> </>
) : ( ) : (
<SuperchatPaymentMethodLabel <SuperchatPaymentMethodLabel

5
src/components/Note/SuperchatCommentMarkdown.tsx

@ -23,7 +23,10 @@ export default function SuperchatCommentMarkdown({
hideMetadata hideMetadata
lazyMedia={false} lazyMedia={false}
className={cn( className={cn(
'prose-xl max-w-none text-foreground [&_p]:text-[1.6875rem] [&_p]:font-semibold [&_p]:leading-snug', 'prose-xl max-w-none text-foreground',
'[&_p]:text-[1.6875rem] [&_p]:font-semibold [&_p]:leading-snug [&_p]:text-foreground',
'[&_a]:text-[hsl(var(--uri-link))] [&_a:hover]:text-[hsl(var(--primary))]',
'[&_strong]:text-foreground [&_em]:text-foreground',
className className
)} )}
/> />

3
src/components/Note/Zap.tsx

@ -6,6 +6,7 @@ import { formatAmount } from '@/lib/lightning'
import { openNoteFromFetchOrCache } from '@/lib/navigation-related-events' import { openNoteFromFetchOrCache } from '@/lib/navigation-related-events'
import { relayHintsFromEventTags } from '@/lib/relay-list-builder' import { relayHintsFromEventTags } from '@/lib/relay-list-builder'
import { getSuperchatPaytoType } from '@/lib/superchat' import { getSuperchatPaytoType } from '@/lib/superchat'
import { superchatTitleClass } from '@/lib/superchat-ui'
import { toProfile } from '@/lib/link' import { toProfile } from '@/lib/link'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Event } from 'nostr-tools' import { Event } from 'nostr-tools'
@ -161,7 +162,7 @@ export default function Zap({
className="px-2.5 py-1.5 text-lg" className="px-2.5 py-1.5 text-lg"
imgClassName="size-5" imgClassName="size-5"
/> />
<span className="text-xl font-semibold text-yellow-400/90">{t('Superchat')}</span> <span className={cn('text-xl', superchatTitleClass)}>{t('Superchat')}</span>
{amount != null ? ( {amount != null ? (
<span className="text-xl font-bold tabular-nums tracking-tight text-foreground"> <span className="text-xl font-bold tabular-nums tracking-tight text-foreground">
{formatAmount(amount)} {t('sats')} {formatAmount(amount)} {t('sats')}

5
src/components/PaytoDialog/LightningInvoiceSection.tsx

@ -13,6 +13,7 @@ import {
parseGroupedIntegerInput parseGroupedIntegerInput
} from '@/lib/lightning' } from '@/lib/lightning'
import { buildPaytoUri, formatPaytoTagValue } from '@/lib/payto' import { buildPaytoUri, formatPaytoTagValue } from '@/lib/payto'
import { superchatLightningAccentClass } from '@/lib/superchat-ui'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { useZap } from '@/providers/ZapProvider' import { useZap } from '@/providers/ZapProvider'
import lightning from '@/services/lightning.service' import lightning from '@/services/lightning.service'
@ -211,7 +212,7 @@ export default function LightningInvoiceSection({
size="default" size="default"
className={cn( className={cn(
'h-10 min-w-0 px-1.5 text-sm tabular-nums sm:text-base', 'h-10 min-w-0 px-1.5 text-sm tabular-nums sm:text-base',
active && 'ring-1 ring-yellow-400/50' active && 'ring-1 ring-amber-600/45 dark:ring-yellow-400/50'
)} )}
onClick={() => setSats(preset)} onClick={() => setSats(preset)}
> >
@ -268,7 +269,7 @@ export default function LightningInvoiceSection({
{creating ? ( {creating ? (
<Skeleton className="size-5 shrink-0 rounded-full" aria-hidden /> <Skeleton className="size-5 shrink-0 rounded-full" aria-hidden />
) : ( ) : (
<Zap className="size-5 shrink-0 text-yellow-400" /> <Zap className={cn('size-5 shrink-0', superchatLightningAccentClass)} />
)} )}
{t('Create invoice')} {t('Create invoice')}
</Button> </Button>

3
src/components/PaytoDialog/index.tsx

@ -31,6 +31,7 @@ import {
resolvePaytoPaymentOpenHandlers, resolvePaytoPaymentOpenHandlers,
resolvePaytoProfileUrl resolvePaytoProfileUrl
} from '@/lib/payto' } from '@/lib/payto'
import { superchatLightningAccentClass } from '@/lib/superchat-ui'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { mergePostPaymentContext, type PostPaymentContext } from '@/lib/post-payment-context' import { mergePostPaymentContext, type PostPaymentContext } from '@/lib/post-payment-context'
@ -194,7 +195,7 @@ export default function PaytoDialog({
> >
<DialogHeader className="shrink-0 space-y-1 border-b border-border/60 px-4 pb-3 pt-4 text-left sm:px-5 sm:pt-5"> <DialogHeader className="shrink-0 space-y-1 border-b border-border/60 px-4 pb-3 pt-4 text-left sm:px-5 sm:pt-5">
<DialogTitle className="flex min-w-0 items-center gap-2 pr-8 text-lg sm:text-xl"> <DialogTitle className="flex min-w-0 items-center gap-2 pr-8 text-lg sm:text-xl">
{isLightning && <Zap className="size-6 shrink-0 text-yellow-400" />} {isLightning && <Zap className={cn('size-6 shrink-0', superchatLightningAccentClass)} />}
<span className="truncate">{label}</span> <span className="truncate">{label}</span>
</DialogTitle> </DialogTitle>
<DialogDescription className="text-left text-sm leading-relaxed sm:text-base"> <DialogDescription className="text-left text-sm leading-relaxed sm:text-base">

6
src/components/PaytoTypeIcon/index.tsx

@ -4,6 +4,7 @@ import {
getPaytoLogoPath, getPaytoLogoPath,
isLightningPaytoType isLightningPaytoType
} from '@/lib/payto' } from '@/lib/payto'
import { superchatLightningAccentClass } from '@/lib/superchat-ui'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { HelpCircle, Zap as ZapIcon } from 'lucide-react' import { HelpCircle, Zap as ZapIcon } from 'lucide-react'
@ -27,7 +28,10 @@ export default function PaytoTypeIcon({
aria-hidden aria-hidden
> >
{isLightning ? ( {isLightning ? (
<ZapIcon className={cn('size-4 shrink-0 text-yellow-400', imgClassName)} strokeWidth={2} /> <ZapIcon
className={cn('size-4 shrink-0', superchatLightningAccentClass, imgClassName)}
strokeWidth={2}
/>
) : logoPath ? ( ) : logoPath ? (
<img src={logoPath} alt="" className={cn('size-4 object-contain', imgClassName)} /> <img src={logoPath} alt="" className={cn('size-4 object-contain', imgClassName)} />
) : iconChar != null ? ( ) : iconChar != null ? (

3
src/components/Profile/ProfileWallSuperchats.tsx

@ -1,6 +1,7 @@
import Superchat from '@/components/Note/Superchat' import Superchat from '@/components/Note/Superchat'
import Zap from '@/components/Note/Zap' import Zap from '@/components/Note/Zap'
import { ExtendedKind } from '@/constants' import { ExtendedKind } from '@/constants'
import { superchatSectionHeadingClass } from '@/lib/superchat-ui'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Skeleton } from '@/components/ui/skeleton' import { Skeleton } from '@/components/ui/skeleton'
import { Event } from 'nostr-tools' import { Event } from 'nostr-tools'
@ -34,7 +35,7 @@ export default function ProfileWallSuperchats({
return ( return (
<section className="mt-4 min-w-0" aria-label={t('Profile wall superchats')}> <section className="mt-4 min-w-0" aria-label={t('Profile wall superchats')}>
<h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-yellow-400/90"> <h3 className={cn('mb-2', superchatSectionHeadingClass)}>
{t('Superchats')} {t('Superchats')}
</h3> </h3>
<div <div

12
src/components/TurnIntoSuperchatButton/index.tsx

@ -8,6 +8,11 @@ import {
getSuperchatPaymentRecipientPubkey, getSuperchatPaymentRecipientPubkey,
isAttestableSuperchatPayment isAttestableSuperchatPayment
} from '@/lib/superchat' } from '@/lib/superchat'
import {
superchatConfirmedBoxClass,
superchatConfirmedTextClass,
superchatProminentButtonClass
} from '@/lib/superchat-ui'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { requestProfileWallRefresh } from '@/hooks/useProfileWall' import { requestProfileWallRefresh } from '@/hooks/useProfileWall'
import { usePaymentAttestationStatus } from '@/hooks/usePaymentAttestationStatus' import { usePaymentAttestationStatus } from '@/hooks/usePaymentAttestationStatus'
@ -78,8 +83,8 @@ function TurnIntoSuperchatButtonInner({
return ( return (
<p <p
className={cn( className={cn(
'text-sm font-medium text-yellow-400/90', superchatConfirmedTextClass,
prominent && 'rounded-md border border-yellow-400/40 bg-yellow-400/10 px-3 py-2 text-center', prominent && superchatConfirmedBoxClass,
className className
)} )}
> >
@ -120,8 +125,7 @@ function TurnIntoSuperchatButtonInner({
type="button" type="button"
variant={prominent ? 'default' : 'secondary'} variant={prominent ? 'default' : 'secondary'}
className={cn( className={cn(
prominent && prominent && superchatProminentButtonClass,
'h-auto min-h-11 w-full gap-2 border-yellow-400/50 bg-yellow-400/20 py-2.5 text-base font-semibold text-yellow-100 shadow-[0_0_16px_rgba(250,204,21,0.25)] hover:bg-yellow-400/30',
className className
)} )}
disabled={checking || publishing} disabled={checking || publishing}

3
src/components/ZapDialog/ZapSatsAmountInput.tsx

@ -5,6 +5,7 @@ import {
shouldHighlightLeadingSatsGroups, shouldHighlightLeadingSatsGroups,
splitSatsGroupedParts splitSatsGroupedParts
} from '@/lib/lightning' } from '@/lib/lightning'
import { superchatSatsLeadingHighlightClass } from '@/lib/superchat-ui'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const inputTypography = const inputTypography =
@ -35,7 +36,7 @@ export default function ZapSatsAmountInput({
{parts.map((part, index) => ( {parts.map((part, index) => (
<span <span
key={`${index}-${part}`} key={`${index}-${part}`}
className={cn(index === 0 && highlightLeading && 'text-yellow-400')} className={cn(index === 0 && highlightLeading && superchatSatsLeadingHighlightClass)}
> >
{part} {part}
</span> </span>

16
src/components/ZapDialog/index.tsx

@ -23,6 +23,7 @@ import { useZap } from '@/providers/ZapProvider'
import { useBtcUsdRate } from '@/hooks/useBtcUsdRate' import { useBtcUsdRate } from '@/hooks/useBtcUsdRate'
import { clampZapSats, formatSatsGrouped, shouldHighlightLeadingSatsGroups } from '@/lib/lightning' import { clampZapSats, formatSatsGrouped, shouldHighlightLeadingSatsGroups } from '@/lib/lightning'
import { formatBtcFromSats, formatUsdFromSats } from '@/lib/sats-fiat' import { formatBtcFromSats, formatUsdFromSats } from '@/lib/sats-fiat'
import { superchatAmountHighlightClass, superchatLightningAccentClass } from '@/lib/superchat-ui'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import lightning from '@/services/lightning.service' import lightning from '@/services/lightning.service'
import noteStatsService from '@/services/note-stats.service' import noteStatsService from '@/services/note-stats.service'
@ -482,8 +483,7 @@ function ZapDialogContent({
> >
<span <span
className={cn( className={cn(
highlightLargeAmount && highlightLargeAmount && superchatAmountHighlightClass
'rounded-md bg-yellow-400/25 px-2 py-0.5 font-semibold text-yellow-200 shadow-[0_0_12px_rgba(250,204,21,0.45)] ring-1 ring-yellow-400/70'
)} )}
> >
{btcEquivalent} {btcEquivalent}
@ -537,7 +537,7 @@ function ZapDialogContent({
id="zap-lightning-address" id="zap-lightning-address"
className="flex min-w-0 items-center gap-2 text-sm text-muted-foreground" className="flex min-w-0 items-center gap-2 text-sm text-muted-foreground"
> >
<span className="shrink-0 text-lg leading-none text-yellow-400" aria-hidden> <span className={cn('shrink-0 text-lg leading-none', superchatLightningAccentClass)} aria-hidden>
</span> </span>
<span className="min-w-0 break-all">{lightningAddressOptions[0]}</span> <span className="min-w-0 break-all">{lightningAddressOptions[0]}</span>
@ -548,7 +548,10 @@ function ZapDialogContent({
<SelectValue placeholder={t('Select lightning address')}> <SelectValue placeholder={t('Select lightning address')}>
{selectedLightning ? ( {selectedLightning ? (
<span className="flex min-w-0 items-center gap-2"> <span className="flex min-w-0 items-center gap-2">
<span className="shrink-0 text-lg leading-none text-yellow-400" aria-hidden> <span
className={cn('shrink-0 text-lg leading-none', superchatLightningAccentClass)}
aria-hidden
>
</span> </span>
<span className="min-w-0 truncate">{selectedLightning}</span> <span className="min-w-0 truncate">{selectedLightning}</span>
@ -560,7 +563,10 @@ function ZapDialogContent({
{lightningAddressOptions.map((addr) => ( {lightningAddressOptions.map((addr) => (
<SelectItem key={addr} value={addr} className="break-all"> <SelectItem key={addr} value={addr} className="break-all">
<span className="flex items-start gap-2"> <span className="flex items-start gap-2">
<span className="shrink-0 text-lg leading-none text-yellow-400" aria-hidden> <span
className={cn('shrink-0 text-lg leading-none', superchatLightningAccentClass)}
aria-hidden
>
</span> </span>
<span className="min-w-0 break-all">{addr}</span> <span className="min-w-0 break-all">{addr}</span>

31
src/lib/superchat-ui.ts

@ -0,0 +1,31 @@
/** Shared superchat accent styles — readable in light and dark mode. */
/** “Superchat” label in thread / notification cards. */
export const superchatTitleClass =
'font-semibold text-amber-700 dark:text-amber-300'
/** Profile wall section heading (“Superchats”). */
export const superchatSectionHeadingClass =
'text-xs font-semibold uppercase tracking-wider text-amber-800/90 dark:text-amber-200/90'
/** Recipient-confirmed state text. */
export const superchatConfirmedTextClass =
'text-sm font-medium text-amber-800 dark:text-amber-200'
/** Recipient-confirmed box (prominent notification layout). */
export const superchatConfirmedBoxClass =
'rounded-md border border-amber-600/35 bg-amber-500/10 px-3 py-2 text-center dark:border-amber-400/40 dark:bg-amber-400/10'
/** Full-width “Turn this into a superchat!” CTA. */
export const superchatProminentButtonClass =
'h-auto min-h-11 w-full gap-2 border-amber-600/45 bg-amber-500/15 py-2.5 text-base font-semibold text-amber-950 shadow-[0_0_16px_rgba(245,158,11,0.2)] hover:bg-amber-500/25 dark:border-yellow-400/50 dark:bg-yellow-400/20 dark:text-yellow-50 dark:shadow-[0_0_16px_rgba(250,204,21,0.25)] dark:hover:bg-yellow-400/30'
/** Large zap amount / BTC equivalent highlight in ZapDialog. */
export const superchatAmountHighlightClass =
'rounded-md bg-amber-500/20 px-2 py-0.5 font-semibold text-amber-950 ring-1 ring-amber-600/45 shadow-[0_0_12px_rgba(245,158,11,0.25)] dark:bg-yellow-400/25 dark:text-yellow-100 dark:ring-yellow-400/70 dark:shadow-[0_0_12px_rgba(250,204,21,0.45)]'
/** Leading digit group highlight on large sats input. */
export const superchatSatsLeadingHighlightClass = 'text-amber-600 dark:text-yellow-400'
/** Lightning bolt accent (zap address rows, payto icons). */
export const superchatLightningAccentClass = 'text-amber-600 dark:text-yellow-400'
Loading…
Cancel
Save