Docs
Theming

Theming

Using utility classes for theming.

Colors

Pixl uses a simple color system to define colors for your app. You can define colors in your pixl.json configuration file which will be used to generate a ui_colors.dart file.

Tailwind color palettes are automatically available for use in your components.

Convention

We use a simple background and foreground convention for colors. The background variable is used for the background color of the component and the foreground variable is used for the text color.

Given the following ui_colors.dart variables:

class UIColors {
  static Color primary = const HSLColor.fromAHSL(1.0, 222.2, 0.474, 0.112).toColor();
  static Color primaryForeground = const HSLColor.fromAHSL(1.0, 210.0, 0.4, 0.98).toColor();
}

The background color of the following component will be UIColors.primary and the foreground color will be UIColors.primaryForeground.

Container(
  color: UIColors.primary,
  child: UIText.p(
    "Deploy your new project in one-click.",
    style: (style) => style.copyWith(
      color: UIColors.primaryForeground
    )),
 
);

List of variables

Here's the list of colors available for customization:

Default background color of app ...etc
"background": {
  "default": "hsl(0, 0%, 100%)",
  "foreground": "hsl(222.2, 47.4%, 11.2%)"
}
Muted backgrounds such as <TabsList />, <Skeleton /> and <Switch />
"muted": {
  "default": "hsl(210, 40%, 96.1%)",
  "foreground": "hsl(215.4, 16.3%, 46.9%)"
}
Background color for <Card />
"card": {
  "default": "hsl(0, 0%, 100%)",
  "foreground": "hsl(222.2, 47.4%, 11.2%)"
}
Background color for popovers such as <DropdownMenu />, <HoverCard />, <Popover />
"popover": {
  "default": "hsl(0, 0%, 100%)",
  "foreground": "hsl(222.2, 47.4%, 11.2%)"
}
Default border color
"border": {
  "description": "Default border color",
  "default": "hsl(214.3, 31.8%, 91.4%)"
}
Border color for inputs such as <Input />, <Select />, <Textarea />
"input": {
  "default": "hsl(214.3, 31.8%, 91.4%)"
},
Primary colors for <Button />
"primary": {
  "default": "hsl(222.2, 47.4%, 11.2%)",
  "foreground": "hsl(210, 40%, 98%)"
}
Secondary colors for <Button />
"secondary": {
  "default": "hsl(210, 40%, 96.1%)",
  "foreground": "hsl(222.2, 47.4%, 11.2%)",
}
Used for accents such as hover effects on <DropdownMenuItem>, <SelectItem>...etc
"accent": {
  "accent": "hsl(210, 40%, 96.1%)",
  "foreground": "hsl(222.2, 47.4%, 11.2%)",
}
Used for destructive actions such as <Button variant="destructive">
"destructive": {
  "default": "hsl(0, 100%, 50%)",
  "foreground": "hsl(210, 40%, 98%)",
},
Used for focus ring
"ring": {
  "default": "hsl(215, 20.2%, 65.1%)",
},

Adding new colors

To add new colors, define them under the colors object in your pixl.json configuration file. You can set colors directly or create nested color objects for more complex color schemes.

Then run the pixl update command to regenerate the ui_colors.dart file.

For example, the provided pixl.json configuration:

pixl.json
{
  "styles": {
    "colors": {
      "warning": {
        "description": "Color for warning messages",
        "default": "hsl(38, 92%, 50%)",
        "foreground": "hsl(48, 96%, 89%)"
      }
    }
  }
}

Will generate a ui_colors.dart file with the following content:

styles/ui_colors.dart
class UIColors {
  /// Color for warning messages
  static Color warning = const HSLColor.fromAHSL(1.0, 38.0, 0.92, 0.5).toColor();
  static Color warningForeground = const HSLColor.fromAHSL(1.0, 48.0, 0.96, 0.89).toColor();
}

You can now use the warning color in your components.

Container(color: UIColors.warning)

Other color formats

I recommend using HSL colors for theming but you can also use other color formats if you prefer.

You can define color values in various formats:

  • Hexadecimal: "#000000"
  • RGB: "rgb(0, 0, 0)"
  • RGBA: "rgba(0, 0, 0, 0.5)"
  • HSL: "hsl(0, 0%, 0%)"

