InputTime

Um input para selecionar um horário.

Uso

Use a diretiva v-model para controlar o horário selecionado.

12
30
PM
<script setup lang="ts">
import { Time } from '@internationalized/date'

const value = shallowRef(new Time(12, 30, 0))
</script>

<template>
  <NInputTime v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { Time } from '@internationalized/date'

const value = shallowRef(new Time(12, 30, 0))
</script>

<template>
  <NInputTime v-model="value" />
</template>

Use a prop default-value para definir o valor inicial quando você não precisa controlar o estado.

9
45
AM
<script setup lang="ts">
import { Time } from '@internationalized/date'

const defaultValue = shallowRef(new Time(9, 45, 0))
</script>

<template>
  <NInputTime :default-value="defaultValue" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { Time } from '@internationalized/date'

const defaultValue = shallowRef(new Time(9, 45, 0))
</script>

<template>
  <NInputTime :default-value="defaultValue" />
</template>
Este componente usa o pacote @internationalized/date para formatação sensível ao locale. O formato da hora é determinado pela prop locale do componente App.
Este componente usa o pacote @internationalized/date para formatação sensível ao locale. O formato da hora é determinado pela prop locale do componente App.

Intervalo

Use a prop range para habilitar a seleção de intervalo de horários, com horário inicial e final.

9
00
AM
5
30
PM
<script setup lang="ts">
import { Time } from '@internationalized/date'

const value = shallowRef({ start: new Time(9, 0, 0), end: new Time(17, 30, 0) })
</script>

<template>
  <NInputTime range v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { Time } from '@internationalized/date'

const value = shallowRef({ start: new Time(9, 0, 0), end: new Time(17, 30, 0) })
</script>

<template>
  <NInputTime range v-model="value" />
</template>

Ciclo de horas

Use a prop hour-cycle para alterar o ciclo de horas do InputTime. O padrão é 12.

16
30
<script setup lang="ts">
import { Time } from '@internationalized/date'

const defaultValue = shallowRef(new Time(16, 30, 0))
</script>

<template>
  <NInputTime :hour-cycle="24" :default-value="defaultValue" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { Time } from '@internationalized/date'

const defaultValue = shallowRef(new Time(16, 30, 0))
</script>

<template>
  <NInputTime :hour-cycle="24" :default-value="defaultValue" />
</template>

Cor

Use a prop color para alterar a cor do InputTime.

––
––
AM
<template>
  <NInputTime color="neutral" highlight />
</template>
A prop highlight é usada aqui para mostrar o estado de foco. Ela é usada internamente quando ocorre um erro de validação.

Variante

Use a prop variant para alterar a variante do InputTime.

––
––
AM
<template>
  <NInputTime variant="subtle" />
</template>

Tamanho

Use a prop size para alterar o tamanho do InputTime.

––
––
AM
<template>
  <NInputTime size="xl" />
</template>

Ícone

Use a prop icon para exibir um Icon dentro do InputTime.

––
––
AM
<template>
  <NInputTime icon="i-lucide-clock" />
</template>
Use as props leading e trailing para definir a posição do ícone ou as props leading-icon e trailing-icon para definir um ícone diferente para cada posição.

Ícone de separador

Use a prop separator-icon para alterar o Icon do separador de intervalo. O padrão é i-lucide-minus.

––
––
AM
––
––
AM
<template>
  <NInputTime range separator-icon="i-lucide-arrow-right" />
</template>
Você pode personalizar esse ícone globalmente no seu app.config.ts na chave ui.icons.minus.
Você pode personalizar esse ícone globalmente no seu vite.config.ts na chave ui.icons.minus.

Avatar

Use a prop avatar para exibir um Avatar dentro do InputTime.

––
––
AM
<template>
  <NInputTime
    :avatar="{
      src: 'https://github.com/vuejs.png',
      loading: 'lazy'
    }"
    size="md"
    variant="outline"
  />
</template>

Desabilitado

Use a prop disabled para desabilitar o InputTime.

––
––
AM
<template>
  <NInputTime disabled />
