组件

Input 输入框

在文本字段中获取用户输入。

用法

tsx
import { Input } from "@chakra-ui/react"
tsx
<Input />

示例

变体

使用 variant prop 可以更改输入框的视觉风格。

tsx
export const InputWithVariants = () => {
  return (
    <Stack gap="4">
      <Input placeholder="Subtle" variant="subtle" />
      <Input placeholder="Outline" variant="outline" />
      <Input placeholder="Flushed" variant="flushed" />
    </Stack>
  )
}

尺寸

使用 size prop 可以更改输入框的尺寸。

tsx
export const InputWithSizes = () => {
  return (
    <Stack gap="4">
      <Input placeholder="size (xs)" size="xs" />
      <Input placeholder="size (sm)" size="sm" />
      <Input placeholder="size (md)" size="md" />
      <Input placeholder="size (lg)" size="lg" />
    </Stack>
  )
}

帮助文本

将输入框与 Field 组件搭配使用可以添加帮助文本。

我们绝不会分享你的邮箱。
tsx
export const InputWithHelperText = () => {
  return (
    <Field.Root required>
      <Field.Label>
        邮箱 <Field.RequiredIndicator />
      </Field.Label>
      <Input placeholder="输入你的邮箱" />
      <Field.HelperText>我们绝不会分享你的邮箱。</Field.HelperText>
    </Field.Root>
  )
}

错误文本

将输入框与 Field 组件配合使用来显示错误文本。

此字段必填
tsx
export const InputWithErrorText = () => {
  return (
    <Field.Root invalid>
      <Field.Label>邮箱</Field.Label>
      <Input placeholder="输入你的邮箱" />
      <Field.ErrorText>此字段必填</Field.ErrorText>
    </Field.Root>
  )
}

Field 组合

将输入框与 Field 组件组合,可以添加标签、帮助文本和错误文本。

tsx
export const InputWithField = () => {
  return (
    <HStack gap="10" width="full">
      <Field.Root required>
        <Field.Label>
          邮箱 <Field.RequiredIndicator />
        </Field.Label>
        <Input placeholder="me@example.com" variant="subtle" />
      </Field.Root>
      <Field.Root required>
        <Field.Label>
          邮箱 <Field.RequiredIndicator />
        </Field.Label>
        <Input placeholder="me@example.com" variant="outline" />
      </Field.Root>
    </HStack>
  )
}

Hook Form

下面是如何将输入框与 react-hook-form 集成的示例。

tsx
interface FormValues {
  firstName: string
  lastName: string
}

export const InputWithHookForm = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormValues>()

  const onSubmit = handleSubmit((data) => console.log(data))

  return (
    <form onSubmit={onSubmit}>
      <Stack gap="4" align="flex-start" maxW="sm">
        <Field.Root invalid={!!errors.firstName}>
          <Field.Label></Field.Label>
          <Input {...register("firstName")} />
          <Field.ErrorText>{errors.firstName?.message}</Field.ErrorText>
        </Field.Root>

        <Field.Root invalid={!!errors.lastName}>
          <Field.Label></Field.Label>
          <Input {...register("lastName")} />
          <Field.ErrorText>{errors.lastName?.message}</Field.ErrorText>
        </Field.Root>

        <Button type="submit">提交</Button>
      </Stack>
    </form>
  )
}

import { Button, Field, Input, Stack } from "@chakra-ui/react"
import { useForm } from "react-hook-form"

元素(Element)

InputGroup 组件上使用 startElement endElement,可以在输入框的开头和结尾添加元素。

开头图标

tsx
export const InputWithStartIcon = () => {
  return (
    <InputGroup startElement={<LuUser />}>
      <Input placeholder="用户名" />
    </InputGroup>
  )
}

import { Input, InputGroup } from "@chakra-ui/react"
import { LuUser } from "react-icons/lu"

开头文本

https://
tsx
export const InputWithStartText = () => {
  return (
    <InputGroup
      startElement="https://"
      startElementProps={{ color: "fg.muted" }}
    >
      <Input ps="7ch" placeholder="yoursite.com" />
    </InputGroup>
  )
}

开头与结尾文本

$
USD
tsx
export const InputWithStartAndEndText = () => {
  return (
    <InputGroup startElement="$" endElement="USD">
      <Input placeholder="0.00" />
    </InputGroup>
  )
}

