diff --git a/docs/app/components/content/examples/input-number/InputNumberWithoutButtonsExample.vue b/docs/app/components/content/examples/input-number/InputNumberWithoutButtonsExample.vue new file mode 100644 index 0000000000..1dc24d30c5 --- /dev/null +++ b/docs/app/components/content/examples/input-number/InputNumberWithoutButtonsExample.vue @@ -0,0 +1,11 @@ + + + diff --git a/docs/content/docs/2.components/input-number.md b/docs/content/docs/2.components/input-number.md index 1ae62cfc6e..97dde5648e 100644 --- a/docs/content/docs/2.components/input-number.md +++ b/docs/content/docs/2.components/input-number.md @@ -248,6 +248,16 @@ name: 'input-number-currency-example' --- :: +### Without buttons + +You can use the `increment` and `decrement` props to control visibility of the buttons. + +::component-example +--- +name: 'input-number-without-buttons-example' +--- +:: + ### Within a FormField You can use the InputNumber within a [FormField](/docs/components/form-field) component to display a label, help text, required indicator, etc. diff --git a/docs/nuxt.config.ts b/docs/nuxt.config.ts index 9d28da69e2..8b6d965913 100644 --- a/docs/nuxt.config.ts +++ b/docs/nuxt.config.ts @@ -183,7 +183,7 @@ export default defineNuxtConfig({ vite: { optimizeDeps: { // prevents reloading page when navigating between components - include: ['@internationalized/date', '@vueuse/shared', '@vueuse/integrations/useFuse', '@tanstack/vue-table', 'reka-ui', 'reka-ui/namespaced', 'embla-carousel-vue', 'embla-carousel-autoplay', 'embla-carousel-auto-scroll', 'embla-carousel-auto-height', 'embla-carousel-class-names', 'embla-carousel-fade', 'embla-carousel-wheel-gestures', 'colortranslator', 'tailwindcss/colors', 'tailwind-variants', 'ufo', 'zod', 'vaul-vue', 'scule', 'motion-v', 'json5', 'ohash', 'shiki-transformer-color-highlight'] + include: ['@ai-sdk/vue', '@internationalized/date', '@nuxt/content/utils', '@tanstack/vue-table', '@vercel/analytics/nuxt', '@vercel/speed-insights/nuxt', '@vue/devtools-core', '@vue/devtools-kit', '@vueuse/integrations/useFuse', '@vueuse/shared', 'ai', 'colortranslator', 'embla-carousel-auto-height', 'embla-carousel-auto-scroll', 'embla-carousel-autoplay', 'embla-carousel-class-names', 'embla-carousel-fade', 'embla-carousel-vue', 'embla-carousel-wheel-gestures', 'json5', 'motion-v', 'ohash', 'ohash/utils', 'prettier', 'reka-ui', 'reka-ui/namespaced', 'scule', 'shiki', 'shiki-stream/vue', 'shiki-transformer-color-highlight', 'shiki/engine-javascript.mjs', 'tailwind-variants', 'tailwindcss/colors', 'ufo', 'vaul-vue', 'zod'] } }, diff --git a/playgrounds/nuxt/nuxt.config.ts b/playgrounds/nuxt/nuxt.config.ts index 1600fdab7e..a8af836933 100644 --- a/playgrounds/nuxt/nuxt.config.ts +++ b/playgrounds/nuxt/nuxt.config.ts @@ -14,7 +14,7 @@ export default defineNuxtConfig({ vite: { optimizeDeps: { // prevents reloading page when navigating between components - include: ['@internationalized/date', '@vueuse/shared', '@vueuse/integrations/useFuse', '@tanstack/vue-table', 'reka-ui', 'reka-ui/namespaced', 'embla-carousel-vue', 'embla-carousel-autoplay', 'embla-carousel-auto-scroll', 'embla-carousel-auto-height', 'embla-carousel-class-names', 'embla-carousel-fade', 'embla-carousel-wheel-gestures', 'colortranslator', 'tailwindcss/colors', 'tailwind-variants', 'ufo', 'zod', 'vaul-vue'] + include: ['@ai-sdk/vue', '@internationalized/date', '@tanstack/vue-table', '@tanstack/vue-virtual', '@vue/devtools-core', '@vue/devtools-kit', '@vueuse/core', '@vueuse/integrations/useFuse', '@vueuse/shared', 'colortranslator', 'embla-carousel-auto-height', 'embla-carousel-auto-scroll', 'embla-carousel-autoplay', 'embla-carousel-class-names', 'embla-carousel-fade', 'embla-carousel-vue', 'embla-carousel-wheel-gestures', 'ohash/utils', 'reka-ui', 'reka-ui/namespaced', 'scule', 'tailwind-variants', 'tailwindcss/colors', 'ufo', 'vaul-vue', 'zod'] } } }) diff --git a/src/runtime/components/InputNumber.vue b/src/runtime/components/InputNumber.vue index a865e9e039..e2f02a4f95 100644 --- a/src/runtime/components/InputNumber.vue +++ b/src/runtime/components/InputNumber.vue @@ -30,7 +30,7 @@ export interface InputNumberProps extends Pick(), { orientation: 'horizontal', - disabledIncrement: false, - disabledDecrement: false + increment: true, + decrement: true }) const emits = defineEmits() defineSlots() @@ -116,7 +116,9 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.inputNumber size: inputSize.value, highlight: highlight.value, orientation: props.orientation, - fieldGroup: orientation.value + fieldGroup: orientation.value, + increment: props.orientation === 'vertical' ? (!!props.increment || !!props.decrement) : !!props.increment, + decrement: props.orientation === 'vertical' ? false : !!props.decrement })) const incrementIcon = computed(() => props.incrementIcon || (props.orientation === 'horizontal' ? appConfig.ui.icons.plus : appConfig.ui.icons.chevronUp)) @@ -180,7 +182,7 @@ defineExpose({ @focus="emitFormFocus" /> -
+
-
+
) => { }, highlight: { true: '' + }, + increment: { + false: '' + }, + decrement: { + false: '' } }, compoundVariants: [...(options.theme.colors || []).map((color: string) => ({ @@ -67,42 +73,46 @@ export default (options: Required) => { class: 'ring ring-inset ring-inverted' }, { orientation: 'horizontal', + decrement: false, + class: 'text-start' + }, { + decrement: true, size: 'xs', - class: 'px-7' + class: 'ps-7' }, { - orientation: 'horizontal', + decrement: true, size: 'sm', - class: 'px-8' + class: 'ps-8' }, { - orientation: 'horizontal', + decrement: true, size: 'md', - class: 'px-9' + class: 'ps-9' }, { - orientation: 'horizontal', + decrement: true, size: 'lg', - class: 'px-10' + class: 'ps-10' }, { - orientation: 'horizontal', + decrement: true, size: 'xl', - class: 'px-11' + class: 'ps-11' }, { - orientation: 'vertical', + increment: true, size: 'xs', class: 'pe-7' }, { - orientation: 'vertical', + increment: true, size: 'sm', class: 'pe-8' }, { - orientation: 'vertical', + increment: true, size: 'md', class: 'pe-9' }, { - orientation: 'vertical', + increment: true, size: 'lg', class: 'pe-10' }, { - orientation: 'vertical', + increment: true, size: 'xl', class: 'pe-11' }], diff --git a/test/components/InputNumber.spec.ts b/test/components/InputNumber.spec.ts index ff56016866..cc4ef654ff 100644 --- a/test/components/InputNumber.spec.ts +++ b/test/components/InputNumber.spec.ts @@ -23,14 +23,20 @@ describe('InputNumber', () => { ['with orientation vertical', { props: { orientation: 'vertical' } }], ['with incrementIcon', { props: { incrementIcon: 'i-lucide-arrow-left' } }], ['with decrementIcon', { props: { decrementIcon: 'i-lucide-arrow-right' } }], + ['without increment', { props: { increment: false } }], + ['without increment vertical', { props: { increment: false, orientation: 'vertical' } }], + ['without decrement', { props: { decrement: false } }], + ['without decrement vertical', { props: { decrement: false, orientation: 'vertical' } }], + ['without increment and decrement', { props: { increment: false, decrement: false } }], + ['without increment and decrement vertical', { props: { increment: false, decrement: false, orientation: 'vertical' } }], ...sizes.map((size: string) => [`with size ${size}`, { props: { size } }]), ...variants.map((variant: string) => [`with primary variant ${variant}`, { props: { variant } }]), ...variants.map((variant: string) => [`with neutral variant ${variant}`, { props: { variant, color: 'neutral' } }]), ['with ariaLabel', { attrs: { 'aria-label': 'Aria label' } }], + ['with .optional modifier', { props: { modelModifiers: { optional: true } } }, { input: '', expected: undefined }], ['with as', { props: { as: 'section' } }], ['with class', { props: { class: 'absolute' } }], ['with ui', { props: { ui: { base: 'rounded-full' } } }], - ['with .optional modifier', { props: { modelModifiers: { optional: true } } }, { input: '', expected: undefined }], // Slots ['with increment slot', { slots: { increment: () => '+' } }], ['with decrement slot', { slots: { decrement: () => '-' } }] diff --git a/test/components/__snapshots__/InputNumber-vue.spec.ts.snap b/test/components/__snapshots__/InputNumber-vue.spec.ts.snap index f49d7f68ae..b70e1f67db 100644 --- a/test/components/__snapshots__/InputNumber-vue.spec.ts.snap +++ b/test/components/__snapshots__/InputNumber-vue.spec.ts.snap @@ -1,7 +1,7 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`InputNumber > renders with .optional modifier correctly 1`] = ` -"
+"
" `; + +exports[`InputNumber > renders without decrement correctly 1`] = ` +"
+
+ + +
" +`; + +exports[`InputNumber > renders without decrement vertical correctly 1`] = ` +"
+
+ + +
" +`; + +exports[`InputNumber > renders without increment and decrement correctly 1`] = ` +"
+ + + +
" +`; + +exports[`InputNumber > renders without increment and decrement vertical correctly 1`] = ` +"
+ + + +
" +`; + +exports[`InputNumber > renders without increment correctly 1`] = ` +"
+ +
+ +
" +`; + +exports[`InputNumber > renders without increment vertical correctly 1`] = ` +"
+ +
+ +
" +`; diff --git a/test/components/__snapshots__/InputNumber.spec.ts.snap b/test/components/__snapshots__/InputNumber.spec.ts.snap index 5e287de339..d3db1af8f8 100644 --- a/test/components/__snapshots__/InputNumber.spec.ts.snap +++ b/test/components/__snapshots__/InputNumber.spec.ts.snap @@ -1,7 +1,7 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`InputNumber > renders with .optional modifier correctly 1`] = ` -"
+"
" `; + +exports[`InputNumber > renders without decrement correctly 1`] = ` +"
+
+ + +
" +`; + +exports[`InputNumber > renders without decrement vertical correctly 1`] = ` +"
+
+ + +
" +`; + +exports[`InputNumber > renders without increment and decrement correctly 1`] = ` +"
+ + + +
" +`; + +exports[`InputNumber > renders without increment and decrement vertical correctly 1`] = ` +"
+ + + +
" +`; + +exports[`InputNumber > renders without increment correctly 1`] = ` +"
+ +
+ +
" +`; + +exports[`InputNumber > renders without increment vertical correctly 1`] = ` +"
+ +
+ +
" +`;