chore: format
This commit is contained in:
parent
4bd4141b54
commit
e490407dd5
225 changed files with 924 additions and 844 deletions
|
|
@ -2,3 +2,4 @@ singleQuote: true
|
|||
semi: false
|
||||
printWidth: 100
|
||||
trailingComma: none
|
||||
plugins: [prettier-plugin-tailwindcss]
|
||||
|
|
|
|||
80
package-lock.json
generated
80
package-lock.json
generated
|
|
@ -95,6 +95,7 @@
|
|||
"globals": "^15.13.0",
|
||||
"postcss": "^8.4.49",
|
||||
"prettier": "3.4.2",
|
||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "~5.6.2",
|
||||
"typescript-eslint": "^8.18.1",
|
||||
|
|
@ -10392,6 +10393,85 @@
|
|||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-tailwindcss": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.7.2.tgz",
|
||||
"integrity": "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.19"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ianvs/prettier-plugin-sort-imports": "*",
|
||||
"@prettier/plugin-hermes": "*",
|
||||
"@prettier/plugin-oxc": "*",
|
||||
"@prettier/plugin-pug": "*",
|
||||
"@shopify/prettier-plugin-liquid": "*",
|
||||
"@trivago/prettier-plugin-sort-imports": "*",
|
||||
"@zackad/prettier-plugin-twig": "*",
|
||||
"prettier": "^3.0",
|
||||
"prettier-plugin-astro": "*",
|
||||
"prettier-plugin-css-order": "*",
|
||||
"prettier-plugin-jsdoc": "*",
|
||||
"prettier-plugin-marko": "*",
|
||||
"prettier-plugin-multiline-arrays": "*",
|
||||
"prettier-plugin-organize-attributes": "*",
|
||||
"prettier-plugin-organize-imports": "*",
|
||||
"prettier-plugin-sort-imports": "*",
|
||||
"prettier-plugin-svelte": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@ianvs/prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"@prettier/plugin-hermes": {
|
||||
"optional": true
|
||||
},
|
||||
"@prettier/plugin-oxc": {
|
||||
"optional": true
|
||||
},
|
||||
"@prettier/plugin-pug": {
|
||||
"optional": true
|
||||
},
|
||||
"@shopify/prettier-plugin-liquid": {
|
||||
"optional": true
|
||||
},
|
||||
"@trivago/prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"@zackad/prettier-plugin-twig": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-astro": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-css-order": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-jsdoc": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-marko": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-multiline-arrays": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-organize-attributes": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-organize-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-svelte": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-bytes": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz",
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@
|
|||
"globals": "^15.13.0",
|
||||
"postcss": "^8.4.49",
|
||||
"prettier": "3.4.2",
|
||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "~5.6.2",
|
||||
"typescript-eslint": "^8.18.1",
|
||||
|
|
|
|||
|
|
@ -339,11 +339,11 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||
>
|
||||
<CurrentRelaysProvider>
|
||||
<NotificationProvider>
|
||||
<div className="flex lg:justify-around w-full">
|
||||
<div className="sticky top-0 lg:w-full flex justify-end self-start h-[var(--vh)]">
|
||||
<div className="flex w-full lg:justify-around">
|
||||
<div className="sticky top-0 flex h-[var(--vh)] justify-end self-start lg:w-full">
|
||||
<Sidebar />
|
||||
</div>
|
||||
<div className="flex-1 w-0 bg-background border-x lg:flex-auto lg:w-[640px] lg:shrink-0">
|
||||
<div className="w-0 flex-1 border-x bg-background lg:w-[640px] lg:flex-auto lg:shrink-0">
|
||||
{!!secondaryStack.length &&
|
||||
secondaryStack.map((item, index) => (
|
||||
<div
|
||||
|
|
@ -369,10 +369,10 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="hidden lg:w-full lg:block" />
|
||||
<div className="hidden lg:block lg:w-full" />
|
||||
</div>
|
||||
<TooManyRelaysAlertDialog />
|
||||
<BackgroundAudio className="fixed bottom-20 right-0 z-50 w-80 rounded-l-full rounded-r-none overflow-hidden shadow-lg border" />
|
||||
<BackgroundAudio className="fixed bottom-20 right-0 z-50 w-80 overflow-hidden rounded-l-full rounded-r-none border shadow-lg" />
|
||||
</NotificationProvider>
|
||||
</CurrentRelaysProvider>
|
||||
</SecondaryPageContext.Provider>
|
||||
|
|
@ -407,20 +407,20 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||
<Sidebar />
|
||||
<div
|
||||
className={cn(
|
||||
'grid grid-cols-2 w-full',
|
||||
themeSetting === 'pure-black' ? '' : 'gap-2 pr-2 py-2'
|
||||
'grid w-full grid-cols-2',
|
||||
themeSetting === 'pure-black' ? '' : 'gap-2 py-2 pr-2'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'bg-background overflow-hidden',
|
||||
'overflow-hidden bg-background',
|
||||
themeSetting === 'pure-black' ? 'border-l' : 'rounded-2xl shadow-lg'
|
||||
)}
|
||||
>
|
||||
{primaryPages.map(({ name, element, props }) => (
|
||||
<div
|
||||
key={name}
|
||||
className="flex flex-col h-full w-full"
|
||||
className="flex h-full w-full flex-col"
|
||||
style={{
|
||||
display: currentPrimaryPage === name ? 'block' : 'none'
|
||||
}}
|
||||
|
|
@ -431,7 +431,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'bg-background overflow-hidden',
|
||||
'overflow-hidden bg-background',
|
||||
themeSetting === 'pure-black' ? 'border-l' : 'rounded-2xl',
|
||||
themeSetting !== 'pure-black' && secondaryStack.length > 0 && 'shadow-lg',
|
||||
secondaryStack.length === 0 ? 'bg-surface' : ''
|
||||
|
|
@ -440,7 +440,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||
{secondaryStack.map((item, index) => (
|
||||
<div
|
||||
key={item.index}
|
||||
className="flex flex-col h-full w-full"
|
||||
className="flex h-full w-full flex-col"
|
||||
style={{ display: index === secondaryStack.length - 1 ? 'block' : 'none' }}
|
||||
>
|
||||
{item.element}
|
||||
|
|
@ -451,7 +451,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||
</div>
|
||||
</div>
|
||||
<TooManyRelaysAlertDialog />
|
||||
<BackgroundAudio className="fixed bottom-20 right-0 z-50 w-80 rounded-l-full rounded-r-none overflow-hidden shadow-lg border" />
|
||||
<BackgroundAudio className="fixed bottom-20 right-0 z-50 w-80 overflow-hidden rounded-l-full rounded-r-none border shadow-lg" />
|
||||
</NotificationProvider>
|
||||
</CurrentRelaysProvider>
|
||||
</SecondaryPageContext.Provider>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export default function AboutInfoDialog({ children }: { children: React.ReactNod
|
|||
<Drawer open={open} onOpenChange={setOpen}>
|
||||
<DrawerTrigger asChild>{children}</DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<div className="p-4 space-y-4">{content}</div>
|
||||
<div className="space-y-4 p-4">{content}</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -37,18 +37,18 @@ export default function AccountList({
|
|||
.finally(() => setSwitchingAccount(null))
|
||||
}}
|
||||
>
|
||||
<div className="flex justify-between items-center p-2">
|
||||
<div className="flex-1 flex items-center gap-2 relative">
|
||||
<div className="flex items-center justify-between p-2">
|
||||
<div className="relative flex flex-1 items-center gap-2">
|
||||
<SimpleUserAvatar userId={act.pubkey} />
|
||||
<div className="flex-1 w-0">
|
||||
<SimpleUsername userId={act.pubkey} className="font-semibold truncate" />
|
||||
<div className="text-sm rounded-full bg-muted px-2 w-fit">
|
||||
<div className="w-0 flex-1">
|
||||
<SimpleUsername userId={act.pubkey} className="truncate font-semibold" />
|
||||
<div className="w-fit rounded-full bg-muted px-2 text-sm">
|
||||
{formatPubkey(act.pubkey)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<SignerTypeBadge signerType={act.signerType} />
|
||||
</div>
|
||||
<Button
|
||||
|
|
@ -65,7 +65,7 @@ export default function AccountList({
|
|||
</div>
|
||||
</div>
|
||||
{switchingAccount && isSameAccount(act, switchingAccount) && (
|
||||
<div className="absolute top-0 left-0 flex w-full h-full items-center justify-center rounded-lg bg-muted/60">
|
||||
<div className="absolute left-0 top-0 flex h-full w-full items-center justify-center rounded-lg bg-muted/60">
|
||||
<Loader size={16} className="animate-spin" />
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export default function BunkerLogin({
|
|||
onChange={handleInputChange}
|
||||
className={errMsg ? 'border-destructive' : ''}
|
||||
/>
|
||||
{errMsg && <div className="text-xs text-destructive pl-3">{errMsg}</div>}
|
||||
{errMsg && <div className="pl-3 text-xs text-destructive">{errMsg}</div>}
|
||||
</div>
|
||||
<Button onClick={handleLogin} disabled={pending}>
|
||||
<Loader className={pending ? 'animate-spin' : 'hidden'} />
|
||||
|
|
|
|||
|
|
@ -186,17 +186,17 @@ export default function NostrConnectLogin({
|
|||
|
||||
return (
|
||||
<div className="relative flex flex-col gap-4">
|
||||
<div ref={qrContainerRef} className="flex flex-col items-center w-full space-y-3 mb-3">
|
||||
<div ref={qrContainerRef} className="mb-3 flex w-full flex-col items-center space-y-3">
|
||||
<a href={loginDetails.connectionString} aria-label="Open with Nostr signer app">
|
||||
<QrCode size={qrCodeSize} value={loginDetails.connectionString} />
|
||||
</a>
|
||||
{nostrConnectionErrMsg && (
|
||||
<div className="text-xs text-destructive text-center pt-1">{nostrConnectionErrMsg}</div>
|
||||
<div className="pt-1 text-center text-xs text-destructive">{nostrConnectionErrMsg}</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex justify-center w-full mb-3">
|
||||
<div className="mb-3 flex w-full justify-center">
|
||||
<div
|
||||
className="flex items-center gap-2 text-sm text-muted-foreground bg-muted px-3 py-2 rounded-full cursor-pointer transition-all hover:bg-muted/80"
|
||||
className="flex cursor-pointer items-center gap-2 rounded-full bg-muted px-3 py-2 text-sm text-muted-foreground transition-all hover:bg-muted/80"
|
||||
style={{
|
||||
width: qrCodeSize > 0 ? `${Math.max(150, Math.min(qrCodeSize, 320))}px` : 'auto'
|
||||
}}
|
||||
|
|
@ -204,14 +204,14 @@ export default function NostrConnectLogin({
|
|||
role="button"
|
||||
tabIndex={0}
|
||||
>
|
||||
<div className="flex-grow min-w-0 truncate select-none">
|
||||
<div className="min-w-0 flex-grow select-none truncate">
|
||||
{loginDetails.connectionString}
|
||||
</div>
|
||||
<div className="flex-shrink-0">{copied ? <Check size={14} /> : <Copy size={14} />}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center w-full my-4">
|
||||
<div className="my-4 flex w-full items-center">
|
||||
<div className="flex-grow border-t border-border/40"></div>
|
||||
<span className="px-3 text-xs text-muted-foreground">OR</span>
|
||||
<div className="flex-grow border-t border-border/40"></div>
|
||||
|
|
@ -219,7 +219,7 @@ export default function NostrConnectLogin({
|
|||
|
||||
<div className="w-full space-y-1">
|
||||
<div className="flex items-start space-x-2">
|
||||
<div className="flex-1 relative">
|
||||
<div className="relative flex-1">
|
||||
<Input
|
||||
placeholder="bunker://..."
|
||||
value={bunkerInput}
|
||||
|
|
@ -229,7 +229,7 @@ export default function NostrConnectLogin({
|
|||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="absolute right-1 top-1/2 -translate-y-1/2 h-8 w-8 p-0"
|
||||
className="absolute right-1 top-1/2 h-8 w-8 -translate-y-1/2 p-0"
|
||||
onClick={startQrScan}
|
||||
disabled={pending}
|
||||
>
|
||||
|
|
@ -237,21 +237,21 @@ export default function NostrConnectLogin({
|
|||
</Button>
|
||||
</div>
|
||||
<Button onClick={() => handleLogin()} disabled={pending}>
|
||||
<Loader className={pending ? 'animate-spin mr-2' : 'hidden'} />
|
||||
<Loader className={pending ? 'mr-2 animate-spin' : 'hidden'} />
|
||||
{t('Login')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{errMsg && <div className="text-xs text-destructive pl-3 pt-1">{errMsg}</div>}
|
||||
{errMsg && <div className="pl-3 pt-1 text-xs text-destructive">{errMsg}</div>}
|
||||
</div>
|
||||
<Button variant="secondary" onClick={back} className="w-full">
|
||||
{t('Back')}
|
||||
</Button>
|
||||
|
||||
<div className={cn('w-full h-full flex justify-center', isScanning ? '' : 'hidden')}>
|
||||
<div className={cn('flex h-full w-full justify-center', isScanning ? '' : 'hidden')}>
|
||||
<video
|
||||
ref={videoRef}
|
||||
className="absolute inset-0 w-full h-full bg-background"
|
||||
className="absolute inset-0 h-full w-full bg-background"
|
||||
autoPlay
|
||||
playsInline
|
||||
muted
|
||||
|
|
@ -259,7 +259,7 @@ export default function NostrConnectLogin({
|
|||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
className="absolute top-2 right-2"
|
||||
className="absolute right-2 top-2"
|
||||
onClick={stopQrScan}
|
||||
>
|
||||
Cancel
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export default function NpubLogin({
|
|||
onChange={handleInputChange}
|
||||
className={errMsg ? 'border-destructive' : ''}
|
||||
/>
|
||||
{errMsg && <div className="text-xs text-destructive pl-3">{errMsg}</div>}
|
||||
{errMsg && <div className="pl-3 text-xs text-destructive">{errMsg}</div>}
|
||||
</div>
|
||||
<Button onClick={handleLogin} disabled={pending}>
|
||||
<Loader className={pending ? 'animate-spin' : 'hidden'} />
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export default function Signup({
|
|||
{(['generate', 'password'] as Step[]).map((s, index) => (
|
||||
<div key={s} className="flex items-center">
|
||||
<div
|
||||
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold ${
|
||||
className={`flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold ${
|
||||
step === s
|
||||
? 'bg-primary text-primary-foreground'
|
||||
: step === 'password' && s === 'generate'
|
||||
|
|
@ -63,7 +63,7 @@ export default function Signup({
|
|||
>
|
||||
{index + 1}
|
||||
</div>
|
||||
{index < 1 && <div className="w-12 h-0.5 bg-muted mx-1" />}
|
||||
{index < 1 && <div className="mx-1 h-0.5 w-12 bg-muted" />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -75,7 +75,7 @@ export default function Signup({
|
|||
{renderStepIndicator()}
|
||||
|
||||
<div className="text-center">
|
||||
<h3 className="text-lg font-semibold mb-2">{t('Create Your Nostr Account')}</h3>
|
||||
<h3 className="mb-2 text-lg font-semibold">{t('Create Your Nostr Account')}</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('Generate your unique private key. This is your digital identity.')}
|
||||
</p>
|
||||
|
|
@ -110,7 +110,7 @@ export default function Signup({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full flex flex-wrap gap-2">
|
||||
<div className="flex w-full flex-wrap gap-2">
|
||||
<Button onClick={handleDownload} className="flex-1">
|
||||
<Download />
|
||||
{t('Download Backup File')}
|
||||
|
|
@ -129,7 +129,7 @@ export default function Signup({
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 ml-2">
|
||||
<div className="ml-2 flex items-center gap-2">
|
||||
<Checkbox
|
||||
id="acknowledge-checkbox"
|
||||
checked={checkedSaveKey}
|
||||
|
|
@ -159,7 +159,7 @@ export default function Signup({
|
|||
{renderStepIndicator()}
|
||||
|
||||
<div className="text-center">
|
||||
<h3 className="text-lg font-semibold mb-2">{t('Secure Your Account')}</h3>
|
||||
<h3 className="mb-2 text-lg font-semibold">{t('Secure Your Account')}</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('Add an extra layer of protection with a password')}
|
||||
</p>
|
||||
|
|
@ -201,7 +201,7 @@ export default function Signup({
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-full flex gap-2">
|
||||
<div className="flex w-full gap-2">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ function AccountManagerNav({
|
|||
return (
|
||||
<div onClick={(e) => e.stopPropagation()} className="flex flex-col gap-8">
|
||||
<div>
|
||||
<div className="text-center text-muted-foreground text-sm font-semibold">
|
||||
<div className="text-center text-sm font-semibold text-muted-foreground">
|
||||
{t('Add an Account')}
|
||||
</div>
|
||||
<div className="space-y-2 mt-4">
|
||||
<div className="mt-4 space-y-2">
|
||||
{!!window.nostr && (
|
||||
<Button onClick={() => nip07Login().then(() => close?.())} className="w-full">
|
||||
{t('Login with Browser Extension')}
|
||||
|
|
@ -69,10 +69,10 @@ function AccountManagerNav({
|
|||
</div>
|
||||
<Separator />
|
||||
<div>
|
||||
<div className="text-center text-muted-foreground text-sm font-semibold">
|
||||
<div className="text-center text-sm font-semibold text-muted-foreground">
|
||||
{t("Don't have an account yet?")}
|
||||
</div>
|
||||
<Button onClick={() => setPage('signup')} className="w-full mt-4">
|
||||
<Button onClick={() => setPage('signup')} className="mt-4 w-full">
|
||||
{t('Create New Account')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -80,7 +80,7 @@ function AccountManagerNav({
|
|||
<>
|
||||
<Separator />
|
||||
<div>
|
||||
<div className="text-center text-muted-foreground text-sm font-semibold">
|
||||
<div className="text-center text-sm font-semibold text-muted-foreground">
|
||||
{t('Logged in Accounts')}
|
||||
</div>
|
||||
<AccountList className="mt-4" afterSwitch={() => close?.()} />
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ export default function AudioPlayer({
|
|||
<div
|
||||
ref={containerRef}
|
||||
className={cn(
|
||||
'flex items-center gap-3 py-2 px-2 border rounded-full max-w-md bg-background',
|
||||
'flex max-w-md items-center gap-3 rounded-full border bg-background px-2 py-2',
|
||||
className
|
||||
)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
|
|
@ -137,12 +137,12 @@ export default function AudioPlayer({
|
|||
<audio ref={audioRef} src={src} preload="metadata" onError={() => setError(false)} />
|
||||
|
||||
{/* Play/Pause Button */}
|
||||
<Button size="icon" className="rounded-full shrink-0" onClick={togglePlay}>
|
||||
<Button size="icon" className="shrink-0 rounded-full" onClick={togglePlay}>
|
||||
{isPlaying ? <Pause fill="currentColor" /> : <Play fill="currentColor" />}
|
||||
</Button>
|
||||
|
||||
{/* Progress Section */}
|
||||
<div className="flex-1 relative">
|
||||
<div className="relative flex-1">
|
||||
<Slider
|
||||
value={[currentTime]}
|
||||
max={duration || 100}
|
||||
|
|
@ -153,14 +153,14 @@ export default function AudioPlayer({
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="text-sm font-mono text-muted-foreground">
|
||||
<div className="font-mono text-sm text-muted-foreground">
|
||||
{formatTime(Math.max(duration - currentTime, 0))}
|
||||
</div>
|
||||
{isMinimized ? (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-full shrink-0 text-muted-foreground"
|
||||
className="shrink-0 rounded-full text-muted-foreground"
|
||||
onClick={() => mediaManager.stopAudioBackground()}
|
||||
>
|
||||
<X />
|
||||
|
|
@ -169,7 +169,7 @@ export default function AudioPlayer({
|
|||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-full shrink-0 text-muted-foreground"
|
||||
className="shrink-0 rounded-full text-muted-foreground"
|
||||
onClick={() => mediaManager.playAudioBackground(src, audioRef.current?.currentTime || 0)}
|
||||
>
|
||||
<Minimize2 />
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export default function BookmarkButton({ stuff }: { stuff: Event | string }) {
|
|||
<button
|
||||
className={`flex items-center gap-1 ${
|
||||
isBookmarked ? 'text-rose-400' : 'text-muted-foreground'
|
||||
} enabled:hover:text-rose-400 px-3 h-full disabled:text-muted-foreground/40 disabled:cursor-default`}
|
||||
} h-full px-3 enabled:hover:text-rose-400 disabled:cursor-default disabled:text-muted-foreground/40`}
|
||||
onClick={isBookmarked ? handleRemoveBookmark : handleBookmark}
|
||||
disabled={!event || updating}
|
||||
title={isBookmarked ? t('Remove bookmark') : t('Bookmark')}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export default function BookmarkList() {
|
|||
|
||||
if (eventIds.length === 0) {
|
||||
return (
|
||||
<div className="mt-2 text-sm text-center text-muted-foreground">
|
||||
<div className="mt-2 text-center text-sm text-muted-foreground">
|
||||
{t('no bookmarks found')}
|
||||
</div>
|
||||
)
|
||||
|
|
@ -79,7 +79,7 @@ export default function BookmarkList() {
|
|||
<NoteCardLoadingSkeleton />
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center text-sm text-muted-foreground mt-2">
|
||||
<div className="mt-2 text-center text-sm text-muted-foreground">
|
||||
{t('no more bookmarks')}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ export default function AccountButton() {
|
|||
profile ? (
|
||||
<SimpleUserAvatar
|
||||
userId={pubkey}
|
||||
className={cn('size-6', active ? 'ring-primary ring-2' : '')}
|
||||
className={cn('size-6', active ? 'ring-2 ring-primary' : '')}
|
||||
/>
|
||||
) : (
|
||||
<Skeleton className={cn('size-6 rounded-full', active ? 'ring-primary ring-2' : '')} />
|
||||
<Skeleton className={cn('size-6 rounded-full', active ? 'ring-2 ring-primary' : '')} />
|
||||
)
|
||||
) : (
|
||||
<UserRound />
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default function BottomNavigationBarItem({
|
|||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
'flex shadow-none items-center bg-transparent w-full h-12 p-3 m-0 rounded-lg [&_svg]:size-6',
|
||||
'm-0 flex h-12 w-full items-center rounded-lg bg-transparent p-3 shadow-none [&_svg]:size-6',
|
||||
active && 'text-primary hover:text-primary'
|
||||
)}
|
||||
variant="ghost"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default function NotificationsButton() {
|
|||
<div className="relative">
|
||||
<Bell />
|
||||
{hasNewNotification && (
|
||||
<div className="absolute -top-0.5 right-0.5 w-2 h-2 ring-2 ring-background bg-primary rounded-full" />
|
||||
<div className="absolute -top-0.5 right-0.5 h-2 w-2 rounded-full bg-primary ring-2 ring-background" />
|
||||
)}
|
||||
</div>
|
||||
</BottomNavigationBarItem>
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import NotificationsButton from './NotificationsButton'
|
|||
export default function BottomNavigationBar() {
|
||||
return (
|
||||
<div
|
||||
className={cn('fixed bottom-0 w-full z-40 bg-background border-t')}
|
||||
className={cn('fixed bottom-0 z-40 w-full border-t bg-background')}
|
||||
style={{
|
||||
paddingBottom: 'env(safe-area-inset-bottom)'
|
||||
}}
|
||||
>
|
||||
<BackgroundAudio className="rounded-none border-x-0 border-t-0 border-b bg-background" />
|
||||
<div className="w-full flex justify-around items-center [&_svg]:size-4 [&_svg]:shrink-0">
|
||||
<BackgroundAudio className="rounded-none border-x-0 border-b border-t-0 bg-background" />
|
||||
<div className="flex w-full items-center justify-around [&_svg]:size-4 [&_svg]:shrink-0">
|
||||
<HomeButton />
|
||||
<ExploreButton />
|
||||
<NotificationsButton />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default function ClientTag({ event }: { event: NostrEvent }) {
|
|||
if (!usingClient) return null
|
||||
|
||||
return (
|
||||
<span className="text-sm text-muted-foreground shrink-0">
|
||||
<span className="shrink-0 text-sm text-muted-foreground">
|
||||
{t('via {{client}}', { client: usingClient })}
|
||||
</span>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export default function Collapsible({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={cn('relative text-left overflow-hidden', className)}
|
||||
className={cn('relative overflow-hidden text-left', className)}
|
||||
ref={containerRef}
|
||||
{...props}
|
||||
style={{
|
||||
|
|
@ -57,8 +57,8 @@ export default function Collapsible({
|
|||
>
|
||||
{children}
|
||||
{shouldCollapse && !expanded && (
|
||||
<div className="absolute bottom-0 h-40 w-full z-10 bg-gradient-to-b from-transparent to-background/90 flex items-end justify-center pb-4">
|
||||
<div className="bg-background rounded-lg">
|
||||
<div className="absolute bottom-0 z-10 flex h-40 w-full items-end justify-center bg-gradient-to-b from-transparent to-background/90 pb-4">
|
||||
<div className="rounded-lg bg-background">
|
||||
<Button
|
||||
className="bg-foreground hover:bg-foreground/80"
|
||||
onClick={(e) => {
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ export default function Content({
|
|||
let imageIndex = 0
|
||||
return (
|
||||
<>
|
||||
<div ref={contentRef} className={cn('text-wrap break-words whitespace-pre-wrap', className)}>
|
||||
<div ref={contentRef} className={cn('whitespace-pre-wrap text-wrap break-words', className)}>
|
||||
{nodes.map((node, index) => {
|
||||
if (node.type === 'text') {
|
||||
return node.data
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function CommunityDefinitionPreview({
|
|||
|
||||
return (
|
||||
<div className={cn('pointer-events-none', className)}>
|
||||
[{t('Community')}] <span className="italic pr-0.5">{metadata.name}</span>
|
||||
[{t('Community')}] <span className="pr-0.5 italic">{metadata.name}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function EmojiPackPreview({
|
|||
|
||||
return (
|
||||
<div className={cn('pointer-events-none', className)}>
|
||||
[{t('Emoji Pack')}] <span className="italic pr-0.5">{title}</span>
|
||||
[{t('Emoji Pack')}] <span className="pr-0.5 italic">{title}</span>
|
||||
{emojis.length > 0 && <span>({emojis.length})</span>}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function FollowPackPreview({
|
|||
|
||||
return (
|
||||
<div className={cn('truncate', className)}>
|
||||
[{t('Follow Pack')}] <span className="italic pr-0.5">{title}</span>
|
||||
[{t('Follow Pack')}] <span className="pr-0.5 italic">{title}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function GroupMetadataPreview({
|
|||
|
||||
return (
|
||||
<div className={cn('pointer-events-none', className)}>
|
||||
[{t('Group')}] <span className="italic pr-0.5">{metadata.name}</span>
|
||||
[{t('Group')}] <span className="pr-0.5 italic">{metadata.name}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default function HighlightPreview({
|
|||
<Content
|
||||
content={translatedEvent?.content ?? event.content}
|
||||
emojiInfos={emojiInfos}
|
||||
className="italic pr-0.5"
|
||||
className="pr-0.5 italic"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function LiveEventPreview({
|
|||
|
||||
return (
|
||||
<div className={cn('pointer-events-none', className)}>
|
||||
[{t('Live event')}] <span className="italic pr-0.5">{metadata.title}</span>
|
||||
[{t('Live event')}] <span className="pr-0.5 italic">{metadata.title}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function LongFormArticlePreview({
|
|||
|
||||
return (
|
||||
<div className={cn('pointer-events-none', className)}>
|
||||
[{t('Article')}] <span className="italic pr-0.5">{metadata.title}</span>
|
||||
[{t('Article')}] <span className="pr-0.5 italic">{metadata.title}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default function PictureNotePreview({
|
|||
|
||||
return (
|
||||
<div className={cn('pointer-events-none', className)}>
|
||||
[{t('Image')}] <span className="italic pr-0.5">{event.content}</span>
|
||||
[{t('Image')}] <span className="pr-0.5 italic">{event.content}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default function PollPreview({ event, className }: { event: Event; classN
|
|||
<Content
|
||||
content={translatedEvent?.content ?? event.content}
|
||||
emojiInfos={emojiInfos}
|
||||
className="italic pr-0.5"
|
||||
className="pr-0.5 italic"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default function VideoNotePreview({
|
|||
|
||||
return (
|
||||
<div className={cn('pointer-events-none', className)}>
|
||||
[{t('Media')}] <span className="italic pr-0.5">{event.content}</span>
|
||||
[{t('Media')}] <span className="pr-0.5 italic">{event.content}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,23 +85,23 @@ export default function DefaultRelaysSetting() {
|
|||
/>
|
||||
<Button onClick={saveNewRelayUrl}>{t('Add')}</Button>
|
||||
</div>
|
||||
{newRelayUrlError && <div className="text-xs text-destructive mt-1">{newRelayUrlError}</div>}
|
||||
{newRelayUrlError && <div className="mt-1 text-xs text-destructive">{newRelayUrlError}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function RelayUrl({ url, onRemove }: { url: string; onRemove: () => void }) {
|
||||
return (
|
||||
<div className="flex items-center justify-between pl-1 pr-3 py-1">
|
||||
<div className="flex gap-3 items-center flex-1 w-0">
|
||||
<RelayIcon url={url} className="w-4 h-4" />
|
||||
<div className="text-muted-foreground text-sm truncate">{url}</div>
|
||||
<div className="flex items-center justify-between py-1 pl-1 pr-3">
|
||||
<div className="flex w-0 flex-1 items-center gap-3">
|
||||
<RelayIcon url={url} className="h-4 w-4" />
|
||||
<div className="truncate text-sm text-muted-foreground">{url}</div>
|
||||
</div>
|
||||
<div className="shrink-0">
|
||||
<CircleX
|
||||
size={16}
|
||||
onClick={onRemove}
|
||||
className="text-muted-foreground hover:text-destructive cursor-pointer"
|
||||
className="cursor-pointer text-muted-foreground hover:text-destructive"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ export default function PlatinumSponsors() {
|
|||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="font-semibold text-center">{t('Platinum Sponsors')}</div>
|
||||
<div className="flex flex-col gap-2 items-center">
|
||||
<div className="text-center font-semibold">{t('Platinum Sponsors')}</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div
|
||||
className="flex items-center gap-4 cursor-pointer"
|
||||
className="flex cursor-pointer items-center gap-4"
|
||||
onClick={() => window.open('https://opensats.org/', '_blank')}
|
||||
>
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -21,23 +21,23 @@ export default function RecentSupporters() {
|
|||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="font-semibold text-center">{t('Recent Supporters')}</div>
|
||||
<div className="text-center font-semibold">{t('Recent Supporters')}</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
{supporters.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-center justify-between rounded-md border p-2 sm:p-4 gap-2"
|
||||
className="flex items-center justify-between gap-2 rounded-md border p-2 sm:p-4"
|
||||
>
|
||||
<div className="flex items-center gap-2 flex-1 w-0">
|
||||
<div className="flex w-0 flex-1 items-center gap-2">
|
||||
<UserAvatar userId={item.pubkey} />
|
||||
<div className="flex-1 w-0">
|
||||
<Username className="font-semibold w-fit" userId={item.pubkey} />
|
||||
<div className="text-xs text-muted-foreground line-clamp-3 select-text">
|
||||
<div className="w-0 flex-1">
|
||||
<Username className="w-fit font-semibold" userId={item.pubkey} />
|
||||
<div className="line-clamp-3 select-text text-xs text-muted-foreground">
|
||||
{item.comment}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="font-semibold text-yellow-400 shrink-0">
|
||||
<div className="shrink-0 font-semibold text-yellow-400">
|
||||
{formatAmount(item.amount)} {t('sats')}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ export default function Donation({ className }: { className?: string }) {
|
|||
const [donationAmount, setDonationAmount] = useState<number | undefined>(undefined)
|
||||
|
||||
return (
|
||||
<div className={cn('p-4 border rounded-lg space-y-4', className)}>
|
||||
<div className={cn('space-y-4 rounded-lg border p-4', className)}>
|
||||
<div className="text-center font-semibold">{t('Enjoying Jumble?')}</div>
|
||||
<div className="text-center text-muted-foreground">
|
||||
{t('Your donation helps me maintain Jumble and make it better! 😊')}
|
||||
</div>
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
|
||||
{[
|
||||
{ amount: 1000, text: '☕️ 1k' },
|
||||
{ amount: 10000, text: '🍜 10k' },
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default function DrawerMenuItem({
|
|||
<DrawerClose className="w-full">
|
||||
<Button
|
||||
onClick={onClick}
|
||||
className={cn('w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5', className)}
|
||||
className={cn('w-full justify-start gap-4 p-6 text-lg [&_svg]:size-5', className)}
|
||||
variant="ghost"
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -42,21 +42,21 @@ export function EmbeddedLNInvoice({ invoice, className }: { invoice: string; cla
|
|||
|
||||
return (
|
||||
<div
|
||||
className={cn('p-3 border rounded-lg cursor-default flex flex-col gap-3 max-w-sm', className)}
|
||||
className={cn('flex max-w-sm cursor-default flex-col gap-3 rounded-lg border p-3', className)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Zap className="w-5 h-5 text-yellow-400" />
|
||||
<div className="font-semibold text-sm">{t('Lightning Invoice')}</div>
|
||||
<Zap className="h-5 w-5 text-yellow-400" />
|
||||
<div className="text-sm font-semibold">{t('Lightning Invoice')}</div>
|
||||
</div>
|
||||
{description && (
|
||||
<div className="text-sm text-muted-foreground break-words">{description}</div>
|
||||
<div className="break-words text-sm text-muted-foreground">{description}</div>
|
||||
)}
|
||||
<div className="text-lg font-bold">
|
||||
{formatAmount(amount)} {t('sats')}
|
||||
</div>
|
||||
<Button onClick={handlePayClick}>
|
||||
{paying && <Loader className="w-4 h-4 animate-spin" />}
|
||||
{paying && <Loader className="h-4 w-4 animate-spin" />}
|
||||
{t('Pay')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export function EmbeddedMention({ userId, className }: { userId: string; classNa
|
|||
<Username
|
||||
userId={userId}
|
||||
showAt
|
||||
className={cn('text-primary font-normal inline', className)}
|
||||
className={cn('inline font-normal text-primary', className)}
|
||||
withoutSkeleton
|
||||
/>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -29,18 +29,18 @@ export function EmbeddedNote({ noteId, className }: { noteId: string; className?
|
|||
function EmbeddedNoteSkeleton({ className }: { className?: string }) {
|
||||
return (
|
||||
<div
|
||||
className={cn('text-left p-2 sm:p-3 border rounded-xl bg-card', className)}
|
||||
className={cn('rounded-xl border bg-card p-2 text-left sm:p-3', className)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Skeleton className="w-9 h-9 rounded-full" />
|
||||
<Skeleton className="h-9 w-9 rounded-full" />
|
||||
<div>
|
||||
<Skeleton className="h-3 w-16 my-1" />
|
||||
<Skeleton className="h-3 w-16 my-1" />
|
||||
<Skeleton className="my-1 h-3 w-16" />
|
||||
<Skeleton className="my-1 h-3 w-16" />
|
||||
</div>
|
||||
</div>
|
||||
<Skeleton className="w-full h-4 my-1 mt-2" />
|
||||
<Skeleton className="w-2/3 h-4 my-1" />
|
||||
<Skeleton className="my-1 mt-2 h-4 w-full" />
|
||||
<Skeleton className="my-1 h-4 w-2/3" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -49,10 +49,10 @@ function EmbeddedNoteNotFound({ noteId, className }: { noteId: string; className
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={cn('text-left p-2 sm:p-3 border rounded-xl bg-card', className)}>
|
||||
<div className="flex flex-col items-center text-muted-foreground font-medium gap-2">
|
||||
<div className={cn('rounded-xl border bg-card p-2 text-left sm:p-3', className)}>
|
||||
<div className="flex flex-col items-center gap-2 font-medium text-muted-foreground">
|
||||
<div>{t('Sorry! The note cannot be found 😔')}</div>
|
||||
<ClientSelect className="w-full mt-2" originalNoteId={noteId} />
|
||||
<ClientSelect className="mt-2 w-full" originalNoteId={noteId} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export function EmbeddedWebsocketUrl({ url }: { url: string }) {
|
|||
}}
|
||||
>
|
||||
[ {url} ]
|
||||
<span className="w-2 h-1 bg-primary" />
|
||||
<span className="h-1 w-2 bg-primary" />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default function Emoji({
|
|||
|
||||
if (typeof emoji === 'string') {
|
||||
return emoji === '+' ? (
|
||||
<Heart className={cn('size-5 text-red-400 fill-red-400', classNames?.img)} />
|
||||
<Heart className={cn('size-5 fill-red-400 text-red-400', classNames?.img)} />
|
||||
) : (
|
||||
<span className={cn('whitespace-nowrap', classNames?.text)}>{emoji}</span>
|
||||
)
|
||||
|
|
@ -34,7 +34,7 @@ export default function Emoji({
|
|||
src={emoji.url}
|
||||
alt={emoji.shortcode}
|
||||
draggable={false}
|
||||
className={cn('inline-block size-5 pointer-events-none', classNames?.img)}
|
||||
className={cn('pointer-events-none inline-block size-5', classNames?.img)}
|
||||
onLoad={() => {
|
||||
setHasError(false)
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export default function EmojiPackList() {
|
|||
|
||||
if (eventIds.length === 0) {
|
||||
return (
|
||||
<div className="mt-2 text-sm text-center text-muted-foreground">
|
||||
<div className="mt-2 text-center text-sm text-muted-foreground">
|
||||
{t('no emoji packs found')}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export default function EmojiPickerDialog({
|
|||
return (
|
||||
<DropdownMenu open={open} onOpenChange={setOpen}>
|
||||
<DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="top" className="p-0 w-fit">
|
||||
<DropdownMenuContent side="top" className="w-fit p-0">
|
||||
<EmojiPicker
|
||||
onEmojiClick={(emoji, e) => {
|
||||
e.stopPropagation()
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
|
|||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<div className="w-screen h-screen flex flex-col items-center justify-center p-4 gap-4">
|
||||
<div className="flex h-screen w-screen flex-col items-center justify-center gap-4 p-4">
|
||||
<h1 className="text-2xl font-bold">Oops, something went wrong.</h1>
|
||||
<p className="text-lg text-center max-w-md">
|
||||
<p className="max-w-md text-center text-lg">
|
||||
Sorry for the inconvenience. If you don't mind helping, you can{' '}
|
||||
<a
|
||||
href="https://github.com/CodyTseng/jumble/issues/new"
|
||||
|
|
@ -61,7 +61,7 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
|
|||
>
|
||||
Copy Error Message
|
||||
</Button>
|
||||
<pre className="bg-destructive/10 text-destructive p-2 rounded text-wrap break-words whitespace-pre-wrap">
|
||||
<pre className="whitespace-pre-wrap text-wrap break-words rounded bg-destructive/10 p-2 text-destructive">
|
||||
Error: {this.state.error.message}
|
||||
</pre>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export default function Explore() {
|
|||
<div className="p-4 max-md:border-b">
|
||||
<Skeleton className="h-6 w-20" />
|
||||
</div>
|
||||
<div className="grid md:px-4 md:grid-cols-2 md:gap-2">
|
||||
<div className="grid md:grid-cols-2 md:gap-2 md:px-4">
|
||||
<RelaySimpleInfoSkeleton className="h-auto px-4 py-3 md:rounded-lg md:border" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -62,13 +62,13 @@ function RelayCollection({ collection }: { collection: TAwesomeRelayCollection }
|
|||
<div>
|
||||
<div
|
||||
className={cn(
|
||||
'sticky bg-background z-20 px-4 py-3 text-2xl font-semibold max-md:border-b',
|
||||
'sticky z-20 bg-background px-4 py-3 text-2xl font-semibold max-md:border-b',
|
||||
deepBrowsing ? 'top-12' : 'top-24'
|
||||
)}
|
||||
>
|
||||
{collection.name}
|
||||
</div>
|
||||
<div className="grid md:px-4 md:grid-cols-2 md:gap-3">
|
||||
<div className="grid md:grid-cols-2 md:gap-3 md:px-4">
|
||||
{collection.relays.map((url) => (
|
||||
<RelayItem key={url} url={url} />
|
||||
))}
|
||||
|
|
@ -82,7 +82,7 @@ function RelayItem({ url }: { url: string }) {
|
|||
const { relayInfo, isFetching } = useFetchRelayInfo(url)
|
||||
|
||||
if (isFetching) {
|
||||
return <RelaySimpleInfoSkeleton className="h-auto px-4 py-3 border-b md:rounded-lg md:border" />
|
||||
return <RelaySimpleInfoSkeleton className="h-auto border-b px-4 py-3 md:rounded-lg md:border" />
|
||||
}
|
||||
|
||||
if (!relayInfo) {
|
||||
|
|
@ -92,7 +92,7 @@ function RelayItem({ url }: { url: string }) {
|
|||
return (
|
||||
<RelaySimpleInfo
|
||||
key={relayInfo.url}
|
||||
className="clickable h-auto px-4 py-3 border-b md:rounded-lg md:border"
|
||||
className="clickable h-auto border-b px-4 py-3 md:rounded-lg md:border"
|
||||
relayInfo={relayInfo}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export default function ExternalContent({
|
|||
|
||||
if (node.type === 'text') {
|
||||
return (
|
||||
<div className={cn('text-wrap break-words whitespace-pre-wrap', className)}>{content}</div>
|
||||
<div className={cn('whitespace-pre-wrap text-wrap break-words', className)}>{content}</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,13 +37,13 @@ export function Tabs({
|
|||
|
||||
return (
|
||||
<div className="w-fit">
|
||||
<div className="flex relative">
|
||||
<div className="relative flex">
|
||||
{TABS.map((tab, index) => (
|
||||
<div
|
||||
key={tab.value}
|
||||
ref={(el) => (tabRefs.current[index] = el)}
|
||||
className={cn(
|
||||
`text-center px-4 py-2 font-semibold clickable cursor-pointer rounded-lg`,
|
||||
`clickable cursor-pointer rounded-lg px-4 py-2 text-center font-semibold`,
|
||||
selectedTab === tab.value ? '' : 'text-muted-foreground'
|
||||
)}
|
||||
onClick={() => onTabChange(tab.value)}
|
||||
|
|
@ -52,7 +52,7 @@ export function Tabs({
|
|||
</div>
|
||||
))}
|
||||
<div
|
||||
className="absolute bottom-0 h-1 bg-primary rounded-full transition-all duration-500"
|
||||
className="absolute bottom-0 h-1 rounded-full bg-primary transition-all duration-500"
|
||||
style={{
|
||||
width: `${indicatorStyle.width}px`,
|
||||
left: `${indicatorStyle.left}px`
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ export default function ExternalContentInteractions({
|
|||
return (
|
||||
<>
|
||||
<div className="flex items-center justify-between">
|
||||
<ScrollArea className="flex-1 w-0">
|
||||
<ScrollArea className="w-0 flex-1">
|
||||
<Tabs selectedTab={type} onTabChange={setType} />
|
||||
<ScrollBar orientation="horizontal" className="opacity-0 pointer-events-none" />
|
||||
<ScrollBar orientation="horizontal" className="pointer-events-none opacity-0" />
|
||||
</ScrollArea>
|
||||
<Separator orientation="vertical" className="h-6" />
|
||||
<div className="size-10 flex items-center justify-center">
|
||||
<div className="flex size-10 items-center justify-center">
|
||||
<TrustScoreFilter filterId={SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ export default function ExternalLink({
|
|||
<div className="py-2">
|
||||
<Button
|
||||
onClick={handleOpenLink}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
|
||||
className="w-full justify-start gap-4 p-6 text-lg [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
>
|
||||
<ExternalLinkIcon />
|
||||
|
|
@ -100,7 +100,7 @@ export default function ExternalLink({
|
|||
</Button>
|
||||
<Button
|
||||
onClick={handleViewDiscussions}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
|
||||
className="w-full justify-start gap-4 p-6 text-lg [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
>
|
||||
<MessageSquare />
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export default function AddNewRelay() {
|
|||
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
placeholder={t('Add a new relay')}
|
||||
value={input}
|
||||
|
|
@ -50,7 +50,7 @@ export default function AddNewRelay() {
|
|||
/>
|
||||
<Button onClick={saveRelay}>{t('Add')}</Button>
|
||||
</div>
|
||||
{errorMsg && <div className="text-destructive text-sm pl-8">{errorMsg}</div>}
|
||||
{errorMsg && <div className="pl-8 text-sm text-destructive">{errorMsg}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export default function AddNewRelaySet() {
|
|||
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
placeholder={t('Add a new relay set')}
|
||||
value={newRelaySetName}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default function FavoriteRelayList() {
|
|||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="text-muted-foreground font-semibold select-none">{t('Relays')}</div>
|
||||
<div className="select-none font-semibold text-muted-foreground">{t('Relays')}</div>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export default function PullRelaySetsButton() {
|
|||
const trigger = (
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-muted-foreground hover:no-underline hover:text-foreground p-0 h-fit"
|
||||
className="h-fit p-0 text-muted-foreground hover:text-foreground hover:no-underline"
|
||||
disabled={!pubkey}
|
||||
>
|
||||
<CloudDownload />
|
||||
|
|
@ -53,7 +53,7 @@ export default function PullRelaySetsButton() {
|
|||
<Drawer open={open} onOpenChange={setOpen}>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[90vh]">
|
||||
<div className="flex flex-col p-4 gap-4 overflow-auto">
|
||||
<div className="flex flex-col gap-4 overflow-auto p-4">
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>{t('Select the relay sets you want to pull')}</DrawerTitle>
|
||||
<DrawerDescription className="hidden" />
|
||||
|
|
|
|||
|
|
@ -20,22 +20,22 @@ export default function RelayItem({ relay }: { relay: string }) {
|
|||
|
||||
return (
|
||||
<div
|
||||
className="relative group clickable flex gap-2 border rounded-lg p-2 pr-2.5 items-center justify-between select-none"
|
||||
className="clickable group relative flex select-none items-center justify-between gap-2 rounded-lg border p-2 pr-2.5"
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
onClick={() => push(toRelay(relay))}
|
||||
>
|
||||
<div className="flex items-center gap-1 flex-1">
|
||||
<div className="flex flex-1 items-center gap-1">
|
||||
<div
|
||||
className="cursor-grab active:cursor-grabbing p-2 hover:bg-muted rounded touch-none shrink-0"
|
||||
className="shrink-0 cursor-grab touch-none rounded p-2 hover:bg-muted active:cursor-grabbing"
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
>
|
||||
<GripVertical className="size-4 text-muted-foreground" />
|
||||
</div>
|
||||
<div className="flex gap-2 items-center flex-1">
|
||||
<div className="flex flex-1 items-center gap-2">
|
||||
<RelayIcon url={relay} />
|
||||
<div className="flex-1 w-0 truncate font-semibold">{relay}</div>
|
||||
<div className="w-0 flex-1 truncate font-semibold">{relay}</div>
|
||||
</div>
|
||||
</div>
|
||||
<SaveRelayDropdownMenu urls={[relay]} />
|
||||
|
|
|
|||
|
|
@ -42,19 +42,19 @@ export default function RelaySet({ relaySet }: { relaySet: TRelaySet }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style} className="relative group">
|
||||
<div className="w-full border rounded-lg px-2 py-2.5">
|
||||
<div className="flex justify-between items-center">
|
||||
<div ref={setNodeRef} style={style} className="group relative">
|
||||
<div className="w-full rounded-lg border px-2 py-2.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className="cursor-grab active:cursor-grabbing p-2 hover:bg-muted rounded touch-none"
|
||||
className="cursor-grab touch-none rounded p-2 hover:bg-muted active:cursor-grabbing"
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
>
|
||||
<GripVertical className="size-4 text-muted-foreground" />
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex justify-center items-center w-6 h-6 shrink-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex h-6 w-6 shrink-0 items-center justify-center">
|
||||
<FolderClosed className="size-4" />
|
||||
</div>
|
||||
<RelaySetName relaySet={relaySet} />
|
||||
|
|
@ -98,20 +98,20 @@ function RelaySetName({ relaySet }: { relaySet: TRelaySet }) {
|
|||
}
|
||||
|
||||
return renamingRelaySetId === relaySet.id ? (
|
||||
<div className="flex gap-1 items-center">
|
||||
<div className="flex items-center gap-1">
|
||||
<Input
|
||||
value={newSetName}
|
||||
onChange={handleRenameInputChange}
|
||||
onBlur={saveNewRelaySetName}
|
||||
onKeyDown={handleRenameInputKeyDown}
|
||||
className="font-semibold w-28"
|
||||
className="w-28 font-semibold"
|
||||
/>
|
||||
<Button variant="ghost" size="icon" onClick={saveNewRelaySetName}>
|
||||
<Check size={18} className="text-green-500" />
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-8 font-semibold flex items-center select-none">{relaySet.name}</div>
|
||||
<div className="flex h-8 select-none items-center font-semibold">{relaySet.name}</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ function RelayUrlsExpandToggle({
|
|||
const { expandedRelaySetId, setExpandedRelaySetId } = useRelaySetsSettingComponent()
|
||||
return (
|
||||
<div
|
||||
className="text-sm text-muted-foreground flex items-center gap-1 cursor-pointer hover:text-foreground"
|
||||
className="flex cursor-pointer items-center gap-1 text-sm text-muted-foreground hover:text-foreground"
|
||||
onClick={() => setExpandedRelaySetId((pre) => (pre === relaySetId ? null : relaySetId))}
|
||||
>
|
||||
<div className="select-none">{children}</div>
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export default function RelaySetList() {
|
|||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="text-muted-foreground font-semibold select-none shrink-0">
|
||||
<div className="shrink-0 select-none font-semibold text-muted-foreground">
|
||||
{t('Relay sets')}
|
||||
</div>
|
||||
<PullRelaySetsButton />
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export default function RelayUrls({ relaySetId }: { relaySetId: string }) {
|
|||
/>
|
||||
<Button onClick={saveNewRelayUrl}>{t('Add')}</Button>
|
||||
</div>
|
||||
{newRelayUrlError && <div className="text-xs text-destructive mt-1">{newRelayUrlError}</div>}
|
||||
{newRelayUrlError && <div className="mt-1 text-xs text-destructive">{newRelayUrlError}</div>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -81,15 +81,15 @@ export default function RelayUrls({ relaySetId }: { relaySetId: string }) {
|
|||
function RelayUrl({ url, onRemove }: { url: string; onRemove: () => void }) {
|
||||
return (
|
||||
<div className="flex items-center justify-between pl-1 pr-3">
|
||||
<div className="flex gap-3 items-center flex-1 w-0">
|
||||
<RelayIcon url={url} className="w-4 h-4" />
|
||||
<div className="text-muted-foreground text-sm truncate">{url}</div>
|
||||
<div className="flex w-0 flex-1 items-center gap-3">
|
||||
<RelayIcon url={url} className="h-4 w-4" />
|
||||
<div className="truncate text-sm text-muted-foreground">{url}</div>
|
||||
</div>
|
||||
<div className="shrink-0">
|
||||
<CircleX
|
||||
size={16}
|
||||
onClick={onRemove}
|
||||
className="text-muted-foreground hover:text-destructive cursor-pointer"
|
||||
className="cursor-pointer text-muted-foreground hover:text-destructive"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ export default function FeedSwitcher({ close }: { close?: () => void }) {
|
|||
close?.()
|
||||
}}
|
||||
>
|
||||
<div className="flex gap-3 items-center">
|
||||
<div className="flex justify-center items-center size-6 shrink-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex size-6 shrink-0 items-center justify-center">
|
||||
<UsersRound className="size-5" />
|
||||
</div>
|
||||
<div className="flex-1">{t('Following')}</div>
|
||||
|
|
@ -56,8 +56,8 @@ export default function FeedSwitcher({ close }: { close?: () => void }) {
|
|||
close?.()
|
||||
}}
|
||||
>
|
||||
<div className="flex gap-3 items-center">
|
||||
<div className="flex justify-center items-center size-6 shrink-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex size-6 shrink-0 items-center justify-center">
|
||||
<Star className="size-5" />
|
||||
</div>
|
||||
<div className="flex-1">{t('Special Follow')}</div>
|
||||
|
|
@ -74,7 +74,7 @@ export default function FeedSwitcher({ close }: { close?: () => void }) {
|
|||
action={
|
||||
<SecondaryPageLink
|
||||
to={toRelaySettings()}
|
||||
className="flex items-center gap-1 text-xs text-primary hover:text-primary-hover transition-colors font-medium"
|
||||
className="flex items-center gap-1 text-xs font-medium text-primary transition-colors hover:text-primary-hover"
|
||||
onClick={() => close?.()}
|
||||
>
|
||||
<Settings2 className="size-3" />
|
||||
|
|
@ -104,9 +104,9 @@ export default function FeedSwitcher({ close }: { close?: () => void }) {
|
|||
close?.()
|
||||
}}
|
||||
>
|
||||
<div className="flex gap-3 items-center w-full">
|
||||
<div className="flex w-full items-center gap-3">
|
||||
<RelayIcon url={relay} className="shrink-0" />
|
||||
<div className="flex-1 w-0 truncate">{simplifyUrl(relay)}</div>
|
||||
<div className="w-0 flex-1 truncate">{simplifyUrl(relay)}</div>
|
||||
</div>
|
||||
</FeedSwitcherItem>
|
||||
))}
|
||||
|
|
@ -119,8 +119,8 @@ export default function FeedSwitcher({ close }: { close?: () => void }) {
|
|||
|
||||
function SectionHeader({ title, action }: { title: string; action?: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex justify-between items-center px-1 py-1">
|
||||
<h3 className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
|
||||
<div className="flex items-center justify-between px-1 py-1">
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
{title}
|
||||
</h3>
|
||||
{action}
|
||||
|
|
@ -142,19 +142,19 @@ function FeedSwitcherItem({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'group relative w-full border rounded-lg px-3 py-2.5 transition-all duration-200',
|
||||
disabled && 'opacity-50 pointer-events-none',
|
||||
'group relative w-full rounded-lg border px-3 py-2.5 transition-all duration-200',
|
||||
disabled && 'pointer-events-none opacity-50',
|
||||
isActive
|
||||
? 'border-primary bg-primary/5 shadow-sm'
|
||||
: 'border-border hover:border-primary/50 hover:bg-accent/50 clickable'
|
||||
: 'clickable border-border hover:border-primary/50 hover:bg-accent/50'
|
||||
)}
|
||||
onClick={() => {
|
||||
if (disabled) return
|
||||
onClick()
|
||||
}}
|
||||
>
|
||||
<div className="flex justify-between items-center gap-2">
|
||||
<div className="font-medium flex-1 min-w-0">{children}</div>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="min-w-0 flex-1 font-medium">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export default function FollowButton({ pubkey }: { pubkey: string }) {
|
|||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button
|
||||
className="rounded-full min-w-28"
|
||||
className="min-w-28 rounded-full"
|
||||
variant={hover ? 'destructive' : 'secondary'}
|
||||
disabled={updating}
|
||||
onMouseEnter={() => setHover(true)}
|
||||
|
|
@ -85,7 +85,7 @@ export default function FollowButton({ pubkey }: { pubkey: string }) {
|
|||
</AlertDialog>
|
||||
</div>
|
||||
) : (
|
||||
<Button className="rounded-full min-w-28" onClick={handleFollow} disabled={updating}>
|
||||
<Button className="min-w-28 rounded-full" onClick={handleFollow} disabled={updating}>
|
||||
{updating ? <Loader className="animate-spin" /> : t('Follow')}
|
||||
</Button>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default function FollowingBadge({ pubkey, userId }: { pubkey?: string; us
|
|||
if (!isFollowing) return null
|
||||
|
||||
return (
|
||||
<div className="rounded-full bg-muted px-2 py-0.5 flex items-center" title={t('Following')}>
|
||||
<div className="flex items-center rounded-full bg-muted px-2 py-0.5" title={t('Following')}>
|
||||
<UserRoundCheck className="!size-3" />
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export default function FollowingFavoriteRelayList() {
|
|||
{showCount < relays.length && <div ref={bottomRef} />}
|
||||
{loading && <RelaySimpleInfoSkeleton className="p-4" />}
|
||||
{!loading && (
|
||||
<div className="text-center text-muted-foreground text-sm mt-2">
|
||||
<div className="mt-2 text-center text-sm text-muted-foreground">
|
||||
{relays.length === 0 ? t('no relays found') : t('no more relays')}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -81,7 +81,7 @@ function RelayItem({ url, users }: { url: string; users: string[] }) {
|
|||
key={url}
|
||||
relayInfo={relayInfo}
|
||||
users={users}
|
||||
className="clickable p-4 border-b"
|
||||
className="clickable border-b p-4"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toRelay(url))
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export default function HighlightButton({ onHighlight, containerRef }: Highlight
|
|||
|
||||
return (
|
||||
<div
|
||||
className="fixed z-50 animate-in fade-in-0 slide-in-from-bottom-4 duration-200"
|
||||
className="fixed z-50 duration-200 animate-in fade-in-0 slide-in-from-bottom-4"
|
||||
style={{
|
||||
top: `${position.top}px`,
|
||||
left: `${position.left}px`
|
||||
|
|
@ -97,7 +97,7 @@ export default function HighlightButton({ onHighlight, containerRef }: Highlight
|
|||
ref={buttonRef}
|
||||
size="sm"
|
||||
variant="default"
|
||||
className="shadow-lg gap-2 -translate-x-1/2"
|
||||
className="-translate-x-1/2 gap-2 shadow-lg"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onHighlight(selectedText)
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ export default function Image({
|
|||
<img
|
||||
src={`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${dim.width}' height='${dim.height}'%3E%3C/svg%3E`}
|
||||
className={cn(
|
||||
'object-cover transition-opacity pointer-events-none w-full h-full',
|
||||
'pointer-events-none h-full w-full object-cover transition-opacity',
|
||||
className
|
||||
)}
|
||||
alt=""
|
||||
|
|
@ -91,7 +91,7 @@ export default function Image({
|
|||
<ThumbHashPlaceholder
|
||||
thumbHash={thumbHash}
|
||||
className={cn(
|
||||
'w-full h-full transition-opacity',
|
||||
'h-full w-full transition-opacity',
|
||||
isLoading ? 'opacity-100' : 'opacity-0'
|
||||
)}
|
||||
/>
|
||||
|
|
@ -99,14 +99,14 @@ export default function Image({
|
|||
<BlurHashCanvas
|
||||
blurHash={blurHash}
|
||||
className={cn(
|
||||
'w-full h-full transition-opacity',
|
||||
'h-full w-full transition-opacity',
|
||||
isLoading ? 'opacity-100' : 'opacity-0'
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<Skeleton
|
||||
className={cn(
|
||||
'w-full h-full transition-opacity',
|
||||
'h-full w-full transition-opacity',
|
||||
isLoading ? 'opacity-100' : 'opacity-0',
|
||||
classNames.skeleton
|
||||
)}
|
||||
|
|
@ -124,8 +124,8 @@ export default function Image({
|
|||
onLoad={handleLoad}
|
||||
onError={handleError}
|
||||
className={cn(
|
||||
'object-cover transition-opacity pointer-events-none w-full h-full',
|
||||
isLoading ? 'opacity-0 absolute inset-0' : '',
|
||||
'pointer-events-none h-full w-full object-cover transition-opacity',
|
||||
isLoading ? 'absolute inset-0 opacity-0' : '',
|
||||
className
|
||||
)}
|
||||
/>
|
||||
|
|
@ -137,12 +137,12 @@ export default function Image({
|
|||
alt={alt}
|
||||
decoding="async"
|
||||
loading="lazy"
|
||||
className={cn('object-cover w-full h-full transition-opacity', className)}
|
||||
className={cn('h-full w-full object-cover transition-opacity', className)}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={cn(
|
||||
'object-cover flex flex-col items-center justify-center w-full h-full bg-muted',
|
||||
'flex h-full w-full flex-col items-center justify-center bg-muted object-cover',
|
||||
className,
|
||||
classNames.errorPlaceholder
|
||||
)}
|
||||
|
|
@ -188,7 +188,7 @@ function BlurHashCanvas({ blurHash, className = '' }: { blurHash: string; classN
|
|||
ref={canvasRef}
|
||||
width={blurHashWidth}
|
||||
height={blurHashHeight}
|
||||
className={cn('w-full h-full object-cover rounded-xl', className)}
|
||||
className={cn('h-full w-full rounded-xl object-cover', className)}
|
||||
style={{
|
||||
imageRendering: 'auto',
|
||||
filter: 'blur(0.5px)'
|
||||
|
|
@ -218,7 +218,7 @@ function ThumbHashPlaceholder({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={cn('w-full h-full object-cover rounded-lg', className)}
|
||||
className={cn('h-full w-full rounded-lg object-cover', className)}
|
||||
style={{
|
||||
backgroundImage: `url(${dataUrl})`,
|
||||
backgroundSize: 'cover',
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export default function ImageGallery({
|
|||
<ImageWithLightbox
|
||||
key={i}
|
||||
image={image}
|
||||
className="max-h-[80vh] sm:max-h-[50vh] object-contain"
|
||||
className="max-h-[80vh] object-contain sm:max-h-[50vh]"
|
||||
classNames={{
|
||||
wrapper: cn('w-fit max-w-full border', className)
|
||||
}}
|
||||
|
|
@ -107,7 +107,7 @@ export default function ImageGallery({
|
|||
imageContent = (
|
||||
<Image
|
||||
key={0}
|
||||
className="max-h-[80vh] sm:max-h-[50vh] object-contain"
|
||||
className="max-h-[80vh] object-contain sm:max-h-[50vh]"
|
||||
classNames={{
|
||||
errorPlaceholder: 'aspect-square h-[30vh]',
|
||||
wrapper: 'cursor-zoom-in border'
|
||||
|
|
@ -118,7 +118,7 @@ export default function ImageGallery({
|
|||
)
|
||||
} else if (displayImages.length === 2 || displayImages.length === 4) {
|
||||
imageContent = (
|
||||
<div className="grid grid-cols-2 gap-2 w-full">
|
||||
<div className="grid w-full grid-cols-2 gap-2">
|
||||
{displayImages.map((image, i) => (
|
||||
<Image
|
||||
key={i}
|
||||
|
|
@ -132,7 +132,7 @@ export default function ImageGallery({
|
|||
)
|
||||
} else {
|
||||
imageContent = (
|
||||
<div className="grid grid-cols-3 gap-2 w-full">
|
||||
<div className="grid w-full grid-cols-3 gap-2">
|
||||
{displayImages.map((image, i) => (
|
||||
<Image
|
||||
key={i}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default function ImageWithLightbox({
|
|||
if (!display) {
|
||||
return (
|
||||
<div
|
||||
className="text-primary hover:underline truncate w-fit cursor-pointer"
|
||||
className="w-fit cursor-pointer truncate text-primary hover:underline"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setDisplay(true)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export default function InfoCard({
|
|||
variant?: 'info' | 'success' | 'alert'
|
||||
}) {
|
||||
return (
|
||||
<div className={cn('p-3 rounded-lg text-sm [&_svg]:size-4', VARIANT_STYLES[variant])}>
|
||||
<div className={cn('rounded-lg p-3 text-sm [&_svg]:size-4', VARIANT_STYLES[variant])}>
|
||||
<div className="flex items-center gap-2">
|
||||
{icon ?? ICON_MAP[variant]}
|
||||
<div className="font-medium">{title}</div>
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export default function KindFilter({
|
|||
>
|
||||
<ListFilter size={16} />
|
||||
{isDifferentFromSaved && (
|
||||
<div className="absolute size-2 rounded-full bg-primary left-7 top-2 ring-2 ring-background" />
|
||||
<div className="absolute left-7 top-2 size-2 rounded-full bg-primary ring-2 ring-background" />
|
||||
)}
|
||||
</Button>
|
||||
)
|
||||
|
|
@ -109,7 +109,7 @@ export default function KindFilter({
|
|||
<div
|
||||
key={label}
|
||||
className={cn(
|
||||
'cursor-pointer grid gap-1.5 rounded-lg border px-4 py-3',
|
||||
'grid cursor-pointer gap-1.5 rounded-lg border px-4 py-3',
|
||||
checked ? 'border-primary/60 bg-primary/5' : 'clickable'
|
||||
)}
|
||||
onClick={() => {
|
||||
|
|
@ -122,14 +122,14 @@ export default function KindFilter({
|
|||
}
|
||||
}}
|
||||
>
|
||||
<p className="leading-none font-medium">{t(label)}</p>
|
||||
<p className="text-muted-foreground text-xs">kind {kindGroup.join(', ')}</p>
|
||||
<p className="font-medium leading-none">{t(label)}</p>
|
||||
<p className="text-xs text-muted-foreground">kind {kindGroup.join(', ')}</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-2 mt-4">
|
||||
<div className="mt-4 grid grid-cols-3 gap-2">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
|
|
@ -155,7 +155,7 @@ export default function KindFilter({
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<Label className="flex items-center gap-2 cursor-pointer mt-4">
|
||||
<Label className="mt-4 flex cursor-pointer items-center gap-2">
|
||||
<Checkbox
|
||||
id="persistent-filter"
|
||||
checked={isPersistent}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export function LoadingBar({ className }: { className?: string }) {
|
|||
return (
|
||||
<div className={cn('h-0.5 w-full overflow-hidden', className)}>
|
||||
<div
|
||||
className="h-full w-full bg-gradient-to-r from-primary/40 from-25% via-primary via-50% to-primary/40 to-75% animate-shimmer"
|
||||
className="h-full w-full animate-shimmer bg-gradient-to-r from-primary/40 from-25% via-primary via-50% to-primary/40 to-75%"
|
||||
style={{
|
||||
backgroundSize: '400% 100%'
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default function LoginDialog({
|
|||
return (
|
||||
<Drawer open={open} onOpenChange={setOpen}>
|
||||
<DrawerContent className="max-h-[90vh]">
|
||||
<div className="flex flex-col p-4 gap-4 overflow-auto">
|
||||
<div className="flex flex-col gap-4 overflow-auto p-4">
|
||||
<AccountManager close={() => setOpen(false)} />
|
||||
</div>
|
||||
</DrawerContent>
|
||||
|
|
@ -27,7 +27,7 @@ export default function LoginDialog({
|
|||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className="w-[520px] max-h-[90vh] py-8 overflow-auto">
|
||||
<DialogContent className="max-h-[90vh] w-[520px] overflow-auto py-8">
|
||||
<AccountManager close={() => setOpen(false)} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
|
|
|||
|
|
@ -38,21 +38,21 @@ export default function MailboxRelay({
|
|||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 flex-1 w-0">
|
||||
<div className="flex w-0 flex-1 items-center gap-2">
|
||||
<div
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
className="cursor-grab active:cursor-grabbing p-2 hover:bg-muted rounded touch-none"
|
||||
className="cursor-grab touch-none rounded p-2 hover:bg-muted active:cursor-grabbing"
|
||||
style={{ touchAction: 'none' }}
|
||||
>
|
||||
<GripVertical size={16} className="text-muted-foreground" />
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center gap-2 flex-1 w-0 cursor-pointer"
|
||||
className="flex w-0 flex-1 cursor-pointer items-center gap-2"
|
||||
onClick={() => push(toRelay(mailboxRelay.url))}
|
||||
>
|
||||
<RelayIcon url={mailboxRelay.url} />
|
||||
<div className="truncate flex-1 w-0">{mailboxRelay.url}</div>
|
||||
<div className="w-0 flex-1 truncate">{mailboxRelay.url}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
|
|
@ -72,7 +72,7 @@ export default function MailboxRelay({
|
|||
<CircleX
|
||||
size={16}
|
||||
onClick={() => removeMailboxRelay(mailboxRelay.url)}
|
||||
className="text-muted-foreground hover:text-destructive clickable"
|
||||
className="clickable text-muted-foreground hover:text-destructive"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export default function NewMailboxRelayInput({
|
|||
/>
|
||||
<Button onClick={save}>{t('Add')}</Button>
|
||||
</div>
|
||||
{newRelayUrlError && <div className="text-destructive text-xs mt-1">{newRelayUrlError}</div>}
|
||||
{newRelayUrlError && <div className="mt-1 text-xs text-destructive">{newRelayUrlError}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default function MailboxSetting() {
|
|||
|
||||
if (!pubkey) {
|
||||
return (
|
||||
<div className="flex flex-col w-full items-center">
|
||||
<div className="flex w-full flex-col items-center">
|
||||
<Button size="lg" onClick={() => checkLogin()}>
|
||||
{t('Login to set')}
|
||||
</Button>
|
||||
|
|
@ -109,7 +109,7 @@ export default function MailboxSetting() {
|
|||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="text-xs text-muted-foreground space-y-1">
|
||||
<div className="space-y-1 text-xs text-muted-foreground">
|
||||
<div>{t('read relays description')}</div>
|
||||
<div>{t('write relays description')}</div>
|
||||
<div>{t('read & write relays notice')}</div>
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export default function MediaPlayer({
|
|||
if (!mustLoad && !display) {
|
||||
return (
|
||||
<div
|
||||
className="text-primary hover:underline truncate w-fit cursor-pointer"
|
||||
className="w-fit cursor-pointer truncate text-primary hover:underline"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setDisplay(true)
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export default function MuteButton({ pubkey }: { pubkey: string }) {
|
|||
<DrawerContent>
|
||||
<div className="py-2">
|
||||
<Button
|
||||
className="w-full p-6 justify-start text-destructive text-lg gap-4 [&_svg]:size-5 focus:text-destructive"
|
||||
className="w-full justify-start gap-4 p-6 text-lg text-destructive focus:text-destructive [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
onClick={(e) => handleMute(e, true)}
|
||||
disabled={updating || changing}
|
||||
|
|
@ -99,7 +99,7 @@ export default function MuteButton({ pubkey }: { pubkey: string }) {
|
|||
{updating ? <Loader className="animate-spin" /> : t('Mute user privately')}
|
||||
</Button>
|
||||
<Button
|
||||
className="w-full p-6 justify-start text-destructive text-lg gap-4 [&_svg]:size-5 focus:text-destructive"
|
||||
className="w-full justify-start gap-4 p-6 text-lg text-destructive focus:text-destructive [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
onClick={(e) => handleMute(e, false)}
|
||||
disabled={updating || changing}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export default function NewNotesButton({
|
|||
{newEvents.length > 0 && (
|
||||
<div
|
||||
className={cn(
|
||||
'w-full flex justify-center z-40 pointer-events-none',
|
||||
'pointer-events-none z-40 flex w-full justify-center',
|
||||
enableSingleColumnLayout ? 'sticky' : 'absolute'
|
||||
)}
|
||||
style={{
|
||||
|
|
@ -48,10 +48,10 @@ export default function NewNotesButton({
|
|||
>
|
||||
<Button
|
||||
onClick={onClick}
|
||||
className="group rounded-full h-fit py-2 pl-2 pr-3 hover:bg-primary-hover pointer-events-auto"
|
||||
className="group pointer-events-auto h-fit rounded-full py-2 pl-2 pr-3 hover:bg-primary-hover"
|
||||
>
|
||||
{pubkeys.length > 0 && (
|
||||
<div className="*:data-[slot=avatar]:ring-background flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:grayscale">
|
||||
<div className="flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background *:data-[slot=avatar]:grayscale">
|
||||
{pubkeys.map((pubkey) => (
|
||||
<SimpleUserAvatar key={pubkey} userId={pubkey} size="small" />
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -29,24 +29,24 @@ export default function Nip05({ pubkey, append }: { pubkey: string; append?: str
|
|||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{nip05Name !== '_' ? (
|
||||
<span className="text-sm text-muted-foreground truncate">@{nip05Name}</span>
|
||||
<span className="truncate text-sm text-muted-foreground">@{nip05Name}</span>
|
||||
) : null}
|
||||
{nip05IsVerified ? (
|
||||
<Favicon
|
||||
domain={nip05Domain}
|
||||
className="w-3.5 h-3.5 rounded-full shrink-0"
|
||||
fallback={<BadgeCheck className="text-primary shrink-0" />}
|
||||
className="h-3.5 w-3.5 shrink-0 rounded-full"
|
||||
fallback={<BadgeCheck className="shrink-0 text-primary" />}
|
||||
/>
|
||||
) : (
|
||||
<BadgeAlert className="text-muted-foreground shrink-0" />
|
||||
<BadgeAlert className="shrink-0 text-muted-foreground" />
|
||||
)}
|
||||
<SecondaryPageLink
|
||||
to={toNoteList({ domain: nip05Domain })}
|
||||
className={`hover:underline truncate text-sm ${nip05IsVerified ? 'text-primary' : 'text-muted-foreground'}`}
|
||||
className={`truncate text-sm hover:underline ${nip05IsVerified ? 'text-primary' : 'text-muted-foreground'}`}
|
||||
>
|
||||
{nip05Domain}
|
||||
</SecondaryPageLink>
|
||||
{append && <span className="text-sm text-muted-foreground truncate">{append}</span>}
|
||||
{append && <span className="truncate text-sm text-muted-foreground">{append}</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export default function NotFound() {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="text-muted-foreground w-full h-full flex flex-col items-center justify-center gap-2">
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-2 text-muted-foreground">
|
||||
<div>{t('Lost in the void')} 🌌</div>
|
||||
<div>(404)</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ export default function CommunityDefinition({
|
|||
const metadata = useMemo(() => getCommunityDefinitionFromEvent(event), [event])
|
||||
|
||||
const communityNameComponent = (
|
||||
<div className="text-xl font-semibold line-clamp-1">{metadata.name}</div>
|
||||
<div className="line-clamp-1 text-xl font-semibold">{metadata.name}</div>
|
||||
)
|
||||
|
||||
const communityDescriptionComponent = metadata.description && (
|
||||
<div className="text-sm text-muted-foreground line-clamp-2">{metadata.description}</div>
|
||||
<div className="line-clamp-2 text-sm text-muted-foreground">{metadata.description}</div>
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
@ -29,16 +29,16 @@ export default function CommunityDefinition({
|
|||
{metadata.image && autoLoadMedia && (
|
||||
<Image
|
||||
image={{ url: metadata.image, pubkey: event.pubkey }}
|
||||
className="aspect-square bg-foreground h-20"
|
||||
className="aspect-square h-20 bg-foreground"
|
||||
hideIfError
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1 w-0 space-y-1">
|
||||
<div className="w-0 flex-1 space-y-1">
|
||||
{communityNameComponent}
|
||||
{communityDescriptionComponent}
|
||||
</div>
|
||||
</div>
|
||||
<ClientSelect className="w-full mt-2" event={event} />
|
||||
<ClientSelect className="mt-2 w-full" event={event} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default function EmojiPack({ event, className }: { event: Event; classNam
|
|||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<h3 className="text-2xl font-semibold">{title}</h3>
|
||||
{accountPubkey && (
|
||||
<Button
|
||||
|
|
@ -55,7 +55,7 @@ export default function EmojiPack({ event, className }: { event: Event; classNam
|
|||
className="shrink-0"
|
||||
>
|
||||
{updating ? (
|
||||
<Loader className="animate-spin mr-1" />
|
||||
<Loader className="mr-1 animate-spin" />
|
||||
) : isCollected ? (
|
||||
<CheckIcon />
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ export default function FollowPack({ event, className }: { event: Event; classNa
|
|||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="flex items-start gap-2 mb-2">
|
||||
<div className="mb-2 flex items-start gap-2">
|
||||
{image && (
|
||||
<Image
|
||||
image={{ url: image, pubkey: event.pubkey }}
|
||||
className="w-24 h-20 object-cover"
|
||||
className="h-20 w-24 object-cover"
|
||||
classNames={{
|
||||
wrapper: 'w-24 h-20 flex-shrink-0',
|
||||
errorPlaceholder: 'w-24 h-20'
|
||||
|
|
@ -34,15 +34,15 @@ export default function FollowPack({ event, className }: { event: Event; classNa
|
|||
hideIfError
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="text-xl font-semibold mb-1 truncate">{title}</h3>
|
||||
<span className="text-xs text-muted-foreground shrink-0">
|
||||
<h3 className="mb-1 truncate text-xl font-semibold">{title}</h3>
|
||||
<span className="shrink-0 text-xs text-muted-foreground">
|
||||
{t('n users', { count: pubkeys.length })}
|
||||
</span>
|
||||
</div>
|
||||
{description && (
|
||||
<p className="text-sm text-muted-foreground line-clamp-2">{description}</p>
|
||||
<p className="line-clamp-2 text-sm text-muted-foreground">{description}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ export default function GroupMetadata({
|
|||
const metadata = useMemo(() => getGroupMetadataFromEvent(event), [event])
|
||||
|
||||
const groupNameComponent = (
|
||||
<div className="text-xl font-semibold line-clamp-1">{metadata.name}</div>
|
||||
<div className="line-clamp-1 text-xl font-semibold">{metadata.name}</div>
|
||||
)
|
||||
|
||||
const groupAboutComponent = metadata.about && (
|
||||
<div className="text-sm text-muted-foreground line-clamp-2">{metadata.about}</div>
|
||||
<div className="line-clamp-2 text-sm text-muted-foreground">{metadata.about}</div>
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
@ -31,16 +31,16 @@ export default function GroupMetadata({
|
|||
{metadata.picture && autoLoadMedia && (
|
||||
<Image
|
||||
image={{ url: metadata.picture, pubkey: event.pubkey }}
|
||||
className="aspect-square bg-foreground h-20"
|
||||
className="aspect-square h-20 bg-foreground"
|
||||
hideIfError
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1 w-0 space-y-1">
|
||||
<div className="w-0 flex-1 space-y-1">
|
||||
{groupNameComponent}
|
||||
{groupAboutComponent}
|
||||
</div>
|
||||
</div>
|
||||
<ClientSelect className="w-full mt-2" event={event} originalNoteId={originalNoteId} />
|
||||
<ClientSelect className="mt-2 w-full" event={event} originalNoteId={originalNoteId} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ export default function Highlight({ event, className }: { event: Event; classNam
|
|||
)
|
||||
|
||||
return (
|
||||
<div className={cn('text-wrap break-words whitespace-pre-wrap space-y-4', className)}>
|
||||
<div className={cn('space-y-4 whitespace-pre-wrap text-wrap break-words', className)}>
|
||||
{comment && <Content event={createFakeEvent({ content: comment, tags: event.tags })} />}
|
||||
<div className="flex gap-4">
|
||||
<div className="w-1 flex-shrink-0 my-1 bg-primary/60 rounded-md" />
|
||||
<div className="my-1 w-1 flex-shrink-0 rounded-md bg-primary/60" />
|
||||
<div
|
||||
className="italic whitespace-pre-line"
|
||||
className="whitespace-pre-line italic"
|
||||
style={{
|
||||
overflowWrap: 'anywhere'
|
||||
}}
|
||||
|
|
@ -112,7 +112,7 @@ function HighlightSource({ event }: { event: Event }) {
|
|||
{t('From')}{' '}
|
||||
<ExternalLink
|
||||
url={sourceTag[1]}
|
||||
className="underline italic text-muted-foreground hover:text-foreground"
|
||||
className="italic text-muted-foreground underline hover:text-foreground"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -124,7 +124,7 @@ function HighlightSource({ event }: { event: Event }) {
|
|||
{pubkey && <UserAvatar userId={pubkey} size="xSmall" className="cursor-pointer" />}
|
||||
{referenceEventId && (
|
||||
<div
|
||||
className="truncate underline pointer-events-auto cursor-pointer hover:text-foreground"
|
||||
className="pointer-events-auto cursor-pointer truncate underline hover:text-foreground"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toNote(referenceEvent ?? referenceEventId))
|
||||
|
|
|
|||
|
|
@ -23,14 +23,14 @@ export default function LiveEvent({ event, className }: { event: Event; classNam
|
|||
<Badge variant="secondary">{metadata.status}</Badge>
|
||||
))
|
||||
|
||||
const titleComponent = <div className="text-xl font-semibold line-clamp-1">{metadata.title}</div>
|
||||
const titleComponent = <div className="line-clamp-1 text-xl font-semibold">{metadata.title}</div>
|
||||
|
||||
const summaryComponent = metadata.summary && (
|
||||
<div className="text-sm text-muted-foreground line-clamp-4">{metadata.summary}</div>
|
||||
<div className="line-clamp-4 text-sm text-muted-foreground">{metadata.summary}</div>
|
||||
)
|
||||
|
||||
const tagsComponent = metadata.tags.length > 0 && (
|
||||
<div className="flex gap-1 flex-wrap">
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{metadata.tags.map((tag) => (
|
||||
<Badge key={tag} variant="secondary">
|
||||
{tag}
|
||||
|
|
@ -45,7 +45,7 @@ export default function LiveEvent({ event, className }: { event: Event; classNam
|
|||
{metadata.image && autoLoadMedia && (
|
||||
<Image
|
||||
image={{ url: metadata.image, pubkey: event.pubkey }}
|
||||
className="w-full aspect-video"
|
||||
className="aspect-video w-full"
|
||||
hideIfError
|
||||
/>
|
||||
)}
|
||||
|
|
@ -54,7 +54,7 @@ export default function LiveEvent({ event, className }: { event: Event; classNam
|
|||
{liveStatusComponent}
|
||||
{summaryComponent}
|
||||
{tagsComponent}
|
||||
<ClientSelect className="w-full mt-2" event={event} />
|
||||
<ClientSelect className="mt-2 w-full" event={event} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -66,18 +66,18 @@ export default function LiveEvent({ event, className }: { event: Event; classNam
|
|||
{metadata.image && autoLoadMedia && (
|
||||
<Image
|
||||
image={{ url: metadata.image, pubkey: event.pubkey }}
|
||||
className="aspect-[4/3] xl:aspect-video bg-foreground h-44"
|
||||
className="aspect-[4/3] h-44 bg-foreground xl:aspect-video"
|
||||
hideIfError
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1 w-0 space-y-1">
|
||||
<div className="w-0 flex-1 space-y-1">
|
||||
{titleComponent}
|
||||
{liveStatusComponent}
|
||||
{summaryComponent}
|
||||
{tagsComponent}
|
||||
</div>
|
||||
</div>
|
||||
<ClientSelect className="w-full mt-2" event={event} />
|
||||
<ClientSelect className="mt-2 w-full" event={event} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default function LongFormArticle({
|
|||
return (
|
||||
<SecondaryPageLink
|
||||
to={toNote(href)}
|
||||
className="break-words underline text-foreground"
|
||||
className="break-words text-foreground underline"
|
||||
>
|
||||
{children}
|
||||
</SecondaryPageLink>
|
||||
|
|
@ -53,7 +53,7 @@ export default function LongFormArticle({
|
|||
return (
|
||||
<SecondaryPageLink
|
||||
to={toProfile(href)}
|
||||
className="break-words underline text-foreground"
|
||||
className="break-words text-foreground underline"
|
||||
>
|
||||
{children}
|
||||
</SecondaryPageLink>
|
||||
|
|
@ -65,7 +65,7 @@ export default function LongFormArticle({
|
|||
href={href}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className="break-words inline-flex items-baseline gap-1"
|
||||
className="inline-flex items-baseline gap-1 break-words"
|
||||
>
|
||||
{children} <ExternalLink className="size-3" />
|
||||
</a>
|
||||
|
|
@ -73,11 +73,11 @@ export default function LongFormArticle({
|
|||
},
|
||||
p: (props) => <p {...props} className="break-words" />,
|
||||
div: (props) => <div {...props} className="break-words" />,
|
||||
code: (props) => <code {...props} className="break-words whitespace-pre-wrap" />,
|
||||
code: (props) => <code {...props} className="whitespace-pre-wrap break-words" />,
|
||||
img: (props) => (
|
||||
<ImageWithLightbox
|
||||
image={{ url: props.src || '', pubkey: event.pubkey }}
|
||||
className="max-h-[80vh] sm:max-h-[50vh] object-contain my-0"
|
||||
className="my-0 max-h-[80vh] object-contain sm:max-h-[50vh]"
|
||||
classNames={{
|
||||
wrapper: 'w-fit max-w-full'
|
||||
}}
|
||||
|
|
@ -91,7 +91,7 @@ export default function LongFormArticle({
|
|||
<>
|
||||
<div
|
||||
ref={contentRef}
|
||||
className={`prose prose-zinc max-w-none dark:prose-invert break-words overflow-wrap-anywhere ${className || ''}`}
|
||||
className={`overflow-wrap-anywhere prose prose-zinc max-w-none break-words dark:prose-invert ${className || ''}`}
|
||||
>
|
||||
<h1 className="break-words">{metadata.title}</h1>
|
||||
{metadata.summary && (
|
||||
|
|
@ -102,7 +102,7 @@ export default function LongFormArticle({
|
|||
{metadata.image && (
|
||||
<ImageWithLightbox
|
||||
image={{ url: metadata.image, pubkey: event.pubkey }}
|
||||
className="w-full aspect-[3/1] object-cover my-0"
|
||||
className="my-0 aspect-[3/1] w-full object-cover"
|
||||
/>
|
||||
)}
|
||||
<Markdown
|
||||
|
|
@ -118,12 +118,12 @@ export default function LongFormArticle({
|
|||
{event.content}
|
||||
</Markdown>
|
||||
{metadata.tags.length > 0 && (
|
||||
<div className="flex gap-2 flex-wrap pb-2">
|
||||
<div className="flex flex-wrap gap-2 pb-2">
|
||||
{metadata.tags.map((tag) => (
|
||||
<div
|
||||
key={tag}
|
||||
title={tag}
|
||||
className="flex items-center rounded-full px-3 bg-muted text-muted-foreground max-w-44 cursor-pointer hover:bg-accent hover:text-accent-foreground"
|
||||
className="flex max-w-44 cursor-pointer items-center rounded-full bg-muted px-3 text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] }))
|
||||
|
|
|
|||
|
|
@ -19,14 +19,14 @@ export default function LongFormArticlePreview({
|
|||
const { autoLoadMedia } = useContentPolicy()
|
||||
const metadata = useMemo(() => getLongFormArticleMetadataFromEvent(event), [event])
|
||||
|
||||
const titleComponent = <div className="text-xl font-semibold line-clamp-2">{metadata.title}</div>
|
||||
const titleComponent = <div className="line-clamp-2 text-xl font-semibold">{metadata.title}</div>
|
||||
|
||||
const tagsComponent = metadata.tags.length > 0 && (
|
||||
<div className="flex gap-1 flex-wrap">
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{metadata.tags.map((tag) => (
|
||||
<div
|
||||
key={tag}
|
||||
className="flex items-center rounded-full text-xs px-2.5 py-0.5 bg-muted text-muted-foreground max-w-32 cursor-pointer hover:bg-accent hover:text-accent-foreground"
|
||||
className="flex max-w-32 cursor-pointer items-center rounded-full bg-muted px-2.5 py-0.5 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] }))
|
||||
|
|
@ -39,7 +39,7 @@ export default function LongFormArticlePreview({
|
|||
)
|
||||
|
||||
const summaryComponent = metadata.summary && (
|
||||
<div className="text-sm text-muted-foreground line-clamp-4">{metadata.summary}</div>
|
||||
<div className="line-clamp-4 text-sm text-muted-foreground">{metadata.summary}</div>
|
||||
)
|
||||
|
||||
if (isSmallScreen) {
|
||||
|
|
@ -48,7 +48,7 @@ export default function LongFormArticlePreview({
|
|||
{metadata.image && autoLoadMedia && (
|
||||
<Image
|
||||
image={{ url: metadata.image, pubkey: event.pubkey }}
|
||||
className="w-full aspect-video"
|
||||
className="aspect-video w-full"
|
||||
hideIfError
|
||||
/>
|
||||
)}
|
||||
|
|
@ -67,11 +67,11 @@ export default function LongFormArticlePreview({
|
|||
{metadata.image && autoLoadMedia && (
|
||||
<Image
|
||||
image={{ url: metadata.image, pubkey: event.pubkey }}
|
||||
className="aspect-[4/3] xl:aspect-video object-cover bg-foreground h-44"
|
||||
className="aspect-[4/3] h-44 bg-foreground object-cover xl:aspect-video"
|
||||
hideIfError
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1 w-0 space-y-1">
|
||||
<div className="w-0 flex-1 space-y-1">
|
||||
{titleComponent}
|
||||
{summaryComponent}
|
||||
{tagsComponent}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export default function MutedNote({ show }: { show: () => void }) {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2 items-center text-muted-foreground font-medium my-4">
|
||||
<div className="my-4 flex flex-col items-center gap-2 font-medium text-muted-foreground">
|
||||
<div>{t('This user has been muted')}</div>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export default function NsfwNote({ show }: { show: () => void }) {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2 items-center text-muted-foreground font-medium my-4">
|
||||
<div className="my-4 flex flex-col items-center gap-2 font-medium text-muted-foreground">
|
||||
<div>{t('🔞 NSFW 🔞')}</div>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ export default function Poll({ event, className }: { event: Event; className?: s
|
|||
key={option.id}
|
||||
title={option.label}
|
||||
className={cn(
|
||||
'relative w-full px-4 py-3 rounded-lg border transition-all flex items-center gap-2 overflow-hidden',
|
||||
'relative flex w-full items-center gap-2 overflow-hidden rounded-lg border px-4 py-3 transition-all',
|
||||
canVote ? 'cursor-pointer' : 'cursor-not-allowed',
|
||||
canVote &&
|
||||
(selectedOptionIds.includes(option.id)
|
||||
|
|
@ -184,7 +184,7 @@ export default function Poll({ event, className }: { event: Event; className?: s
|
|||
disabled={!canVote}
|
||||
>
|
||||
{/* Content */}
|
||||
<div className="flex items-center gap-2 flex-1 w-0 z-10">
|
||||
<div className="z-10 flex w-0 flex-1 items-center gap-2">
|
||||
<div className={cn('line-clamp-2 text-left', isMax ? 'font-semibold' : '')}>
|
||||
{option.label}
|
||||
</div>
|
||||
|
|
@ -195,7 +195,7 @@ export default function Poll({ event, className }: { event: Event; className?: s
|
|||
{showResults && (
|
||||
<div
|
||||
className={cn(
|
||||
'text-muted-foreground shrink-0 z-10',
|
||||
'z-10 shrink-0 text-muted-foreground',
|
||||
isMax ? 'font-semibold text-foreground' : ''
|
||||
)}
|
||||
>
|
||||
|
|
@ -217,13 +217,13 @@ export default function Poll({ event, className }: { event: Event; className?: s
|
|||
</div>
|
||||
|
||||
{/* Results Summary */}
|
||||
<div className="flex justify-between items-center text-sm text-muted-foreground">
|
||||
<div className="flex items-center justify-between text-sm text-muted-foreground">
|
||||
<div>{t('{{number}} votes', { number: pollResults?.totalVotes ?? 0 })}</div>
|
||||
|
||||
{isLoadingResults && t('Loading...')}
|
||||
{!isLoadingResults && showResults && (
|
||||
<div
|
||||
className="hover:underline cursor-pointer"
|
||||
className="cursor-pointer hover:underline"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
fetchResults()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default function RelayReview({ event, className }: { event: Event; classN
|
|||
<Stars stars={stars} />
|
||||
<span className="text-sm text-muted-foreground">→</span>
|
||||
<div
|
||||
className="text-sm text-muted-foreground hover:text-foreground hover:underline cursor-pointer truncate"
|
||||
className="cursor-pointer truncate text-sm text-muted-foreground hover:text-foreground hover:underline"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toRelay(url))
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export default function UnknownNote({ event, className }: { event: Event; classN
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col gap-2 items-center text-muted-foreground font-medium my-4',
|
||||
'my-4 flex flex-col items-center gap-2 font-medium text-muted-foreground',
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -122,14 +122,14 @@ export default function Note({
|
|||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="flex justify-between items-start gap-2">
|
||||
<div className="flex items-center space-x-2 flex-1">
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="flex flex-1 items-center space-x-2">
|
||||
<UserAvatar userId={event.pubkey} size={size === 'small' ? 'medium' : 'normal'} />
|
||||
<div className="flex-1 w-0">
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<Username
|
||||
userId={event.pubkey}
|
||||
className={`font-semibold flex truncate ${size === 'small' ? 'text-sm' : ''}`}
|
||||
className={`flex truncate font-semibold ${size === 'small' ? 'text-sm' : ''}`}
|
||||
skeletonClassName={size === 'small' ? 'h-3' : 'h-4'}
|
||||
/>
|
||||
<FollowingBadge pubkey={event.pubkey} />
|
||||
|
|
@ -149,7 +149,7 @@ export default function Note({
|
|||
<div className="flex items-center">
|
||||
<TranslateButton event={event} className={size === 'normal' ? '' : 'pr-0'} />
|
||||
{size === 'normal' && (
|
||||
<NoteOptions event={event} className="py-1 shrink-0 [&_svg]:size-5" />
|
||||
<NoteOptions event={event} className="shrink-0 py-1 [&_svg]:size-5" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export default function MainNoteCard({
|
|||
<div
|
||||
className={cn(
|
||||
'clickable transition-all duration-200',
|
||||
embedded ? 'p-3 sm:p-4 border rounded-xl bg-card' : 'py-3 hover:bg-accent/30'
|
||||
embedded ? 'rounded-xl border bg-card p-3 sm:p-4' : 'py-3 hover:bg-accent/30'
|
||||
)}
|
||||
>
|
||||
<Collapsible alwaysExpand={embedded}>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default function PinnedButton({ event }: { event: NostrEvent }) {
|
|||
|
||||
if (event.pubkey !== pubkey) {
|
||||
return (
|
||||
<div className="flex gap-1 text-sm items-center text-primary mb-1 px-4 py-0 h-fit">
|
||||
<div className="mb-1 flex h-fit items-center gap-1 px-4 py-0 text-sm text-primary">
|
||||
<Pin size={16} className="shrink-0" />
|
||||
{t('Pinned')}
|
||||
</div>
|
||||
|
|
@ -24,7 +24,7 @@ export default function PinnedButton({ event }: { event: NostrEvent }) {
|
|||
|
||||
return (
|
||||
<Button
|
||||
className="flex gap-1 text-sm text-primary items-center mb-1 px-4 py-0.5 h-fit"
|
||||
className="mb-1 flex h-fit items-center gap-1 px-4 py-0.5 text-sm text-primary"
|
||||
variant="link"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
|
|
@ -36,7 +36,7 @@ export default function PinnedButton({ event }: { event: NostrEvent }) {
|
|||
onMouseLeave={() => setHovered(false)}
|
||||
>
|
||||
{unpinning ? (
|
||||
<Loader size={16} className="animate-spin shrink-0" />
|
||||
<Loader size={16} className="shrink-0 animate-spin" />
|
||||
) : (
|
||||
<Pin size={16} className="shrink-0" />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -22,19 +22,19 @@ export default function RepostDescription({
|
|||
if (!reposters?.length) return null
|
||||
|
||||
return (
|
||||
<div className={cn('flex gap-1 text-sm items-center text-muted-foreground mb-1', className)}>
|
||||
<div className={cn('mb-1 flex items-center gap-1 text-sm text-muted-foreground', className)}>
|
||||
<Repeat2 size={16} className="shrink-0" />
|
||||
<Username
|
||||
key={reposters[0]}
|
||||
userId={reposters[0]}
|
||||
className={cn('font-semibold truncate', reposters.length > 1 && 'after:content-[","]')}
|
||||
className={cn('truncate font-semibold', reposters.length > 1 && 'after:content-[","]')}
|
||||
skeletonClassName="h-3"
|
||||
/>
|
||||
{reposters.length > 1 && (
|
||||
<Username
|
||||
key={reposters[1]}
|
||||
userId={reposters[1]}
|
||||
className={cn('font-semibold truncate', reposters.length === 3 && 'after:content-[","]')}
|
||||
className={cn('truncate font-semibold', reposters.length === 3 && 'after:content-[","]')}
|
||||
skeletonClassName="h-3"
|
||||
/>
|
||||
)}
|
||||
|
|
@ -44,7 +44,7 @@ export default function RepostDescription({
|
|||
<Username
|
||||
key={reposters[2]}
|
||||
userId={reposters[2]}
|
||||
className={cn('font-semibold truncate')}
|
||||
className={cn('truncate font-semibold')}
|
||||
skeletonClassName="h-3"
|
||||
/>
|
||||
) : null}
|
||||
|
|
@ -63,7 +63,7 @@ function AndXOthers({ reposters }: { reposters: string[] }) {
|
|||
{t('and {{x}} others', { x: reposters.length })}
|
||||
</span>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent className="w-fit max-w-60 flex flex-wrap p-2">
|
||||
<HoverCardContent className="flex w-fit max-w-60 flex-wrap p-2">
|
||||
{reposters.map((pubkey) => (
|
||||
<div key={pubkey} className="p-2">
|
||||
<UserAvatar key={pubkey} userId={pubkey} size="small" />
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ export function NoteCardLoadingSkeleton({ className }: { className?: string }) {
|
|||
return (
|
||||
<div className={cn('px-4 py-3', className)}>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Skeleton className="w-10 h-10 rounded-full" />
|
||||
<div className={`flex-1 w-0`}>
|
||||
<Skeleton className="h-10 w-10 rounded-full" />
|
||||
<div className={`w-0 flex-1`}>
|
||||
<div className="py-1">
|
||||
<Skeleton className="h-4 w-16" />
|
||||
</div>
|
||||
|
|
@ -68,10 +68,10 @@ export function NoteCardLoadingSkeleton({ className }: { className?: string }) {
|
|||
</div>
|
||||
<div className="pt-2">
|
||||
<div className="my-1">
|
||||
<Skeleton className="w-full h-4 my-1 mt-2" />
|
||||
<Skeleton className="my-1 mt-2 h-4 w-full" />
|
||||
</div>
|
||||
<div className="my-1">
|
||||
<Skeleton className="w-2/3 h-4 my-1" />
|
||||
<Skeleton className="my-1 h-4 w-2/3" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,13 +39,13 @@ export function Tabs({
|
|||
|
||||
return (
|
||||
<div className="w-fit">
|
||||
<div className="flex relative">
|
||||
<div className="relative flex">
|
||||
{TABS.map((tab, index) => (
|
||||
<div
|
||||
key={tab.value}
|
||||
ref={(el) => (tabRefs.current[index] = el)}
|
||||
className={cn(
|
||||
`text-center px-4 py-2 font-semibold clickable cursor-pointer rounded-lg`,
|
||||
`clickable cursor-pointer rounded-lg px-4 py-2 text-center font-semibold`,
|
||||
selectedTab === tab.value ? '' : 'text-muted-foreground'
|
||||
)}
|
||||
onClick={() => onTabChange(tab.value)}
|
||||
|
|
@ -54,7 +54,7 @@ export function Tabs({
|
|||
</div>
|
||||
))}
|
||||
<div
|
||||
className="absolute bottom-0 h-1 bg-primary rounded-full transition-all duration-500"
|
||||
className="absolute bottom-0 h-1 rounded-full bg-primary transition-all duration-500"
|
||||
style={{
|
||||
width: `${indicatorStyle.width}px`,
|
||||
left: `${indicatorStyle.left}px`
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ export default function NoteInteractions({ event }: { event: Event }) {
|
|||
return (
|
||||
<>
|
||||
<div className="flex items-center justify-between">
|
||||
<ScrollArea className="flex-1 w-0">
|
||||
<ScrollArea className="w-0 flex-1">
|
||||
<Tabs selectedTab={type} onTabChange={setType} />
|
||||
<ScrollBar orientation="horizontal" className="opacity-0 pointer-events-none" />
|
||||
<ScrollBar orientation="horizontal" className="pointer-events-none opacity-0" />
|
||||
</ScrollArea>
|
||||
<Separator orientation="vertical" className="h-6" />
|
||||
<TrustScoreFilter filterId={SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS} />
|
||||
|
|
|
|||
|
|
@ -492,12 +492,12 @@ const NoteList = forwardRef<
|
|||
{shouldShowLoadingIndicator || filtering || initialLoading ? (
|
||||
<NoteCardLoadingSkeleton />
|
||||
) : events.length ? (
|
||||
<div className="text-center text-sm text-muted-foreground mt-2">{t('no more notes')}</div>
|
||||
<div className="mt-2 text-center text-sm text-muted-foreground">{t('no more notes')}</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center w-full mt-8 gap-4">
|
||||
<div className="mt-8 flex w-full flex-col items-center justify-center gap-4">
|
||||
<div className="text-center text-muted-foreground">
|
||||
<div className="text-lg font-medium">{t('No notes found')}</div>
|
||||
<div className="text-sm mt-1">{t('Try again later or check your connection')}</div>
|
||||
<div className="mt-1 text-sm">{t('Try again later or check your connection')}</div>
|
||||
</div>
|
||||
<Button size="lg" onClick={() => setRefreshCount((count) => count + 1)}>
|
||||
{t('Reload')}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export function MobileMenu({
|
|||
<Button
|
||||
key={index}
|
||||
onClick={action.onClick}
|
||||
className={`w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5 ${action.className || ''}`}
|
||||
className={`w-full justify-start gap-4 p-6 text-lg [&_svg]:size-5 ${action.className || ''}`}
|
||||
variant="ghost"
|
||||
>
|
||||
<Icon />
|
||||
|
|
@ -52,18 +52,18 @@ export function MobileMenu({
|
|||
<>
|
||||
<Button
|
||||
onClick={goBackToMainMenu}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5 mb-2"
|
||||
className="mb-2 w-full justify-start gap-4 p-6 text-lg [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
>
|
||||
<ArrowLeft />
|
||||
{subMenuTitle}
|
||||
</Button>
|
||||
<div className="border-t border-border mb-2" />
|
||||
<div className="mb-2 border-t border-border" />
|
||||
{activeSubMenu.map((subAction, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
onClick={subAction.onClick}
|
||||
className={`w-full p-6 justify-start text-lg gap-4 ${subAction.className || ''}`}
|
||||
className={`w-full justify-start gap-4 p-6 text-lg ${subAction.className || ''}`}
|
||||
variant="ghost"
|
||||
>
|
||||
{subAction.label}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export default function RawEventDialog({
|
|||
<DialogDescription className="hidden" />
|
||||
</DialogHeader>
|
||||
<ScrollArea className="h-full">
|
||||
<pre className="text-sm text-muted-foreground select-text">
|
||||
<pre className="select-text text-sm text-muted-foreground">
|
||||
{JSON.stringify(event, null, 2)}
|
||||
</pre>
|
||||
<ScrollBar orientation="horizontal" />
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue