Skip to content

feat: refactor proposal creation flow#892

Merged
dan13ram merged 4 commits intostagingfrom
refactor/proposal-creation-flow
Mar 4, 2026
Merged

feat: refactor proposal creation flow#892
dan13ram merged 4 commits intostagingfrom
refactor/proposal-creation-flow

Conversation

@dan13ram
Copy link
Collaborator

@dan13ram dan13ram commented Mar 3, 2026

Summary by CodeRabbit

  • New Features

    • Multi-stage proposal creation (draft → transactions → review) with visual stage indicator, mobile action bar, draft form, reset confirmation modal, and help links.
  • Improvements

    • Governance timeline for proposals; enhanced proposal review/edit preview and mobile submission flow.
    • Dropdown now supports descriptive options; proposal links support stage/tab parameters.
    • Proposal description supports title and preview mode; editor falls back to editable textarea when needed.

@vercel
Copy link

vercel bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
testnet-nouns-builder Ready Ready Preview Mar 4, 2026 11:21am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
nouns-builder Ignored Ignored Mar 4, 2026 11:21am

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

This PR implements a staged proposal creation flow (draft → transactions → review), refactors the proposal store API (introducing startProposalDraft and draft metadata setters), adds multiple UI components for staging and mobile actions, updates link/layout APIs to accept typed stage/tab params, and removes the old SelectTransactionType component.

Changes

