feat: adapt block page layout for mobile and tablet - #1248
Conversation
|
@Stulikov is attempting to deploy a commit to the Solana Foundation Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThe PR adapts the block detail route and its tabs for responsive mobile and tablet presentation.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Reviews (2): Last reviewed commit: "trigger build" | Re-trigger Greptile |
* chore: bootstrap development branch
* feat(block): match block page layout and overview to the transaction page
- Page shell now mirrors the transaction page: same max width, side padding
and vertical rhythm between blocks; the header drops its underline for the
borderless "Details / Block" treatment.
- Overview moves out of the horizontally-scrolling table into a new
BlockOverviewCard built on the transaction summary's key/value grid, so long
blockhashes and leader addresses wrap instead of scrolling sideways on mobile.
- Copy buttons added to Blockhash, Parent Blockhash and Slot; timestamps
switch from monospace to the regular face.
- Tabs rebuilt as a full-bleed sticky bar matching the transaction page,
replacing the heavier bordered sticky header.
- Card outline set to outer-space-800 to match the tx-inspector design.
* feat(block): responsive layout for block page tabs
Account, program, reward and transaction lists now lay out as an aligned
grid on md+ and collapse into stacked, labelled rows on mobile.
* feat(block): tighten block transactions card and mobile view
- desktop grid from md (was lg); numeric columns tightened
- mobile: Signature/Programs labelled fields, index top-right,
label column matched to Overview
- keep program counters ("N ×") on one line; feed logs into
stories so the Compute column shows
* feat(block): polish transactions card labels, filter and sorting
- rename compute-unit columns to CUs Reserved / CUs Consumed / Cost, plus
the Overview's "Total CUs Consumed"; column header now reads "Signature / Programs"
- fix the "#" header not resetting rows to index order (stale sort param persisted
in the URL)
- filter dropdown gains a visible border and a dot marking the selected option
- widen the index column (fits 4 digits), Fee and CUs Consumed; tighten the
signature/badge wrap gap
* feat(block): sort indicators, program variants, and table polish
- Transactions: sortable headers show a direction indicator — dim up/down
chevrons when clickable, the active column turning white with a bright
arrow; re-clicking the active column reverses the sort (kept in the URL).
Reserved and Consumed columns swapped; CU columns widened to keep their
headers on one line; Cost tightened.
- Block Programs: a chip switcher (1 / 2 / 2a) flips the table between an
aligned count+percentage layout, a parenthesised percentage, and a
swapped variant that foregrounds the percentage. Column headers gained
info icons whose tooltips cite the block's transaction/instruction
totals; Success Rate is shortened to "Success" in the compact variants.
- Block Account Usage: Total and its % of transactions merged into one
column — the header reads "Total" with a matching info tooltip, the share
stays in the rows.
- Rewards: "New Balance" renamed "Post Balance" with a wider column.
- Numbers across the block cards use the standard face with tabular
figures; monospace is kept only for ◎ SOL amounts, and the
count-to-percentage gap is tightened.
* fix(block): stop long addresses overflowing the accounts card
Account links (and the Address wrapper) now shrink and mid-truncate inside
the grid cell instead of forcing horizontal scroll; share label clarified to
"of block transactions".
* feat(block): redesign transactions filter and unify card radius
- Block transactions card: the filter is now a "Filters" button (icon +
active-state dot) with a fixed-width (280px) menu that has a program
search and wraps long option names; the active program filter shows as a
removable chip, and the record count moves into the heading as
"N filtered records" / "N records". The header is a two-column layout
with the filter/collapse actions bottom-aligned.
- CollapsibleSection: new `belowTitle` slot renders full-width content in
the always-visible title group.
- Block tables (history, accounts, programs, rewards): force the tight-card
radius to 8px so they match the overview and transaction-page cards
(were rendering at 12px).
- Block overview: long value rows (cost utilization, reserved CUs) wrap at
spaces instead of breaking mid-token, via a new `Value` breakAll opt-out.
- TokenHistoryCard: broaden Storybook coverage — populated, filter menu,
filtered-by-mint, loading, failed, empty, and >25-token states.
- Reformat touched files with Prettier to fix the failing CI format check.
* feat(block): add mobile sort menu to transactions card
- The grid's sort headers are hidden below md, so mobile gets a
"Filters"-style Sort button (left of the filter) opening every sortable
column split into its two directions ("Lowest …" ascending, "Highest …"
descending); each row pushes an explicit direction through the same
URL-param sort the headers already use.
* feat(block): consistent percentage display across block tabs
- Block Programs settles on one design — count with the percentage in
parentheses ("count (percent)"); the on-page 1/2/2a variant chips are
removed.
- Block Accounts shows Total the same way — "count (percent)".
- Block Overview mutes the "(NN%)" in the compute-utilization rows to
match the Programs table.
* feat(block): tighten mobile tab-bar spacing
- On mobile the sticky tab bar now sits ~12px under the Overview card, with
a balanced 28px band above the tab labels and 36px below the underline;
desktop spacing is unchanged (reset at `lg`).
- BlockOverviewCard takes an optional `className` so the layout can control
its bottom margin.
* feat(block): match page heading spacing to the inspector
The "Details / Block" heading now shares the transaction inspector's
airy vertical rhythm — py-6 padding with a 24px gap above and below,
instead of the previous tighter, uneven spacing.
Pull the header out of the section space-y (moved onto an inner
wrapper) so its own margin controls the gap to the first card, rather
than a section band stacking on top of it.
* dedupe card helpers and tidy comments
* collapse to single card variant and share grid primitives
---------
Co-authored-by: Tania Markina <tania.markina@hoodies.team>
69ea7a1 to
dbe57e8
Compare
|
Deployment failed for project explorer with the following error: View Documentation: https://vercel.com/docs/accounts/team-members-and-roles |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| @@ -0,0 +1,97 @@ | |||
| import { Button } from '@components/shared/ui/button'; | |||
There was a problem hiding this comment.
question/issue: Why are there two components in the PR, this one and the shared collapsible-section?
| if (sort === 'fee') return 'fee'; | ||
| if (sort === 'reservedCUs') return 'reservedCUs'; | ||
| return 'index'; | ||
| const mode: SortMode = |
There was a problem hiding this comment.
issue: This is too much of ternary, hardly readable
| import { Button } from '@/app/components/shared/ui/button'; | ||
| import { Dropdown, DropdownItem, DropdownMenu, DropdownToggle } from '@/app/components/shared/ui/dropdown'; | ||
| import { Input } from '@/app/components/shared/ui/input'; | ||
| import { CollapsibleSection } from '@/app/features/transaction/ui/CollapsibleSection'; |
There was a problem hiding this comment.
todo: Import from the feature barrel file, or explain in comments why it's not a good idea (the only that I could imagine is bundle size implication)
| const nextParams = new URLSearchParams(currentSearchParams?.toString()); | ||
| const nextDirection: SortDirection = | ||
| explicitDirection ?? | ||
| (sortKey && sortKey === sortMode |
There was a problem hiding this comment.
suggestion: Please make it more readable
| // passing no key clears the sort entirely (the old table's "#" reset). The mobile sort menu passes an | ||
| // explicit direction (its rows are per-direction) which short-circuits the toggle. We build the URL | ||
| // from a copy of the current params so a `delete` drops the keys — `pickClusterParams` only overrides. | ||
| const pushSort = React.useCallback( |
There was a problem hiding this comment.
issue: should be tested carefully
| </> | ||
| } | ||
| className="" | ||
| titleClassName="!items-end gap-4" |
There was a problem hiding this comment.
thought/issue: There are conditional classes and important hacks here and there. Hard to read/debug/understand in general. For such cases we usually use cva
| return ( | ||
| <div className="border-b border-solid border-white/10 last:border-b-0"> | ||
| {/* Mobile — stacked labelled rows with the index pinned to the top-right corner. */} | ||
| <div className="relative flex flex-col gap-1.5 px-4 py-3 md:hidden"> |
There was a problem hiding this comment.
suggestion: This is not the best practice to have both branches mounted for every single case when markup is not trivial. See how the problem is addressed in AccountsCard.tsx
| success: { label: 'Success', variant: 'success' }, | ||
| } as const; | ||
|
|
||
| const numberFmt = (n: number) => new Intl.NumberFormat('en-US').format(n); |
There was a problem hiding this comment.
nit: You don't need a new formatter every time, could reuse
| // explicit direction (its rows are per-direction) which short-circuits the toggle. We build the URL | ||
| // from a copy of the current params so a `delete` drops the keys — `pickClusterParams` only overrides. | ||
| const pushSort = React.useCallback( | ||
| (sortKey?: SortMode, explicitDirection?: SortDirection) => { |
There was a problem hiding this comment.
question: Should sortKey be optional? It is not used without a key and maybe shouldn't
| let totalCUs = 0; | ||
| let totalRequestedCUs = 0; | ||
| let totalCostUnits = 0; | ||
| for (const tx of block.transactions) { |
There was a problem hiding this comment.
suggestion: Maybe extract to the lib helper, for example app/entities/compute-unit/lib/block-compute-units.ts and do something like (or even better with some proper named type for the data) + tests:
export function summarizeBlockComputeUnits({ block, epoch, cluster }: {
block: BlockWithV1; epoch: bigint | undefined; cluster: Cluster;
}): { consumed: number; requested: number; cost: number; max: number } { … }The card then receives four numbers and renders them. Right now it's doing too much and the props are messy
Description
Adapts the block detail page (
/block/[slot]) and all its tabs for mobile and tablet. Card headings move outside their cards with collapse/expand behaviour, the data tables become responsive CSS grids that stack into labelled rows on narrow screens, and spacing/padding are reworked so content uses the full width available.mdup and a stacked, labelled layout below. All block tables now share the transaction/overview cards' 8px corner radius.Type of change
Screenshots
Testing
Block page
Related Issues
HOO-801
Checklist
pnpm test,pnpm lint,pnpm typecheck)