HextaUI

BetaVercel UI SDK 0.1.0-beta.2 üzerine kurulu. API’si değişebilir.

Password input

Vercel UI SDK üzerinde göster/gizle düğmesi, Caps Lock uyarısı, güç ölçer ve parola yöneticileri için doğru autocomplete değeri olan bir parola alanı.

Bağımlılıklar
  • @tabler/icons-react
  • @ui-sdk/core
  • @ui-sdk/react
import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputCapsLock,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputDemo() {
  return (
    <div className="flex w-full max-w-64 flex-col gap-2">
      <Label htmlFor="demo-password">Password</Label>
      <PasswordInput>
        <PasswordInputGroup>
          <PasswordInputControl id="demo-password" />
          <PasswordInputToggle />
        </PasswordInputGroup>
        <PasswordInputCapsLock />
      </PasswordInput>
    </div>
  )
}

export { UiSdkPasswordInputDemo }
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-password-input.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

UI SDK, ui-sdk adlı bir cascade katmanında kendi CSS’ini biraz ekler. Sınıflarınızın kazanması için bu katmanı genel stil dosyanızın en üstünde, Tailwind import’unun üzerinde tanımlayın.

@layer ui-sdk;

@import "tailwindcss";
import {
  PasswordInput,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"
<PasswordInput name="password">
  <PasswordInputGroup>
    <PasswordInputControl aria-label="Password" />
    <PasswordInputToggle />
  </PasswordInputGroup>
</PasswordInput>

Denetim yerel bir parola alanı olarak kalır; böylece parola yöneticileri, otomatik doldurma ve form gönderimi her yerdeki gibi çalışır. name, required ve autoComplete gibi form seçeneklerini PasswordInput üzerine, id ve placeholder gibi input özniteliklerini PasswordInputControl üzerine koyun.

autoComplete giriş için varsayılan olarak current-password değerini alır. Kayıt olurken ya da parola değiştirirken tarayıcı güçlü bir parola önersin diye new-password, hesap parolası olmayan gizli bilgiler için off kullanın.

PasswordInput
├── PasswordInputGroup
│   ├── PasswordInputControl
│   └── PasswordInputToggle
├── PasswordInputCapsLock
└── PasswordInputStrength

PasswordInputStrength, parolayı yazılırken 0’dan 4’e puanlar. Kontrol listesi aynı değeri usePasswordInputValue() ile okur. Kurallar örneğe aittir; bileşen bir parola politikası koymaz.

"use client"

import { IconCheck, IconCircleDashed } from "@tabler/icons-react"

import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputCapsLock,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputStrength,
  PasswordInputToggle,
  usePasswordInputValue,
} from "@/components/ui/ui-sdk-password-input"

const rules = [
  {
    label: "At least 12 characters",
    test: (password: string) => password.length >= 12,
  },
  { label: "A number", test: (password: string) => /\d/.test(password) },
  {
    label: "An uppercase and a lowercase letter",
    test: (password: string) =>
      /[a-z]/.test(password) && /[A-Z]/.test(password),
  },
]

function Requirements() {
  const password = usePasswordInputValue()
  return (
    <ul
      aria-label="Password requirements"
      className="m-0 flex list-none flex-col gap-1 p-0 pt-3 text-xs"
    >
      {rules.map((rule) => {
        const done = rule.test(password)
        return (
          <li
            key={rule.label}
            className={
              done
                ? "flex items-center gap-1.5 text-foreground"
                : "flex items-center gap-1.5 text-muted-foreground"
            }
          >
            {done ? (
              <IconCheck aria-hidden="true" className="size-3.5 text-success" />
            ) : (
              <IconCircleDashed aria-hidden="true" className="size-3.5" />
            )}
            <span className="sr-only">{done ? "Done:" : "To do:"}</span>
            {rule.label}
          </li>
        )
      })}
    </ul>
  )
}

function UiSdkPasswordInputNewPassword() {
  return (
    <div className="flex w-full max-w-64 flex-col gap-2">
      <Label htmlFor="create-password">Create a password</Label>
      <PasswordInput autoComplete="new-password">
        <PasswordInputGroup>
          <PasswordInputControl id="create-password" />
          <PasswordInputToggle />
        </PasswordInputGroup>
        <PasswordInputCapsLock />
        <PasswordInputStrength />
        <Requirements />
      </PasswordInput>
    </div>
  )
}

export { UiSdkPasswordInputNewPassword }

