Skip to content

feat(voting): keep the vote buttons in reach on the proposal page - #490

Merged
yhabib merged 9 commits into
mainfrom
ux/proposal-jump-to-vote
Nov 5, 2026
Merged

yhabib merged 9 commits into
mainfrom
ux/proposal-jump-to-vote

Conversation

@yhabib

@yhabib yhabib commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

On the proposal page, the vote buttons are in the voting card after the summary. A long summary pushes them far down, so users must scroll a lot before they can vote.

Changes

  • Moved the Yes/No buttons of the voting card into a sticky footer. It floats at the bottom of the page while the card is below it, and docks under the card when the user reaches it.
  • Added an IntersectionObserver on a sentinel to switch between the floating and the docked style.
  • Showed the footer only when the user can vote. The "Vote cast" footer stays inside the card.
  • Added tests for the docking states and the observed area.
  • Kept the floating bar above the bottom safe area.
  • Used the same dark-mode hover tint for the Yes and No buttons, here and in the proposal list.

Screenshots

Before After
Mobile, reading the summary, before Mobile, reading the summary, after
Mobile, at the voting card, before Mobile, at the voting card, after
Desktop, reading the summary, before Desktop, reading the summary, after
Desktop, at the voting card, before Desktop, at the voting card, after
Dark mode, Yes hovered, before Dark mode, Yes hovered, after

Videos

The page scrolls through the summary to the voting card, back up, and down again.

Mobile

proposal-docking-mobile.mp4

Desktop

proposal-docking-desktop.mp4

Prev. #576 | Next #503

@yhabib
yhabib requested a review from a team as a code owner October 13, 2026 19:34
Copilot AI balanced review requested due to automatic review settings October 13, 2026 19:34
@zeropath-ai

zeropath-ai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

✅ No security or compliance issues detected. Reviewed everything up to 300126e.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► src/governance-app-frontend/src/features/proposals/components/ProposalDetailsVoting.tsx
      Add DockingFooter component and implement floating/docked vote button behavior
► src/governance-app-frontend/src/features/proposals/components/ProposalDetailsVoting.tsx
      Refactor voting UI to use DockingFooter and conditional rendering for voting state
► src/governance-app-frontend/src/features/proposals/components/ProposalListItem.tsx
      Update classNames for Yes vote button styling to include additional dark mode variant

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

📊 Build Bundle Stats

The latest build generated the following assets:

