-
Notifications
You must be signed in to change notification settings - Fork 1
Styling
eQuantic.UI aims to provide a Flutter-inspired developer experience (DX) while leveraging the full power of the Modern Web platform.
The styling architecture is built on three pillars:
- Abstraction: Components define what to style, not how.
- Flexibility: Tailwind CSS is the "Happy Path", but not the only path.
- Performance: Compilation-time class generation, minimizing runtime CSS-in-JS overhead.
At the core, every visual component inherits from HtmlElement, exposing two standard properties:
public abstract class HtmlElement : Component {
/// <summary>
/// Raw CSS classes (space-separated).
/// </summary>
public string ClassName { get; set; }
/// <summary>
/// Inline styles for dynamic values (e.g., coordinates, colors from DB).
/// </summary>
public Dictionary<string, string> Style { get; set; }
}This simple contract means eQuantic.UI does not enforce any CSS framework. It simply renders HTML attributes.
To support multiple frameworks, we propose an ITheme interface in the Code:
public interface ITheme {
string PrimaryButton { get; }
string Card { get; }
string Input { get; }
}We recommend Tailwind CSS v4 as the standard implementation due to its utility-first nature, which aligns perfectly with component composition.
-
Compiler: Transpiles C#
ClassName="p-4"directly to JS/HTML. -
Tailwind CLI: Scans the output folder (
wwwroot/_equantic/**/*.js) for class names. -
Browser: Receives an optimized
.cssfile.
Instead of hardcoding strings, users can use a helper library:
using static eQuantic.UI.Tailwind.Utility;
new Button {
// Type-safe(ish) helpers
ClassName = Flex.Row + Gap(4) + Bg.Blue500 + Text.White
};Note: Strings are still preferred for developers familiar with Tailwind semantics.
To use Tailwind with eQuantic.UI in a .NET project:
Add the Tailwind integration package to your project:
<PackageReference Include="eQuantic.UI.Tailwind" Version="0.1.1" />Create wwwroot/css/styles.css:
@import "tailwindcss";
@theme {
--font-family-sans: "Inter", "sans-serif";
--color-primary: #3b82f6;
}The eQuantic.UI.Tailwind package automatically configures MSBuild targets. Just add this to your .csproj:
<PropertyGroup>
<TailwindInputFile>wwwroot/css/styles.css</TailwindInputFile>
<TailwindOutputFile>wwwroot/css/app.css</TailwindOutputFile>
</PropertyGroup>In your index.html (served by the backend):
<link href="/css/app.css" rel="stylesheet" />Tip
Zero External Dependencies: The Tailwind CLI is bundled via Bun inside the NuGet packages. No Node.js, npm, or global installations required - just dotnet build.
Because ClassName is just a string, adapting to other frameworks is trivial. The user can create extension methods or a dedicated theme package.
A user or a community package (eQuantic.UI.Bootstrap) could provide:
public static class BootstrapTheme {
public const string BtnPrimary = "btn btn-primary";
public const string Card = "card p-3";
}
// Usage
new Button { ClassName = BootstrapTheme.BtnPrimary, Text = "Click Me" }For legacy projects, standard CSS classes work natively:
new Container { ClassName = "my-legacy-sidebar" }To maintain separation of concerns, we suggest splitting the styling helpers:
| Package | Purpose |
|---|---|
| eQuantic.UI.Core | Base definitions, HtmlElement, ITheme interface. |
| eQuantic.UI.Tailwind | (Recommended) Helpers, predefined design system matching basic specifictaion. |
| eQuantic.UI.Bootstrap | (Optional) Token mapping for Bootstrap classes. |
| eQuantic.UI.Material | (Optional) Implementation of Material Design using CSS variables/classes. |
The specific theme implementation is configured at startup (conceptually), although mostly it's a compile-time decision of which CSS file to include in index.html.
In Program.cs or App.cs:
// Defines standard "semantic" tokens for the app
public static class AppTheme {
public static string Primary => "bg-indigo-600 hover:bg-indigo-700 text-white"; // Tailwind impl
// OR
// public static string Primary => "btn btn-primary"; // Bootstrap impl
}Developers are encouraged to create their own specialized components rather than repeating styles:
public class PrimaryButton : Button {
public PrimaryButton() {
ClassName = AppTheme.Primary + " px-4 py-2 rounded shadow";
}
}This brings the "Component-First" mindset of React/Flutter to the styling layer.
eQuantic.UI components now include production-ready features comparable to industry-leading libraries like shadcn/ui.
Components support semantic composition patterns:
new Card {
Variant = CardVariant.Elevated,
Children = {
new CardHeader {
Children = {
new CardTitle { Text = "Title" },
new CardDescription { Text = "Description" }
}
},
new CardBody { /* content */ },
new CardFooter { /* actions */ }
}
}Multiple visual variants for different use cases:
// Card variants
new Card { Variant = CardVariant.Outline } // Border only
new Card { Variant = CardVariant.Elevated } // Prominent shadow
new Card { Variant = CardVariant.Ghost } // Invisible container
// Input variants
new TextInput { /* ... */ } // Uses theme.Input.GetVariant(Variant.Success)Built-in loading indicators:
new Button {
Text = "Submit",
Loading = isSubmitting, // Shows spinner, disables button
OnClick = HandleSubmit
}Comprehensive validation feedback:
new FormField {
Label = "Email",
Required = true,
Error = validationError,
HelperText = "We'll never share your email",
Children = {
new TextInput { Type = "email" }
}
}Combine inputs with addons:
new InputGroup {
Children = {
new InputAddon { Text = "https://" },
new TextInput { Placeholder = "example.com" },
new Button { Text = "Go" }
}
}See Component Robustness for complete documentation.