mirror of
https://github.com/hanzoai/gui.git
synced 2026-10-25 02:31:41 +00:00
React passes ref as a prop, and a forwardRef over props with an index signature drops every named prop through Omit; the font extras are optional in a spread function's config. Co-authored-by: Hanzo Dev <[email protected]>
88 lines
1.9 KiB
TypeScript
88 lines
1.9 KiB
TypeScript
import { getSize, getSpace } from '@hanzogui/get-token'
|
|
import type { SizeTokens } from '@hanzogui/web'
|
|
import {
|
|
GetProps,
|
|
View,
|
|
Text,
|
|
createStyledContext,
|
|
styled,
|
|
useTheme,
|
|
withStaticProperties,
|
|
} from '@hanzogui/web'
|
|
import { cloneElement, useContext } from 'react'
|
|
|
|
export const ButtonContext = createStyledContext({
|
|
size: '$md' as SizeTokens,
|
|
})
|
|
|
|
export const ButtonFrame = styled(View, {
|
|
name: 'Button',
|
|
context: ButtonContext,
|
|
backgroundColor: '$background',
|
|
alignItems: 'center',
|
|
flexDirection: 'row',
|
|
|
|
hoverStyle: {
|
|
backgroundColor: '$backgroundHover',
|
|
},
|
|
|
|
pressStyle: {
|
|
backgroundColor: '$backgroundPress',
|
|
},
|
|
|
|
variants: {
|
|
size: {
|
|
'...size': (name, { tokens }) => {
|
|
return {
|
|
height: tokens.size[name],
|
|
borderRadius: tokens.radius[name],
|
|
// note the getSpace and getSize helpers will let you shift down/up token sizes
|
|
// whereas with gap we just multiply by 0.2
|
|
// this is a stylistic choice, and depends on your design system values
|
|
gap: tokens.space[name].val * 0.2,
|
|
paddingHorizontal: getSpace(name, {
|
|
shift: -1,
|
|
}),
|
|
}
|
|
},
|
|
},
|
|
} as const,
|
|
|
|
defaultVariants: {
|
|
size: '$true',
|
|
},
|
|
})
|
|
|
|
export const ButtonText = styled(Text, {
|
|
name: 'ButtonText',
|
|
context: ButtonContext,
|
|
color: '$color',
|
|
userSelect: 'none',
|
|
|
|
variants: {
|
|
size: {
|
|
'...fontSize': (name, extras) => ({
|
|
fontSize: extras.font?.size[name],
|
|
}),
|
|
},
|
|
} as const,
|
|
})
|
|
|
|
const ButtonIcon = (props: { children: any }) => {
|
|
const { size } = useContext(ButtonContext.context)
|
|
const smaller = getSize(size, {
|
|
shift: -2,
|
|
})
|
|
const theme = useTheme()
|
|
return cloneElement(props.children, {
|
|
size: smaller.val * 0.5,
|
|
color: theme.color?.get(),
|
|
})
|
|
}
|
|
|
|
export const Button = withStaticProperties(ButtonFrame, {
|
|
Props: ButtonContext.Provider,
|
|
Text: ButtonText,
|
|
Icon: ButtonIcon,
|
|
})
|