stack/apps
BilalG1 94541c4a94
fix(dashboard): Restricted row styling + Replays empty state (#1366)
## Summary

Two small UI polish fixes in `apps/dashboard`:

1. **User detail page** — the **Restricted** field now visually matches
its sibling fields (`User ID`, `Display name`, `Primary email`, etc.) by
reusing the same input-box appearance (`rounded-xl` border, ring,
shadow, `h-8`). Previously it rendered as a bare button with
`rounded-md` hover styling, which looked out of place in the user
details grid.
2. **Analytics → Replays page** — the empty state previously read just
*"No session replays yet"* with no guidance. It now shows a short
description of what session replays are, and links out to the docs
(`https://docs.stack-auth.com/docs/apps/analytics`) so new users can
discover more.

## Files changed

-
[`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx`](https://github.com/stack-auth/stack-auth/blob/fix/ui-bugs-users-analytics/apps/dashboard/src/app/%28main%29/%28protected%29/projects/%5BprojectId%5D/users/%5BuserId%5D/page-client.tsx)
— `RestrictedStatusRow` button now styled to mirror the read-only
`EditableInput` look.
-
[`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/replays/page-client.tsx`](https://github.com/stack-auth/stack-auth/blob/fix/ui-bugs-users-analytics/apps/dashboard/src/app/%28main%29/%28protected%29/projects/%5BprojectId%5D/analytics/replays/page-client.tsx)
— empty state now includes a description and a `StyledLink` to the docs.

---

## Bug 1 — Restricted row no longer visually orphaned

Before, the *Restricted* row's value (`No`) was just plain text inside
the grid; every other row (User ID, Display name, Primary email,
Password, 2-factor auth, Signed up at, Risk scores, Sign-up country
code) was rendered inside a styled input box. After the fix,
*Restricted* uses the same boxed style — the row is still clickable and
still opens the existing restriction dialog.

### Before / after toggle (full page)

![user-detail
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_toggle.gif)

### Cropped view of the changed region (clearer)

![user-detail crop
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_crop_toggle.gif)

### Wipe transition

![user-detail
wipe](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_wipe.gif)

### Fade transition

![user-detail
fade](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_fade.gif)

### Pixel diff (only the Restricted cell changes)

![user-detail pixel
diff](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/user_detail_pixel_diff.png)

---

## Bug 2 — Replays empty state explains itself

Before, an empty replays workspace showed only *"No session replays
yet"*. Users had no signal that there is anything they need to do, or
where to look. After the fix, the empty state explains what session
replays are, hints that replays will appear once captured, and links to
the relevant docs page.

> Session replays let you watch how users interact with your app.
Replays will appear here once your project starts capturing them.
>
> [Learn more in the
docs](https://docs.stack-auth.com/docs/apps/analytics)

### Before / after toggle (full page)

![replays
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_toggle.gif?v=2)

### Cropped view of the empty state

![replays crop
toggle](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_crop_toggle.gif?v=2)

### Wipe transition

![replays
wipe](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_wipe.gif?v=2)

### Fade transition

![replays
fade](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_fade.gif?v=2)

### Pixel diff

![replays pixel
diff](https://gist.githubusercontent.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17/raw/replays_pixel_diff.png?v=2)

---

## Test plan

- [x] `pnpm --filter @stackframe/dashboard run lint` passes
- [x] `pnpm --filter @stackframe/dashboard run typecheck` passes
- [x] Manual verification on `localhost:8101`:
- [x] User detail page renders Restricted with the same input-box style
as siblings
  - [x] Clicking Restricted still opens the existing restriction dialog
  - [x] Replays empty state shows description + working docs link
- [x] Light mode visually verified (dark mode untouched, classes are
dark-mode-aware)

## Notes for reviewers

- No change to `RestrictionDialog`, `getRestrictionReasonText`, or any
restriction logic — this is purely visual.
- The replays empty-state copy keeps the existing `MonitorPlayIcon` and
centered layout; only added the description paragraph and the
`StyledLink` (which is already imported in this file).
- Comparison assets (toggles / fades / wipes / pixel diffs) are hosted
in [this
gist](https://gist.github.com/BilalG1/eb9ca0eeec88357728127fd4d759fa17)
for reference.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Style**
* Improved analytics empty state: centered, constrained layout; clearer
primary text, added muted secondary explanatory copy and an external
documentation link that opens in a new tab.
* Restyled restricted-user control: refreshed appearance and spacing,
truncation for long values, and stronger hover/focus feedback while
preserving existing behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-22 17:42:39 -07:00
..
backend fix connected accounts tokens (#1358) 2026-04-20 19:33:47 -07:00
dashboard fix(dashboard): Restricted row styling + Replays empty state (#1366) 2026-04-22 17:42:39 -07:00
dev-launchpad chore: update package versions 2026-04-20 19:06:56 -07:00
e2e fix connected accounts tokens (#1358) 2026-04-20 19:33:47 -07:00
hosted-components chore: update package versions 2026-04-20 19:06:56 -07:00
internal-tool fix(internal-tool): continue dev startup when spacetime publish fails (#1371) 2026-04-22 22:35:27 +00:00
mock-oauth-server chore: update package versions 2026-04-20 19:06:56 -07:00
oauth-mock-server In-source unit tests (#429) 2025-02-14 11:47:52 -08:00