Utilities
Helper components for conditional rendering, translations, and theming.
Use If for type-safe conditional rendering, Trans for i18n translations, LazyRender for IntersectionObserver-based lazy loading, ErrorBoundary for error catching, Stepper for multi-step flows, ModeToggle for theme switching, CookieBanner for GDPR consent, and LanguageSelector for locale switching.
This guide is part of the UI Components documentation.
Utility components handle cross-cutting concerns - conditional rendering, internationalization, lazy loading, error boundaries, and user preferences - providing reusable patterns for common application needs.
- Use If when: you need type-narrowed conditional rendering (cleaner than ternaries).
- Use Trans when: displaying any user-facing text (enables i18n).
- Use LazyRender when: content is below the fold and heavy to render.
- Use ErrorBoundary when: wrapping components that might throw.
If
Conditional rendering component with type inference.
import { If } from '@kit/ui/if';{/* Basic usage */}<If condition={isLoading} fallback={<Content />}> <Spinner /></If>{/* With type inference */}<If condition={error}> {(err) => <ErrorMessage error={err} />}</If>{/* Render prop pattern */}<If condition={user}> {(user) => <UserProfile user={user} />}</If>Trans
Translation component for internationalization.
import { Trans } from '@kit/ui/trans';{/* Simple translation */}<Trans i18nKey="common.welcome" />{/* With variables */}<Trans i18nKey="user.greeting" values={{ name: user.name }}/>{/* With default text */}<Trans i18nKey="common.submit" defaults="Submit"/>{/* Rich text with components */}<Trans i18nKey="terms.agreement" components={{ TermsLink: <a href="/terms" className="underline" />, PrivacyLink: <a href="/privacy" className="underline" />, }}/>Lazy Render
Lazy load content when visible using IntersectionObserver.
import { LazyRender } from '@kit/ui/lazy-render';<LazyRender> <HeavyComponent /></LazyRender>{/* With options */}<LazyRender threshold={0.5} rootMargin="100px" onVisible={() => console.log('Component visible')}> <ExpensiveChart /></LazyRender>Error Boundary
Catch and handle React errors.
import { ErrorBoundary } from '@kit/ui/error-boundary';<ErrorBoundary fallback={ <Alert variant="destructive"> <AlertTitle>Something went wrong</AlertTitle> <AlertDescription> Please refresh the page. </AlertDescription> </Alert> }> <ComponentThatMightError /></ErrorBoundary>Stepper
Multi-step progress indicator.
import { Stepper } from '@kit/ui/stepper';<Stepper steps={['Account', 'Profile', 'Review']} currentStep={1}/>{/* Numbers variant */}<Stepper steps={['Step 1', 'Step 2', 'Step 3']} currentStep={2} variant="numbers"/>{/* Dots variant */}<Stepper steps={['', '', '', '']} currentStep={0} variant="dots"/>Mode Toggle
Dark/light theme switcher.
import { ModeToggle } from '@kit/ui/mode-toggle';<ModeToggle />Sub Menu Variant
import { SubMenuModeToggle } from '@kit/ui/mode-toggle';<SubMenuModeToggle />Theme Preference Card
import { ThemePreferenceCard } from '@kit/ui/mode-toggle';<ThemePreferenceCard currentTheme="system" />Displays cards for Light, Dark, and System theme options. The currentTheme prop sets the initial theme value.
Cookie Banner
GDPR cookie consent banner.
import { CookieBanner, useCookieConsent } from '@kit/ui/cookie-banner';<CookieBanner />Using Consent Hook
const { status, accept, reject, clear } = useCookieConsent();// status: 'unknown' | 'accepted' | 'rejected'Language Selector
Language/locale switcher.
import { LanguageSelector, LanguagePreferenceCard } from '@kit/ui/language-selector';import { useRouter, usePathname } from '@kit/i18n/navigation';const router = useRouter();const pathname = usePathname();<LanguageSelector locales={['en', 'de', 'es']} router={router} pathname={pathname}/>Language Preference Card
Card UI for language selection in settings pages.
<LanguagePreferenceCard locales={['en', 'de', 'es']} router={router} pathname={pathname}/>cn Utility
Class name merging utility.
import { cn } from '@kit/ui/utils';<div className={cn( 'base-classes', isActive && 'active-classes', className)}> Content</div>In MakerKit, we use the If component throughout the codebase instead of ternaries. The type narrowing in the render prop pattern catches null-safety issues that ternaries miss.
Common Pitfalls
- If component with falsy values:
Ifcondition treats 0, '', and false as falsy. For explicit boolean checks, usecondition={value !== null}. - Trans missing translation key: When i18nKey doesn't exist, Trans renders the key itself. Always add keys to your translation files first.
- LazyRender on critical content: Don't use LazyRender for above-the-fold content. It delays rendering until intersection, causing layout shift.
- ErrorBoundary not catching async errors: ErrorBoundary only catches errors during rendering. For async errors, use try/catch in your async functions.
- ModeToggle without ThemeProvider: ModeToggle requires next-themes ThemeProvider in your root layout to work properly.
- CookieBanner blocking renders: CookieBanner checks localStorage on mount. If blocking, use
useCookieConsenthook to defer checks.
Frequently Asked Questions
How does the If component provide type inference?
Can I use Trans in Server Components?
How do I persist theme preference?
What happens if LazyRender never intersects?
How do I customize the Stepper appearance?
Next: Marketing →