dist/index.html                                           5.86 kB │ gzip:   1.66 kB
dist/assets/index-aPstDMk8.css                          149.81 kB │ gzip:  24.00 kB
dist/assets/icpLedger-CMDpldeb.js                         0.23 kB │ gzip:   0.21 kB
dist/assets/Skeleton-Bnd58_Pu.js                          0.44 kB │ gzip:   0.32 kB
dist/assets/webhid-D0yio6wG.js                            0.53 kB │ gzip:   0.32 kB
dist/assets/useTvlValue-CqfJOpcG.js                       0.60 kB │ gzip:   0.41 kB
dist/assets/nnsDapp-l69O7gw3.js                           0.68 kB │ gzip:   0.25 kB
dist/assets/SkeletonPageHeader-Dwd09HnV.js                0.76 kB │ gzip:   0.47 kB
dist/assets/PageHeader-jXzaR6sL.js                        0.77 kB │ gzip:   0.45 kB
dist/assets/CertifiedBadge-BTTwFIUF.js                    0.81 kB │ gzip:   0.48 kB
dist/assets/Separator-DuSBFc-Z.js                         0.83 kB │ gzip:   0.50 kB
dist/assets/SkeletonStatCard-BN_bjvH9.js                  0.91 kB │ gzip:   0.56 kB
dist/assets/useForecastPeriod-BSBgIxE7.js                 1.01 kB │ gzip:   0.61 kB
dist/assets/utils-P2KPuj_Q.js                             1.02 kB │ gzip:   0.59 kB
dist/assets/useIcpIndex-BoyXBORH.js                       1.09 kB │ gzip:   0.64 kB
dist/assets/numbers-DQ_9HfSL.js                           1.15 kB │ gzip:   0.57 kB
dist/assets/routeLoaders-dy7X_ZFJ.js                      1.19 kB │ gzip:   0.55 kB
dist/assets/rolldown-runtime-DAXXjFlN.js                  1.26 kB │ gzip:   0.70 kB
dist/assets/advancedFeatures-5AHaB5_i.js                  1.50 kB │ gzip:   0.74 kB
dist/assets/events-BsvWww9P.js                            1.66 kB │ gzip:   0.86 kB
dist/assets/useLedgerNeuronCall-DnoMzyfE.js               1.89 kB │ gzip:   1.03 kB
dist/assets/errors-C_oENL0S.js                            1.95 kB │ gzip:   0.97 kB
dist/assets/AnimatedNumber-CXlfCmQl.js                    1.98 kB │ gzip:   1.13 kB
dist/assets/useCommandPaletteSettings-CCwF6Zhw.js         2.13 kB │ gzip:   1.07 kB
dist/assets/addressBook-VMzoS4bK.js                       2.14 kB │ gzip:   1.20 kB
dist/assets/useIcpIndexTransactionsPolling-mNItkcDD.js    2.15 kB │ gzip:   1.15 kB
dist/assets/useGovernanceAppCanister-BQa1GNKn.js          2.41 kB │ gzip:   1.07 kB
dist/assets/useShortcutSettings-COHO55vy.js               2.41 kB │ gzip:   1.19 kB
dist/assets/useAddHotkey-Ce23vw-u.js                      2.61 kB │ gzip:   1.34 kB
dist/assets/governance-ByFX6OHd.js                        2.99 kB │ gzip:   1.15 kB
dist/assets/useClaimPendingDeviceStakes-BUh3ywqF.js       3.12 kB │ gzip:   1.43 kB
dist/assets/SkeletonText-Bf-ojXN1.js                      3.71 kB │ gzip:   1.29 kB
dist/assets/ToggleGroup-BFgPIEsr.js                       4.72 kB │ gzip:   1.76 kB
dist/assets/useAccounts-CnBuw7_C.js                       4.96 kB │ gzip:   2.21 kB
dist/assets/tickers-DTvgGV7C.js                           6.04 kB │ gzip:   2.65 kB
dist/assets/useNowInSeconds-Dx6d4ol-.js                   7.13 kB │ gzip:   3.04 kB
dist/assets/DeviceActionDetail-mBX6H9NA.js                8.45 kB │ gzip:   3.03 kB
dist/assets/TopicFollowingAccordion-CahTsDFk.js           8.55 kB │ gzip:   3.41 kB
dist/assets/routes-zcc3gDpA.js                            8.96 kB │ gzip:   3.08 kB
dist/assets/AlertDialog-Dz6_Az2N.js                       8.99 kB │ gzip:   3.16 kB
dist/assets/ledgerIdentity-CbGbEww2.js                   10.16 kB │ gzip:   3.70 kB
dist/assets/MutationDialog-CIHBLgXk.js                   11.55 kB │ gzip:   4.00 kB
dist/assets/spamFilter-HqFR-HFA.js                       11.77 kB │ gzip:   5.02 kB
dist/assets/ResponsiveDialog-Da6aNOkD.js                 14.56 kB │ gzip:   4.07 kB
dist/assets/_id-LAYlVTV2.js                              16.61 kB │ gzip:   5.32 kB
dist/assets/AmountInput-B2p6yXT7.js                      16.85 kB │ gzip:   6.73 kB
dist/assets/_auth-DW91XGKL.js                            22.49 kB │ gzip:   8.30 kB
dist/assets/HideBalancesToggle-BlS5UoU1.js               22.99 kB │ gzip:   8.58 kB
dist/assets/vendor-buffer-EX-AqChq.js                    26.95 kB │ gzip:   8.18 kB
dist/assets/accounts-gzRI-h7T.js                         32.02 kB │ gzip:  10.89 kB
dist/assets/SendICPButton-CkGRVyLY.js                    37.05 kB │ gzip:  13.53 kB
dist/assets/settings-De4YOy1I.js                         54.37 kB │ gzip:  15.53 kB
dist/assets/dashboard-BC996VgP.js                        55.83 kB │ gzip:  18.13 kB
dist/assets/index--qD5khVH.js                            62.67 kB │ gzip:  17.79 kB
dist/assets/voting-DUTwvy17.js                           69.24 kB │ gzip:  21.67 kB
dist/assets/vendor-md-BFlttn4C.js                        73.29 kB │ gzip:  19.98 kB
dist/assets/button-DxJoIYN5.js                           84.65 kB │ gzip:  28.30 kB
dist/assets/neurons-B3Ym_SZ2.js                          90.41 kB │ gzip:  27.08 kB
dist/assets/DisburseModal-CxJrfrvL.js                   101.46 kB │ gzip:  29.62 kB
dist/assets/vendor-tanstack-B8Ai_FW1.js                 120.02 kB │ gzip:  39.22 kB
dist/assets/vendor-jsqr-CjiBYtfG.js                     129.98 kB │ gzip:  47.50 kB
dist/assets/vendor-core-react-bRRjyX41.js               189.81 kB │ gzip:  59.76 kB
dist/assets/vendor-recharts-CWUgUTjK.js                 280.25 kB │ gzip:  76.83 kB
dist/assets/vendor-ledger-Bz6feAP8.js                   403.26 kB │ gzip:  98.84 kB
dist/assets/vendor-icp-e5O_ocwA.js                      468.31 kB │ gzip: 117.84 kB
dist/assets/vendor-libs-WVao-pYB.js                     581.20 kB │ gzip: 187.04 kB

