Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 2x 60x 60x 60x 60x 180x 180x 180x 26x 5x 4x 4x 4x 3x 3x | /**
* ControlCategoryTabs - Tab navigation for control categories
*
* Allows switching between Combat, Movement, and System control views
* Uses BaseButtonOverlayHtml for consistent styling
*
* @module components/screens/controls/components
*/
import React, { useMemo } from "react";
import { hexToRgbaString } from "../../../../utils/colorUtils";
import { useKoreanTheme } from "../../../shared/base/useKoreanTheme";
import { CONTROL_CATEGORIES } from "../constants/ControlsConstants";
export interface ControlCategoryTabsProps {
readonly selectedTab: 'combat' | 'movement' | 'system';
readonly onTabChange: (tab: 'combat' | 'movement' | 'system') => void;
readonly isMobile: boolean;
}
/**
* ControlCategoryTabs Component
*
* Displays tabs for switching between control categories.
* Uses Korean theming and responsive sizing.
*
* @example
* ```tsx
* <ControlCategoryTabs
* selectedTab="combat"
* onTabChange={(tab) => setSelectedTab(tab)}
* isMobile={false}
* />
* ```
*/
export const ControlCategoryTabs: React.FC<ControlCategoryTabsProps> = ({
selectedTab,
onTabChange,
isMobile,
}) => {
const theme = useKoreanTheme({ variant: 'primary', size: 'md', isMobile });
const tabStyle = useMemo(() => ({
display: 'flex',
flexDirection: 'row' as const,
gap: isMobile ? '8px' : '12px',
justifyContent: 'center',
alignItems: 'center',
padding: isMobile ? '10px' : '15px',
flexWrap: 'wrap' as const,
}), [isMobile]);
const buttonBaseStyle = useMemo(() => ({
padding: isMobile ? '8px 16px' : '12px 24px',
borderRadius: '8px',
border: `2px solid ${hexToRgbaString(theme.colors.UI_BORDER, 0.6)}`,
cursor: 'pointer',
transition: 'all 0.2s ease',
fontFamily: 'inherit',
fontSize: isMobile ? '14px' : '16px',
fontWeight: 'bold' as const,
display: 'flex',
alignItems: 'center',
gap: '8px',
}), [isMobile, theme]);
return (
<div style={tabStyle} data-testid="control-category-tabs">
{CONTROL_CATEGORIES.map((category) => {
const isSelected = selectedTab === category.id;
const buttonStyle = {
...buttonBaseStyle,
background: isSelected
? hexToRgbaString(category.color, 0.3)
: hexToRgbaString(theme.colors.UI_BACKGROUND_DARK, 0.8),
borderColor: isSelected
? hexToRgbaString(category.color, 1)
: hexToRgbaString(theme.colors.UI_BORDER, 0.6),
color: isSelected
? `#${category.color.toString(16).padStart(6, '0')}`
: `#${theme.colors.TEXT_SECONDARY.toString(16).padStart(6, '0')}`,
};
return (
<button
key={category.id}
style={buttonStyle}
onClick={() => onTabChange(category.id as 'combat' | 'movement' | 'system')}
data-testid={`tab-${category.id}`}
onMouseEnter={(e) => {
if (!isSelected) {
e.currentTarget.style.background = hexToRgbaString(category.color, 0.1);
e.currentTarget.style.borderColor = hexToRgbaString(category.color, 0.8);
}
}}
onMouseLeave={(e) => {
if (!isSelected) {
e.currentTarget.style.background = hexToRgbaString(theme.colors.UI_BACKGROUND_DARK, 0.8);
e.currentTarget.style.borderColor = hexToRgbaString(theme.colors.UI_BORDER, 0.6);
}
}}
>
<span role="img" aria-label={category.english}>{category.icon}</span>
<span>{category.korean} | {category.english}</span>
</button>
);
})}
</div>
);
};
|