Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Custom Branding Login Block for Radix UI

One sign-in page for three white-label customers: a demo rail picks the tenant, and the page re-skins from typed fields, with its own mark shape, name, welcome line, background pattern and sign-in methods, and no brand colour.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Give every customer their own sign-in without a stylesheet per customer, with this custom branding login block for React with Radix UI. It's the sign-in page of Portalry, white-label customer portals, shown for three of its fictional customers: the page's side rails run its full height, and one band crosses the screen between two rules, with a rail at the start and the page at the end behind a divider. The rail is a demo control, a Toggle Group labelled "Demo: choose a tenant" (a row that scrolls sideways on a phone), and it re-skins the page from typed fields: the tenant's mark in a square, round or pill shape, its name, its welcome line, the faint pattern behind the page (lines, dots or none) and the methods it offers, which are a provider row over the password fields, the password fields alone, or a provider alone. The brand is the mark, name, words, pattern and methods and never a colour, so the page is right in every theme. The Shine Button signs in; the form is checked when it is sent, each problem under its field with focus on the first, and a good press shows the result in the page's own space. All three pages share one grid cell, so choosing a tenant never changes the height. It's built from Toggle Group, Field, Input, Password Input, Button, Shine Button and Guides, with CSS entrances only. For any product that hosts sign-in for its customers.

FAQ

What stays in the page, and how do I wire real tenants?

Everything. The three tenants are typed in TENANTS and the rail is a demo control that only exists so you can see them; sign in waits under a spinner for less than a second, then shows "You're signed in" and the tenant's name, and a polite status message says nothing was sent. For real, pick the tenant from the request (a subdomain, a path or an invitation link), load its settings from your API into the same fields, and send the tenant with the email and password to your auth endpoint where the code says so. Remove the rail.

Why is there no brand colour?

Because a customer's colour dropped into your theme has to pass contrast in light and dark, in every preset, and that is hard to promise for colours you don't choose. This page is branded by what is theirs to supply and safe to render: a mark, a name, a sentence, a pattern and the methods. Your primary button stays the one coloured control. If a customer needs their colour, offer a short list of tested accents rather than free choice.

How are the marks drawn?

As a tile with the tenant's initials or a short word, in one of three shapes, set from shape. They are placeholders: where the code marks the icon slot, drop in the customer's logo, with their permission and under their brand rules. The tile is aria-hidden, and the tenant's name is in the heading as text.

How does the page keep its height when the methods change?

All three pages are laid in one grid cell, the chosen one shown and the other two unseen and inert, so the cell is as tall as the tallest and choosing never moves anything. Typing doesn't carry over to another tenant, since each is its own page: choosing one clears the fields. A polite status message says which tenant is showing and how it signs people in.

Is it usable with a keyboard and a screen reader?

Yes. Tab runs through the rail first, where the arrow keys move between tenants and one is always chosen, then the page: the provider, the email, the password, its show and hide toggle, Forgot password, Sign in and the quiet link. Enter in either field signs in. Each problem is tied to its field, focus goes to the first, and after signing in it moves to the result's heading while a polite status message says what happened.

How does it look on a phone?

The rail becomes a row of three tenants that scrolls sideways above the page, the pattern is dropped and the page fills the width, so Sign in ends on the first screen. The row is a demo control; remove it in your app and the page is the same.