Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 26 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Colour roles use **grouped semantic naming** β€” `textPrimary`, `bgBase`, `actio
| Opacity | `opacity_primitives.dart` | `opacity_semantic.dart` |
| Duration | `duration_primitives.dart` | β€” |
| Offset | `offset_primitives.dart` | `offset_semantic.dart` |
| Animation | β€” | `animation_semantic.dart` |
| Animation | `duration_primitives.dart` | `animation_semantic.dart` |
| Breakpoint | `breakpoint_primitives.dart` | `breakpoint_semantic.dart` |
| Easing | `easing_primitives.dart` | `easing_semantic.dart` |
| Z-Index | β€” | `z_index_semantic.dart` |
Expand All @@ -99,16 +99,16 @@ DievasThemeData ← abstract interface (the contract)
└── [AppThemeData] ← consumer app's brand (lives in the app, not here)
```

`DievasTheme` is an `InheritedModel<DievasThemeAspect>`. Each sub system (`colors`, `typography`, `spacing`, `sizing`, `border`, `elevation`, `opacity`, `components`, `material`) is a named aspect; a widget that depends only on `colors` does not rebuild when `spacing` changes.
`DievasTheme` is an `InheritedModel<DievasThemeAspect>`. Each sub system (`colours`, `typography`, `spacing`, `sizing`, `border`, `elevation`, `opacity`, `animation`, `components`, `material`) is a named aspect; a widget that depends only on `colours` does not rebuild when `spacing` changes.

### Context extension β€” flat API

```dart
// Inside any widget's build method
final color = context.colors.action.actionPrimary;
final color = context.colours.action.actionPrimary;
final style = context.typography.labelMd;
final gap = context.spacing.s4;
final cols = context.grid.columns;
final gap = context.spacing.md;
final cols = context.grid.columns; // inside a DievasGrid
```

### Plugging in a brand theme
Expand All @@ -120,9 +120,9 @@ Consumer apps never touch `DievasLightThemeData` directly. They extend `DievasGl
class ExampleLightThemeData extends DievasGlobalThemeData {
ExampleLightThemeData({super.components})
: super(
colors: DievasColourThemeData(
colours: DievasColourThemeData(
brightness: Brightness.light,
action: ActionColors(actionPrimary: Color(0xFF7C3AED)),
action: ActionColours(actionPrimary: Color(0xFF7C3AED)),
),
border: const DievasBorderThemeData(...),
);
Expand Down Expand Up @@ -168,17 +168,17 @@ Rules components always follow:

37 components shipped across nine groups:

| Group | Count | Components |
| -------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Buttons** | 4 | `DievasFilledButton`, `DievasOutlinedButton`, `DievasTextButton`, `DievasIconButton` |
| **Display** | 9 | `DievasAvatar`, `DievasBadge`, `DievasCircularProgress`, `DievasDivider`, `DievasDotIndicator`, `DievasEmptyState`, `DievasIcon`, `DievasLinearProgress`, `DievasTag` |
| **Form** | 8 | `DievasAuthCode`, `DievasCheckbox`, `DievasRadio`, `DievasSegmentedControl`, `DievasSwitch`, `DievasTextArea`, `DievasTextInput`, `DievasTextInputGroup` |
| **Feedback** | 3 | `DievasAlert`, `DievasBanner`, `DievasSnackbar` |
| **Menu** | 2 | `DievasDropdown`, `DievasMenuItem` |
| **Overlays** | 3 | `DievasBottomSheet`, `DievasModal`, `DievasTooltip` |
| **Search** | 2 | `DievasSearchWithList`, `DievasSearchWithDropdown` |
| **Nav / Disclosure** | 5 | `DievasAccordion`, `DievasBreadcrumb`, `DievasDrawer`, `DievasPopover`, `DievasTabBar` |
| **Utility** | 1 | `DievasLoader` |
| Group | Count | Components |
| -------------------- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Buttons** | 4 | `DievasFilledButton`, `DievasOutlinedButton`, `DievasTextButton`, `DievasIconButton` |
| **Display** | 9 | `DievasAvatar`, `DievasBadge`, `DievasCircularProgress`, `DievasDivider`, `DievasDotIndicator`, `DievasEmptyState`, `DievasIcon`, `DievasLinearProgress`, `DievasTag` |
| **Form** | 8 | `DievasAuthCode`, `DievasCheckbox`, `DievasRadio`, `DievasSegmentedControl`, `DievasSwitch`, `DievasTextArea`, `DievasTextInput`, `DievasTextInputGroup` |
| **Feedback** | 3 | `DievasAlert`, `DievasBanner`, `DievasSnackbar` |
| **Menu** | 2 | `DievasDropdown`, `DievasMenuItem` |
| **Overlays** | 3 | `DievasBottomSheet`, `DievasModal`, `DievasTooltip` |
| **Search** | 2 | `DievasSearchWithList`, `DievasSearchWithDropdown` |
| **Nav / Disclosure** | 5 | `DievasAccordion`, `DievasBreadcrumb`, `DievasDrawer`, `DievasPopover`, `DievasTabBar` |
| **Utility** | 1 | `DievasLoader` |

## Grid System

Expand Down Expand Up @@ -221,15 +221,19 @@ flutter run
SDK: >=3.11.4 <4.0.0
```

