Skip to content

feat(console): unified page-header row + UI polish + i18n sync - #11

Merged
dingyi merged 4 commits into
mainfrom
feature/console-layout-refactor
Apr 27, 2026
Merged

feat(console): unified page-header row + UI polish + i18n sync#11
dingyi merged 4 commits into
mainfrom
feature/console-layout-refactor

Conversation

@dingyi

@dingyi dingyi commented Apr 27, 2026

Copy link
Copy Markdown
Owner

A long-running WIP that had been sitting in the working tree, split into
4 incremental commits for review.

What changed

1. feat(console/layout): host page-level title and actions in the shared header row

The motivating change. Introduces PageHeaderContext so any console
page can call usePageHeader({ title, actions }) to populate the
single page-header row that PageLayout renders next to the sidebar
collapse trigger. Pages that don't push anything (Channel, User,
Token, Log, …) just get a trigger-only row, which keeps the visual
rhythm consistent across the console without touching every page file.

Wire-up: PageLayout wraps in PageHeaderProvider and renders
<ConsolePageHeader/> on console routes, padding moves off <main>
onto an inner wrapper so overflow-y:auto doesn't swallow the bottom
gap; DashboardHeader drops its own row and pushes greeting +
search/refresh into the shared row; SiderBar removes the in-sidebar
trigger so the page-header row owns it exclusively (canonical
heroui-pro Sidebar pattern).

2. refactor(console/pages): drop per-page mt-[60px] px-2 wrapper

Now that PageLayout owns the inner padding, every page that wrapped
its content in <div className='mt-[60px] px-2'> was double-padding.
Strip the wrapper from 12 routes (Channel, Token, User, Log,
Subscription, Task, Midjourney, Model, ModelDeployment, Redemption,
Dashboard, Setting), DeploymentAccessGuard, PersonalSetting,
topup/index. After this commit no page sets mt-[60px] anywhere.

3. refactor(web): polish About / pricing / settings UI

A bundle of HeroUI-aligned visual polish picked up while rewiring the
layout — About page rewritten on top of HeroUI Card / Spinner /
EmptyState; pricing vendor intro condensed (skeleton sheds 200+
lines via reusable HeroUI Skeleton primitives); SearchActions row
rebuilt; SystemSetting / CustomOAuthSetting / 5×Settings/Dashboard /
SettingsGeneral tightened; SelectableButtonGroup gets a
high-contrast active state via --button-bg* overrides;
Dashboard greeting drops the leading 👋 emoji (the sidebar trigger
already anchors the row visually).

4. chore(i18n): sync locale files

bun run i18n:sync output for the new t('...') keys introduced
above and the keys dropped during the same pass. Touches all 7
locales (en / zh-CN / zh-TW / fr / ja / ru / vi).

Test plan

  • bun run dev — every console route shows one and only one
    page-header row (sidebar trigger ▸ optional title ▸ optional
    actions); no double top padding.
  • Dashboard — greeting and search/refresh sit on the same row
    as the sidebar trigger; collapsing the sidebar keeps the trigger
    pinned.
  • Switching between routes (Channel → Dashboard → Setting) — the
    page-header row stays consistently 56px tall, no flicker.
  • Console body bottom padding visible on all pages (px-6 pb-6).
  • About page renders cleanly with home page content present and
    with home page content failing to load.
  • Pricing page header (vendor intro + search) reads tighter than
    before, no overflow on mobile.
  • bun x i18next-cli status — locale files in sync (no missing
    keys, no extras).

This PR was generated automatically by Cursor.

Made with Cursor

dingyi added 4 commits April 28, 2026 00:35
… header row

Introduce PageHeaderContext: a tiny provider exposing a usePageHeader hook
that pages call with `{ title, actions }` to populate the single console
page-header row PageLayout renders next to <Sidebar.Trigger />. Pages
that don't push anything (Channel, User, Token, Log, …) just get a
trigger-only row, which keeps the visual rhythm consistent across the
console without touching every page file.