Insets

The spacing system in Pixl is based on a utility class system similar to Tailwind CSS. You can use the spacing utility classes to add padding and margin to your components.

Spacing

The spacing utility classes are based on baseInset value defined in your pixl.json configuration file.

Based on the default baseInset value of 4, the following utility classe us generated:

styles/ui_insets.dart
import 'package:flutter/material.dart';
import 'package:pixl_primitives/inset.dart';
 
final _baseInset = BaseInset.init(4.0);
 
class UIInsets {
  /// [baseInset] divided by 4
  ///
  /// 4.0 / 4 = 1.0
  static double xs = _baseInset.insetXs();
 
  /// [baseInset] divided by 2
  ///
  /// 4.0 / 2 = 2.0
  static double sm = _baseInset.insetSm();
 
  /// [baseInset]
  ///
  /// baseInset = 4.0
  static double x1 = _baseInset;
 
  /// [baseInset] multiplied by 2
  ///
  /// 4.0 x 2 = 8.0
  static double x2 = _baseInset.insetTimes(2);
 
  /// [baseInset] multiplied by 3
  ///
  /// 4.0 x 3 = 12.0
  static double x3 = _baseInset.insetTimes(3);
 
  /// [baseInset] multiplied by 4
  ///
  /// 4.0 x 4 = 16.0
  static double x4 = _baseInset.insetTimes(4);
 
  /// [baseInset] multiplied by 5
  ///
  /// 4.0 x 5 = 20.0
  static double x5 = _baseInset.insetTimes(5);
 
  /// [baseInset] multiplied by 6
  ///
  /// 4.0 x 6 = 24.0
  static double x6 = _baseInset.insetTimes(6);
 
  /// [baseInset] multiplied by 7
  ///
  /// 4.0 x 7 = 28.0
  static double x7 = _baseInset.insetTimes(7);
 
  /// [baseInset] multiplied by 8
  ///
  /// 4.0 x 8 = 32.0
  static double x8 = _baseInset.insetTimes(8);
 
  /// [baseInset] multiplied by 9
  ///
  /// 4.0 x 9 = 36.0
  static double x9 = _baseInset.insetTimes(9);
 
  /// [baseInset] multiplied by 10
  ///
  /// 4.0 x 10 = 40.0
  static double x10 = _baseInset.insetTimes(10);
 
  /// [baseInset] multiplied by 11
  ///
  /// 4.0 x 11 = 44.0
  static double x11 = _baseInset.insetTimes(11);
 
  /// [baseInset] multiplied by 12
  ///
  /// 4.0 x 12 = 48.0
  static double x12 = _baseInset.insetTimes(12);
 
  /// [baseInset] multiplied by 13
  ///
  /// 4.0 x 13 = 52.0
  static double x13 = _baseInset.insetTimes(13);
 
  /// [baseInset] multiplied by 14
  ///
  /// 4.0 x 14 = 56.0
  static double x14 = _baseInset.insetTimes(14);
 
  /// [baseInset] multiplied by 15
  ///
  /// 4.0 x 15 = 60.0
  static double x15 = _baseInset.insetTimes(15);
 
  /// [baseInset] multiplied by 16
  ///
  /// 4.0 x 16 = 64.0
  static double x16 = _baseInset.insetTimes(16);
 
  /// [baseInset] multiplied by 17
  ///
  /// 4.0 x 17 = 68.0
  static double x17 = _baseInset.insetTimes(17);
 
  /// [baseInset] multiplied by 18
  ///
  /// 4.0 x 18 = 72.0
  static double x18 = _baseInset.insetTimes(18);
 
  /// [baseInset] multiplied by 19
  ///
  /// 4.0 x 19 = 76.0
  static double x19 = _baseInset.insetTimes(19);
 
  /// [baseInset] multiplied by 20
  ///
  /// 4.0 x 20 = 80.0
  static double x20 = _baseInset.insetTimes(20);
 
  /// [baseInset] multiplied by 21
  ///
  /// 4.0 x 21 = 84.0
  static double x21 = _baseInset.insetTimes(21);
 
