d3ro-voice/packages/ui-native/src/components/PhysicalButton.tsx
Yun Chan 660e622a93 refactor(ui-native): d3roNativePalette amber->main 개명 (WS-NATIVE)
- packages/ui-native theme.ts accent: amber->main, amberDim->dim, amberGlow->glow (값 보존)
- apps/mobile 20건 + apps/mobile-rn 18건 + ui-native 컴포넌트 9건 = 47 참조 치환
SKIP: Led/PhosphorText/Header color prop 'amber'(의미론적 컴포넌트 API, 별도 마이그레이션)
       green/greenGlow 키(amber계 범위外)
정책: docs/REFACTOR_POLICY.md DP1, 이식 인사이트 P7
2026-07-22 02:37:45 +09:00

79 lines
2 KiB
TypeScript

// packages/ui-native/src/components/PhysicalButton.tsx
// RN용 PhysicalButton — Pressable 기반 누르는 느낌
import { useState } from 'react'
import {
Pressable,
Text,
type PressableProps,
type ViewStyle,
type TextStyle,
type StyleProp
} from 'react-native'
import { d3roNativePalette, d3roNativeRadius, d3roNativeTypo } from '../theme'
export interface PhysicalButtonProps extends Omit<PressableProps, 'children' | 'style'> {
label: string
variant?: 'primary' | 'secondary' | 'danger'
disabled?: boolean
style?: StyleProp<ViewStyle>
}
export function PhysicalButton({
label,
variant = 'primary',
disabled = false,
style,
onPress,
...rest
}: PhysicalButtonProps): React.ReactElement {
const [pressed, setPressed] = useState(false)
const bgColor =
variant === 'primary'
? d3roNativePalette.accent.main
: variant === 'danger'
? d3roNativePalette.tag.red
: 'transparent'
const borderColor =
variant === 'secondary' ? d3roNativePalette.border.strong : 'transparent'
const textColor =
variant === 'primary' || variant === 'danger'
? d3roNativePalette.text.primary
: d3roNativePalette.text.secondary
const containerStyle: ViewStyle = {
backgroundColor: bgColor,
borderColor,
borderWidth: variant === 'secondary' ? 1 : 0,
borderRadius: d3roNativeRadius.button,
paddingVertical: 14,
paddingHorizontal: 24,
alignItems: 'center',
justifyContent: 'center',
opacity: disabled ? 0.4 : pressed ? 0.75 : 1,
transform: [{ translateY: pressed && !disabled ? 1 : 0 }]
}
const textStyle: TextStyle = {
...d3roNativeTypo.heading,
color: textColor,
textTransform: 'uppercase',
letterSpacing: 1.5
}
return (
<Pressable
onPress={onPress}
onPressIn={() => setPressed(true)}
onPressOut={() => setPressed(false)}
disabled={disabled}
style={[containerStyle, style]}
{...rest}
>
<Text style={textStyle}>{label}</Text>
</Pressable>
)
}