Kbd

⌘K
tsx
export const InputWithKbd = () => (
  <InputGroup flex="1" startElement={<LuSearch />} endElement={<Kbd>⌘K</Kbd>}>
    <Input placeholder="搜索联系人" />
  </InputGroup>
)

import { Input, InputGroup, Kbd } from "@chakra-ui/react"
import { LuSearch } from "react-icons/lu"

下拉选择

https://
tsx
const DomainSelect = () => (
  <NativeSelect.Root size="xs" variant="plain" width="auto" me="-1">
    <NativeSelect.Field defaultValue=".com" fontSize="sm">
      <option value=".com">.com</option>
      <option value=".org">.org</option>
      <option value=".net">.net</option>
    </NativeSelect.Field>
    <NativeSelect.Indicator />
  </NativeSelect.Root>
)

export const InputWithSelect = () => {
  return (
    <InputGroup flex="1" startElement="https://" endElement={<DomainSelect />}>
      <Input ps="4.75em" pe="0" placeholder="yoursite.com" />
    </InputGroup>
  )
}

附加组件(Addon)

使用 InputAddon Group 组件可以为输入框添加附加组件。

开头附加组件

https://
tsx
export const InputWithStartAddon = () => {
  return (
    <InputGroup startAddon="https://">
      <Input placeholder="yoursite.com" />
    </InputGroup>
  )
}

结尾附加组件

.com
tsx
export const InputWithEndAddon = () => {
  return (
    <InputGroup endAddon=".com">
      <Input placeholder="yoursite" />
    </InputGroup>
  )
}

开头与结尾附加组件

$
USD
tsx
export const InputWithStartAndEndAddon = () => {
  return (
    <InputGroup startAddon="$" endAddon="USD">
      <Input placeholder="0.00" />
    </InputGroup>
  )
}

禁用

使用 disabled prop 可以禁用输入框。

tsx
export const InputWithDisabled = () => {
  return <Input disabled placeholder="禁用" />
}

附加按钮

使用 Group 组件可以给输入框附加一个按钮。

tsx
export const InputWithEndButton = () => {
  return (
    <Group attached w="full" maxW="sm">
      <Input flex="1" placeholder="输入你的邮箱" />
      <Button bg="bg.subtle" variant="outline">
        提交
      </Button>
    </Group>
  )
}

import { Button, Group, Input } from "@chakra-ui/react"

焦点与错误颜色

使用 --focus-color --error-color CSS 自定义属性,可以更改输入框在聚焦或处于错误状态时的颜色。

tsx
export const InputWithFocusErrorColor = () => {
  return (
    <Stack gap="4">
      <Field.Root>
        <Field.Label>focusColor=lime</Field.Label>
        <Input placeholder="聚焦我" css={{ "--focus-color": "lime" }} />
      </Field.Root>
      <Field.Root invalid>
        <Field.Label>errorColor=green</Field.Label>
        <Input placeholder="邮箱" css={{ "--error-color": "green" }} />
      </Field.Root>
      <Field.Root invalid>
        <Field.Label>errorColor=blue</Field.Label>
        <Input placeholder="密码" css={{ "--error-color": "blue" }} />
      </Field.Root>

      <Field.Root invalid>
        <Field.Label>variant=outline,focusColor=error</Field.Label>
        <Input placeholder="聚焦我" variant="outline" />
      </Field.Root>
      <Field.Root invalid>
        <Field.Label>variant=subtle,focusColor=error</Field.Label>
        <Input placeholder="聚焦我" variant="subtle" />
      </Field.Root>
      <Field.Root invalid>
        <Field.Label>variant=flushed,focusColor=error</Field.Label>
        <Input placeholder="聚焦我" variant="flushed" />
      </Field.Root>
    </Stack>
  )
}

占位符样式

使用 _placeholder prop 可以设置占位符文本的样式。

tsx
export const InputWithPlaceholderStyle = () => {
  return (
    <Input
      color="teal"
      placeholder="自定义占位符"
      _placeholder={{ color: "inherit" }}
    />
  )
}

浮动标签

下面是一个为输入框构建浮动标签的示例。

tsx
export const InputWithFloatingLabel = () => {
  return (
    <Field.Root>
      <FloatingLabelInput label="邮箱" />
      <Field.ErrorText>此字段必填</Field.ErrorText>
    </Field.Root>
  )
}

