Dartvel, home
Docs
Features
Studio
Cloud
Compared

Search the site

GitHub
pub.dev

GETTING STARTED

Getting started
Existing Flutter apps
Existing Native apps
Run on your phone

APP

UI and styling
Routing
State
Accessibility
Keyboard shortcuts
Localization
Devices and desktop
Native device access
Media, 3D and XR

DATA

Data models
Forms
Search
Sync and offline
Import and export
Change capture
Database
Cache
File storage
Images
Privacy and erasure

BACKEND

Backend functions
Auth and sessions
Authorization
Queues and jobs
Workers and memory
Notifications and mail
Outbound HTTP
AI
Webhooks
GraphQL and OpenAPI
API keys and OAuth
Multi-tenancy
Billing and commerce
Modules

OPERATIONS

Edge security
Secrets and environments
Monitoring
Releases

SHIPPING

Build targets
Telegram Mini Apps
Static web hosting
Servers and deploying

REFERENCE

Testing
CLI reference
Coding agents

APP

UI and styling

Build screens from two widgets: DVBox for layout and DVText for text.

Style both with one chain of modifiers.

ON THIS PAGE

Show text with DVText

Wrap one child with DVBox

Lay out children in a list, row, grid or wrap

Style anything with DVModifier

Make a box react to taps and hover

Adapt to the screen with context.screen

Write reusable widgets as functions

Switch light and dark mode

Status

Show text with DVText

const Widget greeting = DVText('Welcome back');

Copy code to clipboard

Pass a DVModifier to size, weight and colour it.

const DVText('Pricing').modifier(
  DVModifier()
      .fontSize(28)
      .fontWeight(.w700)
      .color(Color(0xFF0B1020))
      .semanticHeading(1),
);

Copy code to clipboard

semanticHeading(1) marks the text as a heading for screen readers and search engines.

maxLines(2) cuts long text with an ellipsis.

Ctrl+F finds text on the web

Flutter draws text on a canvas, so each page also keeps a hidden copy of its text for the browser's find bar. A match scrolls the page to that paragraph. Static web hosting explains how, and which browsers support it.

Wrap one child with DVBox

DVBox(child, modifier) gives a single child padding, a background, a border and corners.

Widget card() => DVBox(
      DVText('One child, with padding and a border'),
      DVModifier()
          .padding(16)
          .backgroundColor(Color(0xFFF4F6FB))
          .border(Border.fromBorderSide(BorderSide(color: Color(0xFFE3E7EF))))
          .rounded(12),
    );

Copy code to clipboard

One child only

DVBox(widget) takes one child. For several, use the layout constructors below.

Lay out children in a list, row, grid or wrap

Widget layouts() => DVBox.list(<Widget>[
      // A column. Children are 8 apart unless you set spacing.
      const DVBox.row(<Widget>[
        DVText('Left'),
        DVText('Right'),
      ], align: .spaceBetween),
      // A line of children that wraps onto the next line when full.
      const DVBox.wrapLine(<Widget>[
        DVText('Dart'),
        DVText('Flutter'),
        DVText('Web'),
      ], spacing: 12),
      // Up to three columns, fewer on narrow screens.
      DVBox.grid(<Widget>[
        for (int i = 1; i <= 6; i++) DVText('Item $i'),
      ], columns: 3),
    ], spacing: 24);

Copy code to clipboard

DVBox.list

Lays out: A vertical column

DVBox.row

Lays out: A row that stacks when it does not fit

DVBox.wrapLine

Lays out: A row that wraps onto new lines

DVBox.grid

Lays out: Columns that step down on narrow screens

DVBox.masonry

Lays out: A grid of uneven heights

DVBox.stack

Lays out: Children on top of each other

DVBox.scrollableList

Lays out: A column that scrolls

DVBox.horizontalScrollable

Lays out: A row that scrolls

DVBox.twoPane

Lays out: Two panes, one each side of a fold

DVBox.threePane

Lays out: Three panes, one per panel of a tri-fold

list, row and wrapLine take spacing (8 by default), align and crossAlign.

align is DVAlign: start, center, end, spaceBetween, spaceAround or spaceEvenly.

crossAlign is DVCrossAlign: stretch (the default), start, center or end.

Style anything with DVModifier

