# Beste UI

> Beautiful, accessible blocks, pieces and components for shadcn/ui and Tailwind CSS, built for React and Next.js. Install one with the shadcn CLI and the code is yours to edit: no runtime dependency, nothing to upgrade.

Markdown rendition of https://ui.beste.co/block/saas105. Every page on the site has one: add `.md` to any address, or send `Accept: text/markdown`.

Last updated: 2026-07-28

Whole catalog for LLMs: https://ui.beste.co/llms.txt. Registry index: https://ui.beste.co/r/registry.json

---
1. /
2. [Blocks](/blocks)
3. /
4. [SaaS](/blocks/saas)
5. /
6. Migration Source Selector

# Migration Source Selector[PRO](/pricing)

A migration section where your current system is picked from frosted glass cards floating on a photo panel, swapping the right side to a plain-language summary, a checked list of what carries across, the typical timeline, and a caveat.

ViewCodeDocs

Base UI

![](https://oud.pics/sm/l/npm.svg)`npx shadcn add https://ui.beste.co/r-base/saas105`

## Saas105: Migration Source Selector

Migration section where the system you are on today is picked from frosted glass cards floating on a photo panel, swapping the right side to a plain-language summary, a checked list of what carries across, the typical timeline, and the caveat that comes with it.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

[Upgrade NowUpgrade Now](/pricing)

### Installation

Swap `YOUR_EMAIL` and `YOUR_KEY` for the email and license key on your account. Find your license key on your [account page](/account).

**Radix flavor**

bashCopy

```
npx shadcn add "https://ui.beste.co/r/saas105?email=YOUR_EMAIL&license_key=YOUR_KEY"
```

**Base UI flavor**

bashCopy

```
npx shadcn add "https://ui.beste.co/r-base/saas105?email=YOUR_EMAIL&license_key=YOUR_KEY"
```

This installs the block to `components/beste/block/saas105.tsx` plus the `badge23` and `button21` components it uses for the eyebrow and the CTA.

### Quick start

The installed file exports `saas105Demo` alongside the block: the exact props behind the preview above. Spread it to get a working selector in one line.

tsxCopy

```
import { Saas105, saas105Demo } from "@/components/beste/block/saas105";

export default function MigrationPage() {
  return <Saas105 {...saas105Demo} />;
}
```

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsxCopy

```
import { Saas105 } from "@/components/beste/block/saas105";

export default function MigrationPage() {
  return (
    <Saas105
      badge={{ label: "Migration" }}
      heading="Bring the last ten years with you"
      description="Whatever you are on today, the history comes across."
      image={{ src: "/images/paperwork.jpg", alt: "Paperwork on a desk" }}
      labels={{
        sourcesLabel: "Where you are today",
        carriesLabel: "What comes across",
        timelineLabel: "Typical timeline",
      }}
      items={[
        {
          name: "Spreadsheets",
          summary: "The most common starting point, and the easiest one.",
          timeline: "2 days, including the review",
          carries: ["Member details and contact history", "Outstanding balances"],
          note: "Column names never match. That part is our job.",
        },
        {
          name: "Another practice system",
          summary: "If yours can export, it can move.",
          timeline: "3 to 5 days, run alongside your live system",
          carries: ["Member records with full history", "Invoice and payment ledger"],
        },
      ]}
      button={{ label: "Plan your migration", href: "/migration" }}
    />
  );
}
```

### Props

| Prop        | Type                            | Default | Description                                                     |
| ----------- | ------------------------------- | ------- | --------------------------------------------------------------- |
| badge       | { label: string }               | –       | Monospace eyebrow above the hairline rule, rendered via Badge23 |
| heading     | string                          | –       | Section heading in the left column                              |
| description | string                          | –       | Supporting paragraph, right-aligned from md up                  |
| image       | { src: string; alt: string }    | –       | Photo behind the source cards                                   |
| labels      | Saas105Labels                   | {}      | Kicker and column headings, see below                           |
| items       | Source\[\]                      | \[\]    | Selectable source systems and what each one implies             |
| button      | { label: string; href: string } | –       | CTA under the timeline column                                   |
| className   | string                          | –       | Extra classes for the outer <section>                           |

tsCopy

```
type Source = {
  name: string;
  summary: string;
  timeline: string;
  carries?: string[];
  note?: string;
};

type Saas105Labels = {
  sourcesLabel?: string;
  carriesLabel?: string;
  timelineLabel?: string;
};
```

### Behavior notes

* The selection is one index in local state starting at 0, so the panel always opens on a real answer rather than an empty prompt.
* The cards are frosted rather than bordered: `backdrop-blur-md` over a translucent fill, with the selected card simply carrying more of that fill. Nothing outlines, so the photo stays readable behind them.
* Those glass classes are applied only when `image` is set. Without a photo the cards fall back to the flat muted fill the rest of the set uses, so the block never renders blur over a plain background.
* The scrim is a gradient rather than a flat wash, which keeps the last card in a long list as legible as the first.
* The photo panel is a fixed dark surface, so the kicker and the card labels use the fixed `text-background` tokens instead of the adaptive ones.
* `carries` and `note` are both optional per source, so a system with nothing to warn about simply ends at its timeline, and the CTA stays where it is.
* The panel splits at `lg`. Below that the photo becomes a band above the detail column, keeping the source cards first in reading order.

## More SaaS blocks

[View all SaaS](/blocks/saas)

[](/block/saas103)

PRO

saas103

### Onboarding Split

A reversed split with an image tile floating a live setup checklist on the left, and an eyebrow, light heading, checked bullets, and an accent button on the right.

[](/block/saas16)

FREE

saas16

### Changelog Timeline

Version history cards with version badges, dates, and update type labels (Feature, Improvement, Fix). Perfect for product update pages and release notes.

[](/block/saas108)

FREE

saas108

### Branching Scoping Form

A contact section that asks a branching set of questions instead of one long form: a rail lists the steps that currently apply and lets you jump between them, and answering the first question adds or removes the steps below it.

[](/block/saas99)

PRO

saas99

### SaaS Integrations Grid

An editorial integrations section pairing a big-type pitch with a bordered mosaic of grayscale partner logo tiles.

[](/block/saas34)

PRO

saas34

### Press Coverage

Media mentions list with publication source badges, headlines, and dates. Perfect for showcasing company press coverage and news articles.

[](/block/saas98)

PRO

saas98

### SaaS Interface Split

Feature split pairing a focused pitch with a built monochrome app-window mockup of skeletons, nav, and metrics.

## Ship the interface, keep the code.

New blocks, pieces and components every week. Install one with a command and it is yours to edit. No runtime dependency, no upgrade path to fight.

[Browse the libraryBrowse the library](/blocks)[See pricingSee pricing](/pricing)

### Library

* [Blocks](/blocks)
* [Pages](/pages)
* [Pieces](/pieces)
* [Components](/components)
* [Search](/search)

### Learn

* [Docs](/docs)
* [AI & MCP](/docs/mcp)
* [Blog](/blog)
* [Free tools](/tools)
* [What's new?](/changelog)
* [Website Builder](https://beste.co)

### More

* [Pricing](/pricing)
* [Referrals](/referrals)
* [License](/license)
* [GitHub](https://github.com/beste-co/beste-ui)

### Shadcn Blocks

* [Shadcn Hero Blocks](/blocks/hero)
* [Shadcn Feature Blocks](/blocks/feature)
* [Shadcn Pricing Blocks](/blocks/pricing)
* [Shadcn CTA Blocks](/blocks/cta)
* [Shadcn FAQ Blocks](/blocks/faq)
* [Shadcn About Blocks](/blocks/about)
* [Shadcn Stats Blocks](/blocks/stats)
* [Shadcn Footer Blocks](/blocks/footer)
* [Shadcn Navigation Blocks](/blocks/navigation)
* [Shadcn Auth Blocks](/blocks/auth)
* [Shadcn Ecommerce Blocks](/blocks/ecommerce)
* [Shadcn Portfolio Blocks](/blocks/portfolio)
* [Shadcn Showcase Blocks](/blocks/showcase)
* [Shadcn Careers Blocks](/blocks/careers)
* [Shadcn Onboarding Blocks](/blocks/onboarding)
* [Shadcn Coming Soon Blocks](/blocks/coming-soon)
* [Shadcn Post Blocks](/blocks/post)
* [Shadcn Legal Blocks](/blocks/legal)
* [Shadcn Workflow Blocks](/blocks/workflow)
* [Shadcn News Blocks](/blocks/news)

© 2026, [Beste](https://beste.co). All rights reserved.