  /// [baseInset] multiplied by 22
  ///
  /// 4.0 x 22 = 88.0
  static double x22 = _baseInset.insetTimes(22);
 
  /// [baseInset] multiplied by 23
  ///
  /// 4.0 x 23 = 92.0
  static double x23 = _baseInset.insetTimes(23);
 
  /// [baseInset] multiplied by 24
  ///
  /// 4.0 x 24 = 96.0
  static double x24 = _baseInset.insetTimes(24);
 
  /// [baseInset] multiplied by 25
  ///
  /// 4.0 x 25 = 100.0
  static double x25 = _baseInset.insetTimes(25);
 
  /// [baseInset] multiplied by 26
  ///
  /// 4.0 x 26 = 104.0
  static double x26 = _baseInset.insetTimes(26);
 
  /// [baseInset] multiplied by 27
  ///
  /// 4.0 x 27 = 108.0
  static double x27 = _baseInset.insetTimes(27);
 
  /// [baseInset] multiplied by 28
  ///
  /// 4.0 x 28 = 112.0
  static double x28 = _baseInset.insetTimes(28);
 
  /// [baseInset] multiplied by 29
  ///
  /// 4.0 x 29 = 116.0
  static double x29 = _baseInset.insetTimes(29);
 
  /// [baseInset] multiplied by 30
  ///
  /// 4.0 x 30 = 120.0
  static double x30 = _baseInset.insetTimes(30);
 
  /// [baseInset] multiplied by 31
  ///
  /// 4.0 x 31 = 124.0
  static double x31 = _baseInset.insetTimes(31);
 
  /// [baseInset] multiplied by 32
  ///
  /// 4.0 x 32 = 128.0
  static double x32 = _baseInset.insetTimes(32);
 
  /// [baseInset] multiplied by 33
  ///
  /// 4.0 x 33 = 132.0
  static double x33 = _baseInset.insetTimes(33);
 
  /// [baseInset] multiplied by 34
  ///
  /// 4.0 x 34 = 136.0
  static double x34 = _baseInset.insetTimes(34);
 
  /// [baseInset] multiplied by 35
  ///
  /// 4.0 x 35 = 140.0
  static double x35 = _baseInset.insetTimes(35);
 
  /// [baseInset] multiplied by 36
  ///
  /// 4.0 x 36 = 144.0
  static double x36 = _baseInset.insetTimes(36);
 
  /// [baseInset] multiplied by 37
  ///
  /// 4.0 x 37 = 148.0
  static double x37 = _baseInset.insetTimes(37);
 
  /// [baseInset] multiplied by 38
  ///
  /// 4.0 x 38 = 152.0
  static double x38 = _baseInset.insetTimes(38);
 
  /// [baseInset] multiplied by 39
  ///
  /// 4.0 x 39 = 156.0
  static double x39 = _baseInset.insetTimes(39);
 
  /// [baseInset] multiplied by 40
  ///
  /// 4.0 x 40 = 160.0
  static double x40 = _baseInset.insetTimes(40);
 
  /// [baseInset] multiplied by 41
  ///
  /// 4.0 x 41 = 164.0
  static double x41 = _baseInset.insetTimes(41);
 
  /// [baseInset] multiplied by 42
  ///
  /// 4.0 x 42 = 168.0
  static double x42 = _baseInset.insetTimes(42);
 
  /// [baseInset] multiplied by 43
  ///
  /// 4.0 x 43 = 172.0
  static double x43 = _baseInset.insetTimes(43);
 
  /// [baseInset] multiplied by 44
  ///
  /// 4.0 x 44 = 176.0
  static double x44 = _baseInset.insetTimes(44);
 
  /// [baseInset] multiplied by 45
  ///
  /// 4.0 x 45 = 180.0
  static double x45 = _baseInset.insetTimes(45);
 
  /// [baseInset] multiplied by 46
  ///
  /// 4.0 x 46 = 184.0
  static double x46 = _baseInset.insetTimes(46);
 
  /// [baseInset] multiplied by 47
  ///
  /// 4.0 x 47 = 188.0
  static double x47 = _baseInset.insetTimes(47);
 
