HextaUI

İlerleme

Bir görevin ne kadar ilerlediğini gösteren, güncellemeler arasında yumuşak geçiş yapan ve toplam bilinmediğinde kayan bir çubuk ya da halka.

Preparing…
x
"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  Progress,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"

export function ProgressDemo() {
  const [value, setValue] = React.useState<number | null>(null)
  const [run, setRun] = React.useState(0)

  React.useEffect(() => {
    let current = 0
    let tick: ReturnType<typeof setInterval> | undefined
    const start = setTimeout(() => {
      setValue(0)
      tick = setInterval(() => {
        current = Math.min(100, current + Math.round(Math.random() * 12 + 3))
        setValue(current)
        if (current === 100) {
          clearInterval(tick)
        }
      }, 400)
    }, 1200)
    return () => {
      clearTimeout(start)
      clearInterval(tick)
    }
  }, [run])

  const label =
    value === null ? "Preparing…" : value === 100 ? "Uploaded" : "Uploading"

  return (
    <div className="flex w-full max-w-sm flex-col items-center gap-6">
      <Progress value={value}>
        <ProgressLabel>{label}</ProgressLabel>
        <ProgressValue />
      </Progress>
      <Button
        variant="outline"
        size="sm"
        onClick={() => {
          setValue(null)
          setRun(run + 1)
        }}
      >
        Restart
      </Button>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/progress.json

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

import {
  Progress,
  ProgressCircle,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"
<Progress value={40}>
  <ProgressLabel>Uploading</ProgressLabel>
  <ProgressValue />
</Progress>

<ProgressCircle value={40} aria-label="Uploading" />

<Progress /> kendi izini ve göstergesini alt öğelerinden sonra çizer; böylece etiket ve değer çubuğun üstünde tek satırda durur. Her güncelleme dolguyu bulunduğu yerden yumuşatır, böylece hızlı güncellemeler adım adım değil tek bir akıcı hareket olarak okunur.

Progress
├── ProgressLabel
└── ProgressValue

ProgressCircle
└── ProgressValue

Boyutlar

xs, sm, default ve lg çubuğun kalınlığını değiştirir. xs, Attachment'ın alt kenarı boyunca çizdiği ince çizgidir.

import {
  Progress,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"

export function ProgressSizes() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-6">
      <Progress value={15} size="xs">
        <ProgressLabel>Extra small</ProgressLabel>
        <ProgressValue />
      </Progress>
      <Progress value={30} size="sm">
        <ProgressLabel>Small</ProgressLabel>
        <ProgressValue />
      </Progress>
      <Progress value={55}>
        <ProgressLabel>Default</ProgressLabel>
        <ProgressValue />
      </Progress>
      <Progress value={80} size="lg">
        <ProgressLabel>Large</ProgressLabel>
        <ProgressValue />
      </Progress>
    </div>
  )
}

Durum

variant yalnızca dolguyu veya halkayı renklendirir; iz, etiket ve değer nötr kalır.

import {
  Progress,
  ProgressCircle,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"

export function ProgressVariants() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-6">
      <Progress value={100} variant="success">
        <ProgressLabel>Backup complete</ProgressLabel>
        <ProgressValue />
      </Progress>
      <Progress value={86} variant="warning">
        <ProgressLabel>Storage almost full</ProgressLabel>
        <ProgressValue />
      </Progress>
      <Progress value={47} variant="destructive">
        <ProgressLabel>Upload failed</ProgressLabel>
        <ProgressValue />
      </Progress>
      <div className="flex items-center gap-4">
        <ProgressCircle value={100} variant="success" aria-label="Synced" />
        <ProgressCircle value={86} variant="warning" aria-label="Almost full" />
        <ProgressCircle value={47} variant="destructive" aria-label="Failed" />
      </div>
    </div>
  )
}

Belirsiz

Toplam bilinmiyorken value={null} verin. Bir bölüm iz boyunca kayar ve bir sayı gelince dolgu baştan büyür.

import { Progress, ProgressLabel } from "@/components/ui/progress"

export function ProgressIndeterminate() {
  return (
    <div className="w-full max-w-sm">
      <Progress value={null}>
        <ProgressLabel>Connecting to server…</ProgressLabel>
      </Progress>
    </div>
  )
}

Daire

<ProgressCircle /> aynı değeri üstten başlayan bir halka olarak çizer. Alt öğeler ortada durur; bu, lg ve xl boyutlarındaki <ProgressValue /> için uygundur.

import { ProgressCircle, ProgressValue } from "@/components/ui/progress"

export function ProgressCircleDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-8">
      <ProgressCircle value={25} size="sm" aria-label="Small" />
      <ProgressCircle value={50} aria-label="Default" />
      <ProgressCircle value={75} size="lg" aria-label="Large">
        <ProgressValue />
      </ProgressCircle>
      <ProgressCircle value={100} size="xl" aria-label="Extra large">
        <ProgressValue />
      </ProgressCircle>
    </div>
  )
}

