fix(cabinet): sweep mobile flex-overflow across all pages + components

Full scan of every page/component for the Connected-Accounts overflow class
(long user data with no truncation pushing siblings off the card on mobile),
adversarially verified. Applied min-w-0 + truncate (break-all for copyable
values, break-words for titles) on text columns and shrink-0 on fixed
siblings across ~23 files: AppHeader, dashboard/SubscriptionCardActive,
subscription purchase/sheets (TariffPurchaseForm, ClassicPurchaseWizard,
SwitchTariffSheet), SuccessNotificationModal, PurchaseSuccess, Wheel sub
picker, ReferralNetwork UserDetailPanel, and the admin pages (AnalyticsTab,
BrandingTab, SubscriptionSubRow, user-detail Info/Referrals tabs,
ApplicationReview, PartnerCampaignAssign, Partners, PromocodeStats,
PromoOfferSend, RemnawaveSquadDetail, TariffCreate, Tickets, Withdrawals).
This commit is contained in:
c0mrade
2026-06-04 23:32:59 +03:00
parent 7383505a12
commit 800daf7506
23 changed files with 90 additions and 74 deletions

View File

@@ -88,9 +88,11 @@ export default function AdminApplicationReview() {
<div className="space-y-3">
<div className="flex items-start justify-between gap-4">
<div className="min-w-0 flex-1">
<div className="mb-1 flex items-center gap-2">
<span className="font-medium text-dark-100">{displayName}</span>
{app.username && <span className="text-sm text-dark-500">@{app.username}</span>}
<div className="mb-1 flex min-w-0 items-center gap-2">
<span className="truncate font-medium text-dark-100">{displayName}</span>
{app.username && (
<span className="shrink-0 text-sm text-dark-500">@{app.username}</span>
)}
</div>
</div>
</div>

View File

@@ -87,9 +87,11 @@ export default function AdminPartnerCampaignAssign() {
</span>
)}
</div>
<div className="mt-1 flex items-center gap-3 text-xs text-dark-500">
<span className="font-mono">?start={campaign.start_parameter}</span>
<span>
<div className="mt-1 flex min-w-0 items-center gap-3 text-xs text-dark-500">
<span className="min-w-0 truncate font-mono">
?start={campaign.start_parameter}
</span>
<span className="shrink-0">
{campaign.registrations_count}{' '}
{t('admin.campaigns.overview.registrations').toLowerCase()}
</span>

View File