  /// [baseInset] multiplied by 48
  ///
  /// 4.0 x 48 = 192.0
  static double x48 = _baseInset.insetTimes(48);
 
  /// [baseInset] multiplied by 49
  ///
  /// 4.0 x 49 = 196.0
  static double x49 = _baseInset.insetTimes(49);
 
  /// [baseInset] multiplied by 50
  ///
  /// 4.0 x 50 = 200.0
  static double x50 = _baseInset.insetTimes(50);
 
  /// [baseInset] multiplied by 51
  ///
  /// 4.0 x 51 = 204.0
  static double x51 = _baseInset.insetTimes(51);
 
  /// [baseInset] multiplied by 52
  ///
  /// 4.0 x 52 = 208.0
  static double x52 = _baseInset.insetTimes(52);
 
  /// [baseInset] multiplied by 53
  ///
  /// 4.0 x 53 = 212.0
  static double x53 = _baseInset.insetTimes(53);
 
  /// [baseInset] multiplied by 54
  ///
  /// 4.0 x 54 = 216.0
  static double x54 = _baseInset.insetTimes(54);
 
  /// [baseInset] multiplied by 55
  ///
  /// 4.0 x 55 = 220.0
  static double x55 = _baseInset.insetTimes(55);
 
  /// [baseInset] multiplied by 56
  ///
  /// 4.0 x 56 = 224.0
  static double x56 = _baseInset.insetTimes(56);
 
  /// [baseInset] multiplied by 57
  ///
  /// 4.0 x 57 = 228.0
  static double x57 = _baseInset.insetTimes(57);
 
  /// [baseInset] multiplied by 58
  ///
  /// 4.0 x 58 = 232.0
  static double x58 = _baseInset.insetTimes(58);
 
  /// [baseInset] multiplied by 59
  ///
  /// 4.0 x 59 = 236.0
  static double x59 = _baseInset.insetTimes(59);
 
  /// [baseInset] multiplied by 60
  ///
  /// 4.0 x 60 = 240.0
  static double x60 = _baseInset.insetTimes(60);
 
  /// [baseInset] multiplied by 61
  ///
  /// 4.0 x 61 = 244.0
  static double x61 = _baseInset.insetTimes(61);
 
  /// [baseInset] multiplied by 62
  ///
  /// 4.0 x 62 = 248.0
  static double x62 = _baseInset.insetTimes(62);
 
  /// [baseInset] multiplied by 63
  ///
  /// 4.0 x 63 = 252.0
  static double x63 = _baseInset.insetTimes(63);
 
  /// [baseInset] multiplied by 64
  ///
  /// 4.0 x 64 = 256.0
  static double x64 = _baseInset.insetTimes(64);
 
  /// [baseInset] multiplied by 65
  ///
  /// 4.0 x 65 = 260.0
  static double x65 = _baseInset.insetTimes(65);
 
  /// [baseInset] multiplied by 66
  ///
  /// 4.0 x 66 = 264.0
  static double x66 = _baseInset.insetTimes(66);
 
  /// [baseInset] multiplied by 67
  ///
  /// 4.0 x 67 = 268.0
  static double x67 = _baseInset.insetTimes(67);
 
  /// [baseInset] multiplied by 68
  ///
  /// 4.0 x 68 = 272.0
  static double x68 = _baseInset.insetTimes(68);
 
  /// [baseInset] multiplied by 69
  ///
  /// 4.0 x 69 = 276.0
  static double x69 = _baseInset.insetTimes(69);
 
  /// [baseInset] multiplied by 70
  ///
  /// 4.0 x 70 = 280.0
  static double x70 = _baseInset.insetTimes(70);
 
  /// [baseInset] multiplied by 71
  ///
  /// 4.0 x 71 = 284.0
  static double x71 = _baseInset.insetTimes(71);
 
  /// [baseInset] multiplied by 72
  ///
  /// 4.0 x 72 = 288.0
  static double x72 = _baseInset.insetTimes(72);
 
  /// [baseInset] multiplied by 73
  ///
  /// 4.0 x 73 = 292.0
  static double x73 = _baseInset.insetTimes(73);
 
  /// [baseInset] multiplied by 74
  ///
  /// 4.0 x 74 = 296.0
  static double x74 = _baseInset.insetTimes(74);
 