Dart 3 idioms throughout β€” pattern matching with `switch` expressions, sealed classes, records, exhaustive matching. No legacy pre null safety patterns.
Dart 3 idioms throughout: pattern matching with `switch` expressions, sealed classes, records, exhaustive matching.

No legacy pre null safety patterns.

## Reference Systems

| Reference | Role in Dievas |
| --------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
| [Moon Design System](https://flutter.moon.io) | Component catalogue, visual language | **Landing page** β€” Jaspr SSR + Tailwind v4, deployed on Railway at `dievas.serticode.com`. |
| --------------------------------------------- | ------------------------------------ |
| [Moon Design System](https://flutter.moon.io) | Component catalogue, visual language |

The landing page is a Jaspr SSR + Tailwind v4 site deployed on Railway at `dievas.serticode.com`.

Token bridge: `landing/tool/generate_theme.dart` reads `dievas_tokens` constants and emits Tailwind `@theme {}` CSS β€” the same token values power both the Flutter widgets and the server rendered landing page.
Token bridge: `landing/tool/generate_theme.dart` reads `dievas_tokens` constants and emits Tailwind `@theme {}` CSS; the same token values power both the Flutter widgets and the server rendered landing page.

## Team

Expand Down
48 changes: 48 additions & 0 deletions packages/dievas/example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

# Widget Preview related
.widget_preview/
67 changes: 65 additions & 2 deletions packages/dievas/example/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,66 @@
# dievas_example
# Dievas Example App

A new Flutter project.
A complete, runnable reference app for the [Dievas design system](../README.md).

This is the app to study before wiring Dievas into your own Flutter project.

It evolves as the design system grows into maturity and at its core, it demonstrates two things end to end:

1. **How to set up your app's theme properly**: brand tokens, a custom typography ramp, and light/dark theme data that extend `DievasGlobalThemeData` (the exact pattern every consumer app follows).
2. **How to consume the system**: every context extension, the `DievasTheme` statics, the responsive grid, overlays, localizations, and a broad slice of the component library.

No names from any other design system appear here. Everything is branded "Example" so you can rename it to your own app.

## Run it

```bash
cd packages/dievas/example
flutter pub get
flutter run
```

Requires the Melos workspace to be bootstrapped first (`melos bootstrap` at the repo root), because the example depends on `dievas` and `dievas_tokens` by path.

## What each file teaches

### `lib/main.dart`

The entry point. A single `DievasScope` wraps the whole app and:

- resolves the active theme from `themeMode` + platform brightness,
- inserts the `DievasTheme` InheritedModel into the tree,
- bridges to Material by passing `theme.material` to `MaterialApp`,
- registers `DievasLocalizations` so component copy resolves via `context.l10n`,
- hosts a `NavigationBar` shell with three demo screens.

### This is the only place an app talks to Dievas directly. Everything below reads the theme through `context.*`

### `lib/example_theme/` β€” the brand theme (copy this folder)

The template every consumer app copies. Study the files in order:

| File | Teaches |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `example_tokens.dart` | Raw `int` brand colours + fonts. Pure values, no `Color` wrapping, no Flutter. |
| `example_typography.dart` | Building a `DievasTypographyThemeData` over the `DievasTypographySemantic` ramp with your own font (Cascadia Code via `google_fonts`). |
| `example_light_theme.dart` | `ExampleLightThemeData extends DievasGlobalThemeData` β€” supplies the light colour set and typography; everything else is derived. |
| `example_dark_theme.dart` | The same for dark mode. |

To make it your brand: rename `Example*` β†’ `YourBrand*`, replace
`ExampleColours` with your palette, and point the fonts at your typefaces.

### `lib/screens/`

| Screen | Teaches |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `example_overview_screen.dart` | Theme switching (`DievasScope.of(context).setThemeMode`), banner/snackbar overlays (`showBanner` / `showSnackbar`), the responsive grid (`DievasGrid` + `context.grid`), and `context.l10n`. |
| `example_foundations_screen.dart` | Every aspect scoped subsystem β€” `colours`, `typography`, `spacing`, `sizing`, `border`, `elevation`, `opacity`, `animation` β€” plus the `DievasTheme.of` statics and a per instance component override via `copyWith`. |
| `example_components_screen.dart` | The component library: buttons, form controls, display components, progress, feedback, overlays, tooltips, loaders, and empty states β€” all driven by the theme. |

## Key concepts to notice

- **Granular rebuilds.** `DievasTheme` is an `InheritedModel`; reading `context.colours` rebuilds only when colours change, never when `spacing` changes.
- **Nothing is hardcoded.** No component in the screens hardcodes a colour, size, or spacing; every value comes from `context.*`.
- **Contrast is a contract.** Dievas draws text on action surfaces using `colours.core.onBrand`, so `onBrand` must contrast `actionPrimary`. This brand's light-mode primary action is ink, so `onBrand` is lavender here β€” read the notes in `example_light_theme.dart` / `example_dark_theme.dart` before remapping any role.
- **Per instance overrides.** Wrap a subtree in `DievasTheme(data: copy)` to override a component for that subtree only (see the Foundations screen).
- **Material bridge.** Standard Flutter widgets (`NavigationBar`, `Scaffold`, `MaterialApp`) work automatically through `theme.material`.
11 changes: 11 additions & 0 deletions packages/dievas/example/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
include: package:flutter_lints/flutter.yaml

analyzer:
exclude:
- build/**
- android/**
- ios/**
- web/**
- windows/**
- macos/**
- linux/**
Loading