</template>

Exemplos

Dentro de um FormField

Você pode usar o InputTime dentro de um componente FormField para exibir um rótulo, texto de ajuda, indicador de obrigatório, etc.

12
30
PM
Especifique o horário

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

color'primary' "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error" | "neutral"
variant'outline' "outline" | "soft" | "subtle" | "ghost" | "none"
size'md' "xs" | "sm" | "md" | "lg" | "xl"
highlightboolean

Highlight the ring color like a focus state.

fixedboolean

Keep the mobile text size on all breakpoints.

autofocusboolean
autofocusDelay0 number
separatorIconappConfig.ui.icons.minusany

The icon to use as a range separator.

rangefalse R

Enable time range selection.

defaultValueTime | CalendarDateTime | ZonedDateTime
modelValuenull | Time | CalendarDateTime | ZonedDateTime
iconany

Display an icon based on the leading and trailing props.

avatar AvatarProps

Display an avatar on the left side.

leadingboolean

When true, the icon will be displayed on the left side.

leadingIconany

Display an icon on the left side.

trailingboolean

When true, the icon will be displayed on the right side.

trailingIconany

Display an icon on the right side.

loadingboolean

When true, the loading icon will be displayed.

loadingIconappConfig.ui.icons.loadingany

The icon when the loading prop is true.

defaultPlaceholderTime | CalendarDateTime | ZonedDateTime
placeholderTime | CalendarDateTime | ZonedDateTime
hourCycle 12 | 24

The hour cycle used for formatting times. Defaults to the local preference

step DateStep

The stepping interval for the time fields. Defaults to 1.

stepSnappingboolean

Whether to enforce snapping the value to the nearest step increment after input. Defaults to false.

granularity "hour" | "minute" | "second"

The granularity to use for formatting times. Defaults to minute if a Time is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity

hideTimeZoneboolean

Whether or not to hide the time zone segment of the field

maxValueTime | CalendarDateTime | ZonedDateTime
minValueTime | CalendarDateTime | ZonedDateTime
locale string

The locale to use for formatting dates

disabledboolean

Whether or not the time field is disabled

readonlyboolean

Whether or not the time field is readonly

id string

Id of the element

name string

The name of the field. Submitted with its owning form as part of a name/value pair.

requiredboolean

When true, indicates that the user must set the value before the owning form can be submitted.

isTimeUnavailable (date: DateValue): boolean

A function that returns whether or not a time is unavailable

ui { base?: SlotClass; leading?: SlotClass; leadingIcon?: SlotClass; leadingAvatar?: SlotClass; leadingAvatarSize?: SlotClass; trailing?: SlotClass; trailingIcon?: SlotClass; segment?: SlotClass; separatorIcon?: SlotClass; }

Slots

Slot Type
leading{ ui: object; }
default{ ui: object; }
trailing{ ui: object; }
separator{ ui: object; }

Emits

Event Type
update:modelValue[value: InputTimeModelValue<R>]
update:placeholder[date: TimeValue] & [date: TimeValue]
change[event: Event]
blur[event: FocusEvent]
focus[event: FocusEvent]

Tema

