fix(cabinet): stop long user data overflowing flex rows on mobile

Same flex-overflow class as the Connected-Accounts card — a long
user-controlled string with no truncation pushes its sibling badge/button
out of the card on narrow screens. Found via a scan of the high-risk
screens; fixed with min-w-0 + truncate/break-words on the text column and
shrink-0 on the fixed siblings:
- Balance: promocode-target tariff name vs days-left badge
- ReferralNetwork CampaignDetailPanel: start_parameter + top-referrer username
- ServerManagementSheet: country/server name vs flag emoji
- Contests / Polls: contest/poll title vs prize/reward badge
This commit is contained in:
c0mrade
2026-06-04 23:03:42 +03:00
parent c39c164d51
commit 63863a048b
5 changed files with 30 additions and 26 deletions

View File

@@ -168,15 +168,15 @@ export function ServerManagementSheet({
: 'border-champagne-300/60 bg-champagne-200/40 hover:border-champagne-400'
} ${!country.is_available && !isCurrentlyConnected ? 'cursor-not-allowed opacity-50' : ''}`}
>
<div className="flex items-center gap-3">
<span className="text-lg">
<div className="flex min-w-0 items-center gap-3">
<span className="shrink-0 text-lg">
{willBeAdded ? '' : willBeRemoved ? '' : isSelected ? '✅' : '⚪'}
</span>
<div>
<div className="flex items-center gap-2 font-medium text-dark-100">
{country.name}
<div className="min-w-0">
<div className="flex min-w-0 items-center gap-2 font-medium text-dark-100">
<span className="truncate">{country.name}</span>
{country.has_discount && !isCurrentlyConnected && (
<span className="rounded bg-success-500/20 px-1.5 py-0.5 text-xs text-success-400">
<span className="shrink-0 rounded bg-success-500/20 px-1.5 py-0.5 text-xs text-success-400">
-{country.discount_percent}%
</span>
)}
@@ -217,7 +217,7 @@ export function ServerManagementSheet({
</div>
</div>
{country.country_code && (
<span className="text-xl">{getFlagEmoji(country.country_code)}</span>
<span className="shrink-0 text-xl">{getFlagEmoji(country.country_code)}</span>
)}
</button>
);

View File

@@ -275,10 +275,10 @@ export default function Balance() {
key={sub.id}
onClick={() => handlePromocodeActivate(sub.id)}
disabled={promocodeLoading}
className="flex w-full items-center justify-between rounded-linear border border-dark-600 bg-dark-700 px-3 py-2 text-sm text-dark-200 transition-colors hover:border-accent-500/50 hover:bg-dark-600"
className="flex w-full min-w-0 items-center justify-between gap-3 rounded-linear border border-dark-600 bg-dark-700 px-3 py-2 text-sm text-dark-200 transition-colors hover:border-accent-500/50 hover:bg-dark-600"
>
<span>{sub.tariff_name}</span>
<span className="text-dark-400">
<span className="truncate">{sub.tariff_name}</span>
<span className="shrink-0 text-dark-400">
{t('balance.promocode.daysLeft', '{{count}} дн.', { count: sub.days_left })}
</span>
</button>

View File

@@ -198,14 +198,14 @@ export default function Contests() {
<div className="grid gap-4 sm:grid-cols-2">
{contests.map((contest) => (
<div key={contest.id} className="card">
<div className="flex items-start justify-between">
<div>
<h3 className="text-lg font-semibold">{contest.name}</h3>
<div className="flex items-start justify-between gap-2">
<div className="min-w-0">
<h3 className="break-words text-lg font-semibold">{contest.name}</h3>
{contest.description && (
<p className="mt-1 text-sm text-dark-400">{contest.description}</p>
)}
</div>
<div className="flex items-center gap-1 text-accent-400">
<div className="flex shrink-0 items-center gap-1 text-accent-400">
<TrophyIcon />
<span className="text-sm font-medium">
+{t('contests.days', { count: contest.prize_days })}

View File

@@ -205,9 +205,9 @@ export default function Polls() {
<div className="grid gap-4 sm:grid-cols-2">
{polls.map((poll) => (
<div key={poll.id} className="card">
<div className="flex items-start justify-between">
<div className="flex-1">
<h3 className="text-lg font-semibold">{poll.title}</h3>
<div className="flex items-start justify-between gap-2">
<div className="min-w-0 flex-1">
<h3 className="break-words text-lg font-semibold">{poll.title}</h3>
{poll.description && (
<p className="mt-1 text-sm text-dark-400">{poll.description}</p>
)}
@@ -219,7 +219,7 @@ export default function Polls() {
</div>
</div>
{poll.reward_amount && (
<div className="flex items-center gap-1 text-accent-400">
<div className="flex shrink-0 items-center gap-1 text-accent-400">
<GiftIcon className="h-5 w-5" />
<span className="text-sm font-medium">+{poll.reward_amount}</span>
</div>

View File

@@ -60,11 +60,13 @@ export function CampaignDetailPanel({ campaignId, className }: CampaignDetailPan
<div className="space-y-5">
{/* Info */}
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span className="text-dark-500">
<div className="flex items-center justify-between gap-2 text-sm">
<span className="shrink-0 text-dark-500">
{t('admin.referralNetwork.campaign.startParam')}
</span>
<span className="font-mono text-dark-200">{campaign.start_parameter}</span>
<span className="min-w-0 truncate font-mono text-dark-200">
{campaign.start_parameter}
</span>
</div>
<div className="flex justify-end">
<span
@@ -133,17 +135,19 @@ export function CampaignDetailPanel({ campaignId, className }: CampaignDetailPan
{campaign.top_referrers.map((referrer, index) => (
<div
key={referrer.user_id}
className="flex items-center justify-between text-sm"
className="flex items-center justify-between gap-2 text-sm"
>
<div className="flex items-center gap-2">
<span className="flex h-5 w-5 items-center justify-center rounded-full bg-dark-700 text-[10px] font-medium text-dark-300">
<div className="flex min-w-0 items-center gap-2">
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-dark-700 text-[10px] font-medium text-dark-300">
{index + 1}
</span>
<span className="text-dark-200">
<span className="truncate text-dark-200">
{referrer.username ? `@${referrer.username}` : `#${referrer.user_id}`}
</span>
</div>
<span className="font-mono text-dark-300">{referrer.referral_count}</span>
<span className="shrink-0 font-mono text-dark-300">
{referrer.referral_count}
</span>
</div>
))}
</div>