From 2a000e17e289bacf2ed6fcbba7657c3703c001f3 Mon Sep 17 00:00:00 2001 From: Segun Adebayo Date: Tue, 28 Jul 2026 11:21:58 +0200 Subject: [PATCH 1/5] fix(vue): respect controlled paths on SignaturePad.Root --- .changeset/vue-signature-pad-paths.md | 5 ++++ .../signature-pad/examples/controlled.tsx | 28 +++++++++++++++++++ .../signature-pad/signature-pad.stories.tsx | 1 + .../signature-pad/examples/controlled.tsx | 28 +++++++++++++++++++ .../signature-pad/signature-pad.stories.tsx | 1 + .../signature-pad/examples/controlled.svelte | 23 +++++++++++++++ .../signature-pad/signature-pad.stories.ts | 7 +++++ .../signature-pad/examples/controlled.vue | 26 +++++++++++++++++ .../signature-pad/signature-pad.stories.ts | 8 ++++++ .../signature-pad/signature-pad.types.ts | 4 +++ .../pages/components/signature-pad.mdx | 7 +++++ .../types/vue/signature-pad.types.json | 1 + 12 files changed, 139 insertions(+) create mode 100644 .changeset/vue-signature-pad-paths.md create mode 100644 packages/react/src/components/signature-pad/examples/controlled.tsx create mode 100644 packages/solid/src/components/signature-pad/examples/controlled.tsx create mode 100644 packages/svelte/src/lib/components/signature-pad/examples/controlled.svelte create mode 100644 packages/vue/src/components/signature-pad/examples/controlled.vue diff --git a/.changeset/vue-signature-pad-paths.md b/.changeset/vue-signature-pad-paths.md new file mode 100644 index 0000000000..26c84ffde4 --- /dev/null +++ b/.changeset/vue-signature-pad-paths.md @@ -0,0 +1,5 @@ +--- +"@ark-ui/vue": patch +--- + +Fixed `SignaturePad.Root` ignoring the controlled `paths` prop. diff --git a/packages/react/src/components/signature-pad/examples/controlled.tsx b/packages/react/src/components/signature-pad/examples/controlled.tsx new file mode 100644 index 0000000000..4c512ff565 --- /dev/null +++ b/packages/react/src/components/signature-pad/examples/controlled.tsx @@ -0,0 +1,28 @@ +import { SignaturePad } from '@ark-ui/react/signature-pad' +import { RotateCcwIcon } from 'lucide-react' +import { useState } from 'react' +import button from 'styles/button.module.css' +import styles from 'styles/signature-pad.module.css' + +export const Controlled = () => { + const [paths, setPaths] = useState([]) + + return ( +
+ paths: {paths.length} + setPaths(details.paths)}> + Sign below + + + + + + + + + +
+ ) +} diff --git a/packages/react/src/components/signature-pad/signature-pad.stories.tsx b/packages/react/src/components/signature-pad/signature-pad.stories.tsx index 1d9418641c..cc8d825803 100644 --- a/packages/react/src/components/signature-pad/signature-pad.stories.tsx +++ b/packages/react/src/components/signature-pad/signature-pad.stories.tsx @@ -7,6 +7,7 @@ const meta: Meta = { export default meta export { Basic } from './examples/basic.tsx' +export { Controlled } from './examples/controlled.tsx' export { ImagePreview } from './examples/image-preview.tsx' export { RootProvider } from './examples/root-provider.tsx' export { WithField } from './examples/with-field.tsx' diff --git a/packages/solid/src/components/signature-pad/examples/controlled.tsx b/packages/solid/src/components/signature-pad/examples/controlled.tsx new file mode 100644 index 0000000000..4dcc8686b2 --- /dev/null +++ b/packages/solid/src/components/signature-pad/examples/controlled.tsx @@ -0,0 +1,28 @@ +import { SignaturePad } from '@ark-ui/solid/signature-pad' +import { RotateCcwIcon } from 'lucide-solid' +import { createSignal } from 'solid-js' +import button from 'styles/button.module.css' +import styles from 'styles/signature-pad.module.css' + +export const Controlled = () => { + const [paths, setPaths] = createSignal([]) + + return ( +
+ paths: {paths().length} + setPaths(details.paths)}> + Sign below + + + + + + + + + +
+ ) +} diff --git a/packages/solid/src/components/signature-pad/signature-pad.stories.tsx b/packages/solid/src/components/signature-pad/signature-pad.stories.tsx index f1218009e4..108c2515cf 100644 --- a/packages/solid/src/components/signature-pad/signature-pad.stories.tsx +++ b/packages/solid/src/components/signature-pad/signature-pad.stories.tsx @@ -7,6 +7,7 @@ const meta: Meta = { export default meta export { Basic } from './examples/basic.tsx' +export { Controlled } from './examples/controlled.tsx' export { ImagePreview } from './examples/image-preview.tsx' export { RootProvider } from './examples/root-provider.tsx' export { WithField } from './examples/with-field.tsx' diff --git a/packages/svelte/src/lib/components/signature-pad/examples/controlled.svelte b/packages/svelte/src/lib/components/signature-pad/examples/controlled.svelte new file mode 100644 index 0000000000..6fecb451d0 --- /dev/null +++ b/packages/svelte/src/lib/components/signature-pad/examples/controlled.svelte @@ -0,0 +1,23 @@ + + +
+ paths: {paths.length} + + Sign below + + + + + + + + + +
diff --git a/packages/svelte/src/lib/components/signature-pad/signature-pad.stories.ts b/packages/svelte/src/lib/components/signature-pad/signature-pad.stories.ts index d6a0fccb17..26b8794557 100644 --- a/packages/svelte/src/lib/components/signature-pad/signature-pad.stories.ts +++ b/packages/svelte/src/lib/components/signature-pad/signature-pad.stories.ts @@ -1,5 +1,6 @@ import type { Meta } from '@storybook/svelte' import BasicExample from './examples/basic.svelte' +import ControlledExample from './examples/controlled.svelte' import RootProviderExample from './examples/root-provider.svelte' import WithContextExample from './examples/with-context.svelte' @@ -15,6 +16,12 @@ export const Basic = { }), } +export const Controlled = { + render: () => ({ + Component: ControlledExample, + }), +} + export const RootProvider = { render: () => ({ Component: RootProviderExample, diff --git a/packages/vue/src/components/signature-pad/examples/controlled.vue b/packages/vue/src/components/signature-pad/examples/controlled.vue new file mode 100644 index 0000000000..f6303acbeb --- /dev/null +++ b/packages/vue/src/components/signature-pad/examples/controlled.vue @@ -0,0 +1,26 @@ + + + diff --git a/packages/vue/src/components/signature-pad/signature-pad.stories.ts b/packages/vue/src/components/signature-pad/signature-pad.stories.ts index e9f0a97473..88cc42d0a1 100644 --- a/packages/vue/src/components/signature-pad/signature-pad.stories.ts +++ b/packages/vue/src/components/signature-pad/signature-pad.stories.ts @@ -1,6 +1,7 @@ import type { Meta } from '@storybook/vue3-vite' import BasicExample from './examples/basic.vue' +import ControlledExample from './examples/controlled.vue' import ImagePreviewExample from './examples/image-preview.vue' import RootProviderExample from './examples/root-provider.vue' import WithFieldExample from './examples/with-field.vue' @@ -18,6 +19,13 @@ export const Basic = { }), } +export const Controlled = { + render: () => ({ + components: { Component: ControlledExample }, + template: '', + }), +} + export const ImagePreview = { render: () => ({ components: { Component: ImagePreviewExample }, diff --git a/packages/vue/src/components/signature-pad/signature-pad.types.ts b/packages/vue/src/components/signature-pad/signature-pad.types.ts index ffe5f6c974..f1c928d3b9 100644 --- a/packages/vue/src/components/signature-pad/signature-pad.types.ts +++ b/packages/vue/src/components/signature-pad/signature-pad.types.ts @@ -14,6 +14,10 @@ export interface RootProps { * The default paths of the signature pad. */ defaultPaths?: string[] + /** + * The controlled paths of the signature pad. + */ + paths?: string[] /** * The unique identifier of the machine. */ diff --git a/website/src/content/pages/components/signature-pad.mdx b/website/src/content/pages/components/signature-pad.mdx index 07a7cd0b21..aee834115d 100644 --- a/website/src/content/pages/components/signature-pad.mdx +++ b/website/src/content/pages/components/signature-pad.mdx @@ -25,6 +25,13 @@ description: A component that allows users to draw a signature using a signature +### Controlled + +Use the `paths` prop with `onDraw` (React/Solid), `v-model:paths` (Vue), or `bind:paths` (Svelte) to control the +signature pad externally. The example tracks the path count and can clear the signature from outside the component. + + + ### Image Preview After the user draws a signature, you can display a preview of the signature as an image. This is useful when you want diff --git a/website/src/content/types/vue/signature-pad.types.json b/website/src/content/types/vue/signature-pad.types.json index 368ab6508e..538a60403b 100644 --- a/website/src/content/types/vue/signature-pad.types.json +++ b/website/src/content/types/vue/signature-pad.types.json @@ -92,6 +92,7 @@ "isRequired": false, "description": "The name of the signature pad. Useful for form submission." }, + "paths": { "type": "string[]", "isRequired": false, "description": "The controlled paths of the signature pad." }, "readOnly": { "type": "boolean", "isRequired": false, "description": "Whether the signature pad is read-only." }, "required": { "type": "boolean", "isRequired": false, "description": "Whether the signature pad is required." }, "translations": { From 52b84a583707bb0da591301486816173fcd71c87 Mon Sep 17 00:00:00 2001 From: Segun Adebayo Date: Tue, 28 Jul 2026 13:12:23 +0200 Subject: [PATCH 2/5] fix(vue): restore missing controlled Root props and v-model emits --- .changeset/vue-controlled-vmodel-emits.md | 7 +++++++ .changeset/vue-file-upload-accepted-files.md | 5 +++++ .../src/components/date-input/date-input.types.ts | 8 ++++++++ .../vue/src/components/date-input/use-date-input.ts | 5 +++++ packages/vue/src/components/dialog/dialog.types.ts | 4 ++++ .../components/dialog/examples/multiple-triggers.vue | 7 ++++--- packages/vue/src/components/dialog/use-dialog.ts | 1 + packages/vue/src/components/drawer/drawer.types.ts | 12 ++++++++++++ .../components/drawer/examples/multiple-triggers.vue | 10 ++++------ packages/vue/src/components/drawer/use-drawer.ts | 3 +++ .../src/components/file-upload/file-upload.types.ts | 4 ++++ .../hover-card/examples/multiple-triggers.vue | 7 ++++--- .../src/components/hover-card/hover-card.types.ts | 4 ++++ .../vue/src/components/hover-card/use-hover-card.ts | 1 + packages/vue/src/components/listbox/listbox.types.ts | 4 ++++ packages/vue/src/components/listbox/use-listbox.ts | 1 + packages/vue/src/components/marquee/marquee.types.ts | 4 ++++ packages/vue/src/components/marquee/use-marquee.ts | 1 + packages/vue/src/components/menu/menu.types.ts | 4 ++++ packages/vue/src/components/menu/use-menu.ts | 1 + .../popover/examples/multiple-triggers.vue | 7 ++++--- packages/vue/src/components/popover/popover.types.ts | 4 ++++ packages/vue/src/components/popover/use-popover.ts | 1 + .../components/toggle-group/examples/controlled.vue | 2 +- .../tooltip/examples/multiple-triggers.vue | 7 ++++--- packages/vue/src/components/tooltip/tooltip.types.ts | 4 ++++ packages/vue/src/components/tooltip/use-tooltip.ts | 1 + 27 files changed, 100 insertions(+), 19 deletions(-) create mode 100644 .changeset/vue-controlled-vmodel-emits.md create mode 100644 .changeset/vue-file-upload-accepted-files.md diff --git a/.changeset/vue-controlled-vmodel-emits.md b/.changeset/vue-controlled-vmodel-emits.md new file mode 100644 index 0000000000..478c994e7c --- /dev/null +++ b/.changeset/vue-controlled-vmodel-emits.md @@ -0,0 +1,7 @@ +--- +'@ark-ui/vue': patch +--- + +Fixed missing `v-model` emit wiring for `Drawer` (`open`, `snapPoint`), `Listbox` (`highlightedValue`), `Marquee` +(`paused`), `DateInput` (`placeholderValue`), and `triggerValue` on Dialog, Drawer, HoverCard, Menu, Popover, and +Tooltip. diff --git a/.changeset/vue-file-upload-accepted-files.md b/.changeset/vue-file-upload-accepted-files.md new file mode 100644 index 0000000000..12bfeb6a5a --- /dev/null +++ b/.changeset/vue-file-upload-accepted-files.md @@ -0,0 +1,5 @@ +--- +'@ark-ui/vue': patch +--- + +Fixed `FileUpload.Root` ignoring the controlled `acceptedFiles` prop. diff --git a/packages/vue/src/components/date-input/date-input.types.ts b/packages/vue/src/components/date-input/date-input.types.ts index 86aa83db82..4a662df98e 100644 --- a/packages/vue/src/components/date-input/date-input.types.ts +++ b/packages/vue/src/components/date-input/date-input.types.ts @@ -120,6 +120,10 @@ export type RootEmits = { * Function invoked when the focused segment changes. */ focusChange: [details: dateInput.FocusChangeDetails] + /** + * Function invoked when the placeholder value changes. + */ + placeholderChange: [details: dateInput.PlaceholderChangeDetails] /** * Function invoked when the selected value changes. */ @@ -128,4 +132,8 @@ export type RootEmits = { * The callback fired when the model value changes. */ 'update:modelValue': [value: dateInput.DateValue[]] + /** + * The callback fired when the placeholder value changes. + */ + 'update:placeholderValue': [placeholderValue: dateInput.DateValue] } diff --git a/packages/vue/src/components/date-input/use-date-input.ts b/packages/vue/src/components/date-input/use-date-input.ts index e395a884c2..5f6957254c 100644 --- a/packages/vue/src/components/date-input/use-date-input.ts +++ b/packages/vue/src/components/date-input/use-date-input.ts @@ -34,6 +34,11 @@ export const useDateInput = (props: MaybeRef = {}, emit?: Emi emit?.('focusChange', details) localeProps.onFocusChange?.(details) }, + onPlaceholderChange: (details) => { + emit?.('placeholderChange', details) + emit?.('update:placeholderValue', details.placeholderValue) + localeProps.onPlaceholderChange?.(details) + }, onValueChange: (details) => { emit?.('valueChange', details) emit?.('update:modelValue', details.value) diff --git a/packages/vue/src/components/dialog/dialog.types.ts b/packages/vue/src/components/dialog/dialog.types.ts index 8243fcfbf7..64ef5d8714 100644 --- a/packages/vue/src/components/dialog/dialog.types.ts +++ b/packages/vue/src/components/dialog/dialog.types.ts @@ -134,4 +134,8 @@ export type RootEmits = { * The callback fired when the open state changes. */ 'update:open': [open: boolean] + /** + * The callback fired when the trigger value changes. + */ + 'update:triggerValue': [triggerValue: string | null] } diff --git a/packages/vue/src/components/dialog/examples/multiple-triggers.vue b/packages/vue/src/components/dialog/examples/multiple-triggers.vue index 46de5d455a..4bf18e58de 100644 --- a/packages/vue/src/components/dialog/examples/multiple-triggers.vue +++ b/packages/vue/src/components/dialog/examples/multiple-triggers.vue @@ -1,7 +1,7 @@