dacs 0.3.0
dacs: ^0.3.0 copied to clipboard
Tailwind-like utility classes for Flutter. Apply text styles, padding, margins, colors, and borders via concise string expressions.
DACS #
DACS brings Tailwind-inspired utility classes to Flutter. Write concise string expressions to define text styles, padding, colors, borders, shadows, transforms, gradients, and more.
Text('Hello, World!', style: 'text-2xl font-medium text-sky-500'.dText)
Features #
- Zero-config — just install and use
- Tailwind v3 color palette — 22 colors × 11 shades
- Spacing scale — 0 to 384px in Tailwind increments
- Text utilities — size, weight, color, letter spacing, line height, decoration
- Background & border — colors, border width, border radius with directional variants
- Sizing, shadows & opacity — width, height, box shadows, opacity
- Position — inset-, top-, right-, bottom-, left-*
- Transform — scale, rotate, translate, skew
- Gradient — linear gradients from Tailwind color tokens
- Theme colors from
ColorScheme—text-primary,bg-surface,border-error - Arbitrary values —
text-[#ff0000],p-[20],w-[50%],rounded-[12] - Material widget extensions — style any Material widget:
.dButton(context),.dCheckbox(context),.dCard(context), etc. - WidgetState variants —
hover:,focus:,disabled:,pressed:,selected:,error:,dragged:,scrolledUnder: - Chained compound variants — combine any prefixes:
dark:hover:,dark:md:focus:,light:lg:disabled: - Dark/Light mode & responsive variants —
dark:,light:,sm:,md:,lg:,xl:,2xl:
Installation #
dependencies:
dacs: ^0.3.0
Usage #
Text styles #
Text('Heading', style: 'text-3xl font-bold text-gray-900'.dText)
Text('Body', style: 'text-base leading-relaxed text-gray-600'.dText)
Padding & Margin #
Container(
padding: 'px-4 py-2'.dPads,
margin: 'mt-4'.dPads,
child: Text('Content', style: 'text-base'.dText),
)
Box decoration #
Container(
decoration: 'bg-blue-500 rounded-lg shadow-md'.dBox,
child: Text('Button', style: 'text-white font-medium'.dText),
)
Gradients #
Container(
decoration: 'bg-gradient-to-r from-sky-400 to-blue-600'.dBox,
child: Text('Gradient', style: 'text-white text-xl'.dText),
)
Shadows #
Container(decoration: 'bg-white rounded-xl shadow-lg'.dBox)
// Or just the shadow list:
final shadows = 'shadow-lg'.dShadow;
Sizing #
final (width, height) = 'w-64 h-48'.dSize;
Position (for Stack) #
final (top, right, bottom, left) = 'inset-0'.dPosition;
Transform #
Transform(
transform: 'scale-125 rotate-45'.dTransform,
child: Text('Styled'),
)
Dark / Light mode variants #
// Resolves automatically from MediaQuery:
Text(
'Responsive text',
style: 'text-gray-900 dark:text-white'.dTextOf(context),
)
Container(
decoration: 'bg-white dark:bg-gray-900'.dBoxOf(context),
child: Text(
'Content',
style: 'text-base text-gray-600 dark:text-gray-300'.dTextOf(context),
),
)
Responsive variants #
// Applies breakpoints based on screen width from MediaQuery:
Text(
'Responsive heading',
style: 'text-base sm:text-lg md:text-xl lg:text-2xl'.dTextOf(context),
)
Container(
padding: 'p-4 md:p-8 lg:p-12'.dPadsOf(context),
decoration: 'bg-white dark:bg-gray-900 rounded-lg'.dBoxOf(context),
child: Text(
'Content',
style: 'text-sm md:text-base'.dTextOf(context),
),
)
Theme colors #
Use any ColorScheme key as a color — no need to import or reference the theme directly:
Text('Primary', style: 'text-primary font-bold'.dTextOf(context))
Container(decoration: 'bg-surface rounded-lg border-outline'.dBoxOf(context))
Checkbox(checkboxTheme: 'checked:bg-primary unchecked:bg-surface'.dCheckbox(context))
Supported keys: primary, onPrimary, primaryContainer, onPrimaryContainer, secondary, onSecondary, secondaryContainer, onSecondaryContainer, tertiary, onTertiary, tertiaryContainer, onTertiaryContainer, error, onError, errorContainer, onErrorContainer, surface, onSurface, surfaceVariant, onSurfaceVariant, outline, outlineVariant, inverseSurface, onInverseSurface, inversePrimary, shadow, scrim
Arbitrary values #
Use square brackets for one-off values:
'text-[#ff0000]' // exact color
'bg-[rgb(255,0,0)]' // rgb syntax
'p-[20]' // 20px padding
'w-[50%]' // 50% width
'rounded-[12]' // 12px border radius
'opacity-[0.75]' // 75% opacity
'scale-[200]' // 2x scale
Material widget extensions #
Style Material widgets directly via context-aware methods:
ElevatedButton(
style: 'bg-primary text-white rounded-lg'.dButton(context),
onPressed: () {},
child: const Text('Submit'),
)
Checkbox(
theme: 'bg-primary hover:bg-primaryContainer'.dCheckbox(context),
)
Card(
theme: 'bg-surface rounded-xl shadow-md'.dCard(context),
)
All 26 Material widgets are supported: dButton, dCheckbox, dSwitch, dRadio, dChip, dAppBar, dCard, dListTile, dTabBar, dBottomNav, dInput, dProgress, dTooltip, dDivider, dScrollbar, dSnackBar, dDialog, dBottomSheet, dExpansionTile, dNavBar, dFab, dDataTable, dSearchBar, dMenu, dIcon, dShape.
WidgetState variants #
For Material widgets, use interactive state variants:
ElevatedButton(
style: 'bg-primary hover:bg-primaryContainer disabled:bg-surface'.
dButton(context),
onPressed: () {},
child: const Text('Submit'),
)
State order: base → disabled → pressed → hover → focus → selected → error → dragged → scrolledUnder.
Chained compound variants #
Combine any variant prefixes with ::
// Applies only in dark mode AND when hovered
Text(
'Styled text',
style: 'text-white dark:hover:text-primary'.dTextOf(context),
)
// Triple compound: dark mode, medium breakpoint, hover
Container(
decoration: 'bg-primary dark:md:hover:bg-error'.dBoxOf(context),
)
Raw style access #
final style = 'text-lg font-bold text-red-600'.dStyle;
print(style.fontSize); // 18
print(style.fontWeight); // FontWeight.w700
print(style.color); // Color(0xFFDC2626)
Extension methods #
Simple getters (no context) #
These parse classes and convert immediately. Useful when you don't need variant resolution.
| Getter | Returns |
|---|---|
.dText |
TextStyle |
.dPads |
EdgeInsets |
.dBox |
BoxDecoration |
.dStyle |
DacsStyle |
.dShadow |
List<BoxShadow> |
.dSize |
(double?, double?) |
.dPosition |
(double?, double?, double?, double?) |
.dTransform |
Matrix4 |
.dGradient |
LinearGradient? |
Context-aware methods (resolve variants) #
These accept a BuildContext to resolve dark/light mode, responsive breakpoints, and theme colors from MediaQuery / Theme.
| Method | Returns |
|---|---|
.dTextOf(context) |
TextStyle |
.dPadsOf(context) |
EdgeInsets |
.dMarginOf(context) |
EdgeInsets |
.dBoxOf(context) |
BoxDecoration |
.dStyleOf(context) |
DacsStyle |
.dShadowOf(context) |
List<BoxShadow> |
.dSizeOf(context) |
(double?, double?) |
.dPositionOf(context) |
(double?, double?, double?, double?) |
.dTransformOf(context) |
Matrix4 |
.dGradientOf(context) |
LinearGradient? |
Material widget extensions #
These accept a BuildContext and return Material theme data with variant resolution.
| Method | Returns |
|---|---|
.dButton(context) |
ButtonStyle |
.dCheckbox(context) |
CheckboxThemeData |
.dSwitch(context) |
SwitchThemeData |
.dRadio(context) |
RadioThemeData |
.dChip(context) |
ChipThemeData |
.dAppBar(context) |
AppBarTheme |
.dCard(context) |
CardTheme |
.dListTile(context) |
ListTileThemeData |
.dTabBar(context) |
TabBarTheme |
.dBottomNav(context) |
BottomNavigationBarThemeData |
.dInput(context) |
InputDecoration |
.dProgress(context) |
ProgressIndicatorThemeData |
.dTooltip(context) |
TooltipThemeData |
.dDivider(context) |
DividerThemeData |
.dScrollbar(context) |
ScrollbarThemeData |
.dSnackBar(context) |
SnackBarThemeData |
.dDialog(context) |
DialogTheme |
.dBottomSheet(context) |
BottomSheetThemeData |
.dExpansionTile(context) |
ExpansionTileThemeData |
.dNavBar(context) |
NavigationBarThemeData |
.dFab(context) |
FloatingActionButtonThemeData |
.dDataTable(context) |
DataTableThemeData |
.dSearchBar(context) |
SearchBarThemeData |
.dMenu(context) |
MenuStyle |
.dIcon(context) |
IconThemeData |
.dShape(context) |
ShapeDecoration |
Supported classes #
Typography #
| Class | Flutter property |
|---|---|
text-xs … text-9xl |
fontSize (12 … 128) |
font-thin … font-black |
fontWeight (100 … 900) |
leading-3 … leading-10 |
height (line height) |
leading-none … leading-loose |
height (relative) |
tracking-tighter … tracking-widest |
letterSpacing |
italic / not-italic |
fontStyle |
underline / line-through / no-underline |
textDecoration |
decoration-solid / double / dotted / dashed / wavy |
textDecorationStyle |
decoration-{1..} |
textDecorationThickness |
decoration-{color}-{shade} |
textDecorationColor |
Colors (text, background, border, decoration) #
Format: {prefix}-{color}-{shade}
'text-sky-500' // text color
'bg-blue-200' // background color
'border-red-600' // border color
'decoration-green-500' // text decoration color
Supported colors: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose
Shades: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950
Also: text-black, text-white, text-transparent
Spacing #
| Class | Output |
|---|---|
p-4 |
EdgeInsets.all(16) |
px-4 |
EdgeInsets.symmetric(horizontal: 16) |
py-2 |
EdgeInsets.symmetric(vertical: 8) |
pt-4, pr-4, pb-4, pl-4 |
Directional padding |
m-*, mx-*, my-*, mt-*, mr-*, mb-*, ml-* |
Same for margin |
Spacing keys: 0, px, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96
Border #
| Class | Output |
|---|---|
rounded-none |
BorderRadius.circular(0) |
rounded-sm |
BorderRadius.circular(2) |
rounded |
BorderRadius.circular(4) |
rounded-md / rounded-lg / rounded-xl / rounded-2xl / rounded-3xl |
6 / 8 / 12 / 16 / 24 |
rounded-full |
BorderRadius.circular(9999) |
rounded-t-lg, rounded-b-sm, rounded-l-md, rounded-r-xl |
Directional |
rounded-tl-lg, rounded-tr-lg, rounded-bl-lg, rounded-br-lg |
Corner-specific |
border |
Border.all(width: 1) |
border-2 … border-8 |
Border.all(width: size) |
Sizing & opacity #
'w-64' // width: 256
'h-32' // height: 128
'w-full' // width: double.infinity
'opacity-50' // opacity: 0.5
Shadows #
| Class | BoxShadows |
|---|---|
shadow-sm |
1 shadow (subtle) |
shadow |
2 shadows (default) |
shadow-md / shadow-lg / shadow-xl / shadow-2xl |
Increasing blur/spread |
shadow-inner |
Inset shadow |
shadow-none |
Empty list |
Position #
| Class | Properties |
|---|---|
inset-0 |
top=0, right=0, bottom=0, left=0 |
inset-x-4 |
left=16, right=16 |
inset-y-2 |
top=8, bottom=8 |
top-4, right-4, bottom-4, left-4 |
Individual inset |
Transform #
| Class | Property |
|---|---|
scale-125 |
scaleX=1.25, scaleY=1.25 |
scale-x-150 |
scaleX=1.5 |
scale-y-75 |
scaleY=0.75 |
rotate-45 |
rotateDegrees=45 |
translate-x-4 |
translateX=16 |
translate-y-2 |
translateY=8 |
skew-x-12 |
skewX=12 |
skew-y-6 |
skewY=6 |
Gradient #
'bg-gradient-to-r from-red-500 to-blue-600'
'bg-gradient-to-tl from-amber-400 via-orange-500 to-red-600'
Directions: to-r, to-l, to-t, to-b, to-tr, to-tl, to-br, to-bl
Variants #
Prefix any class with a variant to scope it:
| Variant | Trigger |
|---|---|
dark: |
Applies when MediaQuery.platformBrightness == Brightness.dark |
light: |
Applies when MediaQuery.platformBrightness == Brightness.light |
sm: |
Applies at min-width: 640px |
md: |
Applies at min-width: 768px |
lg: |
Applies at min-width: 1024px |
xl: |
Applies at min-width: 1280px |
2xl: |
Applies at min-width: 1536px |
hover: |
WidgetState.hovered |
focus: |
WidgetState.focused |
active: / pressed: |
WidgetState.pressed |
disabled: |
WidgetState.disabled |
selected: |
WidgetState.selected |
error: |
WidgetState.error |
dragged: |
WidgetState.dragged |
scrolledUnder: |
WidgetState.scrolledUnder |
Resolution order (Material contexts): base → disabled → pressed → hover → focus → selected → error → dragged → scrolledUnder.
Chained compound variants: combine multiple prefix types with :.
'dark:hover:text-white' // dark mode + hover
'light:md:bg-primary' // light mode + md breakpoint
'dark:lg:focus:border-error' // dark + lg + focus
Compound variants match only when ALL conditions are met. WidgetState conditions re-map to simple keys for Material widget resolution.
Additional information #
- Report issues
- View source
- Licensed under the MIT License