테마
Tinyrack Material 3 라이트·다크 테마를 앱에 적용해요.
앱 경계에서 두 테마를 함께 적용해요.
MaterialApp(
theme: TinyrackTheme.light(),
darkTheme: TinyrackTheme.dark(),
themeMode: ThemeMode.system,
home: const App(),
);
두 테마 모두 Material 3를 사용하고 TinyrackThemeData를
ThemeExtension으로 설치해요. 시맨틱 surface 색상을 Material의 canvas와
scaffold 배경에 연결하므로 라우팅된 페이지도 기본적으로 같은 라이트·다크
표면을 사용해요. 사용자 정의 위젯에서 Tinyrack 컴포넌트와 같은 시맨틱 색상이
필요하면 context.tinyrackTheme에서 읽으세요. 포커스, 키보드, 제스처,
semantics, text scaling은 Flutter 규약을 그대로 따라요.
IBM Plex Sans, Mono, 한국어, 일본어 글꼴 파일 11개를 패키지에 포함해요. 플랫폼 패키징 전 크기는 약 16.4MB이며 앱의 Flutter 에셋 번들에 함께 들어가요. 실행 중에 글꼴을 따로 내려받지는 않아요.
UI 밀도
좁거나 터치를 우선하는 화면에서 UI 전체를 더 편하게 읽고 조작하려면
TRUiDensityScope를 사용하세요. 반응형 조건은 제품에서 정해요. scope는
standard에서 기존 기본값을 유지하고, comfortable에서 48px
TRUiSize.xl 컨트롤, 한 단계 큰 타이포그래피, 넉넉한 기본 카드 여백과 상태
표시를 사용해요.
LayoutBuilder(
builder: (context, constraints) => TRUiDensityScope(
density: constraints.maxWidth < TRBreakpoints.small
? TRUiDensity.comfortable
: TRUiDensity.standard,
child: const AppContent(),
),
);
크기를 고정해야 하는 컴포넌트에는 uiSize나 카드 여백을 직접 지정하세요.
명시한 sm, md, lg, xl은 scope보다 우선해요. 시스템 text scaling은
밀도에서 고른 타이포그래피 위에 그대로 적용돼요.
Flutter가 그리는 팝업 행은 앵커 컨트롤과 별도로 밀도를 결정해요. standard는
TRUiSize.sm 행 지표(높이 28px, 레이블 12px)를 사용하고, comfortable은
TRUiSize.lg 행 지표(높이 40px, 레이블 14px)를 사용해요. 메뉴, 중첩 메뉴,
메뉴바, Flutter 컨텍스트 메뉴, 셀렉트, 자동완성, 콤보박스, 인라인 제안은 root
overlay에서도 앵커의 밀도를 유지해요. 메뉴에 명시한 uiSize는 계속 트리거만
바꾸며, 특정 팝업을 작게 유지하려면 앵커를 중첩 standard scope로 감싸세요.
페이지 전환
두 테마 모두 모든 TargetPlatform에 TRPageTransitionsBuilder를 설치해요.
Android는 Flutter의 predictive Back 전환을 사용하고 iOS, macOS, Linux,
Windows는 Material forward-fade 모션을 사용해요. 플랫폼이
disableAnimations를 알리면 모션 없이 페이지를 그대로 반환해요.
라우팅된 영역에 다른 모션 규약이 필요할 때만 별도 빌더를 설치하세요. Page의
수명주기와 identity는 유지하면서 고정된 영역을 움직이지 않으려면
TRPageTransitionsBuilder.none()을 사용하세요.
ThemeData theme = TinyrackTheme.light().copyWith(
pageTransitionsTheme: const PageTransitionsTheme(
builders: <TargetPlatform, PageTransitionsBuilder>{
TargetPlatform.windows: TRPageTransitionsBuilder.none(),
},
),
);
크로스 플랫폼 컴포넌트 규약
React와 Flutter에 같은 개념이 있으면 시맨틱 토큰과 컴포넌트의 목적을 공유해요. 공개 API, 구성, 상호작용 방식, 렌더링 픽셀까지 같다고 보장하지는 않아요.
| 이전 | 현재 |
|---|---|
Alert와 Badge의 intent | variant: TRStatusVariant.* |
| 시각·로딩 옵션이 없던 IconButton | appearance, loading, loadingLabel |
| Card의 자유 형식 여백 | TRCardPadding, TRCardVariant, Card 구성 위젯 |
| 상위 색상만 따르던 Spinner | variant: TRSpinnerVariant.* |
Text의 role, TRTextStyle, 임의 색상 | TRTextVariant와 타입이 지정된 color, align, weight, truncate |
TRTextField의 Flutter Form 생명 주기 속성은 그대로 사용할 수 있어요.
저장소 검사는 모든 공개 컴포넌트를 공통 목적, 명시적인 플랫폼 적응,
플랫폼 전용 기능 중 하나로 분류해요. React 브라우저 테스트와 Flutter
위젯·golden 테스트는 각 렌더링 엔진 안에서 동작과 모양을 검증해요.