Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .sync/log/269080a85dc877a2140bdc951c32ccd5626f4684.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Port: fix(Button): allow inline event handlers with non-void return types (#6668)

**Upstream:** `269080a85dc877a2140bdc951c32ccd5626f4684` (nuxt/ui)
**Decision:** port

## Upstream change
Narrows the handler-prop types from `(e) => void | Promise<void>` to
`(e) => void` on `onClick`/`onSubmit` across Button, Form, LinkBase, PageCard,
PageFeature, User, BlogPost, ChangelogVersion, and the inertia LinkBase
override. Counter-intuitively this **widens** what callers may pass: TypeScript's
void-return bivalence means a function returning *anything* is assignable to a
`=> void` parameter type, so inline template handlers whose expression returns a
non-void value (e.g. `@click="count++"`) are accepted instead of erroring
against the `void | Promise<void>` union.

## b24ui port — 1:1 + one b24ui extension
Applied `=> void | Promise<void>` → `=> void` (both the single-arg and the
`Array<…>`/`() => …` union variants) in the b24ui-matching files:
`Button.vue` (onClick), `Form.vue` (onSubmit), `LinkBase.vue` (onClick),
`PageCard.vue` (onClick), `PageFeature.vue` (onClick), `User.vue` (onClick),
`vue/overrides/inertia/LinkBase.vue` (onClick). Upstream's `BlogPost.vue` /
`ChangelogVersion.vue` are **absent** in b24ui (N/A).

**b24ui extension:** b24ui's `Badge.vue` is clickable and carries an
`onCloseClick?: ((e) => void | Promise<void>) | Array<…>` prop that upstream's
Badge does not have. Same bug, same fix — applied there too so b24ui's Badge
close handler accepts inline non-void handlers consistently. (Deviation noted in
the PR.)

8 files, +8/−8 (one line each). No renames (`ui`→`b24ui` etc. not involved).

## Tests
Type-only change, no runtime/markup change → no snapshot churn. Full suite
unchanged (225 files, 5147 passed / 6 skipped).

## Verify (CI=true)
`dev:prepare` · `lint` · `typecheck` · `test` · `build` — all green.
12 changes: 9 additions & 3 deletions .sync/nuxt-ui.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"upstream": "nuxt/ui",
"branch": "v4",
"sync_enabled": false,
"cursor": "dfbbfeb5a9ab3cbaf9582ba3393cceb1584baa5e",
"cursor": "269080a85dc877a2140bdc951c32ccd5626f4684",
"_cursor_note": "cursor = last upstream commit ported into b24ui (oldest-first, manual cadence). sync_enabled stays false until Phase 2 (porter workflow #67 + CLAUDE_CODE_OAUTH_TOKEN) is wired and trusted. `processed` is maintained per port from now on (backfilled #68-#72 on 2026-06-09).",
"stats": {
"queue_depth": 0,
Expand Down Expand Up @@ -845,10 +845,16 @@
"summary": "chore(github): update reproduire workflow version — NO-OP: re-pins Hebilicious/reproduire @v1 -> @4b686ae...#v0.0.9 in .github/workflows/reproduire.yml (partial revert of df099a5's un-pin). b24ui has no reproduire.yml (only ci/deploy/npm-publish workflows); same N/A basis as df099a5 (#232). Bookkeeping only"
},
"dfbbfeb5a9ab3cbaf9582ba3393cceb1584baa5e": {
"pr": null,
"b24ui_sha": "pending-merge",
"pr": 238,
"b24ui_sha": "a2c59cf0",
"decision": "skip",
"summary": "chore(deps): migrate AI SDK to v7 (#6636) — SKIPPED/DEFERRED (maintainer call): major dep migration ai ^6->^7, @ai-sdk/anthropic ^3->^4, @ai-sdk/gateway ^3->^4, @ai-sdk/mcp ^1->^2, @ai-sdk/vue ^3->^4 + docs/playground client (new Chat()->useChat()) + server routes (system->instructions, stepCountIs->isStepCount, toUIMessageStreamResponse->toUIMessageStream+createUIMessageStreamResponse, toTextStreamResponse->createTextStreamResponse, onFinish->onEnd, model ids). Upstream touched NO src/runtime, but b24ui runtime imports ai (ChatMessages/ChatMessage/ChatPromptSubmit + utils/ai.ts) AND has a b24ui-only bx-assistant module (AssistantPanel/search.ts/useAssistant.ts) using @ai-sdk/vue+streamText with no upstream reference -> not a mechanical replay; needs a deliberate v7 adoption pass verifying runtime types + hand-migrating bx-assistant + lockfile regen + end-to-end test. Also verbatim .patch fetch egress-blocked this session. b24ui stays on ai@6. Consistent with prior deferrals #220/#194. Bookkeeping only, cursor advances; tracked for future AI-SDK-v7 task"
},
"269080a85dc877a2140bdc951c32ccd5626f4684": {
"pr": null,
"b24ui_sha": "pending-merge",
"decision": "port",
"summary": "fix(Button): allow inline event handlers with non-void return types (#6668) — narrow handler types `=> void | Promise<void>` -> `=> void` on onClick/onSubmit (TS void-bivalence widens accepted return types so inline template handlers returning non-void no longer error). b24ui files: Button(onClick), Form(onSubmit), LinkBase(onClick), PageCard, PageFeature, User, vue/overrides/inertia/LinkBase — all single+Array/()=> union variants. BlogPost/ChangelogVersion absent (N/A). +b24ui extension: Badge.onCloseClick (b24ui-only clickable-close prop, same pattern/fix). 8 files +8/-8. Type-only, no snapshot churn"
}
}
}
2 changes: 1 addition & 1 deletion src/runtime/components/Badge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export interface BadgeProps extends Omit<UseComponentIconsProps, 'loading' | 'lo
* @defaultValue false
*/
useClose?: boolean
onCloseClick?: ((event: MouseEvent) => void | Promise<void>) | Array<((event: MouseEvent) => void | Promise<void>)>
onCloseClick?: ((event: MouseEvent) => void) | Array<((event: MouseEvent) => void)>
class?: any
b24ui?: Badge['slots']
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/Button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export interface ButtonProps extends Omit<UseComponentIconsProps, 'trailing' | '
* @defaultValue false
*/
useDropdown?: boolean
onClick?: ((event: MouseEvent) => void | Promise<void>) | Array<((event: MouseEvent) => void | Promise<void>)>
onClick?: ((event: MouseEvent) => void) | Array<((event: MouseEvent) => void)>
class?: any
/**
* The class to apply when the link is active
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export type FormProps<S extends FormSchema, T extends boolean = true, N extends
loadingAuto?: boolean
class?: any
b24ui?: { base?: any }
onSubmit?: ((event: FormSubmitEvent<FormData<S, T>>) => void | Promise<void>) | (() => void | Promise<void>)
onSubmit?: ((event: FormSubmitEvent<FormData<S, T>>) => void) | (() => void)
} & /** @vue-ignore */ Omit<FormHTMLAttributes, 'name'>

