Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
gkalabin committed Jan 3, 2025
1 parent 05361bf commit c9316af
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/app/(authenticated)/overview/OverviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
NotConfiguredYet,
} from '@/components/NotConfiguredYet';
import {Button} from '@/components/ui/button';
import SpoilerText from '@/components/ui/spoiler-text';
import {
CoreDataContextProvider,
useCoreDataContext,
Expand Down
12 changes: 8 additions & 4 deletions src/app/(authenticated)/overview/stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {useHideBalances} from '@/app/(authenticated)/overview/hide-balances';
import {accountsSum} from '@/app/(authenticated)/overview/modelHelpers';
import {useExchangedTransactions} from '@/app/(authenticated)/stats/modelHelpers';
import {Card, CardContent} from '@/components/ui/card';
import SpoilerText from '@/components/ui/spoiler-text';
import {AmountWithCurrency} from '@/lib/AmountWithCurrency';
import {useCoreDataContext} from '@/lib/context/CoreDataContext';
import {useDisplayCurrency} from '@/lib/context/DisplaySettingsContext';
Expand Down Expand Up @@ -31,15 +32,18 @@ export function StatsWidget() {
if (!total || hideBalances) {
return <></>;
}
const totalFormatted = total.round().format();
return (
<>
<div className="py-5">
<div className="text-2xl font-bold">Your total balance</div>
<div className="text-3xl font-bold">
<div className="inline-block bg-gradient-to-r from-indigo-600 via-purple-500 via-55% to-orange-400 bg-clip-text text-transparent">
{total.round().format()}
<SpoilerText textLength={totalFormatted.length}>
<div className="text-3xl font-bold">
<div className="inline-block bg-gradient-to-r from-indigo-600 via-purple-500 via-55% to-orange-400 bg-clip-text text-transparent">
{totalFormatted}
</div>
</div>
</div>
</SpoilerText>
</div>
<Last30DaysIncomeExpense />
</>
Expand Down
82 changes: 82 additions & 0 deletions src/components/ui/spoiler-text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {cn} from '@/lib/utils';
import {useMemo, useRef, useState} from 'react';

/**
* SpoilerText
*
* Renders a string of text hidden behind an animated layer of floating dots.
* Clicking the layer reveals the text.
*
* @param {string} text - The text to display once revealed.
*/
export default function SpoilerText({
children,
textLength,
}: {
children: React.ReactNode;
textLength: number;
}) {
const [revealed, setRevealed] = useState(false);
const componentRef = useRef(null);
const dotsCount = textLength * 95;
const dots = useMemo(() => <Dots count={dotsCount} />, [dotsCount]);

// Otherwise, show the floating-dots overlay
return (
<span
className="relative inline-block cursor-pointer"
onClick={() => setRevealed(!revealed)}
>
<div ref={componentRef} className={cn(!revealed && 'invisible')}>
{children}
</div>
<div className={cn(revealed && 'invisible')}>{dots}</div>
</span>
);
}

function Dots({count}: {count: number}) {
console.log('dots dots dots', count);

const dots = [];
for (let i = 0; i < count; i++) {
// Random position in the container (0–100%)
const top = Math.random() * 100;
const left = Math.random() * 100;

// Random angle (0–360) and distance (~4–8px)
const angle = 2 * Math.PI * Math.random();
const distance = 4 + Math.random() * 4; // 4–8px
const tx = distance * Math.cos(angle);
const ty = distance * Math.sin(angle);

// Random delay up to 2s, random total duration ~1.5–2.5s
const delay = 0;
const duration = 1.5 + Math.random() * 2;

dots.push({top, left, tx, ty, delay, duration});
}
// Otherwise, show the floating-dots overlay
return (
<>
{dots.map((dot, i) => (
<span
key={i}
className="absolute block h-[1px] w-[1px] animate-float-dot rounded-full bg-gray-500"
style={
{
// Position each dot randomly within the container
top: `${dot.top}%`,
left: `${dot.left}%`,
// Use the custom CSS variables that the keyframe will pick up
'--tx': `${dot.tx}px`,
'--ty': `${dot.ty}px`,
// Stagger them with random delays/durations
animationDuration: `${dot.duration}s`,
} as React.CSSProperties
}
/>
))}
</>
);
}
14 changes: 14 additions & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,24 @@ const config = {
from: {height: 'var(--radix-accordion-content-height)'},
to: {height: '0'},
},
'float-dot': {
'0%': {
opacity: '0',
transform: 'translate(0, 0)',
},
'10%': {
opacity: '1',
},
'100%': {
opacity: '0',
transform: 'translate(var(--tx), var(--ty))',
},
},
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out',
'float-dot': 'float-dot 2s infinite ease-in-out',
},
},
},
Expand Down

0 comments on commit c9316af

Please sign in to comment.