Files
asciinevrdie/lib/src/features/game/widgets/menu/retro_menu_widgets.dart
JiWoong Sul c5eaecfa6a refactor(ui): mobile_carousel_layout.dart 분할 (1220→689 LOC)
- RetroSelectDialog, RetroOptionItem: 선택 다이얼로그
- RetroSoundDialog: 사운드 설정 다이얼로그
- RetroConfirmDialog: 확인 다이얼로그
- RetroMenuSection, RetroMenuItem, RetroSpeedChip: 메뉴 위젯
2026-01-21 17:33:52 +09:00

205 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:asciineverdie/src/shared/retro_colors.dart';
/// 메뉴 섹션 타이틀
class RetroMenuSection extends StatelessWidget {
const RetroMenuSection({
super.key,
required this.title,
this.color,
});
final String title;
final Color? color;
@override
Widget build(BuildContext context) {
final gold = color ?? RetroColors.goldOf(context);
return Row(
children: [
Container(width: 4, height: 14, color: gold),
const SizedBox(width: 8),
Text(
title,
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 9,
color: gold,
letterSpacing: 1,
),
),
],
);
}
}
/// 메뉴 아이템
class RetroMenuItem extends StatelessWidget {
const RetroMenuItem({
super.key,
required this.icon,
required this.iconColor,
required this.label,
this.value,
this.subtitle,
this.trailing,
this.onTap,
});
final IconData icon;
final Color iconColor;
final String label;
final String? value;
final String? subtitle;
final Widget? trailing;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
final border = RetroColors.borderOf(context);
final panelBg = RetroColors.panelBgOf(context);
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
decoration: BoxDecoration(
color: panelBg,
border: Border.all(color: border, width: 1),
),
child: Row(
children: [
Icon(icon, size: 16, color: iconColor),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 16,
color: RetroColors.textPrimaryOf(context),
),
),
if (subtitle != null) ...[
const SizedBox(height: 4),
Text(
subtitle!,
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 12,
color: RetroColors.textMutedOf(context),
),
),
],
],
),
),
if (value != null)
Text(
value!,
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 14,
color: RetroColors.goldOf(context),
),
),
if (trailing != null) trailing!,
],
),
),
);
}
}
/// 속도 선택 칩
///
/// - 배속 토글 버튼
/// - 부스트 활성화 중: 반투명, 비활성
/// - 부스트 비활성화: 불투명, 활성
class RetroSpeedChip extends StatelessWidget {
const RetroSpeedChip({
super.key,
required this.speed,
required this.isSelected,
required this.onTap,
this.isAdBased = false,
this.isDisabled = false,
});
final int speed;
final bool isSelected;
final VoidCallback onTap;
final bool isAdBased;
/// 비활성 상태 (반투명, 탭 무시)
final bool isDisabled;
@override
Widget build(BuildContext context) {
final gold = RetroColors.goldOf(context);
final warning = RetroColors.warningOf(context);
final border = RetroColors.borderOf(context);
// 비활성 상태면 반투명 처리
final opacity = isDisabled ? 0.4 : 1.0;
final Color bgColor;
final Color textColor;
final Color borderColor;
if (isSelected) {
bgColor = isAdBased
? warning.withValues(alpha: 0.3 * opacity)
: gold.withValues(alpha: 0.3 * opacity);
textColor = (isAdBased ? warning : gold).withValues(alpha: opacity);
borderColor = (isAdBased ? warning : gold).withValues(alpha: opacity);
} else if (isAdBased) {
bgColor = Colors.transparent;
textColor = warning.withValues(alpha: opacity);
borderColor = warning.withValues(alpha: opacity);
} else {
bgColor = Colors.transparent;
textColor = RetroColors.textMutedOf(context).withValues(alpha: opacity);
borderColor = border.withValues(alpha: opacity);
}
return GestureDetector(
// 비활성 상태면 탭 무시
onTap: isDisabled ? null : onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: bgColor,
border: Border.all(color: borderColor, width: isSelected ? 2 : 1),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (isAdBased && !isSelected && !isDisabled)
Padding(
padding: const EdgeInsets.only(right: 2),
child: Text(
'',
style: TextStyle(fontSize: 7, color: warning),
),
),
Text(
'${speed}x',
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 8,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
color: textColor,
),
),
],
),
),
);
}
}