Cohort / File(s) Summary
Link/Navigation API
apps/web/src/components/LinksProvider.tsx, packages/types/src/links.ts, packages/ui/src/LinksProvider/LinksProvider.tsx
Typed tab/stage params added (DaoTab, ProposalTab, ProposalCreateStage); getProposalCreateLink/get*Link signatures accept optional stage and build ?stage= query when present.
Layout Infrastructure
apps/web/src/layouts/BaseLayout/BaseLayout.tsx, apps/web/src/layouts/DaoLayout/DaoLayout.tsx
BaseLayout uses flex column with minHeight:100vh; DaoLayout exposes new DaoLayoutOptions and passes hideFooterOnMobile to DefaultLayout.
Proposal Store API
packages/stores/src/hooks/useProposalStore.ts
Removed createProposal; added startProposalDraft, setTitle, setSummary, setDraftMetadata. startProposalDraft initializes/merges a partial draft (title, summary, transactions, disabled, transactionType).
Core Proposal Pages
apps/web/src/pages/dao/.../proposal/create.tsx, .../proposal/review.tsx, apps/web/src/pages/dao/[network]/[token]/[tokenId].tsx, .../index.tsx
Create page refactored to multi-stage flow with stage state, validation, ProposalStageIndicator, ProposalDraftForm, MobileProposalActionBar, and server-side props; review page wired to stages and can auto-redirect; openProposalCreatePage now accepts optional stage.
New UI Components
packages/create-proposal-ui/src/components/ProposalStageIndicator/*, ProposalDraftForm/*, ProposalHelpLinks/*, MobileProposalActionBar/*, ResetConfirmationModal/*
Added ProposalStageIndicator (onboarding + clickable stages), ProposalDraftForm, ProposalHelpLinks, MobileProposalActionBar (bottom actions + modals), and ResetConfirmationModal with exports and index barrels.
CreateProposalHeading & Review Form
packages/create-proposal-ui/src/components/CreateProposalHeading/*, .../ReviewProposalForm/ReviewProposalForm.tsx
CreateProposalHeading props extended for back/reset/continue flows and help links; ReviewProposalForm gains mobile callbacks, preview/edit metadata mode, governance timeline, and MobileProposalActionBar integration.
Component Removals / API Surface
packages/create-proposal-ui/src/components/SelectTransactionType/*
Removed SelectTransactionType, AdminNav, and TransactionTypeCard; index export removed and public API adjusted accordingly.
Integration Updates
packages/dao-ui/*, packages/proposal-ui/* (multiple files)
Multiple components switched from calling createProposal/addTransaction to startProposalDraft; Gallery/other props updated to accept optional ProposalCreateStage.
UI/Utility Refinements
packages/ui/src/DropdownSelect/DropdownSelect.tsx, packages/ui/src/MarkdownEditor/MarkdownEditor.tsx, packages/zord/src/elements/Spinner.css.ts, packages/zord/src/icons.ts, packages/hooks/src/useDecodedTransactions.ts, packages/create-proposal-ui/src/components/TransactionForm/Droposal/*, packages/create-proposal-ui/src/components/Queue/Queue.tsx
DropdownSelect adds optional option descriptions and optional value; MarkdownEditor adds textarea fallback; spinner uses currentColor; pencil/queue icons added; useDecodedTransactions adds enabled flag; Droposal/Queue spacing/layout tweaks.

Sequence Diagram

sequenceDiagram
    actor User
    participant Page as CreateProposalPage
    participant Store as ProposalStore
    participant UI as UI Components
    participant Nav as Navigation

    User->>Page: Open create page / click create
    Page->>Store: startProposalDraft(optional transactionType)
    Store->>Store: initialize/merge draft state
    Page->>UI: render ProposalStageIndicator + Draft form

    User->>UI: enter title/summary
    UI->>Store: setTitle / setSummary
    User->>Page: click Continue
    Page->>Page: validate draft
    alt valid
        Page->>UI: show Transactions stage (TransactionForm)
    else invalid
        UI->>User: show validation errors
    end

    User->>UI: add/configure transactions
    UI->>Store: addTransaction()
    User->>Page: click Continue
    Page->>Nav: navigate/reveal Review stage
    Page->>UI: render ProposalDescription (preview)
    User->>UI: submit -> Page triggers final submission flow
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 I hopped from draft to transactions bright,
I nudged the stages into gentle sight,
With pencil and queue my path made clear,
From title seed to review near—
Hooray, the proposals now take flight!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is missing entirely. The repository template requires sections for Description, Motivation & context, Code review, Type of change, and a Checklist, none of which are present. Add a comprehensive description including the problem statement, motivation for the refactoring, relevant context, code review notes, type of change selection, and completed checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: refactor proposal creation flow' directly and clearly summarizes the main change: a refactoring of the proposal creation flow with multiple stages, new UI components, and updated store actions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/proposal-creation-flow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/create-proposal-ui/src/components/TransactionForm/Droposal/DroposalForm.tsx (1)

88-96: ⚠️ Potential issue | 🟡 Minor

Fix helper-link copy typo (“Lean more” → “Learn more”).

Line 95 has a user-facing typo in the link text.

✏️ Suggested fix
-                  Lean more
+                  Learn more
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/create-proposal-ui/src/components/TransactionForm/Droposal/DroposalForm.tsx`
around lines 88 - 96, In the DroposalForm component update the user-facing link
text inside the Text JSX (the anchor within the Text element) from "Lean more"
to the correct "Learn more"; locate the Text block in DroposalForm.tsx that
references the ZORA 721 Contract and replace the typo in the anchor content so
the displayed link reads "Learn more".
🧹 Nitpick comments (6)
packages/ui/src/DropdownSelect/DropdownSelect.tsx (1)

133-133: Remove redundant conditional in alignment prop.

Line 133 resolves to 'center' in both branches, so the ternary adds noise.

Optional cleanup
-        align={option.description ? 'center' : 'center'}
+        align={'center'}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/DropdownSelect/DropdownSelect.tsx` at line 133, The align
prop in DropdownSelect.tsx is using a redundant ternary (option.description ?
'center' : 'center'); simplify by replacing that expression with a single
literal 'center' for the align prop in the DropdownSelect component (remove the
ternary and reference to option.description).
packages/types/src/links.ts (1)

25-29: Consider exporting a shared ProposalCreateStage type.

The inline union is correct, but centralizing it avoids drift across UI/web link providers.

♻️ Proposed refactor
 export type ProposalLinkHandler = (
   chainId: CHAIN_ID,
   daoTokenAddress: AddressType,
   proposalId: number | string | bigint,
   tab?: string
 ) => LinkOptions

+export type ProposalCreateStage = 'draft' | 'transactions'
+
 export type ProposalCreateLinkHandler = (
   chainId: CHAIN_ID,
   daoTokenAddress: AddressType,
-  stage?: 'draft' | 'transactions'
+  stage?: ProposalCreateStage
 ) => LinkOptions
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/types/src/links.ts` around lines 25 - 29, Introduce a shared
exported type alias ProposalCreateStage = 'draft' | 'transactions' and replace
the inline union in the ProposalCreateLinkHandler signature with that alias so
the handler becomes (chainId: CHAIN_ID, daoTokenAddress: AddressType, stage?:
ProposalCreateStage) => LinkOptions; update any other types/usages referencing
the inline union to import and use ProposalCreateStage to prevent drift across
consumers (keep LinkOptions and existing symbols unchanged).
apps/web/src/modules/coin/CreateContentCoinForm/NoCreatorCoinWarning.tsx (1)

45-48: Avoid spreading full router.query into proposal-create navigation.

Passing all existing query params can leak unrelated state into the create route. Prefer explicit network/token/stage keys here for deterministic URLs.

Suggested adjustment
     router.push({
       pathname: '/dao/[network]/[token]/proposal/create',
       query: {
-        ...router.query,
+        network: router.query.network,
+        token: router.query.token,
         stage: 'transactions',
       },
     })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/modules/coin/CreateContentCoinForm/NoCreatorCoinWarning.tsx`
around lines 45 - 48, The navigation currently spreads router.query into the new
URL (router.query), which can leak unrelated params; instead build the query
object explicitly by selecting only the needed keys (e.g., network, token) and
setting stage: 'transactions' before calling router.push or link builder in
NoCreatorCoinWarning; locate the code that uses router.query (the query: {
...router.query, stage: 'transactions' } block) and replace the spread with an
explicit object like { network: router.query.network, token: router.query.token,
stage: 'transactions' } (or using optional chaining/defaults) so only
deterministic params are forwarded.
packages/create-proposal-ui/src/components/CreateProposalHeading/CreateProposalHeading.tsx (1)

121-146: Extract reset-confirmation modal into a shared component.

Line 121–146 duplicates reset modal structure already present in MobileProposalActionBar. A shared modal component would keep copy/actions/styles consistent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/create-proposal-ui/src/components/CreateProposalHeading/CreateProposalHeading.tsx`
around lines 121 - 146, Create a reusable ResetConfirmationModal component and
replace the duplicated modal markup in CreateProposalHeading (the block using
AnimatedModal, setResetModalOpen, resetModalOpen, and onReset) and the similar
block in MobileProposalActionBar with that component: implement
ResetConfirmationModal props for open, onConfirm, onCancel, title, description,
confirmLabel and cancelLabel (or reasonable defaults), move the modal JSX into
that component (using AnimatedModal and the same styles), and update
CreateProposalHeading and MobileProposalActionBar to render
<ResetConfirmationModal open={resetModalOpen} onConfirm={() => { onReset();
setResetModalOpen(false); }} onCancel={() => setResetModalOpen(false)} /> so
copy/actions/styles remain consistent and centralized.
apps/web/src/pages/dao/[network]/[token]/proposal/create.tsx (1)

210-251: Simplify continueHelperText by deriving it from requirement arrays.

Line 210–251 has a large branch matrix that can drift from missingDraftRequirements / missingReviewRequirements. Consider generating the message from those arrays to reduce complexity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/pages/dao/`[network]/[token]/proposal/create.tsx around lines
210 - 251, The current giant branch in continueHelperText should be replaced by
deriving missing requirements from the existing requirement arrays instead of
manual conditionals: inside the useMemo for continueHelperText, compute
requiredMissing = createStage === 'draft' ?
missingDraftRequirements.filter(Boolean) :
missingReviewRequirements.filter(Boolean) (or build an array from booleans
isMissingTitle/isMissingDescription/isMissingTransactions mapped to friendly
labels), then if requiredMissing.length === 0 return null else return a single
string like "To continue, add " + join the friendly labels with commas and " and
" for the last item; reference continueHelperText, createStage,
missingDraftRequirements/missingReviewRequirements (or
isMissingTitle/isMissingDescription/isMissingTransactions) to locate where to
change. Ensure the hook dependencies include the arrays/flags used.
packages/create-proposal-ui/src/components/ProposalHelpLinks/ProposalHelpLinks.tsx (1)

4-6: Avoid hardcoded help URLs in this shared package.

Line 16 and Line 32 hardcode destinations. In a reusable component package, this tightly couples behavior to one app/routing setup. Prefer passing hrefs via props (or a link provider) so host apps can control destinations.

♻️ Suggested refactor
 type ProposalHelpLinksProps = {
   align?: 'left' | 'center'
+  createProposalGuideHref?: string
+  proposalTipsHref?: string
 }
 
 export const ProposalHelpLinks: React.FC<ProposalHelpLinksProps> = ({
   align = 'left',
+  createProposalGuideHref = 'https://docs.nouns.build/onboarding/builder-proposal/',
+  proposalTipsHref = '/guidelines',
 }) => {
@@
-      <a href="https://docs.nouns.build/onboarding/builder-proposal/" ...>
+      <a href={createProposalGuideHref} ...>
@@
-      <a href="/guidelines" ...>
+      <a href={proposalTipsHref} ...>

Also applies to: 15-33

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/create-proposal-ui/src/components/ProposalHelpLinks/ProposalHelpLinks.tsx`
around lines 4 - 6, The component ProposalHelpLinks currently hardcodes help
destinations; update it to accept hrefs via props (e.g., add optional props like
proposalGuidelinesHref and howToVoteHref or a single links prop) and use those
props instead of fixed URLs inside the ProposalHelpLinks component, falling back
to existing defaults if props are undefined; update the ProposalHelpLinksProps
type to include the new href properties and use them where the component renders
the help links so host apps can control destinations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/layouts/BaseLayout/BaseLayout.tsx`:
- Around line 43-45: The inline style { flex: 1 } on the Box can be lost when
props.style is passed; update BaseLayout so you merge props.style but ensure
flex: 1 wins (e.g., extract style from props with const { style, ...rest } =
props and render <Box style={{ ...style, flex: 1 }} {...rest}> {children}
</Box>) so other style attributes are preserved while guaranteeing flex: 1
remains applied.

In
`@packages/create-proposal-ui/src/components/ProposalStageIndicator/ProposalStageIndicator.tsx`:
- Around line 103-118: The Stack container currently uses onClick for selection
but is not keyboard-accessible; update the element rendered by
ProposalStageIndicator (the Stack with key={stage.id}) to support keyboard
activation by adding role="button" (or appropriate role), tabIndex={clickable &&
!isLocked ? 0 : -1}, aria-disabled={isLocked}, and a onKeyDown handler that
calls onStageSelect(stage.id) when Enter or Space is pressed (but only when
clickable and not isLocked), while preserving the existing onClick behavior;
ensure the handler prevents default for Space key so the page doesn't scroll.

In
`@packages/create-proposal-ui/src/components/ReviewProposalForm/ReviewProposalForm.tsx`:
- Around line 273-283: The timeline estimate logic incorrectly treats zero
values as missing; update the conditionals that compute estimatedVotingStartsAt,
estimatedVotingEndsAt, and estimatedEarliestExecutionAt to check for
null/undefined explicitly (e.g., votingDelay !== undefined && votingDelay !==
null) instead of using truthy checks so that 0 is preserved; ensure the same
explicit null/undefined checks are used where formatTimestamp consumes these
timestamps so DAOs with zero delays render correctly (refer to variables
votingDelay, votingPeriod, timelockDelay, nowTimestamp, estimatedVotingStartsAt,
estimatedVotingEndsAt, estimatedEarliestExecutionAt, and formatTimestamp).

In
`@packages/proposal-ui/src/components/ProposalDescription/StreamDetails/StreamItem.tsx`:
- Around line 218-219: The effect currently calls onOpenProposalReview() without
awaiting it, risking unhandled promise rejections; update the async callback
that references onOpenProposalReview, startProposalDraft, lockupAddress, and
liveData to await onOpenProposalReview() and wrap the call in try/catch so any
rejection is caught and handled (e.g., log or surface the error) before
proceeding.

In `@packages/stores/src/hooks/useProposalStore.ts`:
- Around line 71-75: startProposalDraft currently spreads the incoming draft
directly into state which allows explicit undefined values (e.g.,
draft.transactions or draft.disabled) to overwrite required fields in
initialState; sanitize the draft before merging by removing keys whose values
are undefined (e.g., build a sanitizedDraft from draft by filtering out entries
with value === undefined) and then set state with {...initialState,
...sanitizedDraft} so required fields on State (transactions, disabled, etc.)
can never be clobbered by undefined.

In `@packages/ui/src/DropdownSelect/DropdownSelect.tsx`:
- Line 102: The displayLabel assignment in DropdownSelect.tsx uses || which
treats valid falsy labels (like '' or 0) as missing; update the expression that
defines displayLabel (the const displayLabel in the DropdownSelect component) to
use the nullish coalescing operator (??) instead of || so it falls back only on
null/undefined (e.g. const displayLabel = customLabel ?? selectedOption?.label
?? 'Select option').

In `@packages/ui/src/MarkdownEditor/MarkdownEditor.tsx`:
- Around line 103-117: The fallback textarea in the MarkdownEditor component
lacks a programmatic label, hurting accessibility; update the <textarea>
rendered in MarkdownEditor (the element using props value and onChange) to
include a semantic label (either add an aria-label or aria-labelledby pointing
to an associated <label> element) so screen readers announce the field name;
ensure the chosen label string matches the visible label text and use the same
unique identifier (id) if using aria-labelledby so the association is explicit.

---

Outside diff comments:
In
`@packages/create-proposal-ui/src/components/TransactionForm/Droposal/DroposalForm.tsx`:
- Around line 88-96: In the DroposalForm component update the user-facing link
text inside the Text JSX (the anchor within the Text element) from "Lean more"
to the correct "Learn more"; locate the Text block in DroposalForm.tsx that
references the ZORA 721 Contract and replace the typo in the anchor content so
the displayed link reads "Learn more".

---

Nitpick comments:
In `@apps/web/src/modules/coin/CreateContentCoinForm/NoCreatorCoinWarning.tsx`:
- Around line 45-48: The navigation currently spreads router.query into the new
URL (router.query), which can leak unrelated params; instead build the query
object explicitly by selecting only the needed keys (e.g., network, token) and
setting stage: 'transactions' before calling router.push or link builder in
NoCreatorCoinWarning; locate the code that uses router.query (the query: {
...router.query, stage: 'transactions' } block) and replace the spread with an
explicit object like { network: router.query.network, token: router.query.token,
stage: 'transactions' } (or using optional chaining/defaults) so only
deterministic params are forwarded.

In `@apps/web/src/pages/dao/`[network]/[token]/proposal/create.tsx:
- Around line 210-251: The current giant branch in continueHelperText should be
replaced by deriving missing requirements from the existing requirement arrays
instead of manual conditionals: inside the useMemo for continueHelperText,
compute requiredMissing = createStage === 'draft' ?
missingDraftRequirements.filter(Boolean) :
missingReviewRequirements.filter(Boolean) (or build an array from booleans
isMissingTitle/isMissingDescription/isMissingTransactions mapped to friendly
labels), then if requiredMissing.length === 0 return null else return a single
string like "To continue, add " + join the friendly labels with commas and " and
" for the last item; reference continueHelperText, createStage,
missingDraftRequirements/missingReviewRequirements (or
isMissingTitle/isMissingDescription/isMissingTransactions) to locate where to
change. Ensure the hook dependencies include the arrays/flags used.

In
`@packages/create-proposal-ui/src/components/CreateProposalHeading/CreateProposalHeading.tsx`:
- Around line 121-146: Create a reusable ResetConfirmationModal component and
replace the duplicated modal markup in CreateProposalHeading (the block using
AnimatedModal, setResetModalOpen, resetModalOpen, and onReset) and the similar
block in MobileProposalActionBar with that component: implement
ResetConfirmationModal props for open, onConfirm, onCancel, title, description,
confirmLabel and cancelLabel (or reasonable defaults), move the modal JSX into
that component (using AnimatedModal and the same styles), and update
CreateProposalHeading and MobileProposalActionBar to render
<ResetConfirmationModal open={resetModalOpen} onConfirm={() => { onReset();
setResetModalOpen(false); }} onCancel={() => setResetModalOpen(false)} /> so
copy/actions/styles remain consistent and centralized.

In
`@packages/create-proposal-ui/src/components/ProposalHelpLinks/ProposalHelpLinks.tsx`:
- Around line 4-6: The component ProposalHelpLinks currently hardcodes help
destinations; update it to accept hrefs via props (e.g., add optional props like
proposalGuidelinesHref and howToVoteHref or a single links prop) and use those
props instead of fixed URLs inside the ProposalHelpLinks component, falling back
to existing defaults if props are undefined; update the ProposalHelpLinksProps
type to include the new href properties and use them where the component renders
the help links so host apps can control destinations.

In `@packages/types/src/links.ts`:
- Around line 25-29: Introduce a shared exported type alias ProposalCreateStage
= 'draft' | 'transactions' and replace the inline union in the
ProposalCreateLinkHandler signature with that alias so the handler becomes
(chainId: CHAIN_ID, daoTokenAddress: AddressType, stage?: ProposalCreateStage)
=> LinkOptions; update any other types/usages referencing the inline union to
import and use ProposalCreateStage to prevent drift across consumers (keep
LinkOptions and existing symbols unchanged).

In `@packages/ui/src/DropdownSelect/DropdownSelect.tsx`:
- Line 133: The align prop in DropdownSelect.tsx is using a redundant ternary
(option.description ? 'center' : 'center'); simplify by replacing that
expression with a single literal 'center' for the align prop in the
DropdownSelect component (remove the ternary and reference to
option.description).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59fe4070-144f-4c40-bf84-02b1cfa144ca

📥 Commits

Reviewing files that changed from the base of the PR and between efa0536 and 11a3d60.

⛔ Files ignored due to path filters (2)
  • packages/zord/src/assets/pencil.svg is excluded by !**/*.svg
  • packages/zord/src/assets/queue.svg is excluded by !**/*.svg
📒 Files selected for processing (44)
  • apps/web/src/components/LinksProvider.tsx
  • apps/web/src/layouts/BaseLayout/BaseLayout.tsx
  • apps/web/src/layouts/DaoLayout/DaoLayout.tsx
  • apps/web/src/modules/coin/CreateContentCoinForm/NoCreatorCoinWarning.tsx
  • apps/web/src/pages/dao/[network]/[token]/[tokenId].tsx
  • apps/web/src/pages/dao/[network]/[token]/index.tsx
  • apps/web/src/pages/dao/[network]/[token]/proposal/create.tsx
  • apps/web/src/pages/dao/[network]/[token]/proposal/review.tsx
  • packages/create-proposal-ui/src/components/CreateProposalHeading/CreateProposalHeading.tsx
  • packages/create-proposal-ui/src/components/MobileProposalActionBar/MobileProposalActionBar.css.ts
  • packages/create-proposal-ui/src/components/MobileProposalActionBar/MobileProposalActionBar.tsx
  • packages/create-proposal-ui/src/components/MobileProposalActionBar/index.ts
  • packages/create-proposal-ui/src/components/ProposalDraftForm/ProposalDraftForm.tsx
  • packages/create-proposal-ui/src/components/ProposalDraftForm/index.ts
  • packages/create-proposal-ui/src/components/ProposalHelpLinks/ProposalHelpLinks.tsx
  • packages/create-proposal-ui/src/components/ProposalHelpLinks/index.ts
  • packages/create-proposal-ui/src/components/ProposalStageIndicator/ProposalStageIndicator.tsx
  • packages/create-proposal-ui/src/components/ProposalStageIndicator/index.ts
  • packages/create-proposal-ui/src/components/Queue/Queue.tsx
  • packages/create-proposal-ui/src/components/ReviewProposalForm/ReviewProposalForm.tsx
  • packages/create-proposal-ui/src/components/SelectTransactionType/AdminNav.tsx
  • packages/create-proposal-ui/src/components/SelectTransactionType/SelectTransactionType.tsx
  • packages/create-proposal-ui/src/components/SelectTransactionType/TransactionTypeCard.tsx
  • packages/create-proposal-ui/src/components/SelectTransactionType/index.ts
  • packages/create-proposal-ui/src/components/TransactionForm/Droposal/DroposalForm.tsx
  • packages/create-proposal-ui/src/components/TransactionForm/Droposal/DroposalPreview.tsx
  • packages/create-proposal-ui/src/components/index.ts
  • packages/dao-ui/src/components/Activity/Activity.tsx
  • packages/dao-ui/src/components/AdminForm/AdminForm.tsx
  • packages/dao-ui/src/components/FixRendererBase/FixRendererBase.tsx
  • packages/dao-ui/src/components/Gallery/Gallery.tsx
  • packages/dao-ui/src/components/Upgrade/Upgrade.tsx
  • packages/hooks/src/useDecodedTransactions.ts
  • packages/proposal-ui/src/components/ProposalDescription/MilestoneDetails/EscrowInstance.tsx
  • packages/proposal-ui/src/components/ProposalDescription/ProposalDescription.tsx
  • packages/proposal-ui/src/components/ProposalDescription/Section.tsx
  • packages/proposal-ui/src/components/ProposalDescription/StreamDetails/StreamItem.tsx
  • packages/stores/src/hooks/useProposalStore.ts
  • packages/types/src/links.ts
  • packages/ui/src/DropdownSelect/DropdownSelect.tsx
  • packages/ui/src/LinksProvider/LinksProvider.tsx
  • packages/ui/src/MarkdownEditor/MarkdownEditor.tsx
  • packages/zord/src/elements/Spinner.css.ts
  • packages/zord/src/icons.ts
💤 Files with no reviewable changes (4)
  • packages/create-proposal-ui/src/components/SelectTransactionType/index.ts
  • packages/create-proposal-ui/src/components/SelectTransactionType/SelectTransactionType.tsx
  • packages/create-proposal-ui/src/components/SelectTransactionType/TransactionTypeCard.tsx
  • packages/create-proposal-ui/src/components/SelectTransactionType/AdminNav.tsx

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
packages/ui/src/DropdownSelect/DropdownSelect.tsx (1)

65-65: Consider requiring explicit value prop for API consistency, though current usage is safe.

The optional value?: T pattern allows callers to omit it entirely. While all current call sites provide the prop explicitly (including value={undefined} where appropriate), making it required as value: T | undefined would strengthen the API contract and prevent accidental omission. The component currently handles undefined values gracefully with fallback logic ('Select option'), so this is a refinement rather than a bug fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/DropdownSelect/DropdownSelect.tsx` at line 65, Change the
prop type for DropdownSelect to require the value prop explicitly by replacing
the optional signature `value?: T` with `value: T | undefined` in the
DropdownSelect props/interface; update any places that construct or spread those
props (referencing the DropdownSelect component and its props type) to pass
`value` explicitly (use `value={undefined}` where omission was intended) so
compiler enforces callers provide the prop while component logic (fallback to
'Select option') remains unchanged.
packages/create-proposal-ui/src/components/ResetConfirmationModal/ResetConfirmationModal.tsx (1)

33-39: Consider using a destructive variant for the reset confirmation button.

The "Reset" action is destructive (clears title, summary, and queued transactions), but the confirm button uses the default primary variant. Typically, destructive confirmation buttons use a distinct visual treatment (e.g., red/danger styling) to signal the irreversible nature of the action.

If the Button component supports a variant="destructive" or similar, consider using it for the confirm button.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/create-proposal-ui/src/components/ResetConfirmationModal/ResetConfirmationModal.tsx`
around lines 33 - 39, The confirm button in ResetConfirmationModal is using the
default primary style but should signal a destructive action; update the Button
that renders {confirmLabel} (the one with onClick={onConfirm}) to use the
destructive/danger variant supported by the Button API (e.g.,
variant="destructive" or variant="danger") so the Reset confirm is visually
distinct and communicates its irreversible effect.
packages/create-proposal-ui/src/components/MobileProposalActionBar/MobileProposalActionBar.tsx (1)

48-55: Add explicit type="button" to all buttons for safe form embedding.

These buttons are rendered inside a <form> element in ReviewProposalForm. While the Button component from @buildeross/zord currently defaults to type="button" (line 66 of Button.tsx), explicitly setting this type prevents accidental form submissions if component defaults change in the future.

Apply to: Back (line 48), Queue (line 57), Reset (line 66), and Continue (line 75) buttons.

Proposed patch
         {showBack && onBack && (
           <Button
+            type="button"
             variant="secondary"
             aria-label="Back"
             disabled={backDisabled}
             onClick={onBack}
           >
@@
         {showQueue && transactions.length > 0 && (
           <Button
+            type="button"
             variant="secondary"
             aria-label={`Open queue with ${transactions.length} transactions`}
             onClick={() => setQueueModalOpen(true)}
           >
@@
         {showReset && onReset && (
           <Button
+            type="button"
             variant="secondary"
             aria-label="Reset proposal"
             onClick={() => setResetModalOpen(true)}
           >
@@
         {showContinue && onContinue && (
           <Button
+            type="button"
             className={mobileActionPrimary}
             disabled={continueDisabled}
             loading={continueLoading}
             onClick={onContinue}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/create-proposal-ui/src/components/MobileProposalActionBar/MobileProposalActionBar.tsx`
around lines 48 - 55, The Button elements in MobileProposalActionBar (the Back,
Queue, Reset, and Continue Button instances) need an explicit type attribute to
avoid accidental form submissions; update each Button JSX (the Back Button with
Icon id="arrowLeft", the Queue Button, the Reset Button, and the Continue
Button) to include type="button" so they no longer rely on the Button component
default.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@packages/create-proposal-ui/src/components/MobileProposalActionBar/MobileProposalActionBar.tsx`:
- Around line 48-55: The Button elements in MobileProposalActionBar (the Back,
Queue, Reset, and Continue Button instances) need an explicit type attribute to
avoid accidental form submissions; update each Button JSX (the Back Button with
Icon id="arrowLeft", the Queue Button, the Reset Button, and the Continue
Button) to include type="button" so they no longer rely on the Button component
default.

In
`@packages/create-proposal-ui/src/components/ResetConfirmationModal/ResetConfirmationModal.tsx`:
- Around line 33-39: The confirm button in ResetConfirmationModal is using the
default primary style but should signal a destructive action; update the Button
that renders {confirmLabel} (the one with onClick={onConfirm}) to use the
destructive/danger variant supported by the Button API (e.g.,
variant="destructive" or variant="danger") so the Reset confirm is visually
distinct and communicates its irreversible effect.

In `@packages/ui/src/DropdownSelect/DropdownSelect.tsx`:
- Line 65: Change the prop type for DropdownSelect to require the value prop
explicitly by replacing the optional signature `value?: T` with `value: T |
undefined` in the DropdownSelect props/interface; update any places that
construct or spread those props (referencing the DropdownSelect component and
its props type) to pass `value` explicitly (use `value={undefined}` where
omission was intended) so compiler enforces callers provide the prop while
component logic (fallback to 'Select option') remains unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 81904fcd-c57c-4f87-be16-0b1966dfcbed

📥 Commits

Reviewing files that changed from the base of the PR and between 11a3d60 and d847cbb.

📒 Files selected for processing (23)
  • apps/web/src/components/LinksProvider.tsx
  • apps/web/src/layouts/BaseLayout/BaseLayout.tsx
  • apps/web/src/modules/coin/CreateContentCoinForm/NoCreatorCoinWarning.tsx
  • apps/web/src/pages/dao/[network]/[token]/[tokenId].tsx
  • apps/web/src/pages/dao/[network]/[token]/index.tsx
  • apps/web/src/pages/dao/[network]/[token]/proposal/create.tsx
  • apps/web/src/pages/dao/[network]/[token]/proposal/review.tsx
  • packages/create-proposal-ui/src/components/CreateProposalHeading/CreateProposalHeading.tsx
  • packages/create-proposal-ui/src/components/MobileProposalActionBar/MobileProposalActionBar.tsx
  • packages/create-proposal-ui/src/components/ProposalHelpLinks/ProposalHelpLinks.tsx
  • packages/create-proposal-ui/src/components/ProposalStageIndicator/ProposalStageIndicator.tsx
  • packages/create-proposal-ui/src/components/ResetConfirmationModal/ResetConfirmationModal.tsx
  • packages/create-proposal-ui/src/components/ResetConfirmationModal/index.ts
  • packages/create-proposal-ui/src/components/ReviewProposalForm/ReviewProposalForm.tsx
  • packages/create-proposal-ui/src/components/TransactionForm/Droposal/DroposalForm.tsx
  • packages/create-proposal-ui/src/components/index.ts
  • packages/dao-ui/src/components/Gallery/Gallery.tsx
  • packages/proposal-ui/src/components/ProposalDescription/StreamDetails/StreamItem.tsx
  • packages/stores/src/hooks/useProposalStore.ts
  • packages/types/src/links.ts
  • packages/ui/src/DropdownSelect/DropdownSelect.tsx
  • packages/ui/src/LinksProvider/LinksProvider.tsx
  • packages/ui/src/MarkdownEditor/MarkdownEditor.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/create-proposal-ui/src/components/ProposalStageIndicator/ProposalStageIndicator.tsx
  • packages/proposal-ui/src/components/ProposalDescription/StreamDetails/StreamItem.tsx
  • packages/create-proposal-ui/src/components/ProposalHelpLinks/ProposalHelpLinks.tsx
  • apps/web/src/modules/coin/CreateContentCoinForm/NoCreatorCoinWarning.tsx
  • apps/web/src/components/LinksProvider.tsx
  • packages/ui/src/MarkdownEditor/MarkdownEditor.tsx

@dan13ram dan13ram merged commit 00a6eec into staging Mar 4, 2026
4 checks passed
@dan13ram dan13ram deleted the refactor/proposal-creation-flow branch March 4, 2026 11:45
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