Şablonlar
Başlarken listesi
Ana sayfada kurulum adımları; ilerleme, açık duran sıradaki adım, tamamlanan adımlar, sonunda başarı durumu ve geri alınabilen gizleme.
Başlarken listesi, yeni bir çalışma alanının ilk kurulum adımlarını sırayla gösterir. Yalnız sıradaki adım açıktır ve tek bir eylem taşır; bitenler işaretlenir. Liste her zaman gizlenebilir, gizleme kısa bildirimden geri alınır.
Önizleme
Bölüm başlığı “Önizleme”Sıradaki adımın düğmesine basın: adım tamamlanır, ilerleme çubuğu dolar ve bir sonraki adım açılır. Son adımdan sonra kart başarı durumuna döner. Sayfa başlığındaki marka ve mod seçimi önizlemeyi de değiştirir.
pnpm add @bigbang/ui| Veri | Tür | Not |
|---|---|---|
| Adımlar | { title, text, action }[] |
Sıra sabittir; her adımın kendi ekranı vardır, dönüşte tamamlanmış sayılır. |
completed |
number |
Sunucudan gelen tamamlanmış adım sayısı. |
| Gizlendi | boolean |
Kullanıcı başına saklanır; gizlenen liste kendiliğinden geri gelmez. |
import { Button, Card, Heading, Icon, Inline, ProgressBar, ResultState, Stack, Text, VisuallyHidden, motion, useToast } from '@bigbang/ui';import { useState } from 'react';import type { Lang } from '../../patterns/lang';import { AppShellTemplate } from '../../templates/app-shell/AppShellTemplate';
const copy = { tr: { page: 'Ana sayfa', pageDescription: 'Çalışma alanınızı birkaç adımda hazırlayın.', title: 'Başlarken', progress: 'Kurulum ilerlemesi', progressText: (done: number, total: number) => `${total} adımdan ${done} tamamlandı`, done: 'Tamamlandı', current: 'Sıradaki adım', hide: 'Listeyi gizle', hidden: 'Başlarken listesi gizlendi.', show: 'Geri getir', steps: [ { title: 'Profilinizi tamamlayın', text: 'Adınızı ve fotoğrafınızı ekleyin; ekip sizi tanısın.', action: 'Profili aç' }, { title: 'Ekip arkadaşı davet edin', text: 'E-posta adresiyle davet gönderin; rolünü sonra değiştirebilirsiniz.', action: 'Davet gönder' }, { title: 'İlk projeyi oluşturun', text: 'Proje, kayıtları ve görevleri bir arada tutar.', action: 'Proje oluştur' }, { title: 'Bildirim tercihlerini seçin', text: 'Hangi olaylarda e-posta alacağınızı belirleyin.', action: 'Tercihleri aç' }, ], completedTitle: 'Çalışma alanınız hazır', completedText: 'Tüm adımları tamamladınız. Bu kartı artık kapatabilirsiniz.', close: 'Kartı kapat', }, en: { page: 'Home', pageDescription: 'Get your workspace ready in a few steps.', title: 'Getting started', progress: 'Setup progress', progressText: (done: number, total: number) => `${done} of ${total} steps done`, done: 'Done', current: 'Next step', hide: 'Hide the list', hidden: 'Getting started list hidden.', show: 'Bring back', steps: [ { title: 'Complete your profile', text: 'Add your name and photo so the team knows you.', action: 'Open profile' }, { title: 'Invite a teammate', text: 'Send an invitation by email; you can change their role later.', action: 'Send invitation' }, { title: 'Create the first project', text: 'A project keeps records and tasks together.', action: 'Create project' }, { title: 'Choose notification preferences', text: 'Decide which events send you an email.', action: 'Open preferences' }, ], completedTitle: 'Your workspace is ready', completedText: 'You have done every step. You can close this card now.', close: 'Close the card', },};
export type OnboardingChecklistBlockProps = { lang?: Lang; /** How many steps are already done on first render. */ completed?: number;};
/** * A getting-started checklist on the home page: progress, the next step open with its action, * done steps checked, a success state at the end and a hide action with undo. */export function OnboardingChecklistBlock({ lang = 'tr', completed = 1 }: OnboardingChecklistBlockProps) { const t = copy[lang]; return ( <AppShellTemplate lang={lang} current="home" title={t.page} description={t.pageDescription} width="md"> <Checklist lang={lang} completed={completed} /> </AppShellTemplate> );}
function Checklist({ lang, completed }: { lang: Lang; completed: number }) { const t = copy[lang]; const toast = useToast(); const total = t.steps.length; const [done, setDone] = useState(() => Math.min(completed, total)); const [pending, setPending] = useState(false); const [visible, setVisible] = useState(true); const titleId = `onboarding-${lang}`;
// The pause stands in for the step's own screen; the demo marks it done on return. const complete = () => { setPending(true); setTimeout(() => { setPending(false); setDone((value) => Math.min(value + 1, total)); }, 600); };
const hide = () => { setVisible(false); toast.show({ title: t.hidden, action: { label: t.show, onClick: () => setVisible(true) } }); };
if (!visible) return null;
return ( <Card variant="outlined" padding="lg" className={motion.reveal}> <section {...(done === total ? { 'aria-label': t.title } : { 'aria-labelledby': titleId })}> {done === total ? ( <ResultState tone="success" headingLevel={2} // Focus moves to the result only when the last step was just finished here. focusOnMount={completed < total} title={t.completedTitle} description={t.completedText} actions={ <Button variant="secondary" onClick={hide}> {t.close} </Button> } /> ) : ( <Stack gap="lg"> <Inline justify="between" align="center" gap="md" wrap> <Heading level={2} size="md" id={titleId}> {t.title} </Heading> <Button variant="tertiary" size="sm" onClick={hide}> {t.hide} </Button> </Inline> <ProgressBar label={t.progress} value={done} max={total} valueText={t.progressText(done, total)} description={t.progressText(done, total)} showValue={false} size="sm" /> <ol className="flex flex-col gap-xs"> {t.steps.map((step, index) => { const state = index < done ? 'done' : index === done ? 'current' : 'todo'; return ( <li key={step.title} aria-current={state === 'current' ? 'step' : undefined} className={['flex gap-md rounded-md p-md', state === 'current' ? 'bg-surface-sunken' : ''].join(' ')} > <span className="mt-xxs flex size-6 shrink-0 items-center justify-center" aria-hidden="true"> {state === 'done' ? ( <Icon name="circle-check" tone="success" className={motion.success} /> ) : ( <span className={['flex size-5 items-center justify-center rounded-full border type-label-sm', state === 'current' ? 'border-line-selected text-fg-default' : 'border-line-default text-fg-subtle'].join(' ')}> {index + 1} </span> )} </span> <Stack gap="xs" className="min-w-0 flex-1"> <Text weight="medium" tone={state === 'done' ? 'subtle' : 'default'} {...(state === 'done' ? { className: 'line-through' } : {})}> {state === 'done' ? <VisuallyHidden>{`${t.done}:`}</VisuallyHidden> : null} {state === 'done' ? ' ' : null} {step.title} </Text> {state === 'current' ? ( <div className={motion.collapsible}> <Stack gap="sm"> <Text size="sm" tone="subtle"> {step.text} </Text> <div> <Button size="sm" loading={pending} onClick={complete} endIcon={<Icon name="arrow-right" />}> {step.action} </Button> </div> </Stack> </div> ) : null} </Stack> </li> ); })} </ol> </Stack> )} </section> </Card> );}- AppShell şablonu (
width="md"),h1“Ana sayfa”. - Card içinde
h2“Başlarken” ve “Listeyi gizle”. smProgressBar: “4 adımdan 1 tamamlandı”.- Sıralı liste (
ol): biten adımlar onay ikonu ve üstü çizili başlıkla; sıradaki adım açık, açıklama ve eylem düğmesiyle; kalanlar yalnız numara ve başlık. - Bütün adımlar bitince kart
h2başlıklı ResultState olur. - Gizleme ve geri getirme bir Toast ile.
Hareket
Bölüm başlığı “Hareket”Kart motion.reveal ile girer. Sıradaki adımın içeriği motion.collapsible ile açılır; biten adımın onay ikonu motion.success ile büyür; ilerleme çubuğu motion.progress ile dolar. Azaltılmış harekette ölçek ve kayma kalkar.
Erişilebilirlik
Bölüm başlığı “Erişilebilirlik”- Liste gerçek bir
ol’dur; sıradaki adımaria-current="step"taşır. - Biten adımlar görünmez “Tamamlandı:” ön ekiyle okunur; üstü çizili yazı ve yeşil ikon tek başına anlam taşımaz.
- İlerleme çubuğunun değeri “4 adımdan 1 tamamlandı” olarak okunur, yüzde olarak değil.
- Son adım burada bitirilince odak başarı başlığına gider ve sonuç hemen okunur; sayfa zaten bitmiş listeyle açılırsa odak taşınmaz.
- “Geri getir” düğmesine F6 ile bildirim bölgesinden ulaşılır.
Kullanılan bileşenler
Bölüm başlığı “Kullanılan bileşenler”Card, ProgressBar, ResultState, Button, Icon, Toast, VisuallyHidden. Kalıplar: Boş durumlar, Bildirimler.