# Repo Deploy Bars

> Bars twin of Repo Deploy: repository, branch and root-directory fields, then a monospace build log that fills on a timer, with progress drawn as segments instead of orb indicators.

A shadcn/ui block from the [@01orbital](https://01orbital.dev/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/01orbital/repo-deploy-bars).

- Page, with a live preview: https://shadcn.exchange/r/01orbital/repo-deploy-bars
- Screenshot: https://shadcn.exchange/shot/01orbital/repo-deploy-bars/light.png
- Registry item: https://01orbital.dev/r/repo-deploy-bars.json
- Categories: stepper
- Listed: 2026-11-01, source last changed 2026-11-01

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/01orbital/repo-deploy-bars.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `@01orbital/button`, `@01orbital/field`, `@01orbital/font-geist-mono`, `@01orbital/input`, `@01orbital/stepper`

## Files

### `blocks/stepper/repo-deploy-bars/index.tsx`

```tsx
"use client"

import { useEffect, useId, useState } from "react"

import {
  Stepper,
  StepperContent,
  StepperItem,
  StepperList,
  StepperSeparator,
  StepperTitle,
} from "@/components/stepper/stepper"
import { Button } from "@/components/ui/button"
import { Field, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

// The copy: change text here, not in the markup.
const COPY = {
  title: "Deploy a project",
  back: "Back",
  next: "Continue",
  deploy: "Deploy",
  steps: [
    { title: "Connect", palette: "delft" },
    { title: "Configure", palette: "marigold" },
    { title: "Deploy", palette: "aurora" },
  ],
  repo: "Repository",
  branch: "Production branch",
  root: "Root directory",
  idle: "Press Deploy to start the build.",
  deploying: "Deploying",
  log: [
    "Cloning orbcore/registry@main",
    "Installing 299 packages",
    "Building with Next 16",
    "Uploading 1,204 files",
    "Ready at registry.orbcore.dev",
  ],
} as const

// The bars twin of repo-deploy: one segment per stage. The last step shows
// the build log as it would run.
export default function RepoDeployBars() {
  const id = useId()
  const [step, setStep] = useState(0)
  // Local stand-in for a build: lines appear on a timer. A real block
  // streams them from your deploy API.
  const [lines, setLines] = useState(0)
  const running = lines > 0 && lines < COPY.log.length
  useEffect(() => {
    if (!running) return
    const t = setTimeout(() => setLines((n) => n + 1), 700)
    return () => clearTimeout(t)
  }, [running, lines])
  const last = COPY.steps.length - 1
  return (
    <section className="mx-auto w-full max-w-lg">
      <h2 className="mb-6 text-xl font-semibold tracking-tight">
        {COPY.title}
      </h2>
      <Stepper value={step} onValueChange={setStep} variant="bars">
        <StepperList>
          {COPY.steps.map((s, i) => (
            <StepperItem key={s.title} value={i}>
              <StepperSeparator />
              <StepperTitle className="sr-only">{s.title}</StepperTitle>
            </StepperItem>
          ))}
        </StepperList>
        <StepperContent keepMounted value={0}>
          <Field>
            <FieldLabel htmlFor={`${id}rd-repo`}>{COPY.repo}</FieldLabel>
            <Input
              id={`${id}rd-repo`}
              defaultValue="github.com/orbcore/registry"
            />
          </Field>
        </StepperContent>
        <StepperContent keepMounted value={1} className="gap-4">
          <Field>
            <FieldLabel htmlFor={`${id}rd-branch`}>{COPY.branch}</FieldLabel>
            <Input id={`${id}rd-branch`} defaultValue="main" />
          </Field>
          <Field>
            <FieldLabel htmlFor={`${id}rd-root`}>{COPY.root}</FieldLabel>
            <Input id={`${id}rd-root`} defaultValue="apps/www" />
          </Field>
        </StepperContent>
        <StepperContent keepMounted value={2}>
          <pre
            aria-live="polite"
            className="min-h-24 overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs leading-6 text-muted-foreground"
          >
            {lines === 0
              ? COPY.idle
              : COPY.log
                  .slice(0, lines)
                  .map((l, i) => `${String(i * 12).padStart(3, " ")}s  ${l}`)
                  .join("\n")}
          </pre>
        </StepperContent>
        <div className="flex justify-between">
          <Button
            variant="outline"
            disabled={step === 0 || running || lines === COPY.log.length}
            onClick={() => setStep(step - 1)}
          >
            {COPY.back}
          </Button>
          <Button
            disabled={running || lines === COPY.log.length}
            onClick={() => (step < last ? setStep(step + 1) : setLines(1))}
          >
            {step < last ? COPY.next : running ? COPY.deploying : COPY.deploy}
          </Button>
        </div>
      </Stepper>
    </section>
  )
}
```