app.config.ts
export default defineAppConfig({
  ui: {
    inputTime: {
      slots: {
        base: [
          'group relative inline-flex items-center rounded-md select-none',
          'transition-colors'
        ],
        leading: 'absolute inset-y-0 start-0 flex items-center',
        leadingIcon: 'shrink-0 text-dimmed',
        leadingAvatar: 'shrink-0',
        leadingAvatarSize: '',
        trailing: 'absolute inset-y-0 end-0 flex items-center',
        trailingIcon: 'shrink-0 text-dimmed',
        segment: [
          'rounded text-center outline-hidden data-placeholder:text-dimmed data-[segment=literal]:text-muted data-invalid:text-error data-disabled:cursor-not-allowed data-disabled:opacity-75',
          'transition-colors'
        ],
        separatorIcon: 'shrink-0 size-4 text-muted'
      },
      variants: {
        fieldGroup: {
          horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
          vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
        },
        size: {
          xs: {
            base: [
              'px-2 py-1 text-sm/4 gap-1',
              'gap-0.25'
            ],
            leading: 'ps-2',
            trailing: 'pe-2',
            leadingIcon: 'size-4',
            leadingAvatarSize: '3xs',
            trailingIcon: 'size-4',
            segment: 'not-data-[segment=literal]:w-8'
          },
          sm: {
            base: [
              'px-2.5 py-1.5 text-sm/4 gap-1.5',
              'gap-0.5'
            ],
            leading: 'ps-2.5',
            trailing: 'pe-2.5',
            leadingIcon: 'size-4',
            leadingAvatarSize: '3xs',
            trailingIcon: 'size-4',
            segment: 'not-data-[segment=literal]:w-8'
          },
          md: {
            base: [
              'px-2.5 py-1.5 text-base/5 gap-1.5',
              'gap-0.5'
            ],
            leading: 'ps-2.5',
            trailing: 'pe-2.5',
            leadingIcon: 'size-5',
            leadingAvatarSize: '2xs',
            trailingIcon: 'size-5',
            segment: 'not-data-[segment=literal]:w-9'
          },
          lg: {
            base: [
              'px-3 py-2 text-base/5 gap-2',
              'gap-0.75'
            ],
            leading: 'ps-3',
            trailing: 'pe-3',
            leadingIcon: 'size-5',
            leadingAvatarSize: '2xs',
            trailingIcon: 'size-5',
            segment: 'not-data-[segment=literal]:w-9'
          },
          xl: {
            base: [
              'px-3 py-2 text-base gap-2',
              'gap-0.75'
            ],
            leading: 'ps-3',
            trailing: 'pe-3',
            leadingIcon: 'size-6',
            leadingAvatarSize: 'xs',
            trailingIcon: 'size-6',
            segment: 'not-data-[segment=literal]:w-10'
          }
        },
        variant: {
          outline: 'text-highlighted bg-default ring ring-inset ring-accented',
          soft: 'text-highlighted bg-elevated/50 hover:bg-elevated has-focus:bg-elevated disabled:bg-elevated/50',
          subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
          ghost: 'text-highlighted bg-transparent hover:bg-elevated has-focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
          none: 'text-highlighted bg-transparent has-focus:outline-none'
        },
        color: {
          primary: '',
          secondary: '',
          accent: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        leading: {
          true: ''
        },
        trailing: {
          true: ''
        },
        loading: {
          true: ''
        },
        highlight: {
          true: ''
        },
        fixed: {
          false: ''
        },
        type: {
          file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none'
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'outline-primary/25 has-focus-visible:outline-3 has-focus-visible:ring-primary'
        },
        {
          color: 'primary',
          variant: [
            'soft',
            'ghost'
          ],
          class: 'outline-primary/25 has-focus-visible:outline-3'
        },
        {
          color: 'primary',
          highlight: true,
          class: 'ring ring-inset ring-primary'
        },
        {
          color: 'neutral',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'outline-inverted/25 has-focus-visible:outline-3 has-focus-visible:ring-inverted'
        },
        {
          color: 'neutral',
          variant: [
            'soft',
            'ghost'
          ],
          class: 'outline-inverted/25 has-focus-visible:outline-3'
        },
        {
          color: 'neutral',
          highlight: true,
          class: 'ring ring-inset ring-inverted'
        },
        {
          leading: true,
          size: 'xs',
          class: 'ps-7'
        },
        {
          leading: true,
          size: 'sm',
          class: 'ps-8'
        },
        {
          leading: true,
          size: 'md',
          class: 'ps-9'
        },
        {
          leading: true,
          size: 'lg',
          class: 'ps-10'
        },
        {
          leading: true,
          size: 'xl',
          class: 'ps-11'
        },
        {
          trailing: true,
          size: 'xs',
          class: 'pe-7'
        },
        {
          trailing: true,
          size: 'sm',
          class: 'pe-8'
        },
        {
          trailing: true,
          size: 'md',
          class: 'pe-9'
        },
        {
          trailing: true,
          size: 'lg',
          class: 'pe-10'
        },
        {
          trailing: true,
          size: 'xl',
          class: 'pe-11'
        },
        {
          loading: true,
          leading: true,
          class: {
            leadingIcon: 'animate-spin'
          }
        },
        {
          loading: true,
          leading: false,
          trailing: true,
          class: {
            trailingIcon: 'animate-spin'
          }
        },
        {
          fixed: false,
          size: 'xs',
          class: 'md:text-xs'
        },
        {
          fixed: false,
          size: 'sm',
          class: 'md:text-xs'
        },
        {
          fixed: false,
          size: 'md',
          class: 'md:text-sm'
        },
        {
          fixed: false,
          size: 'lg',
          class: 'md:text-sm'
        },
        {
          variant: 'outline',
          class: {
            segment: 'focus:bg-elevated'
          }
        },
        {
          variant: 'soft',
          class: {
            segment: 'focus:bg-accented/50 group-hover:focus:bg-accented'
          }
        },
        {
          variant: 'subtle',
          class: {
            segment: 'focus:bg-accented'
          }
        },
        {
          variant: 'ghost',
          class: {
            segment: 'focus:bg-elevated group-hover:focus:bg-accented'
          }
        },
        {
          variant: 'none',
          class: {
            segment: 'focus:bg-elevated'
          }
        }
      ],
      defaultVariants: {
        size: 'md',
        color: 'accent',
        variant: 'outline'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nitro/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        inputTime: {
          slots: {
            base: [
              'group relative inline-flex items-center rounded-md select-none',
              'transition-colors'
            ],
            leading: 'absolute inset-y-0 start-0 flex items-center',
            leadingIcon: 'shrink-0 text-dimmed',
            leadingAvatar: 'shrink-0',
            leadingAvatarSize: '',
            trailing: 'absolute inset-y-0 end-0 flex items-center',
            trailingIcon: 'shrink-0 text-dimmed',
            segment: [
              'rounded text-center outline-hidden data-placeholder:text-dimmed data-[segment=literal]:text-muted data-invalid:text-error data-disabled:cursor-not-allowed data-disabled:opacity-75',
              'transition-colors'
            ],
            separatorIcon: 'shrink-0 size-4 text-muted'
          },
          variants: {
            fieldGroup: {
              horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
              vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
            },
            size: {
              xs: {
                base: [
                  'px-2 py-1 text-sm/4 gap-1',
                  'gap-0.25'
                ],
                leading: 'ps-2',
                trailing: 'pe-2',
                leadingIcon: 'size-4',
                leadingAvatarSize: '3xs',
                trailingIcon: 'size-4',
                segment: 'not-data-[segment=literal]:w-8'
              },
              sm: {
                base: [
                  'px-2.5 py-1.5 text-sm/4 gap-1.5',
                  'gap-0.5'
                ],
                leading: 'ps-2.5',
                trailing: 'pe-2.5',
                leadingIcon: 'size-4',
                leadingAvatarSize: '3xs',
                trailingIcon: 'size-4',
                segment: 'not-data-[segment=literal]:w-8'
              },
              md: {
                base: [
                  'px-2.5 py-1.5 text-base/5 gap-1.5',
                  'gap-0.5'
                ],
                leading: 'ps-2.5',
                trailing: 'pe-2.5',
                leadingIcon: 'size-5',
                leadingAvatarSize: '2xs',
                trailingIcon: 'size-5',
                segment: 'not-data-[segment=literal]:w-9'
              },
              lg: {
                base: [
                  'px-3 py-2 text-base/5 gap-2',
                  'gap-0.75'
                ],
                leading: 'ps-3',
                trailing: 'pe-3',
                leadingIcon: 'size-5',
                leadingAvatarSize: '2xs',
                trailingIcon: 'size-5',
                segment: 'not-data-[segment=literal]:w-9'
              },
              xl: {
                base: [
                  'px-3 py-2 text-base gap-2',
                  'gap-0.75'
                ],
                leading: 'ps-3',
                trailing: 'pe-3',
                leadingIcon: 'size-6',
                leadingAvatarSize: 'xs',
                trailingIcon: 'size-6',
                segment: 'not-data-[segment=literal]:w-10'
              }
            },
            variant: {
              outline: 'text-highlighted bg-default ring ring-inset ring-accented',
              soft: 'text-highlighted bg-elevated/50 hover:bg-elevated has-focus:bg-elevated disabled:bg-elevated/50',
              subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
              ghost: 'text-highlighted bg-transparent hover:bg-elevated has-focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
              none: 'text-highlighted bg-transparent has-focus:outline-none'
            },
            color: {
              primary: '',
              secondary: '',
              accent: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            leading: {
              true: ''
            },
            trailing: {
              true: ''
            },
            loading: {
              true: ''
            },
            highlight: {
              true: ''
            },
            fixed: {
              false: ''
            },
            type: {
              file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none'
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'outline-primary/25 has-focus-visible:outline-3 has-focus-visible:ring-primary'
            },
            {
              color: 'primary',
              variant: [
                'soft',
                'ghost'
              ],
              class: 'outline-primary/25 has-focus-visible:outline-3'
            },
            {
              color: 'primary',
              highlight: true,
              class: 'ring ring-inset ring-primary'
            },
            {
              color: 'neutral',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'outline-inverted/25 has-focus-visible:outline-3 has-focus-visible:ring-inverted'
            },
            {
              color: 'neutral',
              variant: [
                'soft',
                'ghost'
              ],
              class: 'outline-inverted/25 has-focus-visible:outline-3'
            },
            {
              color: 'neutral',
              highlight: true,
              class: 'ring ring-inset ring-inverted'
            },
            {
              leading: true,
              size: 'xs',
              class: 'ps-7'
            },
            {
              leading: true,
              size: 'sm',
              class: 'ps-8'
            },
            {
              leading: true,
              size: 'md',
              class: 'ps-9'
            },
            {
              leading: true,
              size: 'lg',
              class: 'ps-10'
            },
            {
              leading: true,
              size: 'xl',
              class: 'ps-11'
            },
            {
              trailing: true,
              size: 'xs',
              class: 'pe-7'
            },
            {
              trailing: true,
              size: 'sm',
              class: 'pe-8'
            },
            {
              trailing: true,
              size: 'md',
              class: 'pe-9'
            },
            {
              trailing: true,
              size: 'lg',
              class: 'pe-10'
            },
            {
              trailing: true,
              size: 'xl',
              class: 'pe-11'
            },
            {
              loading: true,
              leading: true,
              class: {
                leadingIcon: 'animate-spin'
              }
            },
            {
              loading: true,
              leading: false,
              trailing: true,
              class: {
                trailingIcon: 'animate-spin'
              }
            },
            {
              fixed: false,
              size: 'xs',
              class: 'md:text-xs'
            },
            {
              fixed: false,
              size: 'sm',
              class: 'md:text-xs'
            },
            {
              fixed: false,
              size: 'md',
              class: 'md:text-sm'
            },
            {
              fixed: false,
              size: 'lg',
              class: 'md:text-sm'
            },
            {
              variant: 'outline',
              class: {
                segment: 'focus:bg-elevated'
              }
            },
            {
              variant: 'soft',
              class: {
                segment: 'focus:bg-accented/50 group-hover:focus:bg-accented'
              }
            },
            {
              variant: 'subtle',
              class: {
                segment: 'focus:bg-accented'
              }
            },
            {
              variant: 'ghost',
              class: {
                segment: 'focus:bg-elevated group-hover:focus:bg-accented'
              }
            },
            {
              variant: 'none',
              class: {
                segment: 'focus:bg-elevated'
              }
            }
          ],
          defaultVariants: {
            size: 'md',
            color: 'accent',
            variant: 'outline'
          }
        }
      }
    })
  ]
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitLab.

Changelog

No recent changes