export interface FormEmits<S extends FormSchema, T extends boolean = true> {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/LinkBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface LinkBaseProps {
as?: string
type?: string
disabled?: boolean
onClick?: ((e: MouseEvent) => void | Promise<void>) | Array<((e: MouseEvent) => void | Promise<void>)>
onClick?: ((e: MouseEvent) => void) | Array<((e: MouseEvent) => void)>
href?: string | null
navigate?: (e: MouseEvent) => void
target?: LinkProps['target']
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/PageCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export interface PageCardProps {
variant?: PageCard['variants']['variant']
to?: LinkProps['to']
target?: LinkProps['target']
onClick?: (event: MouseEvent) => void | Promise<void>
onClick?: (event: MouseEvent) => void
class?: any
b24ui?: PageCard['slots']
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/PageFeature.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface PageFeatureProps {
orientation?: PageFeature['variants']['orientation']
to?: LinkProps['to']
target?: LinkProps['target']
onClick?: (event: MouseEvent) => void | Promise<void>
onClick?: (event: MouseEvent) => void
class?: any
b24ui?: PageFeature['slots']
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/User.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface UserProps {
orientation?: User['variants']['orientation']
to?: LinkProps['to']
target?: LinkProps['target']
onClick?: (event: MouseEvent) => void | Promise<void>
onClick?: (event: MouseEvent) => void
class?: any
b24ui?: User['slots']
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/vue/overrides/inertia/LinkBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface LinkBaseProps {
as?: string
type?: string
disabled?: boolean
onClick?: ((e: MouseEvent) => void | Promise<void>) | Array<((e: MouseEvent) => void | Promise<void>)>
onClick?: ((e: MouseEvent) => void) | Array<((e: MouseEvent) => void)>
href?: string
target?: LinkProps['target']
rel?: LinkProps['rel']
Expand Down