Search the site
APP
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
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.
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.
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.
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
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.
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])
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.
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.
Built
Spec section: UI
Partial
Spec section: Styling
FSL-1.1-MIT licensed. Built with Dartvel.
Dartvel is made by
To the bottom