feat(uat-b2): visual breakpoint fixes + form-error UX rollout
B2 Wave A (visual breakpoints):
- Documents Hub folder rail: widen ResizablePanel default 20→22%,
min 14→18%, add min-w-[180px] CSS floor so names don't truncate
at tablet 768
- Website analytics KPI tiles: switch lg grid 6→3 cols, restore 6
at xl so "Visit duration" stops truncating in the 1024+sidebar
layout
- Pipeline Value tile per-stage rows: compact $3.5M format on
sm- breakpoint (responsive sm:hidden / hidden sm:inline pair)
B2 Wave D (form-error UX rollout):
- useFormScrollToError + FormErrorSummary wired into 5 high-impact
forms: client-form, interest-form, yacht-form, company-form,
berth-form. Validation failures now scroll the first errored
field into view + render a top-of-form summary banner when ≥2
errors exist. Remaining ~23 form surfaces queued for follow-up.
B2 Wave B (Umami follow-ups):
- TopList primitive: add onExpandRange + expandRangeLabel props
for the empty-state nudge ("Try last 30 days" button). Callers
can opt in to drive the page-level DateRange.
B2 Wave C (FieldLabel + admin tooltip audit):
- Verified FieldLabel primitive already exists + is adopted in
custom-field-form. Registry-driven-form renders entry.description
inline below labels for every entry — the broad sweep across
15-20 admin pages is deferred to a focused polish session.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import Link from 'next/link';
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import type { UmamiMetricRow } from '@/lib/services/umami.service';
|
||||
@@ -18,6 +19,12 @@ interface Props {
|
||||
viewAllHref?: string;
|
||||
/** Cap for the inline list (default 10). The full page uses no cap. */
|
||||
limit?: number;
|
||||
/** Optional callback invoked when the empty-state "expand range" CTA is
|
||||
* clicked. When supplied, the empty state shows a nudge button suggesting
|
||||
* the rep try a wider range. */
|
||||
onExpandRange?: () => void;
|
||||
/** Label for the expand-range button when `onExpandRange` is supplied. */
|
||||
expandRangeLabel?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,6 +40,8 @@ export function TopList({
|
||||
defaultLabel = '-',
|
||||
viewAllHref,
|
||||
limit = 10,
|
||||
onExpandRange,
|
||||
expandRangeLabel = 'Try last 30 days',
|
||||
}: Props) {
|
||||
return (
|
||||
<Card>
|
||||
@@ -61,7 +70,14 @@ export function TopList({
|
||||
<Skeleton className="h-4 w-3/6" />
|
||||
</div>
|
||||
) : !rows || rows.length === 0 ? (
|
||||
<div className="py-6 text-center text-sm text-muted-foreground">No data</div>
|
||||
<div className="space-y-2 py-6 text-center text-sm text-muted-foreground">
|
||||
<p>No data in this range.</p>
|
||||
{onExpandRange ? (
|
||||
<Button size="sm" variant="outline" onClick={onExpandRange}>
|
||||
{expandRangeLabel}
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<ul className="space-y-1.5">
|
||||
{rows.slice(0, limit).map((row, i) => {
|
||||
|
||||
@@ -124,8 +124,11 @@ export function WebsiteAnalyticsShell() {
|
||||
strip at the very top. Polling only fires while expanded. */}
|
||||
<RealtimePanel />
|
||||
|
||||
{/* Live indicator + KPI tiles - mirrors Umami's overview row. */}
|
||||
<div className="grid gap-3 grid-cols-2 sm:gap-4 md:grid-cols-3 lg:grid-cols-6">
|
||||
{/* Live indicator + KPI tiles - mirrors Umami's overview row.
|
||||
At lg the six tiles wrap to 3+3 so "Visit duration" doesn't
|
||||
truncate to "2." in the cramped 1024-with-sidebar layout.
|
||||
xl restores the single 6-column row when there's real room. */}
|
||||
<div className="grid gap-3 grid-cols-2 sm:gap-4 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-6">
|
||||
<ActiveVisitorsBadge value={active.data?.data?.visitors} loading={active.isLoading} />
|
||||
<KpiPair
|
||||
label="Visitors"
|
||||
|
||||
Reference in New Issue
Block a user