  /// [baseInset] multiplied by 75
  ///
  /// 4.0 x 75 = 300.0
  static double x75 = _baseInset.insetTimes(75);
 
  /// [baseInset] multiplied by 76
  ///
  /// 4.0 x 76 = 304.0
  static double x76 = _baseInset.insetTimes(76);
 
  /// [baseInset] multiplied by 77
  ///
  /// 4.0 x 77 = 308.0
  static double x77 = _baseInset.insetTimes(77);
 
  /// [baseInset] multiplied by 78
  ///
  /// 4.0 x 78 = 312.0
  static double x78 = _baseInset.insetTimes(78);
 
  /// [baseInset] multiplied by 79
  ///
  /// 4.0 x 79 = 316.0
  static double x79 = _baseInset.insetTimes(79);
 
  /// [baseInset] multiplied by 80
  ///
  /// 4.0 x 80 = 320.0
  static double x80 = _baseInset.insetTimes(80);
 
  /// [baseInset] multiplied by 81
  ///
  /// 4.0 x 81 = 324.0
  static double x81 = _baseInset.insetTimes(81);
 
  /// [baseInset] multiplied by 82
  ///
  /// 4.0 x 82 = 328.0
  static double x82 = _baseInset.insetTimes(82);
 
  /// [baseInset] multiplied by 83
  ///
  /// 4.0 x 83 = 332.0
  static double x83 = _baseInset.insetTimes(83);
 
  /// [baseInset] multiplied by 84
  ///
  /// 4.0 x 84 = 336.0
  static double x84 = _baseInset.insetTimes(84);
 
  /// [baseInset] multiplied by 85
  ///
  /// 4.0 x 85 = 340.0
  static double x85 = _baseInset.insetTimes(85);
 
  /// [baseInset] multiplied by 86
  ///
  /// 4.0 x 86 = 344.0
  static double x86 = _baseInset.insetTimes(86);
 
  /// [baseInset] multiplied by 87
  ///
  /// 4.0 x 87 = 348.0
  static double x87 = _baseInset.insetTimes(87);
 
  /// [baseInset] multiplied by 88
  ///
  /// 4.0 x 88 = 352.0
  static double x88 = _baseInset.insetTimes(88);
 
  /// [baseInset] multiplied by 89
  ///
  /// 4.0 x 89 = 356.0
  static double x89 = _baseInset.insetTimes(89);
 
  /// [baseInset] multiplied by 90
  ///
  /// 4.0 x 90 = 360.0
  static double x90 = _baseInset.insetTimes(90);
 
  /// [baseInset] multiplied by 91
  ///
  /// 4.0 x 91 = 364.0
  static double x91 = _baseInset.insetTimes(91);
 
  /// [baseInset] multiplied by 92
  ///
  /// 4.0 x 92 = 368.0
  static double x92 = _baseInset.insetTimes(92);
 
  /// [baseInset] multiplied by 93
  ///
  /// 4.0 x 93 = 372.0
  static double x93 = _baseInset.insetTimes(93);
 
  /// [baseInset] multiplied by 94
  ///
  /// 4.0 x 94 = 376.0
  static double x94 = _baseInset.insetTimes(94);
 
  /// [baseInset] multiplied by 95
  ///
  /// 4.0 x 95 = 380.0
  static double x95 = _baseInset.insetTimes(95);
 
  /// [baseInset] multiplied by 96
  ///
  /// 4.0 x 96 = 384.0
  static double x96 = _baseInset.insetTimes(96);
}

Radius

ui_insets.dart
import 'package:flutter/material.dart';
import 'package:pixl_primitives/inset.dart';
 
final _baseRadius = BaseInset.init(8.0);
 
class UIRadius {
  /// [baseRadius] divided by 2
  ///
  /// 8.0 / 2 = 4.0
  static double sm = _baseRadius.insetSm();
 
  /// [baseRadius]
  ///
  /// baseRadius = 8.0
  static double x1 = _baseRadius;
 
  /// [baseRadius] multiplied by 2
  ///
  /// 8.0 x 2 = 16.0
  static double x2 = _baseRadius.insetTimes(2);
}