interface FloatingLabelInputProps extends InputProps {
  label: ReactNode
  value?: string | undefined
  defaultValue?: string | undefined
  onValueChange?: ((value: string) => void) | undefined
}

const FloatingLabelInput = (props: FloatingLabelInputProps) => {
  const { label, onValueChange, value, defaultValue = "", ...rest } = props

  const [inputState, setInputState] = useControllableState({
    defaultValue,
    onChange: onValueChange,
    value,
  })

  const [focused, setFocused] = useState(false)
  const shouldFloat = inputState.length > 0 || focused

  return (
    <Box pos="relative" w="full">
      <Input
        {...rest}
        onFocus={(e) => {
          props.onFocus?.(e)
          setFocused(true)
        }}
        onBlur={(e) => {
          props.onBlur?.(e)
          setFocused(false)
        }}
        onChange={(e) => {
          props.onChange?.(e)
          setInputState(e.target.value)
        }}
        value={inputState}
        data-float={shouldFloat || undefined}
      />
      <Field.Label css={floatingStyles} data-float={shouldFloat || undefined}>
        {label}
      </Field.Label>
    </Box>
  )
}

import {
  Box,
  Field,
  Input,
  defineStyle,
  useControllableState,
} from "@chakra-ui/react"
import { useState } from "react"

掩码

下面是一个使用 use-mask-input 库为输入框形状添加掩码的示例。

tsx
export const InputWithMask = () => {
  return (
    <Input placeholder="(99) 99999-9999" ref={withMask("(99) 99999-9999")} />
  )
}

import { Input } from "@chakra-ui/react"
import { withMask } from "use-mask-input"

字符计数

下面是一个为输入框添加字符计数的示例。

0 / 20
tsx
const MAX_CHARACTERS = 20

export const InputWithCharacterCounter = () => {
  const [value, setValue] = useState("")
  return (
    <InputGroup
      endElement={
        <Span color="fg.muted" textStyle="xs">
          {value.length} / {MAX_CHARACTERS}
        </Span>
      }
    >
      <Input
        placeholder="输入你的消息"
        value={value}
        maxLength={MAX_CHARACTERS}
        onChange={(e) => {
          setValue(e.currentTarget.value.slice(0, MAX_CHARACTERS))
        }}
      />
    </InputGroup>
  )
}

import { Input, InputGroup, Span } from "@chakra-ui/react"
import { useState } from "react"

卡号

下面是一个使用 react-payment-inputs 创建卡号输入框的示例。

tsx
export const InputWithCardNumber = () => {
  const { wrapperProps, getCardNumberProps } = usePaymentInputs()
  return (
    <InputGroup {...wrapperProps} endElement={<LuCreditCard />}>
      <Input {...getCardNumberProps()} />
    </InputGroup>
  )
}

import { Input, InputGroup } from "@chakra-ui/react"
import { LuCreditCard } from "react-icons/lu"
import { usePaymentInputs } from "react-payment-inputs"

清除按钮

Input CloseButton 组件组合可以创建一个清除按钮。这对于构建搜索输入框非常有用。

tsx
export const InputWithClearButton = () => {
  const [value, setValue] = useState("初始值")
  const inputRef = useRef<HTMLInputElement | null>(null)

  const endElement = value ? (
    <CloseButton
      size="xs"
      onClick={() => {
        setValue("")
        inputRef.current?.focus()
      }}
      me="-2"
    />
  ) : undefined

  return (
    <InputGroup endElement={endElement}>
      <Input
        ref={inputRef}
        placeholder="邮箱"
        value={value}
        onChange={(e) => {
          setValue(e.currentTarget.value)
        }}
      />
    </InputGroup>
  )
}

import { CloseButton, Input, InputGroup } from "@chakra-ui/react"
import { useRef, useState } from "react"

属性(Props)

以下是 Input 组件的常用属性。

colorPalette

默认值:'gray'

'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink'

组件的颜色方案

size

默认值:'md'

'2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'

组件的尺寸

variant

默认值:'outline'

'outline' | 'subtle' | 'flushed'

组件的变体样式

as

默认值:

React.ElementType

要渲染的底层元素。

asChild

默认值:false

boolean

将传入的子元素作为默认渲染的元素,并组合它们的 props 与行为。