Start from DVModifier() and chain. Each call returns a new modifier, so you can keep one and reuse it.

Spacing and size

Methods: padding, paddingSymmetric, paddingOnly, margin, width, height, maxWidth, minWidth, maxHeight, minHeight, align, centered

Surface

Methods: backgroundColor, gradient, backgroundImage, border, rounded, radius, shadow, card, clipContent

Effects

Methods: opacity, blur, backdropBlur, rotate

Text

Methods: color, fontSize, fontWeight, fontFamily, letterSpacing, lineHeight, maxLines, overflow, decoration

Interaction

Methods: onTap, onPressed, hover, onHoverChanged, input, minimumTapTarget

Accessibility

Methods: semanticLabel, semanticHint, semanticButton, semanticRole, semanticHeading

Motion

Methods: animate, revealOnScroll

Combining

Methods: merge

Make a box react to taps and hover

Widget saveButton(VoidCallback onSave) => DVText('Save').modifier(
      DVModifier()
          .paddingSymmetric(horizontal: 20, vertical: 12)
          .backgroundColor(const Color(0xFF2F6BFF))
          .color(const Color(0xFFFFFFFF))
          .rounded(8)
          .animate(const Duration(milliseconds: 150))
          .hover(const DVModifier().opacity(0.9))
          .semanticButton()
          .onTap(onSave),
    );

Copy code to clipboard

hover(...) layers a second modifier on while the pointer is over the box.

animate(duration) eases between the two, and respects the reduced motion setting.

semanticButton() tells assistive technology the text is a button.

Adapt to the screen with context.screen

Widget productGrid(BuildContext context, List<Widget> products) => DVBox.grid(
      products,
      columns: context.screen.value<int>(mobile: 1, tablet: 2, desktop: 4),
      spacing: context.screen.isMobile ? 12 : 24,
    );

Copy code to clipboard

value(mobile:, tablet:, desktop:, wide:) picks by breakpoint and falls back to smaller sizes.

The breakpoints are 840, 1200 and 1600 logical pixels.

isMobile, isTablet, isDesktop, width, height and reducedMotion are there too.

Layouts adapt before you add a breakpoint. A row that is too wide for a watch or a phone stacks its children, and a grid drops columns.

On a foldable, context.screen.folds says where the fold is and posture says book or tabletop. DVBox.twoPane puts one pane each side of it.

On a tri-fold, DVBox.threePane puts one pane on each panel and nothing in a crease. Across one fold the first pane has a side and the other two share the other, or with oneFold: DVThreePaneFold.lastAlone the first two share and the third is alone. With no fold: three columns on a desktop, two on a tablet, stacked on a phone. Right-to-left languages start on the right, and a screen reader reads first to last.

twoPane

threePane

No fold

Folded once

Tri-fold

List Inbox, 24 messages

Detail The open message

Inspector Sender and attachments

DVBox.threePane([list, detail, inspector])

Write reusable widgets as functions

Annotate a private function with @DVFunctionalWidget. Dartvel generates a widget class with a const constructor.

Functional

Class

// lib/components/price_tag.dart
@DVFunctionalWidget()
Widget _priceTag(BuildContext context, int cents, {String currency = 'USD'}) =>
    DVText('$currency ${(cents / 100).toStringAsFixed(2)}').modifier(
      const DVModifier().fontWeight(.w600),
    );

// Used anywhere as a widget: PriceTag(2499, currency: 'EUR')

Copy code to clipboard

Prefer classes? Every sample written as a function has a Class tab beside it. A page is a class extending DVClassWidget with @DVPage on it, and a widget is an ordinary StatelessWidget. Both shapes build and route the same way.

Switch light and dark mode

void useDarkMode() => DV.Theme.setMode(.dark);

Copy code to clipboard

Partial

Spec section: Theme

Planned work and implementation limits

Only the light, dark and system mode switch is built.

Design tokens, fonts, per-tenant themes and icon generation are not built yet.

Status

Built

Spec section: UI

Partial

Spec section: Styling

PREVIOUS Run on your phone Pair a development build with dartvel dev
NEXT Routing File pages, parameters, layouts and links
GitHub
pub.dev
npm
Acknowledgements
Privacy
Terms

FSL-1.1-MIT licensed. Built with Dartvel.

Dartvel is made by

SigmaDev Digital

To the bottom