Copilot AI 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.

🟡 Changes recommended

The jump behavior suppresses visible focus and does not honor reduced-motion preferences.

2 open findings
What changed in this PR

Adds vote shortcuts to proposal details for eligible users.

Changes:

  • Adds desktop and mobile jump-to-vote controls.
  • Focuses and smoothly scrolls to the voting card.
  • Adds visibility and eligibility tests.
File Description
routes/​_auth/​voting/​proposals/​$id/​index.tsx Integrates vote shortcuts.
i18n/​en/​proposal.json Adds the Vote label.
features/​proposals/​utils.ts Adds voting-card navigation utilities.
features/​proposals/​components/​ProposalJumpToVote.tsx Implements responsive shortcuts.
features/​proposals/​components/​ProposalJumpToVote.test.tsx Tests shortcut behavior.
features/​proposals/​components/​ProposalDetailsVoting.tsx Makes the voting card focusable.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI previously approved these changes Oct 13, 2026

Copilot AI 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.

🟢 Approved

The responsive navigation, accessibility behavior, and tests are complete and consistent.

0 open findings

2 resolved since last review

🧠 Review effort: Balanced

@yhabib
yhabib marked this pull request as draft October 14, 2026 14:42
@yhabib yhabib changed the title feat(voting): add a link from the proposal header to the vote card feat(voting): keep the vote buttons in reach on the proposal page Oct 14, 2026
@yhabib
yhabib requested a balanced review from Copilot October 14, 2026 15:10
Copilot AI dismissed their stale review, a newer Copilot review was requested October 14, 2026 15:10

Copilot AI 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.

🟡 Changes recommended

The observer boundary becomes stale when responsive padding changes.

1 open finding

🧠 Review effort: Balanced

@yhabib
yhabib force-pushed the ux/proposal-jump-to-vote branch from 43d7023 to af3e4b1 Compare October 15, 2026 09:42
@yhabib
yhabib changed the base branch from main to ux/proposal-detail-view November 5, 2026 10:41
@yhabib
yhabib marked this pull request as ready for review November 5, 2026 10:41
Copilot AI balanced review requested due to automatic review settings November 5, 2026 10:41

Copilot AI 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.

🟡 Changes recommended

For long proposals without a selfDescribingAction, the strict boundary comparison can leave the footer floating at maximum scroll, requiring equality to trigger docking and an exact-boundary test.

1 open issue
1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 5, 2026 10:46

Copilot AI 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.

🔵 Needs a closer look

Footer-docking edge cases involving safe-area offsets and missed observer updates during scroll jumps require human assessment.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 5, 2026 10:53
Copilot AI previously approved these changes Nov 5, 2026

Copilot AI 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.

🟢 Approved

No active review issues are reported for the sticky voting-footer change.

No open issues 🎉

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 5, 2026 11:17
Copilot AI dismissed their stale review, a newer Copilot review was requested November 5, 2026 11:17

Copilot AI 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.

🟢 Approved

No active review issues were identified for the sticky voting footer change.

No open issues 🎉

Review effort: Balanced

Base automatically changed from ux/proposal-detail-view to main November 5, 2026 15:23
@yhabib
yhabib enabled auto-merge November 5, 2026 15:27
Add a "Vote" badge link to the header badge row. It scrolls smoothly to
the voting card and moves the focus to it.

Below the lg breakpoint, show a sticky "Vote" button above the bottom
navigation. Hide it when the voting card is in view or above it.

Show both only when the user can vote on the proposal.
…card

Replace the jump link and the sticky jump button with a sticky footer.
The Yes/No buttons float at the bottom of the page while the voting
card is below it, and dock under the card when the user reaches it.

Show the footer only when the user can vote. Keep the "Vote cast"
footer inside the card.
…cked footer

Recreate the observer when the size of main changes, so the docked
state follows the bottom padding at each breakpoint.

Draw the footer outline with inset shadows. A transparent top border
left a 1px notch in the side borders where the footer joins the card.
The Yes button used a light tint on hover in dark mode, and the No
button used a dark tint. Both now use the 900 shade at 10%.
@yhabib
yhabib force-pushed the ux/proposal-jump-to-vote branch from de30fdc to 300126e Compare November 5, 2026 15:39
@yhabib
yhabib added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit 01ec37b Nov 5, 2026
12 checks passed
@yhabib
yhabib deleted the ux/proposal-jump-to-vote branch November 5, 2026 15:57
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.

3 participants