Why
---
Before this change every console page either rendered its own duplicate
trigger row, or the trigger sat alone on a separate row above the page's
actual title — both ugly. The Dashboard greeting in particular ("👋 早上好,
admin") landed on a row of its own, while the sidebar collapse button
floated awkwardly above it.

After
-----
PageLayout renders one row per console route:
    [trigger]  [page-supplied title]  [page-supplied actions]
matching heroui-pro's AppLayout where the navbar row hosts both the
sidebar trigger and page-level content.

Wire-up
-------
- PageLayout: wrap children in PageHeaderProvider, render
  <ConsolePageHeader/> on console routes (reads via usePageHeaderContent)
  and move padding off <main> onto an inner wrapper so overflow-y:auto
  doesn't swallow the bottom gap.
- DashboardHeader: drop its own header row, push greeting + search /
  refresh into the shared row via usePageHeader().
- SiderBar: remove the in-sidebar <CollapsedHeaderTrigger/> — the
  trigger now lives in the page-header row exclusively, matching the
  canonical heroui-pro Sidebar pattern. Add `pt-4` to Sidebar.Content
  so the first group label has breathing room (we omit Sidebar.Header).

Made-with: Cursor
Now that PageLayout renders a single page-header row above <main> and
applies the inner padding itself, every console page was double-padding
(top gap + side gutter twice). Strip the per-page <div mt-[60px] px-2>
wrappers — pages just return their content directly.

Pages migrated:
- Channel, Token, User, Log, Subscription, Task, Midjourney, Model,
  ModelDeployment, Redemption, Dashboard — table / data pages
- Setting/index — drop <main className='min-w-0'> wrapper, rely on
  PageLayout's <main> instead
- DeploymentAccessGuard — same wrapper inside the access-guard branch
- PersonalSetting — drop mt-[60px] (was already centered, just needed
  the top offset gone)
- topup/index — drop mt-[60px] px-2

After this commit no page sets `mt-[60px]` anywhere.

Made-with: Cursor
A bundle of HeroUI-aligned visual polish across pages that fell behind
the rest of the v3 cleanup, picked up while rewiring the console layout:

About page
- Replace the flat <Construction/> placeholder with a HeroUI Card +
  Spinner + EmptyState + Chip layout that mirrors the rest of the
  console: hero title, status pills, link buttons to docs / GitHub /
  settings, fallback state when home content fails to load.

Model pricing
- PricingPage / PricingContent: hand off layout to the standard console
  page wrapper (no longer needs its own top offset).
- PricingVendorIntro & Skeleton: condense the giant per-vendor intro
  into a tighter HeroUI Card + Chip stack; skeleton sheds 200+ lines
  by reusing HeroUI Skeleton primitives.
- SearchActions: refactor the search/filter row to use HeroUI Input
  + Button compounds with proper kbd shortcuts.
- PricingCardView / PricingTable: tweak chip / pagination styling
  to match the new vendor intro.

Settings
- SystemSetting / CustomOAuthSetting: tighten card spacing, reuse the
  shared CheckboxRow primitive, drop a few duplicate tone overrides.
- Settings/Dashboard/{APIInfo, Announcements, DataDashboard, FAQ,
  UptimeKuma}: small polish — consistent empty states, tighter form
  rows.
- Setting/Operation/SettingsGeneral: align section headers / spacing
  with the rest of the console.

Common
- SelectableButtonGroup: bump active state contrast — black bg / white
  fg via --button-bg* CSS variable overrides so the selected option
  reads clearly against the surrounding `outline` shells; inactive
  rows fade to text-muted.
- useDashboardData: drop the leading 👋 emoji from the greeting; the
  shared page-header row already has a clear visual anchor (sidebar
  trigger on the left), so the emoji read as noise.

Made-with: Cursor
Run `bun run i18n:sync` to pick up the new `t('...')` keys introduced
across the console layout refactor and the About / pricing / settings
polish, and prune keys that were dropped along the way (e.g. the
removed Stripe / Creem placeholder copy that moved into the unified
payment gateway flow upstream).

Touches en / zh-CN / zh-TW / fr / ja / ru / vi.

Made-with: Cursor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9210cdfd7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

className='flex-1 min-w-0 relative overflow-y-auto'
style={{ WebkitOverflowScrolling: 'touch' }}
>
<div className={shouldInnerPadding ? 'p-6' : ''}>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve full-height parent for unpadded app content

When shouldInnerPadding is false, this wrapper renders without any sizing class, so routes that rely on h-full children (notably /pricing after PricingPage switched to h-full containers) lose a concrete height ancestor. In that case percentage heights resolve to auto, and the pricing layout falls back to outer-page scrolling instead of keeping its intended bounded/independent scroll regions. Please keep a full-height context here (or skip the extra wrapper when no padding is needed).

Useful? React with 👍 / 👎.

@dingyi
dingyi merged commit 008449f into main Apr 27, 2026
1 check passed
@dingyi
dingyi deleted the feature/console-layout-refactor branch April 27, 2026 18:27
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