2024. 4. 13. 09:26ㆍ개발/Flutter
회사에서 피그마 value 값을 토큰화 시키는 작업을 진행중이다.
(참고로 style dictionary 는 아래와 같은 토큰값을 지원한다)
color
dimension
custom-radius
custom-spacing
custom-fontStyle
custom-icon
https://github.com/aloisdeniel/style-dictionary-figma-flutter
GitHub - aloisdeniel/style-dictionary-figma-flutter: Custom style-dictionary transforms and formats to generate Flutter resource
Custom style-dictionary transforms and formats to generate Flutter resources from a Figma Design Token plugin export.. - aloisdeniel/style-dictionary-figma-flutter
github.com
아무튼
code generator를 사용해서 만들어지는 값들은(ex: style dictionary) 영 마음에 안들어서...
final Color colorsMultipleFills0;
final Color colorsMultipleFills1;
final Color colorsRefBlue;
final Color colorsSingleBlue;
final Color colorsSpecialCharacters;
final Color colorsSpecialCharactersNderung;
final Color darkBackground;
final Color invalidEmpty;
final Color lightBackground;
이런식으로 이름 그대로 지정이 된다.
color는 material color 사용하는것처럼 color를 만들고, (이건 다음 글로)
static const dsRed = MaterialColor(_dsRedPrimaryValue, <int, Color>{
100: Color(0xFFFFD6DA),
200: Color(0xFFFFA3AC),
300: Color(0xFFFF808B),
400: Color(0xFFFF5262),
500: Color(_dsRedPrimaryValue),
600: Color(0xFFCC0013),
700: Color(0xFF99000E),
800: Color(0xFF66000A),
900: Color(0xFF330005),
});
static const _dsRedPrimaryValue = 0xFFFF0018;
(이렇게 사용하면 dsRed[100]과 같은 형태로 사용이 가능하다)
padding widget은 side flag를 넣어서 아래와 같이 방향, 픽셀값만 지정하면 사용할 수 있게끔 util화 시켰다.
import 'package:flutter/material.dart';
class Dimension {
late _DimensionSide _left;
late _DimensionSide _top;
late _DimensionSide _right;
late _DimensionSide _bottom;
late _DimensionSide _horizontal;
late _DimensionSide _vertical;
late _DimensionSide _all;
Dimension() {
_left = _DimensionSide(_SideFlag(1, 0, 0, 0));
_top = _DimensionSide(_SideFlag(0, 1, 0, 0));
_right = _DimensionSide(_SideFlag(0, 0, 1, 0));
_bottom = _DimensionSide(_SideFlag(0, 0, 0, 1));
_horizontal = _DimensionSide(_SideFlag(1, 0, 1, 0));
_vertical = _DimensionSide(_SideFlag(0, 1, 0, 1));
_all = _DimensionSide(_SideFlag(1, 1, 1, 1));
}
_DimensionSide get left => _left;
_DimensionSide get top => _top;
_DimensionSide get right => _right;
_DimensionSide get bottom => _bottom;
_DimensionSide get horizontal => _horizontal;
_DimensionSide get vertical => _vertical;
_DimensionSide get all => _all;
}
class _DimensionSide {
_SideFlag sideFlag;
_DimensionSide(this.sideFlag);
EdgeInsets get none {
return _DimensionSize(sideFlag, _Helper.none).data;
}
EdgeInsets get px_4 {
return _DimensionSize(sideFlag, _Helper.px_4).data;
}
EdgeInsets get px_6 {
return _DimensionSize(sideFlag, _Helper.px_6).data;
}
EdgeInsets get px_8 {
return _DimensionSize(sideFlag, _Helper.px_8).data;
}
EdgeInsets get px_12 {
return _DimensionSize(sideFlag, _Helper.px_12).data;
}
EdgeInsets get px_16 {
return _DimensionSize(sideFlag, _Helper.px_16).data;
}
EdgeInsets get px_24 {
return _DimensionSize(sideFlag, _Helper.px_24).data;
}
}
class _DimensionSize {
_SideFlag sideFlag;
double factor;
_DimensionSize(this.sideFlag, this.factor);
get data => EdgeInsets.fromLTRB(
sideFlag.leftFlag * factor,
sideFlag.topFlag * factor,
sideFlag.rightFlag * factor,
sideFlag.bottomFlag * factor,
);
}
class _SideFlag {
double leftFlag = 0;
double topFlag = 0;
double rightFlag = 0;
double bottomFlag = 0;
_SideFlag(
this.leftFlag,
this.topFlag,
this.rightFlag,
this.bottomFlag,
);
}
class _Helper {
static double none = 0;
static double px_4 = 4;
static double px_6 = 6;
static double px_8 = 8;
static double px_12 = 12;
static double px_16 = 16;
static double px_24 = 24;
}
Dimension spacer = Dimension();
코드를 보면 알겠지만, sideflag는 boxshadow등등, 방향 지정이 필요한 곳에서 반복적으로 사용될것이므로 private로 선언했다.
helper 키워드 같은 경우에는, 피그마에서 토큰 값이 추가될 경우 변경되는 부분이다. 현재 우리는 저 7가지 값만을 사용중이다.
전역으로 사용 가능한 객체인 spacer를 사용하면
class DSDotTag extends StatelessWidget {
final String label;
final Color? backgroundColor;
final Color? textColor;
final TextStyle textStyle;
const DSDotTag({
super.key,
required this.label,
required this.backgroundColor,
required this.textColor,
required this.textStyle,
});
@override
Widget build(BuildContext context) {
return Card(
elevation: 0,
color: backgroundColor,
shape: RoundedRectangleBorder(
borderRadius: borderRadiusWidget.px_6,
),
child: Padding(
padding: spacer.top.px_4 + spacer.bottom.px_4 + spacer.left.px_8 + spacer.right.px_6,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
size: 4,
Icons.circle,
color: textColor,
),
sizedBox.horizontal.px_4,
Text(
label,
style: textStyle.copyWith(color: textColor),
),
],
),
),
);
}
}
이 예시처럼
요런 식으로..
padding: spacer.top.px_4 + spacer.bottom.px_4 + spacer.left.px_8 + spacer.right.px_6,
spacer를 불러와 어느 위젯에서든 자유자재로 지정이 가능하다.
회사 디자인 시스템의 uikit를 flutter로 구현하면서,
구체적인 하드코딩 값을 사용하지 않는 위젯 코드를 끊임없이 연구중이다.
앞으로도 자주 구체적인 사례를 공유하러 와야지..
끗!