BlazorNova BlazorNova
BlazorNova BlazorNova
☰
☰ Menu
Getting Started
Installation
Project Setup
Source Generator
Core Concepts
Surface System
Color Palette
Fluent CSS API
Style Overrides
CSS Precedence
BlazorNova Classes
Layout
Flexbox & Grid
Spacing
Sizing
Typography
Backgrounds
Borders
Effects
Filters
Transitions & Transforms
Interactivity
Components
Forms
BnEditForm
FormState
Monitors
MenuBar
Horizontal
Vertical
Tabs
BnTab
Icons
Icon Gallery
Buttons
BnButton
Layout
BnStackPanel
BnDrawer
Grid
BnGrid
BnPagedGrid
Navigation
BnNavigator
Carousel
BnCarousel
Charts
BnChart
PDF Viewer
BnPdfViewer
Meet
BnVideoCall

Fluent CSS API

BlazorNova replaces raw CSS class strings with a type-safe, IntelliSense-driven fluent builder. Every Tailwind-style utility is available as a C# property, so misspellings are caught at compile time and discovery is instant via autocomplete.

BlazorNova.New — Starting a Style Chain

BlazorNova.New creates a fresh builder with no surface context. Chain utility properties to compose your class list, then drop the expression directly into a class="@(...)" attribute — the builder's ToString() emits the final CSS class string.

razor
@* In a Razor file — the expression becomes a class string *@
<div class="@@BlazorNova.New.flex.gap_4.items_center.p_3">
    <span class="@@BlazorNova.New.font_bold.text_lg">Hello</span>
</div>

@* Renders as: *@
<div class="flex gap-4 items-center p-3">
    <span class="font-bold text-lg">Hello</span>
</div>

Because each property returns the same BlazorNova instance, chains can be as long as you need. Properties use lowercase with underscores to mirror Tailwind naming — flex_row is flex-row, max_w_xl is max-w-xl. This keeps the mental mapping instant for anyone familiar with Tailwind, while the uppercase methods (Sm, Hover, If) clearly mark structural operations like breakpoints and conditionals.

Naming Convention

Utility properties are lowercase with underscores — a deliberate departure from C# naming conventions. This is a domain-specific API, not a general class library. The lowercase style:

  • Maps 1:1 to Tailwind class names (underscore = hyphen)
  • Clusters beautifully in IntelliSense — type flex_ to see all flex utilities
  • Visually distinguishes styling from business logic in Razor files
csharp
// Utility properties — lowercase, underscore = hyphen
BlazorNova.New.flex_row          // → flex-row
BlazorNova.New.max_w_xl          // → max-w-xl
BlazorNova.New.whitespace_pre    // → whitespace-pre
BlazorNova.New.bg_EmphasisBg     // → bg-EmphasisBg (surface-aware)

// Structural methods — PascalCase
BlazorNova.New.Sm(x => x.flex_col)   // breakpoint
BlazorNova.New.Hover(x => x.opacity_80)  // pseudo-state
BlazorNova.New.If(() => cond, x => x.font_bold)  // conditional

Arbitrary Values

When the built-in scale doesn't have the value you need, use method-style utilities that accept a string parameter. These generate Tailwind arbitrary-value classes like w-[480px].

csharp
// Width/height with exact values
BlazorNova.New.W("480px").H("100vh")

// Grid with custom template
BlazorNova.New.GridCols("220px 1fr").gap_4

// Z-index
BlazorNova.New.Z("101")

// Custom border
BlazorNova.New.Border("2px solid red")

CSS Property Deduplication

The builder tracks which CSS property each utility maps to. If you set the same property twice, the later value wins — just like writing CSS. This means modifiers and conditionals can safely override defaults without accumulating conflicting classes.

csharp
// px_4 sets the "padding-inline" CSS property
// px_0 also sets "padding-inline" — so it overwrites px_4
BlazorNova.New.px_4.py_2.px_0
// Output: py-2 px-0  (px_4 is gone)

// This is why BnModifier overrides work cleanly —
// the modifier runs after defaults, and later values
// for the same CSS property replace earlier ones.

NextBn and CurrentBn — Surface-Aware Styles

Inside any component that inherits BlazorNovaComponentBase, two additional builders are available:

  • NextBn — starts one surface level deeper than the parent. Use this for the component's own background and content areas.
  • CurrentBn — stays at the same surface level as the parent. Use this for elements that should blend with the container rather than elevate.

Surface-aware utilities like bg_Bg, text_OnBg, and bg_rel1_Bg resolve to different colours depending on the surface context — see the Surface System docs for details.

csharp
// Inside a component inheriting BlazorNovaComponentBase:

// NextBn — one level deeper than the parent surface
// Use for the component's own background
<div class="@@NextBn.bg_Bg.text_OnBg.rounded_md.p_3">
    @@ChildContent
</div>

// CurrentBn — same level as the parent surface
// Use for elements that should blend with the container
<button class="@@CurrentBn.bg_Bg.text_OnBg
                .Hover(h => h.bg_EmphasisBg)">
    @@Label
</button>

Conditionals

.If() adds classes only when a condition is true at render time. Chain .Else() for the alternate branch. Conditions are evaluated each time the builder's ToString() is called, so they stay reactive.

csharp
BlazorNova.New
    .flex.items_center.p_2
    .If(() => isActive, x => x.font_bold.bg_EmphasisBg)
    .Else(x => x.opacity_70)

// Multiple independent conditions
BlazorNova.New
    .w_full
    .If(() => hasError, x => x.border_red_500.border_2)
    .If(() => isDisabled, x => x.opacity_50.cursor_not_allowed)

Pseudo-States

Hover, focus, disabled, and other pseudo-states are expressed as methods that take a lambda. The source generator detects these and emits the correct CSS selectors.

csharp
BlazorNova.New
    .bg_Bg.text_OnBg
    .Hover(x => x.bg_EmphasisBg.cursor_pointer)
    .Focus(x => x.outline_2.outline_blue_500)
    .Disabled(x => x.opacity_50.cursor_not_allowed)
    .Active(x => x.scale_95)

Responsive Breakpoints

Breakpoint methods (Sm, Md, Lg, etc.) wrap utilities in responsive media queries. Like Tailwind, breakpoints are mobile-first — Md means "at medium and above."

csharp
// Mobile-first: base styles + overrides at larger sizes
BlazorNova.New
    .flex_col.gap_2           // mobile default
    .Sm(x => x.flex_row)      // >= 640px
    .Md(x => x.gap_4)         // >= 768px
    .Lg(x => x.gap_8)         // >= 1024px

// Available breakpoints:
// XXS(320) XS(480) Sm(640) Md(768) Lg(1024) XL(1440) XXL(1920) XXXL(2560)

AddClass — Escape Hatch

When you need a class that isn't in the generated API — a third-party class, a custom utility, or a one-off override — use .AddClass("class-name") to inject it into the builder's output.

csharp
// Inject a custom or third-party class
BlazorNova.New.flex.gap_4.AddClass("my-custom-animation")

// Inject surface-specific classes from a palette
BlazorNova.New.AddClass(SurfacePalette.GetInputClasses())

Source Generator Integration

The BlazorNova source generator scans your Razor and C# files for fluent API usage and emits only the CSS classes your project actually uses. This means:

  • No unused CSS — the generated stylesheet is minimal
  • Breakpoints, pseudo-states, and conditionals are all detected automatically
  • BnModifier.Create(x => x.…) lambdas are scanned too — use this exact pattern so the generator can find your classes