Theming
The components are built from the same tokens as the rest of a shadcn/ui app, so they follow your theme, your radius and your dark mode without extra work. When you need more, there are two more levels.
Requirements
- Tailwind CSS v4. The styling is Tailwind classes. An app that does not use Tailwind gets no styling from these components.
- shadcn/ui set up with CSS variables (
shadcn initdoes this), sobg-card,text-muted-foregroundand the other tokens exist. - React 19. Several components take
refas a normal prop. - tw-animate-css. for the entrance animations (
shadcn initinstalls it). Without it they are skipped, and motion is off for users who ask for reduced motion.
Try it
The same checkout in four themes. Each theme is only a few CSS variables set on a wrapper. Nothing in the component changes. Walk through the flow in each one, including a failure or a timeout.
Paiement
/* app/globals.css: the same tokens the rest of your shadcn app uses */
:root {
--primary: oklch(0.52 0.15 150);
--primary-foreground: oklch(0.98 0 0);
--radius: 1rem;
/* Optional. The receipt checkmark uses this, or --primary if you leave it out. */
--success: oklch(0.52 0.15 150);
}- Default: Whatever theme this site is using: shadcn's neutral theme.
- Dark: The app's dark mode, switched on with the dark class.
- Green brand, soft corners: A green primary color, a matching --success and larger corners.
- Warm, sharp corners: An orange primary color, a warm background and square corners.
1. The tokens the components read
| Token | Where it shows up |
|---|---|
| --background | Payment method cards, badges and the phone field. |
| --foreground | Text. Inherited from the page. |
| --card | The checkout, the USSD prompt and the receipt. |
| --muted / --muted-foreground | Secondary text, hints, hover states and disabled dots. |
| --primary / --primary-foreground | The Pay button, the selected card, the waiting dots and the receipt checkmark. |
| --destructive | Error messages, and the failure and timeout panel. |
| --border / --input | Card borders and the phone field border. |
| --ring | Focus rings on the cards and buttons. |
| --radius | Corner radius of every card, button and field. |
| --success (optional) | The receipt checkmark. Falls back to --primary when you do not define it. |
The buttons and inputs are your own shadcn Button and Input, so they carry your variants. The operator dots are the exception: their colors come from the country data, and you can replace them with your own logos.
2. className and classNames
className styles the root of a component. The larger ones also take classNames for their inner parts, and every part has a data-slot attribute. Classes are merged with the built-in ones, so yours win when they conflict.
<MomoCheckout
amount={25000}
onPay={onPay}
className="max-w-md shadow-sm"
classNames={{
title: "text-xl",
total: "border-dashed",
submit: "uppercase tracking-wide",
receipt: "bg-muted",
}}
/>
<PaymentMethodPicker
classNames={{
option: "p-4 has-[:checked]:shadow-md", // the selected card
optionLabel: "font-semibold",
}}
/>| Component | classNames keys |
|---|---|
| MomoCheckout | title, summary, total, amount, form, submit, picker, prompt, cancel, receipt, failure, footer |
| PaymentMethodPicker | legend, options, option, optionLabel, optionDescription, phone, error |
| PhoneInput | label, field, prefix, input, badge, hint, error |
| UssdPrompt | indicator, title, phone, codeBox, code, status, bar, countdown, retry |
| ReceiptCard | icon, title, amount, list, done |
/* Every part has a data-slot attribute, so you can also style it from CSS. */
[data-slot="momo-checkout-submit"] { letter-spacing: 0.02em; }
[data-slot="ussd-prompt-code"] { font-size: 2rem; }
[data-slot="operator-badge"] { border-color: currentColor; }3. Edit the source
Like the rest of shadcn/ui, the components are copied into your project, so anything the two levels above do not cover you can change directly. Text sizes and spacing are plain Tailwind classes in the files under components/mpui-kit/.