autoComplete="username" ayarlı bir e-posta alanıyla eşleştirin. Parolada Enter formu gönderir; gönderim, tarayıcı kaydetmeyi önersin diye görünen parolayı yeniden gizler.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputCapsLock,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputSignIn() {
  const [message, setMessage] = React.useState<string | null>(null)

  return (
    <form
      className="flex w-full max-w-64 flex-col gap-4"
      onSubmit={(event) => {
        event.preventDefault()
        const data = new FormData(event.currentTarget)
        const length = String(data.get("password")).length
        setMessage(
          `Signed in as ${data.get("email")}, with a password of ${length} characters.`
        )
      }}
      onReset={() => setMessage(null)}
    >
      <div className="flex flex-col gap-2">
        <Label htmlFor="sign-in-email">Email</Label>
        <Input
          id="sign-in-email"
          name="email"
          type="email"
          autoComplete="username"
          required
        />
      </div>
      <div className="flex flex-col gap-2">
        <Label htmlFor="sign-in-password">Password</Label>
        <PasswordInput name="password" required>
          <PasswordInputGroup>
            <PasswordInputControl id="sign-in-password" />
            <PasswordInputToggle />
          </PasswordInputGroup>
          <PasswordInputCapsLock />
        </PasswordInput>
      </div>
      <div className="flex items-center gap-3">
        <Button type="submit" size="sm">
          Sign in
        </Button>
        <Button type="reset" size="sm" variant="ghost">
          Reset
        </Button>
      </div>
      <p className="m-0 text-sm text-muted-foreground">
        {message ?? "Press Enter in the password to submit."}
      </p>
    </form>
  )
}

export { UiSdkPasswordInputSignIn }

defaultVisible, kişilerin okuması gereken bir gizli bilgi için metni görünür başlatır, örneğin bir Wi-Fi parolası.

import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputVisible() {
  return (
    <div className="flex w-full max-w-64 flex-col gap-2">
      <Label htmlFor="wifi-password">Wi-Fi password</Label>
      <PasswordInput
        defaultVisible
        defaultValue="maple-orbit-42"
        autoComplete="off"
      >
        <PasswordInputGroup>
          <PasswordInputControl id="wifi-password" />
          <PasswordInputToggle />
        </PasswordInputGroup>
      </PasswordInput>
      <p className="m-0 text-xs text-muted-foreground">
        Guests read it from here, so it starts shown.
      </p>
    </div>
  )
}

export { UiSdkPasswordInputVisible }

createPasswordInputController() ile oluşturulan bir denetleyici, alanı herhangi bir düğmeden ayarlar, gösterir, gizler, temizler ve odaklar. Yazmalar, yazma gibi onValueChange üzerinden geçer.

"use client"

import * as React from "react"
import { IconSparkles } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputStrength,
  PasswordInputToggle,
  createPasswordInputController,
} from "@/components/ui/ui-sdk-password-input"

const alphabet =
  "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789-_!?"

function generatePassword(length = 20) {
  const bytes = crypto.getRandomValues(new Uint32Array(length))
  return Array.from(bytes, (byte) => alphabet[byte % alphabet.length]).join("")
}

function UiSdkPasswordInputController() {
  const [password] = React.useState(createPasswordInputController)

  return (
    <div className="flex w-full max-w-72 flex-col gap-2">
      <div className="flex items-center justify-between gap-2">
        <Label htmlFor="generated-password">New password</Label>
        <Button
          size="xs"
          variant="ghost"
          onClick={() => {
            password.setValue(generatePassword())
            password.setVisible(true)
            password.focus()
          }}
        >
          <IconSparkles aria-hidden="true" />
          Suggest
        </Button>
      </div>
      <PasswordInput controller={password} autoComplete="new-password">
        <PasswordInputGroup>
          <PasswordInputControl id="generated-password" />
          <PasswordInputToggle />
        </PasswordInputGroup>
        <PasswordInputStrength />
      </PasswordInput>
      <div className="flex gap-2 pt-1">
        <Button
          size="sm"
          variant="outline"
          onClick={() => password.toggleVisible()}
        >
          Toggle
        </Button>
        <Button size="sm" variant="ghost" onClick={() => password.clear()}>
          Clear
        </Button>
      </div>
    </div>
  )
}

export { UiSdkPasswordInputController }

visible ve onVisibleChange verin. Neden, düğmeye basmayı form gönderiminden, sıfırlamadan ya da sayfanın gizlenmesinden ayırır.

"use client"

import * as React from "react"

