Skip to content

[Dashboard] Standardize table empty states with a shared component#9983

Open
stephenkevn wants to merge 3 commits into
skypilot-org:masterfrom
stephenkevn:se/table-empty-states
Open

[Dashboard] Standardize table empty states with a shared component#9983
stephenkevn wants to merge 3 commits into
skypilot-org:masterfrom
stephenkevn:se/table-empty-states

Conversation

@stephenkevn

@stephenkevn stephenkevn commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a reusable EmptyState block (a neutral icon in a 40px circle, a title, and an optional description and action) under components/elements/, plus an EmptyTableState helper in components/ui/table.jsx that renders it inside a full-width colSpan row so the column headers and pagination stay visible.
  • Empty tables now show a vertically centered, fixed 280px region instead of collapsing to a thin "No data" strip.
  • Applied to the clusters, jobs (managed jobs + pools), users (+ service-account tokens), volumes, and workspaces tables, with icons matching the nav and concise, action-first copy.
  • Also add an empty state to the Infrastructure page's Nodes table, which previously rendered nothing when a context had no nodes.
  • A ?empty URL flag forces the empty state on populated tables so the styling can be reviewed without clearing real data. Colors are inline hex because the theme CSS variables can resolve to white in some render contexts.

Test plan

  • npm run lint and npx prettier --check on the touched files — both clean.
  • npm run build — succeeds.
  • npm run dev, then for each table visit ?empty=1: the empty state renders (icon + title + description) centered in a 280px region with the column headers and pagination intact; removing the flag renders rows normally; no console errors. For Infrastructure, a context with no nodes shows the empty state instead of a blank section.
Screenshot 2026-06-29 at 4 34 11 PM

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a standardized empty-state UI across the dashboard by creating the EmptyState and EmptyTableState components, which are integrated into the clusters, jobs, pools, users, volumes, and workspaces views. It also adds a isForceEmpty utility function to allow developers and QA to force empty states via a URL query parameter. The review feedback suggests refactoring the inline styles in the new EmptyState component to Tailwind CSS classes to improve maintainability and consistency with the rest of the codebase.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +29 to +59
<div
className="flex items-center justify-center"
style={{
width: 40,
height: 40,
marginBottom: 16,
borderRadius: 9999,
backgroundColor: '#f9fafb',
border: '1px solid #e5e7eb',
color: '#9ca3af',
}}
>
{icon || <Inbox size={20} strokeWidth={1.75} />}
</div>
<div style={{ fontSize: 16, fontWeight: 500, color: '#111827' }}>
{title}
</div>
{description ? (
<div
style={{
marginTop: 6,
fontSize: 14,
lineHeight: 1.55,
color: '#6b7280',
maxWidth: 360,
}}
>
{description}
</div>
) : null}
{action ? <div style={{ marginTop: 20 }}>{action}</div> : null}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While the comment explains that colors are inline on purpose, many other styling properties like width, height, margin, borderRadius, fontSize, and fontWeight are also defined using inline styles. This makes the component harder to maintain and inconsistent with the rest of the codebase that uses Tailwind CSS.

To improve maintainability, consider refactoring these inline styles into Tailwind classes. You can use Tailwind's arbitrary value support to specify hex colors directly in the class names (e.g., bg-[#f9fafb]) to address the concern about theme variables. This keeps all styling within the className prop.

Here's a suggested refactoring:

      <div
        className="mb-4 flex h-10 w-10 items-center justify-center rounded-full border border-[#e5e7eb] bg-[#f9fafb] text-[#9ca3af]"
      >
        {icon || <Inbox size={20} strokeWidth={1.75} />}
      </div>
      <div className="text-base font-medium text-[#111827]">{title}</div>
      {description ? (
        <div className="mt-1.5 max-w-[360px] text-sm leading-[1.55] text-[#6b7280]">
          {description}
        </div>
      ) : null}
      {action ? <div className="mt-5">{action}</div> : null}

Add a reusable EmptyState block (neutral icon in a 40px circle, title,
optional description and action) and an EmptyTableState helper that drops
it into a table body via a colSpan row, keeping column headers and
pagination visible. The block is vertically centered in a fixed 280px
region so empty tables no longer collapse to a thin strip.

Apply it to the clusters, jobs (managed + pools), users (+ service
account tokens), volumes, and workspaces tables, with icons matching the
nav and concise, action-first copy. A '?empty' URL flag forces the empty
state on populated tables for review.

Colors are inline hex because the theme CSS variables can resolve to
white in some render contexts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@stephenkevn stephenkevn force-pushed the se/table-empty-states branch from 6363e40 to 2ca1fbc Compare June 29, 2026 23:54
stephenkevn and others added 2 commits June 29, 2026 17:04
When a context has no nodes the Nodes section rendered nothing; show the
shared EmptyState (icon + title) so it matches the other tables.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant