Skip to content

Commit 31c7f78

Browse files
committed
better spacing on activity graph
1 parent 9a8c6b5 commit 31c7f78

1 file changed

Lines changed: 15 additions & 13 deletions

File tree

  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]

apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { DesignCategoryTabs, DesignEditableGrid, DesignMenu, type DesignCategory
44
import { EditableInput } from "@/components/editable-input";
55
import { FormDialog, SmartFormDialog } from "@/components/form-dialog";
66
import { InputField, SelectField } from "@/components/form-fields";
7+
import { Link } from "@/components/link";
78
import { MetadataSection } from "@/components/metadata-editor";
89
import {
910
Accordion,
@@ -33,13 +34,13 @@ import {
3334
Typography,
3435
useToast
3536
} from "@/components/ui";
36-
import { Link } from "@/components/link";
3737
import { DeleteUserDialog, ImpersonateUserDialog } from "@/components/user-dialogs";
3838
import { ALL_APPS_FRONTEND } from "@/lib/apps-frontend";
3939
import { isAppEnabled } from "@/lib/apps-utils";
4040
import { parseRiskScore } from "@/lib/risk-score-utils";
4141
import { useUserActivityOrThrow } from "@/lib/stack-app-internals";
4242
import { AtIcon, CalendarIcon, CheckIcon, DatabaseIcon, EnvelopeIcon, GlobeIcon, HashIcon, PlusIcon, ProhibitIcon, ShieldIcon, SquareIcon, XIcon } from "@phosphor-icons/react";
43+
import { type DataGridColumnDef } from "@stackframe/dashboard-ui-components";
4344
import { ServerContactChannel, ServerOAuthProvider, ServerTeam, ServerUser } from "@stackframe/stack";
4445
import { KnownErrors } from "@stackframe/stack-shared";
4546
import { AppId } from "@stackframe/stack-shared/dist/apps/apps-config";
@@ -48,7 +49,6 @@ import { fromNow } from "@stackframe/stack-shared/dist/utils/dates";
4849
import { captureError, StackAssertionError, throwErr } from '@stackframe/stack-shared/dist/utils/errors';
4950
import { runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/promises";
5051
import { deindent } from "@stackframe/stack-shared/dist/utils/strings";
51-
import { type DataGridColumnDef } from "@stackframe/dashboard-ui-components";
5252
import { Suspense, useCallback, useMemo, useState, type ReactNode } from "react";
5353
import * as yup from "yup";
5454
import { AppEnabledGuard } from "../../app-enabled-guard";
@@ -111,7 +111,7 @@ function UserHeader({ user }: UserHeaderProps) {
111111
}}/>
112112
<p>Last active {fromNow(user.lastActiveAt)}</p>
113113
</div>
114-
<div>
114+
<div className="shrink-0 mr-8">
115115
<DesignMenu
116116
variant="actions"
117117
trigger="icon"
@@ -1340,13 +1340,13 @@ const ACTIVITY_GRID_CELLS = ACTIVITY_GRID_COLUMNS * ACTIVITY_GRID_ROWS;
13401340
const ACTIVITY_CELL_SIZE_PX = 8;
13411341
const ACTIVITY_GRID_GAP_PX = 2;
13421342
const ACTIVITY_WEEKDAY_LABELS = [
1343+
{ label: "", ariaLabel: null },
13431344
{ label: "M", ariaLabel: "Monday" },
13441345
{ label: "", ariaLabel: null },
13451346
{ label: "W", ariaLabel: "Wednesday" },
13461347
{ label: "", ariaLabel: null },
13471348
{ label: "F", ariaLabel: "Friday" },
13481349
{ label: "", ariaLabel: null },
1349-
{ label: "S", ariaLabel: "Sunday" },
13501350
] as const;
13511351

13521352
// Activity heatmap color ramp. Indexed by 0 = no activity, 1..4 = increasing
@@ -1403,17 +1403,17 @@ function formatActivityIsoDate(date: Date): string {
14031403
return date.toISOString().slice(0, 10);
14041404
}
14051405

1406-
function getMondayWeekStart(date: Date): Date {
1406+
function getSundayWeekStart(date: Date): Date {
14071407
const weekStart = new Date(date);
14081408
weekStart.setUTCHours(0, 0, 0, 0);
1409-
const dayIndex = (weekStart.getUTCDay() + 6) % 7;
1409+
const dayIndex = weekStart.getUTCDay();
14101410
weekStart.setUTCDate(weekStart.getUTCDate() - dayIndex);
14111411
return weekStart;
14121412
}
14131413

14141414
function ActivityShell({ children }: { children: ReactNode }) {
14151415
return (
1416-
<div className="hidden xl:flex flex-col items-end gap-1.5 shrink-0 pt-1">
1416+
<div className="hidden xl:flex flex-col items-center gap-1.5 shrink-0 pt-1">
14171417
<span className="text-[11px] font-medium text-muted-foreground tracking-wide uppercase">Activity</span>
14181418
<div
14191419
className="grid text-[9px] leading-none text-muted-foreground/70"
@@ -1477,12 +1477,14 @@ function ActivityGraph({ userId }: { userId: string }) {
14771477
const latestDate = dataPoints.length > 0
14781478
? parseActivityDate(dataPoints[dataPoints.length - 1].date)
14791479
: new Date();
1480-
const startDate = getMondayWeekStart(latestDate);
1481-
startDate.setUTCDate(startDate.getUTCDate() - (ACTIVITY_GRID_ROWS - 1) * ACTIVITY_GRID_COLUMNS);
1482-
1480+
// GitHub-style: weeks start on Sunday; grid rows go top → bottom from newest week
1481+
// to oldest; within each row, columns are Sun → Sat.
1482+
const week0Sunday = getSundayWeekStart(latestDate);
14831483
return Array.from({ length: ACTIVITY_GRID_CELLS }, (_, index) => {
1484-
const date = new Date(startDate);
1485-
date.setUTCDate(startDate.getUTCDate() + index);
1484+
const row = Math.floor(index / ACTIVITY_GRID_COLUMNS);
1485+
const col = index % ACTIVITY_GRID_COLUMNS;
1486+
const date = new Date(week0Sunday);
1487+
date.setUTCDate(week0Sunday.getUTCDate() - row * ACTIVITY_GRID_COLUMNS + col);
14861488
const isoDate = formatActivityIsoDate(date);
14871489
return {
14881490
date: isoDate,
@@ -1567,7 +1569,7 @@ function UserPage({ user }: { user: ServerUser }) {
15671569

15681570
return (
15691571
<PageLayout>
1570-
<div className="relative flex flex-col gap-6 xl:pr-24">
1572+
<div className="relative flex flex-col gap-6 xl:pr-36">
15711573
<RestrictionBanner user={user} />
15721574
<div className="absolute right-0 top-0 z-[100] hidden xl:block">
15731575
<Suspense fallback={<ActivityLoadingFallback />}>

0 commit comments

Comments
 (0)