fix: mobile responsiveness across all pages

- SiteNav: add horizontal scroll for 8 tabs on mobile
- NotificationCenter: full-width dropdown on mobile
- ContentStats/Locations/TechSpecs: scrollable tab bars
- FrustrationTable: fix selector text overflow
- FrustrationByPageTable: horizontal scroll on mobile
- CDN: better stat card grid breakpoints
- Home: reduce stat card height, prevent button wrap
- Billing: shorter invoice labels on mobile
- Bump @ciphera-net/ui to 0.2.6 (AppLauncher mobile fix)
This commit is contained in:
Usman Baig
2026-03-15 18:15:06 +01:00
parent 7103a39273
commit 24c71f7991
13 changed files with 30 additions and 21 deletions

View File

@@ -45,7 +45,7 @@ export default function FrustrationByPageTable({ pages, loading }: FrustrationBy
{loading ? (
<SkeletonRows />
) : hasData ? (
<div>
<div className="overflow-x-auto -mx-6 px-6">
{/* Header */}
<div className="flex items-center justify-between px-2 -mx-2 mb-2 text-xs font-medium text-neutral-400 dark:text-neutral-500 uppercase tracking-wider">
<span>Page</span>
@@ -72,7 +72,7 @@ export default function FrustrationByPageTable({ pages, loading }: FrustrationBy
style={{ width: `${barWidth}%` }}
/>
<span
className="relative text-sm text-neutral-900 dark:text-white truncate max-w-[300px]"
className="relative text-sm text-neutral-900 dark:text-white truncate max-w-[200px] sm:max-w-[300px]"
title={page.page_path}
>
{page.page_path}

View File

@@ -81,7 +81,7 @@ function Row({
return (
<div className="flex items-center justify-between h-9 group hover:bg-neutral-50 dark:hover:bg-neutral-800 rounded-lg px-2 -mx-2 transition-colors">
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 min-w-0 overflow-hidden">
<SelectorCell selector={item.selector} />
<span
className="text-xs text-neutral-400 dark:text-neutral-500 truncate shrink-0"

View File

@@ -115,7 +115,7 @@ export default function ContentStats({ topPages, entryPages, exitPages, domain,
</button>
)}
</div>
<div className="flex gap-1" role="tablist" aria-label="Pages view tabs" onKeyDown={handleTabKeyDown}>
<div className="flex gap-1 overflow-x-auto scrollbar-hide" role="tablist" aria-label="Pages view tabs" onKeyDown={handleTabKeyDown}>
{(['top_pages', 'entry_pages', 'exit_pages'] as Tab[]).map((tab) => (
<button
key={tab}

View File

@@ -233,7 +233,7 @@ export default function Locations({ countries, cities, regions, geoDataLevel = '
</button>
)}
</div>
<div className="flex gap-1" role="tablist" aria-label="Location view tabs" onKeyDown={handleTabKeyDown}>
<div className="flex gap-1 overflow-x-auto scrollbar-hide" role="tablist" aria-label="Location view tabs" onKeyDown={handleTabKeyDown}>
{(['map', 'globe', 'countries', 'regions', 'cities'] as Tab[]).map((tab) => (
<button
key={tab}

View File

@@ -36,7 +36,7 @@ export default function SiteNav({ siteId }: SiteNavProps) {
return (
<div className="border-b border-neutral-200 dark:border-neutral-800 mb-6">
<nav className="flex gap-1" role="tablist" aria-label="Site navigation" onKeyDown={handleTabKeyDown}>
<nav className="flex gap-1 overflow-x-auto scrollbar-hide" role="tablist" aria-label="Site navigation" onKeyDown={handleTabKeyDown}>
{tabs.map((tab) => (
<Link
key={tab.href}
@@ -44,7 +44,7 @@ export default function SiteNav({ siteId }: SiteNavProps) {
role="tab"
aria-selected={isActive(tab.href)}
tabIndex={isActive(tab.href) ? 0 : -1}
className={`relative px-3 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-orange rounded-t cursor-pointer -mb-px ${
className={`relative shrink-0 whitespace-nowrap px-3 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-orange rounded-t cursor-pointer -mb-px ${
isActive(tab.href)
? 'text-neutral-900 dark:text-white'
: 'text-neutral-400 dark:text-neutral-500 hover:text-neutral-700 dark:hover:text-neutral-300'

View File

@@ -145,7 +145,7 @@ export default function TechSpecs({ browsers, os, devices, screenResolutions, co
</button>
)}
</div>
<div className="flex gap-1" role="tablist" aria-label="Technology view tabs" onKeyDown={handleTabKeyDown}>
<div className="flex gap-1 overflow-x-auto scrollbar-hide" role="tablist" aria-label="Technology view tabs" onKeyDown={handleTabKeyDown}>
{(['browsers', 'os', 'devices', 'screens'] as Tab[]).map((tab) => (
<button
key={tab}

View File

@@ -152,7 +152,7 @@ export default function NotificationCenter() {
id="notification-dropdown"
role="dialog"
aria-label="Notifications"
className="absolute right-0 top-full mt-2 w-80 sm:w-96 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-xl shadow-xl overflow-hidden z-[100]"
className="fixed left-4 right-4 top-16 sm:absolute sm:left-auto sm:right-0 sm:top-full sm:mt-2 sm:w-96 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-xl shadow-xl overflow-hidden z-[100]"
>
<div className="flex items-center justify-between px-4 py-3 border-b border-neutral-200 dark:border-neutral-700">
<h3 className="font-semibold text-neutral-900 dark:text-white">Notifications</h3>

View File

@@ -1098,7 +1098,7 @@ export default function OrganizationSettings() {
<a href={invoice.invoice_pdf} target="_blank" rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-2.5 py-1.5 text-xs font-medium text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white hover:bg-neutral-100 dark:hover:bg-neutral-800 rounded-lg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-orange" title="Download PDF">
<DownloadIcon className="w-3.5 h-3.5" />
Download PDF
<span className="hidden sm:inline">Download</span> PDF
</a>
)}
{invoice.hosted_invoice_url && (
@@ -1110,7 +1110,7 @@ export default function OrganizationSettings() {
}`}
title={invoice.status === 'open' ? 'Pay now' : 'View invoice'}>
<ExternalLinkIcon className="w-3.5 h-3.5" />
{invoice.status === 'open' ? 'Pay now' : 'View invoice'}
{invoice.status === 'open' ? 'Pay now' : <><span className="hidden sm:inline">View </span>Invoice</>}
</a>
)}
</div>