mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-19 22:41:42 +01:00
feat(InputNumber): implement component (#2577)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
@@ -220,7 +220,7 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
|
||||
<template>
|
||||
<div class="my-5">
|
||||
<div>
|
||||
<div v-if="options.length" class="flex items-center gap-2.5 border border-[var(--ui-color-neutral-200)] dark:border-[var(--ui-color-neutral-700)] border-b-0 relative rounded-t-[calc(var(--ui-radius)*1.5)] px-4 py-2.5 overflow-x-auto">
|
||||
<div v-if="options.length" class="flex items-center gap-2.5 border border-[var(--ui-border-muted)] border-b-0 relative rounded-t-[calc(var(--ui-radius)*1.5)] px-4 py-2.5 overflow-x-auto">
|
||||
<template v-for="option in options" :key="option.name">
|
||||
<UFormField
|
||||
:label="option.label"
|
||||
@@ -269,7 +269,7 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="component" class="flex justify-center border border-b-0 border-[var(--ui-color-neutral-200)] dark:border-[var(--ui-color-neutral-700)] relative p-4 z-[1]" :class="[!options.length && 'rounded-t-[calc(var(--ui-radius)*1.5)]', props.class]">
|
||||
<div v-if="component" class="flex justify-center border border-b-0 border-[var(--ui-border-muted)] relative p-4 z-[1]" :class="[!options.length && 'rounded-t-[calc(var(--ui-radius)*1.5)]', props.class]">
|
||||
<component :is="component" v-bind="{ ...componentProps, ...componentEvents }">
|
||||
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
|
||||
<MDCSlot :name="slot" unwrap="p">
|
||||
|
||||
@@ -117,8 +117,8 @@ const optionsValues = ref(props.options?.reduce((acc, option) => {
|
||||
<template>
|
||||
<div class="my-5">
|
||||
<template v-if="preview">
|
||||
<div class="border border-[var(--ui-color-neutral-200)] dark:border-[var(--ui-color-neutral-700)] relative z-[1]" :class="[{ 'border-b-0 rounded-t-[calc(var(--ui-radius)*1.5)]': props.source, 'rounded-[calc(var(--ui-radius)*1.5)]': !props.source }]">
|
||||
<div v-if="props.options?.length || !!slots.options" class="flex gap-4 p-4 border-b border-[var(--ui-color-neutral-200)] dark:border-[var(--ui-color-neutral-700)]">
|
||||
<div class="border border-[var(--ui-border-muted)] relative z-[1]" :class="[{ 'border-b-0 rounded-t-[calc(var(--ui-radius)*1.5)]': props.source, 'rounded-[calc(var(--ui-radius)*1.5)]': !props.source }]">
|
||||
<div v-if="props.options?.length || !!slots.options" class="flex gap-4 p-4 border-b border-[var(--ui-border-muted)]">
|
||||
<slot name="options" />
|
||||
|
||||
<UFormField
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { FormSubmitEvent } from '@nuxt/ui'
|
||||
|
||||
const schema = z.object({
|
||||
input: z.string().min(10),
|
||||
inputNumber: z.number().min(10),
|
||||
inputMenu: z.any().refine(option => option?.value === 'option-2', {
|
||||
message: 'Select Option 2'
|
||||
}),
|
||||
@@ -56,7 +57,7 @@ async function onSubmit(event: FormSubmitEvent<any>) {
|
||||
<UForm ref="form" :state="state" :schema="schema" class="w-full" @submit="onSubmit">
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<UFormField label="Input" name="input">
|
||||
<UInput v-model="state.input" placeholder="john@lennon.com" class="w-40" />
|
||||
<UInput v-model="state.input" placeholder="john@lennon.com" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
@@ -74,37 +75,37 @@ async function onSubmit(event: FormSubmitEvent<any>) {
|
||||
</UFormField>
|
||||
|
||||
<UFormField name="select" label="Select">
|
||||
<USelect v-model="state.select" :items="items" class="w-48" />
|
||||
<USelect v-model="state.select" :items="items" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField name="selectMenu" label="Select Menu">
|
||||
<USelectMenu v-model="state.selectMenu" :items="items" class="w-48" />
|
||||
<USelectMenu v-model="state.selectMenu" :items="items" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField name="selectMenuMultiple" label="Select Menu (Multiple)">
|
||||
<USelectMenu v-model="state.selectMenuMultiple" multiple :items="items" class="w-48" />
|
||||
<USelectMenu v-model="state.selectMenuMultiple" multiple :items="items" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField name="inputMenu" label="Input Menu">
|
||||
<UInputMenu v-model="state.inputMenu" :items="items" />
|
||||
<UInputMenu v-model="state.inputMenu" :items="items" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField name="inputMenuMultiple" label="Input Menu (Multiple)">
|
||||
<UInputMenu v-model="state.inputMenuMultiple" multiple :items="items" />
|
||||
<UInputMenu v-model="state.inputMenuMultiple" multiple :items="items" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<span />
|
||||
<UFormField name="inputNumber" label="Input Number">
|
||||
<UInputNumber v-model="state.inputNumber" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField label="Textarea" name="textarea">
|
||||
<UTextarea v-model="state.textarea" />
|
||||
<UTextarea v-model="state.textarea" class="w-full" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField name="radioGroup">
|
||||
<URadioGroup v-model="state.radioGroup" legend="Radio group" :items="items" />
|
||||
</UFormField>
|
||||
|
||||
<span />
|
||||
|
||||
<UFormField name="pin" label="Pin Input" :error-pattern="/(pin)\..*/">
|
||||
<UPinInput v-model="state.pin" />
|
||||
</UFormField>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(1500)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UInputNumber
|
||||
v-model="value"
|
||||
:format-options="{
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
currencyDisplay: 'code',
|
||||
currencySign: 'accounting'
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(5)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UInputNumber
|
||||
v-model="value"
|
||||
:format-options="{
|
||||
signDisplay: 'exceptZero',
|
||||
minimumFractionDigits: 1
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
const retries = ref(0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UFormField label="Retries" help="Specify number of attempts" required>
|
||||
<UInputNumber v-model="retries" placeholder="Enter retries" />
|
||||
</UFormField>
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(0.05)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UInputNumber
|
||||
v-model="value"
|
||||
:step="0.01"
|
||||
:format-options="{
|
||||
style: 'percent'
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(5)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UInputNumber v-model="value">
|
||||
<template #decrement>
|
||||
<UButton size="xs" icon="i-lucide-minus" />
|
||||
</template>
|
||||
|
||||
<template #increment>
|
||||
<UButton size="xs" icon="i-lucide-plus" />
|
||||
</template>
|
||||
</UInputNumber>
|
||||
</template>
|
||||
@@ -6,7 +6,7 @@ const value = ref('Click to clear')
|
||||
<UInput
|
||||
v-model="value"
|
||||
placeholder="Type something..."
|
||||
:ui="{ trailing: 'pr-0.5' }"
|
||||
:ui="{ trailing: 'pe-1' }"
|
||||
>
|
||||
<template v-if="value?.length" #trailing>
|
||||
<UButton
|
||||
|
||||
@@ -40,7 +40,7 @@ const text = computed(() => {
|
||||
placeholder="Password"
|
||||
:color="color"
|
||||
:type="show ? 'text' : 'password'"
|
||||
:ui="{ trailing: 'pr-0.5' }"
|
||||
:ui="{ trailing: 'pe-1' }"
|
||||
:aria-invalid="score < 4"
|
||||
aria-describedby="password-strength"
|
||||
class="w-full"
|
||||
|
||||
@@ -8,7 +8,7 @@ const password = ref('password')
|
||||
v-model="password"
|
||||
placeholder="Password"
|
||||
:type="show ? 'text' : 'password'"
|
||||
:ui="{ trailing: 'pr-0.5' }"
|
||||
:ui="{ trailing: 'pe-1' }"
|
||||
>
|
||||
<template #trailing>
|
||||
<UButton
|
||||
|
||||
@@ -67,7 +67,7 @@ class: 'p-8'
|
||||
|
||||
### Prev / Next
|
||||
|
||||
Use the `prev` and `next` props to customize the prev and next buttons.
|
||||
Use the `prev` and `next` props to customize the prev and next buttons with any [Button](/components/button) props.
|
||||
|
||||
::component-example
|
||||
---
|
||||
@@ -76,7 +76,7 @@ class: 'p-8'
|
||||
---
|
||||
::
|
||||
|
||||
### Prev Icon / Next Icon
|
||||
### Prev / Next Icons
|
||||
|
||||
Use the `prev-icon` and `next-icon` props to customize the buttons [Icon](/components/icon). Defaults to `i-lucide-arrow-left` / `i-lucide-arrow-right`.
|
||||
|
||||
|
||||
291
docs/content/3.components/input-number.md
Normal file
291
docs/content/3.components/input-number.md
Normal file
@@ -0,0 +1,291 @@
|
||||
---
|
||||
title: InputNumber
|
||||
description: Input numerical values with a customizable range.
|
||||
links:
|
||||
- label: Number Field
|
||||
icon: i-custom-radix-vue
|
||||
to: https://www.radix-vue.com/components/number-field
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/InputNumber.vue
|
||||
navigation.badge: New
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `v-model` directive to control the value of the InputNumber.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
---
|
||||
::
|
||||
|
||||
Use the `default-value` prop to set the initial value when you do not need to control its state.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- defaultValue
|
||||
props:
|
||||
defaultValue: 5
|
||||
---
|
||||
::
|
||||
|
||||
### Min / Max
|
||||
|
||||
Use the `min` and `max` props to set the minimum and maximum values of the InputNumber.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
min: 0
|
||||
max: 10
|
||||
---
|
||||
::
|
||||
|
||||
### Step
|
||||
|
||||
Use the `step` prop to set the step value of the InputNumber.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
step: 2
|
||||
---
|
||||
::
|
||||
|
||||
### Orientation
|
||||
|
||||
Use the `orientation` prop to change the orientation of the InputNumber.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
orientation: vertical
|
||||
---
|
||||
::
|
||||
|
||||
### Placeholder
|
||||
|
||||
Use the `placeholder` prop to set a placeholder text.
|
||||
|
||||
::component-code
|
||||
---
|
||||
props:
|
||||
placeholder: 'Enter a number'
|
||||
---
|
||||
::
|
||||
|
||||
### Color
|
||||
|
||||
Use the `color` prop to change the ring color when the InputNumber is focused.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
color: neutral
|
||||
highlight: true
|
||||
---
|
||||
::
|
||||
|
||||
### Variant
|
||||
|
||||
Use the `variant` prop to change the variant of the InputNumber.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
variant: subtle
|
||||
color: neutral
|
||||
highlight: false
|
||||
---
|
||||
::
|
||||
|
||||
### Size
|
||||
|
||||
Use the `size` prop to change the size of the InputNumber.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
size: xl
|
||||
---
|
||||
::
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable the InputNumber.
|
||||
|
||||
::component-code
|
||||
---
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
disabled: true
|
||||
---
|
||||
::
|
||||
|
||||
### Increment / Decrement
|
||||
|
||||
Use the `increment` and `decrement` props to customize the increment and decrement buttons with any [Button](/components/button) props. Defaults to `{ variant: 'link' }`{lang="ts-type"}.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
ignore:
|
||||
- modelValue
|
||||
- increment.size
|
||||
- increment.color
|
||||
- increment.variant
|
||||
- decrement.size
|
||||
- decrement.color
|
||||
- decrement.variant
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
increment:
|
||||
color: neutral
|
||||
variant: solid
|
||||
size: xs
|
||||
decrement:
|
||||
color: neutral
|
||||
variant: solid
|
||||
size: xs
|
||||
---
|
||||
::
|
||||
|
||||
### Increment / Decrement Icons
|
||||
|
||||
Use the `increment-icon` and `decrement-icon` props to customize the buttons [Icon](/components/icon). Defaults to `i-lucide-plus` / `i-lucide-minus`.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: 5
|
||||
incrementIcon: 'i-lucide-arrow-right'
|
||||
decrementIcon: 'i-lucide-arrow-left'
|
||||
---
|
||||
::
|
||||
|
||||
## Examples
|
||||
|
||||
### With decimal format
|
||||
|
||||
Use the `format-options` prop to customize the format of the value.
|
||||
|
||||
::component-example
|
||||
---
|
||||
name: 'input-number-decimal-example'
|
||||
---
|
||||
::
|
||||
|
||||
### With percentage format
|
||||
|
||||
Use the `format-options` prop with `style: 'percent'` to customize the format of the value.
|
||||
|
||||
::component-example
|
||||
---
|
||||
name: 'input-number-percentage-example'
|
||||
---
|
||||
::
|
||||
|
||||
### With currency format
|
||||
|
||||
Use the `format-options` prop with `style: 'currency'` to customize the format of the value.
|
||||
|
||||
::component-example
|
||||
---
|
||||
name: 'input-number-currency-example'
|
||||
---
|
||||
::
|
||||
|
||||
### Within a FormField
|
||||
|
||||
You can use the InputNumber within a [FormField](/components/form-field) component to display a label, help text, required indicator, etc.
|
||||
|
||||
::component-example
|
||||
---
|
||||
name: 'input-number-form-field-example'
|
||||
---
|
||||
::
|
||||
|
||||
### With slots
|
||||
|
||||
Use the `#increment` and `#decrement` slots to customize the buttons.
|
||||
|
||||
::component-example
|
||||
---
|
||||
name: 'input-number-slots-example'
|
||||
---
|
||||
::
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
:component-props
|
||||
|
||||
### Slots
|
||||
|
||||
:component-slots
|
||||
|
||||
### Emits
|
||||
|
||||
:component-emits
|
||||
|
||||
### Expose
|
||||
|
||||
When accessing the component via a template ref, you can use the following:
|
||||
|
||||
| Name | Type |
|
||||
|----------------------------|-------------------------------------------------|
|
||||
| `inputRef`{lang="ts-type"} | `Ref<HTMLInputElement \| null>`{lang="ts-type"} |
|
||||
|
||||
## Theme
|
||||
|
||||
:component-theme
|
||||
@@ -25,15 +25,15 @@ props:
|
||||
|
||||
Use the `type` prop to change the input type. Defaults to `text`.
|
||||
|
||||
Some types have been implemented in their own components such as [Checkbox](/components/checkbox), [Radio](/components/radio-group), etc. and others have been styled like `file` for example.
|
||||
Some types have been implemented in their own components such as [Checkbox](/components/checkbox), [Radio](/components/radio-group), [InputNumber](/components/input-number) etc. and others have been styled like `file` for example.
|
||||
|
||||
::component-code
|
||||
---
|
||||
items:
|
||||
type:
|
||||
- text
|
||||
- password
|
||||
- number
|
||||
- password
|
||||
- search
|
||||
- file
|
||||
props:
|
||||
|
||||
@@ -5,6 +5,7 @@ links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/PinInput.vue
|
||||
navigation.badge: New
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Reference in New Issue
Block a user