Best Practices

Component composition patterns and performance optimization tips

Component composition patterns

Rizzo components are designed to be composed in layouts and with each other. Follow these patterns so behavior and styling stay consistent across Vanilla, Astro, Svelte, React, and Vue.

Container and slot patterns

Many components act as containers that wrap arbitrary content:

  • Card — Single root with optional variant; put content inside (e.g. card__body or your own structure).
  • Modal — Trigger opens a dialog; slot or prop for body content.
  • Tabs — Pass an array of { id, label, content? } or use slot panels.
  • Accordion — Pass items (id, title, content) or use slot children.

Preserve the root BEM block and expected child classes (e.g. card__body, tabs__panel, accordion__panel) so Rizzo CSS applies correctly.

Data-driven components

Use the shared data shapes so markup stays consistent and TypeScript types apply:

  • TabsTab[]: id, label, optional content, optional icon.
  • DropdownMenuItem[]: label, value, href, onClick, disabled, separator, submenu.
  • BreadcrumbBreadcrumbItem[]: label, optional href.
  • TableTableColumn[]: key, label, optional sortable.
  • AccordionAccordionItem[]: id, title, content.
  • FooterFooterLink[]: label, href.

These types are in src/types/components.ts and re-exported from src/types. Use them in Astro props or Svelte so the same structures work across frameworks.

Component dependency chains

When adding components via the CLI or by hand, respect dependencies:

  • Navbar — Adds Search and Settings (so the navbar can show search trigger and settings button).
  • Settings — Adds ThemeSwitcher, FontSwitcher, SoundEffects (and scaffold/config/fonts.ts when added via CLI).
  • Toast — Uses Alert (toast uses alert styles and close behavior).

If you add Navbar, include Search and Settings so the layout doesn’t have missing pieces. The CLI auto-includes dependencies.

Composing Navbar, Search, and Settings

Place Search and Settings in the desktop actions area (navbar__actions-desktop). On mobile, search/settings are often icon-only in the header. Use the same BEM structure as the Navbar component; the scaffold uses window.openSettings() for the settings button. The layout must include the Settings panel and the script that registers openSettings. See the scaffold layouts (Vanilla, Astro, Svelte, React, Vue) for full examples.

Modifiers and shared types

Use BEM modifiers for variants (e.g. btn-primary, btn-ghost, card--elevated, tabs--pills) and semantic props where supported. When extending or wrapping Rizzo components, import types from ../types (Astro) or the same in Svelte so APIs stay consistent.

Performance optimization tips

CSS loading

  • Single import — Import Rizzo CSS once in your root layout or main entry. Avoid loading it multiple times.
  • CDN — Pin the version (e.g. rizzo-css@0.0.76) so cache hits are reliable. Verify with curl -I <url> (200).
  • No duplicate CSS — Use either the npm package or a copied file in public/ or static/, not both.

Theme and font flash prevention

Apply the user’s stored theme (or system preference) before first paint. The scaffold layouts include an inline script in <head> that runs immediately: reads localStorage.getItem('theme') and sets data-theme on <html>. Keep this script small and synchronous. For custom font pairs, consider preloading key font files so text doesn’t swap visibly.

Bundle and assets

  • Rizzo ships a single minified CSS file; no tree-shaking. Load it once.
  • Reuse the same icon and sound assets across the app to avoid duplicate payloads.
  • Sound effects are optional and loaded on demand by the Settings script.

Critical CSS and lazy loading (optional)

If above-the-fold content is blocked by Rizzo CSS, you can experiment with critical CSS (inline above-the-fold rules, full stylesheet async). Themes are combined into one file; lazy-loading themes is possible but not default. Use your framework’s code-splitting for routes or heavy components.

Measuring

Use the Network and Performance panels to confirm CSS loads once and is cached, and that the theme script runs early enough to avoid a visible flash. Run Lighthouse for performance and accessibility.

Summary: Use container/slot and data-driven patterns; respect component dependencies; use shared types from src/types. Load Rizzo CSS once; pin CDN version; prevent theme flash with early scripts. For design-system rules (variables, BEM, contrast, accessibility), see Design System – Best Practices and Accessibility.