import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputControlled() {
  const [visible, setVisible] = React.useState(false)
  const [reason, setReason] = React.useState<string | null>(null)

  return (
    <div className="flex w-full max-w-64 flex-col gap-2">
      <Label htmlFor="controlled-password">Password</Label>
      <PasswordInput
        visible={visible}
        onVisibleChange={(next, details) => {
          setVisible(next)
          setReason(details.reason)
        }}
      >
        <PasswordInputGroup>
          <PasswordInputControl id="controlled-password" />
          <PasswordInputToggle />
        </PasswordInputGroup>
      </PasswordInput>
      <p className="m-0 text-xs text-muted-foreground">
        {reason
          ? `${visible ? "Shown" : "Hidden"} by ${reason}.`
          : "Hidden. Press the eye to show it."}
      </p>
    </div>
  )
}

export { UiSdkPasswordInputControlled }

invalid alanı işaretler ve input öğesine aria-invalid koyar. aria-describedby özniteliğini mesajınıza yönlendirin. Zorunlu bir alan, biri onu boş bırakınca da kırmızıya döner.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputInvalid() {
  const [invalid, setInvalid] = React.useState(true)

  return (
    <form
      className="flex w-full max-w-64 flex-col gap-2"
      onSubmit={(event) => {
        event.preventDefault()
        const password = new FormData(event.currentTarget).get("password")
        setInvalid(password !== "correct-horse")
      }}
    >
      <Label htmlFor="checked-password">Password</Label>
      <PasswordInput
        name="password"
        invalid={invalid}
        onValueChange={() => setInvalid(false)}
      >
        <PasswordInputGroup>
          <PasswordInputControl
            id="checked-password"
            aria-describedby={invalid ? "checked-password-error" : undefined}
          />
          <PasswordInputToggle />
        </PasswordInputGroup>
      </PasswordInput>
      {invalid ? (
        <p
          id="checked-password-error"
          className="m-0 text-xs text-destructive"
        >
          That password isn’t right. Try “correct-horse”.
        </p>
      ) : null}
      <Button type="submit" size="sm" className="mt-1 self-start">
        Unlock
      </Button>
    </form>
  )
}

export { UiSdkPasswordInputInvalid }

Salt okunur bir alan odaklanabilir, gösterilebilir ve kopyalanabilir ama değiştirilemez; yine de gönderilir.

import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputReadOnly() {
  return (
    <div className="flex w-full max-w-64 flex-col gap-2">
      <Label htmlFor="recovery-key">Recovery key</Label>
      <PasswordInput readOnly defaultValue="7Hq2-vX9p-Lm4c" autoComplete="off">
        <PasswordInputGroup>
          <PasswordInputControl id="recovery-key" />
          <PasswordInputToggle aria-label="Show recovery key" />
        </PasswordInputGroup>
      </PasswordInput>
      <p className="m-0 text-xs text-muted-foreground">
        You can show it, but not change it.
      </p>
    </div>
  )
}

export { UiSdkPasswordInputReadOnly }

Tab, devre dışı bir alanı ve düğmesini atlar; değer gönderilmez.

import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputDisabled() {
  return (
    <div className="flex w-full max-w-64 flex-col gap-2">
      <Label htmlFor="managed-password">Password</Label>
      <PasswordInput disabled defaultValue="hunter22">
        <PasswordInputGroup>
          <PasswordInputControl id="managed-password" />
          <PasswordInputToggle />
        </PasswordInputGroup>
      </PasswordInput>
      <p className="m-0 text-xs text-muted-foreground">
        Your administrator manages this password.
      </p>
    </div>
  )
}

export { UiSdkPasswordInputDisabled }

Düğme solda durur, güç ölçer sağdan dolar. Etiketleri kendi dilinizde verin.

import { Label } from "@/components/ui/label"
import {
  PasswordInput,
  PasswordInputCapsLock,
  PasswordInputControl,
  PasswordInputGroup,
  PasswordInputStrength,
  PasswordInputToggle,
} from "@/components/ui/ui-sdk-password-input"

function UiSdkPasswordInputRtl() {
  return (
    <div dir="rtl" className="flex w-full max-w-64 flex-col gap-2">
      <Label htmlFor="rtl-password">كلمة المرور</Label>
      <PasswordInput autoComplete="new-password">
        <PasswordInputGroup>
          <PasswordInputControl id="rtl-password" />
          <PasswordInputToggle aria-label="إظهار كلمة المرور" />
        </PasswordInputGroup>
        <PasswordInputCapsLock>مفتاح الأحرف الكبيرة مفعّل</PasswordInputCapsLock>
        <PasswordInputStrength
          label="قوة كلمة المرور"
          labels={["", "ضعيفة", "مقبولة", "جيدة", "قوية"]}
        />
      </PasswordInput>
    </div>
  )
}