Belirsiz daire

Bir değer gelene kadar halkanın çevresinde bir yay döner.

import { ProgressCircle } from "@/components/ui/progress"

export function ProgressCircleIndeterminate() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-8">
      <ProgressCircle value={null} size="sm" aria-label="Syncing" />
      <ProgressCircle value={null} aria-label="Syncing" />
      <ProgressCircle value={null} size="lg" aria-label="Syncing" />
      <ProgressCircle value={null} size="xl" aria-label="Syncing" />
    </div>
  )
}

Özel aralık ve biçim

Herhangi bir aralık için min ve max, sayı için format, metin için <ProgressValue /> üzerinde bir fonksiyon alt öğesi ayarlayın. Ekran okuyuculara aynı sözleri getAriaValueText ile verin.

"use client"

import {
  Progress,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"

export function ProgressFormat() {
  return (
    <div className="w-full max-w-sm">
      <Progress
        value={37.5}
        max={50}
        format={{ maximumFractionDigits: 1 }}
        getAriaValueText={(formatted) => `${formatted} of 50 GB used`}
      >
        <ProgressLabel>Storage</ProgressLabel>
        <ProgressValue>{(formatted) => `${formatted} of 50 GB`}</ProgressValue>
      </Progress>
    </div>
  )
}

Animasyonlu değer

Yalnızca değişen hanelerin dolguyla uyumlu dönmesi için <ProgressValue /> içinde <NumberFlow /> işleyin.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { NumberFlow } from "@/components/ui/number-flow"
import {
  Progress,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"

export function ProgressNumberFlow() {
  const [value, setValue] = React.useState(42)

  return (
    <div className="flex w-full max-w-sm flex-col items-center gap-6">
      <Progress value={value}>
        <ProgressLabel>Course completed</ProgressLabel>
        <ProgressValue>
          {(_, current) => <NumberFlow value={current ?? 0} suffix="%" />}
        </ProgressValue>
      </Progress>
      <div className="flex gap-2">
        <Button
          variant="outline"
          size="sm"
          onClick={() => setValue(Math.max(0, value - 13))}
        >
          −13
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => setValue(Math.min(100, value + 13))}
        >
          +13
        </Button>
      </div>
    </div>
  )
}

Uzun etiketler

Uzun adlar kendi satırlarına sarar ve değer sonda kalır. Halkalar her satırın yanında kompakt bir durum olarak işe yarar.

import {
  Progress,
  ProgressCircle,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"

const files = [
  {
    name: "quarterly-report-final-v3-approved-by-legal-and-finance.pdf",
    value: 64,
  },
  { name: "IMG_20260914_183022_HDR_edited_export.jpg", value: 100 },
  { name: "brand-assets.zip", value: 12 },
]

export function ProgressFiles() {
  return (
    <ul className="flex w-full max-w-sm flex-col gap-5">
      {files.map((file) => (
        <li key={file.name} className="flex items-start gap-3">
          <ProgressCircle value={file.value} aria-label={file.name} />
          <div className="min-w-0 flex-1">
            <Progress value={file.value} size="sm">
              <ProgressLabel>{file.name}</ProgressLabel>
              <ProgressValue />
            </Progress>
          </div>
        </li>
      ))}
    </ul>
  )
}

Görünür etiket olmadan

Bağlam neyin yüklendiğini zaten söylüyorsa çubuğu aria-label ile adlandırın.

import { Progress } from "@/components/ui/progress"

export function ProgressUnlabeled() {
  return (
    <div className="w-full max-w-sm">
      <Progress value={45} aria-label="Profile setup" />
    </div>
  )
}

Sağdan sola

Dolgu ve belirsiz kayma sağdan başlar. Değeri okuyucunun rakamlarıyla biçimlendirmek için locale verin.

import {
  Progress,
  ProgressCircle,
  ProgressLabel,
  ProgressValue,
} from "@/components/ui/progress"

export function ProgressRtl() {
  return (
    <div dir="rtl" className="flex w-full max-w-sm flex-col gap-6">
      <Progress value={65} locale="ar-EG">
        <ProgressLabel>جارٍ التحميل</ProgressLabel>
        <ProgressValue />
      </Progress>
      <Progress value={null}>
        <ProgressLabel>جارٍ الاتصال…</ProgressLabel>
      </Progress>
      <ProgressCircle value={65} size="xl" locale="ar-EG" aria-label="التقدم">
        <ProgressValue />
      </ProgressCircle>
    </div>
  )
}
  • Kök, aria-valuenow, aria-valuemin, aria-valuemax ve biçimlendirilmiş bir aria-valuetext içeren bir progressbar'dır. Belirsizken geçerli değeri yoktur.
  • <ProgressLabel /> çubuğu adlandırır. Yoksa aria-label verin.
  • <ProgressValue /> ekran okuyuculardan gizlenir, çünkü progressbar değeri zaten duyurur.
  • Azaltılmış harekette dolgu her yeni değere atlar; belirsiz çubuk ve halka hareket etmek yerine yerinde nabız atar.
  • locale vermedikçe değerler en-US ile biçimlendirilir; böylece sunucu ve tarayıcı aynı metni işler.

Base UI progress üzerine kuruludur. Her parça sardığı ilkelin prop'larını kabul eder.

PropTürVarsayılan
valuenull çubuğu belirsiz yapar.
number | null–
min
number0
max
number100
size
"xs" | "sm" | "default" | "lg""default"
variant
"default" | "success" | "warning" | "destructive""default"
formatDeğeri biçimlendirir. Olmadan değer yüzde olarak gösterilir.
Intl.NumberFormatOptions–
locale
Intl.LocalesArgument"en-US"
getAriaValueText
(formattedValue: string, value: number | null) => string–
className
string | (state) => string–
render
ReactElement | (props, state) => ReactElement<div>
ÖznitelikAçıklama
data-slot="progress"Kök.
data-sizeBoyut: xs, sm, default veya lg.
data-variantDurum varyantı.
data-progressingDeğer max değerinin altındayken bulunur.
data-completeDeğer max değerine ulaştığında bulunur.
data-indeterminateDeğer null veya sonlu bir sayı olmadığında bulunur.

Progressbar'ı adlandırır. Bir <span> işler ve kökle aynı durum niteliklerini alır.

PropTürVarsayılan
render
ReactElement | (props, state) => ReactElement<span>
ÖznitelikAçıklama
data-slot="progress-label"Etiket.
PropTürVarsayılan
childrenÖzel metin. Olmadan biçimlendirilmiş değer gösterilir, belirsizken ise hiçbir şey.
(formattedValue: string | null, value: number | null) => ReactNode–
render
ReactElement | (props, state) => ReactElement<span>
ÖznitelikAçıklama
data-slot="progress-value"Değer.

<Progress /> tarafından işlenir ve size değeriyle boyutlandırılır. Özel bileşimler için dışa aktarılır.

ÖznitelikAçıklama
data-slot="progress-track"İz.
--progress-dir1 ya da sağdan solda -1; böylece belirsiz kayma okuma yönünü izler.

Dolgu. Genişliği değerden satır içi ayarlanır ve güncellemeler arasında yumuşar.

ÖznitelikAçıklama
data-slot="progress-indicator"Dolgu.
PropTürVarsayılan
valuenull bir yay döndürür.
number | null–
min
number0
max
number100
size
"sm" | "default" | "lg" | "xl""default"
variant
"default" | "success" | "warning" | "destructive""default"
locale
Intl.LocalesArgument"en-US"
childrenHalkanın ortasında gösterilir.
ReactNode–
render
ReactElement | (props, state) => ReactElement<div>
ÖznitelikAçıklama
data-slot="progress-circle"Kök.
data-sizeBoyut: sm, default, lg veya xl.
data-variantDurum varyantı.
data-progressingDeğer max değerinin altındayken bulunur.
data-completeDeğer max değerine ulaştığında bulunur.
data-indeterminateDeğer null veya sonlu bir sayı olmadığında bulunur.
--progress-circle-sizeHalkanın genişliği ve yüksekliği.
--progress-strokeHalkanın çizgi kalınlığı.