@@ -129,12 +129,14 @@ export default function AdminPartners() {
>
<div className="flex items-start justify-between gap-4">
<div className="min-w-0 flex-1">
<div className="mb-1 flex items-center gap-2">
<div className="mb-1 flex min-w-0 items-center gap-2">
<h3 className="truncate font-medium text-dark-100">
{partner.first_name || partner.username || `#${partner.user_id}`}
</h3>
{partner.username && (
<span className="text-sm text-dark-500">@{partner.username}</span>
<span className="shrink-0 text-sm text-dark-500">
@{partner.username}
</span>
)}
</div>
<div className="flex flex-wrap gap-x-4 gap-y-1 text-sm text-dark-400">
@@ -177,12 +179,12 @@ export default function AdminPartners() {
<div key={app.id} className="rounded-xl border border-dark-700 bg-dark-800 p-4">
<div className="mb-3 flex items-start justify-between gap-4">
<div className="min-w-0 flex-1">
<div className="mb-1 flex items-center gap-2">
<div className="mb-1 flex min-w-0 items-center gap-2">
<h3 className="truncate font-medium text-dark-100">
{app.first_name || app.username || `#${app.user_id}`}
</h3>
{app.username && (
<span className="text-sm text-dark-500">@{app.username}</span>
<span className="shrink-0 text-sm text-dark-500">@{app.username}</span>
)}
</div>
{app.company_name && (

View File

@@ -339,18 +339,18 @@ export default function AdminPromoOfferSend() {
<div ref={searchRef} className="relative">
{selectedUser ? (
// Selected user display
<div className="flex items-center justify-between rounded-lg border border-accent-500 bg-accent-500/10 px-3 py-2.5">
<div className="flex items-center gap-3">
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-dark-600">
<div className="flex items-center justify-between gap-2 rounded-lg border border-accent-500 bg-accent-500/10 px-3 py-2.5">
<div className="flex min-w-0 items-center gap-3">
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-dark-600">
<UserIcon />
</div>
<div>
<div className="text-sm font-medium text-dark-100">
<div className="min-w-0">
<div className="truncate text-sm font-medium text-dark-100">
{selectedUser.full_name ||
selectedUser.username ||
`ID: ${selectedUser.telegram_id}`}
</div>
<div className="text-xs text-dark-400">
<div className="truncate text-xs text-dark-400">
{selectedUser.username && `@${selectedUser.username} · `}
Telegram: {selectedUser.telegram_id}
</div>
@@ -358,7 +358,7 @@ export default function AdminPromoOfferSend() {
</div>
<button
onClick={handleClearUser}
className="rounded-lg p-1.5 text-dark-400 transition-colors hover:bg-dark-600 hover:text-dark-100"
className="shrink-0 rounded-lg p-1.5 text-dark-400 transition-colors hover:bg-dark-600 hover:text-dark-100"
>
<CloseIcon className="h-4 w-4" />
</button>

View File

@@ -100,7 +100,7 @@ export default function AdminPromocodeStats() {
<AdminBackButton to="/admin/promocodes" />
<div className="flex flex-wrap items-center gap-2">
<div
className={`rounded-lg px-3 py-1.5 font-mono text-lg font-bold ${getTypeColor(promocode.type)}`}
className={`min-w-0 break-all rounded-lg px-3 py-1.5 font-mono text-lg font-bold ${getTypeColor(promocode.type)}`}
>
{promocode.code}
</div>

View File

@@ -229,11 +229,11 @@ export default function AdminRemnawaveSquadDetail() {
key={idx}
className="flex items-center justify-between rounded-lg bg-dark-700/50 px-4 py-3"
>
<span className="text-sm text-dark-200">
<span className="min-w-0 flex-1 truncate text-sm text-dark-200">
{String(inbound.tag || inbound.uuid || `Inbound ${idx + 1}`)}
</span>
{typeof inbound.type === 'string' && (
<span className="rounded bg-dark-600 px-2 py-1 text-xs text-dark-400">
<span className="ml-2 shrink-0 rounded bg-dark-600 px-2 py-1 text-xs text-dark-400">
{inbound.type}
</span>
)}

View File

@@ -697,8 +697,10 @@ export default function AdminTariffCreate() {
>
{isSelected && <CheckIcon />}
</div>
<span className="flex-1 text-sm font-medium">{squad.name}</span>
<span className="text-xs text-dark-500">
<span className="min-w-0 flex-1 truncate text-sm font-medium">
{squad.name}
</span>
<span className="shrink-0 text-xs text-dark-500">
{squad.members_count} {t('admin.tariffs.externalSquadUsers')}
</span>
</button>
@@ -1059,7 +1061,9 @@ export default function AdminTariffCreate() {
>
{isSelected && <CheckIcon />}
</div>
<span className="flex-1 text-sm font-medium">{group.name}</span>
<span className="min-w-0 flex-1 truncate text-sm font-medium">
{group.name}
</span>
</button>
);
})}

View File

@@ -443,7 +443,7 @@ export default function AdminTickets() {
</span>
</div>
</div>
<div className="mb-4 flex items-center gap-2 text-sm text-dark-500">
<div className="mb-4 flex flex-wrap items-center gap-2 text-sm text-dark-500">
<span>
{t('admin.tickets.from')}: {formatUser(selectedTicket)}
{selectedTicket.user?.telegram_id && (

View File

@@ -116,7 +116,7 @@ export default function AdminWithdrawals() {
<div className="min-w-0 flex-1">
{/* User and amount */}
<div className="mb-2 flex items-center gap-2">
<span className="truncate font-medium text-dark-100">
<span className="min-w-0 truncate font-medium text-dark-100">
{item.username
? `@${item.username}`
: item.first_name || `#${item.user_id}`}

View File

@@ -60,9 +60,9 @@ function CopyableField({ label, value }: { label: string; value: string }) {
return (
<div className="flex items-center gap-2 rounded-xl bg-dark-800/50 px-4 py-3">
<div className="flex-1 text-left">
<div className="min-w-0 flex-1 text-left">
<p className="text-xs text-dark-400">{label}</p>
<p className="mt-0.5 font-mono text-sm text-dark-100">{value}</p>
<p className="mt-0.5 break-all font-mono text-sm text-dark-100">{value}</p>
</div>
<button
type="button"

View File

@@ -61,9 +61,9 @@ export function UserDetailPanel({ userId, className }: UserDetailPanelProps) {
{/* Identity */}
<div className="space-y-2">
{user.username && (
<div className="flex items-center justify-between text-sm">
<span className="text-dark-500">@</span>
<span className="font-mono text-dark-200">{user.username}</span>
<div className="flex items-center justify-between gap-2 text-sm">
<span className="shrink-0 text-dark-500">@</span>
<span className="min-w-0 truncate font-mono text-dark-200">{user.username}</span>
</div>
)}
{user.tg_id && (
@@ -196,11 +196,11 @@ export function UserDetailPanel({ userId, className }: UserDetailPanelProps) {
</span>
</div>
{user.campaign_name && (
<div className="flex items-center justify-between text-sm">
<span className="text-dark-400">
<div className="flex items-center justify-between gap-2 text-sm">
<span className="shrink-0 text-dark-400">
{t('admin.referralNetwork.user.fromCampaign')}
</span>
<span className="text-dark-200">{user.campaign_name}</span>
<span className="min-w-0 truncate text-dark-200">{user.campaign_name}</span>
</div>
)}
</div>

View File

@@ -599,16 +599,16 @@ export default function Wheel() {
key={sub.id}
onClick={() => setSelectedSubscriptionId(sub.id)}
disabled={isSpinning}
className={`flex w-full items-center justify-between rounded-lg px-3 py-2 text-sm transition-all ${
className={`flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2 text-sm transition-all ${
selectedSubscriptionId === sub.id
? 'bg-accent-500/15 text-accent-400'
: 'text-dark-400 hover:text-dark-200'
}`}
>
<span className="font-medium">
<span className="min-w-0 truncate font-medium">
{sub.tariff_name || t('subscription.defaultName', 'Подписка')}
</span>
<span className="text-xs opacity-60">
<span className="shrink-0 text-xs opacity-60">
{sub.days_left} {t('common.units.days', 'дней')}
</span>
</button>