- 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
79 lines
2 KiB
TypeScript
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>
|
|
)
|
|
}
|