export { UiSdkPasswordInputRtl }
TuşAction
TabAlandan düğmeye geçer.
SpaceEnterDüğmeden parolayı gösterir ya da gizler ve odağı düğmede tutar.
EnterAlandan formu gönderir. Düğmeye asla basmaz.

Düğme sabit adlı bir aç/kapa düğmesidir, “Show password”; aria-pressed ekran okuyuculara parolanın görünüp görünmediğini söyler. Başka gizli bilgiler ve diller için yeniden adlandırın. Düğmeye işaretçiyle basmak, imleci alanda olduğu yerde bırakır.

PasswordInputCapsLock, Caps Lock açıkken ve alan odaktayken alanın altında açılır ve bunu bir durum bölgesiyle bildirir. PasswordInputStrength, değer metni güç etiketi olan bir ölçerdir; her tuşta duyurulmaz, istenince okunur. Görünen parolalar yazım denetimi, otomatik düzeltme ve büyük harfe çevirme dışında kalır.

Hiçbir parça parolayı bir data-* özniteliğine yazmaz. Kök ve denetim yalnızca data-filled gibi boolean değerler, ölçer ise puanı taşır. Denetimli bir value ise React’in DOM’da bir value özniteliği tutmasına yol açar; parolayı bunun yerine onValueChange ya da usePasswordInputValue() ile okuyun.

Her parça aynı adlı UI SDK parçasını sarar ve render ile parçanın durumuna bağlı bir fonksiyon olabilen className dahil tüm prop’larını kabul eder.

PropTürVarsayılan
value
string–
defaultValue
string–
onValueChange
(value: string, details) => void–
visible
boolean–
defaultVisible
booleanfalse
onVisibleChangedetails.reason; toggle-press, form-submit, reset, page-hide ya da imperative olur.
(visible: boolean, details) => void–
autoComplete
"current-password" | "new-password" | "off" | string"current-password"
invalid
booleanfalse
disabled
booleanfalse
readOnly
booleanfalse
required
booleanfalse
name
string–
form
string–
controllercreatePasswordInputController() ile oluşturulur.
PasswordInputController–
ÖznitelikAçıklama
data-slot="password-input"CSS’te parola girişini hedefler.
data-visibleParola gösterilirken bulunur.
data-capslockCaps Lock açıkken ve alan odaktayken bulunur.
data-filledAlanda herhangi bir metin varken bulunur.
data-invalidGeçersiz olduğunda bulunur.
data-disabledDevre dışıyken bulunur.
data-readonlySalt okunur olduğunda bulunur.
data-requiredParola zorunlu olduğunda bulunur.

Alanın ve düğmenin çevresindeki kutu. Alan odaktayken odak halkasını çizer.

PropTürVarsayılan
id
string–
placeholder
string–
render
ReactElement | (props, state) => ReactElement–
ÖznitelikAçıklama
data-slot="password-input-control"CSS’te yerel input öğesini hedefler.
data-visibleMetin alanıyken bulunur.
PropTürVarsayılan
aria-label
string"Show password"
childrenVarsayılan olarak kapalı göze geçişle dönüşen bir göz.
ReactNode | (state) => ReactNode–
render
ReactElement | (props, state) => ReactElement–
ÖznitelikAçıklama
data-slot="password-input-toggle"CSS'te toggle'ı hedefleyin.
aria-pressedParola görünürken true.
PropTürVarsayılan
children
ReactNode"Caps Lock is on"
ÖznitelikAçıklama
data-slot="password-input-capslock"CSS’te ipucunu hedefler.
data-activeCaps Lock açıkken bulunur.
PropTürVarsayılan
getStrengthParolayı puanlar. Varsayılan; uzunluğu, karakter çeşitliliğini, tekrarları ve yaygın parolaları tartar. Gerçek politikalar için zxcvbn gibi daha güçlü bir tahminci kullanın.
(password: string) => 0 | 1 | 2 | 3 | 4scorePassword
labels
[string, string, string, string, string]["", "Weak", "Fair", "Good", "Strong"]
label
string"Password strength"
ÖznitelikAçıklama
data-slot="password-input-strength"CSS’te ölçeri hedefler.
data-scorePuan; boş için 0’dan 4’e kadar.