Add some form elements
This commit is contained in:
+5
-7
@@ -4,14 +4,10 @@ import type {Mutable} from '#/alf/types'
|
||||
export type ThemeName = 'light' | 'dark'
|
||||
export type ReadonlyTheme = typeof light
|
||||
export type Theme = Mutable<ReadonlyTheme>
|
||||
export type ReadonlyPalette = typeof lightPalette
|
||||
export type Palette = Mutable<ReadonlyPalette>
|
||||
|
||||
export type Palette = {
|
||||
primary: string
|
||||
positive: string
|
||||
negative: string
|
||||
}
|
||||
|
||||
export const lightPalette: Palette = {
|
||||
export const lightPalette = {
|
||||
primary: tokens.color.blue_500,
|
||||
positive: tokens.color.green_500,
|
||||
negative: tokens.color.red_500,
|
||||
@@ -24,6 +20,7 @@ export const darkPalette: Palette = {
|
||||
} as const
|
||||
|
||||
export const light = {
|
||||
name: 'light',
|
||||
palette: lightPalette,
|
||||
atoms: {
|
||||
text: {
|
||||
@@ -66,6 +63,7 @@ export const light = {
|
||||
}
|
||||
|
||||
export const dark: Theme = {
|
||||
name: 'dark',
|
||||
palette: darkPalette,
|
||||
atoms: {
|
||||
text: {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
|
||||
import {atoms, tokens, web, native} from '#/alf'
|
||||
import {useTheme, atoms, tokens, web, native} from '#/alf'
|
||||
|
||||
export type ButtonType = 'primary' | 'secondary' | 'negative'
|
||||
export type ButtonSize = 'small' | 'large'
|
||||
@@ -217,6 +217,8 @@ export function ButtonText({
|
||||
disabled,
|
||||
...rest
|
||||
}: ButtonTextProps) {
|
||||
const t = useTheme()
|
||||
|
||||
const textStyles = React.useMemo(() => {
|
||||
const baseStyles = []
|
||||
|
||||
@@ -244,6 +246,7 @@ export function ButtonText({
|
||||
break
|
||||
}
|
||||
default:
|
||||
baseStyles.push(t.atoms.text)
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
@@ -267,7 +270,7 @@ export function ButtonText({
|
||||
}
|
||||
|
||||
return baseStyles
|
||||
}, [type, size, disabled])
|
||||
}, [t, type, size, disabled])
|
||||
|
||||
return (
|
||||
<Text
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms} from '#/alf'
|
||||
|
||||
/**
|
||||
* NOT FINISHED, just here as a reference
|
||||
*/
|
||||
export function InputGroup(props: React.PropsWithChildren<{}>) {
|
||||
const children = React.Children.toArray(props.children)
|
||||
const total = children.length
|
||||
return (
|
||||
<View style={[atoms.w_full]}>
|
||||
{children.map((child, i) => {
|
||||
return React.isValidElement(child) ? (
|
||||
<React.Fragment key={i}>
|
||||
{React.cloneElement(child, {
|
||||
// @ts-ignore
|
||||
style: [
|
||||
...(Array.isArray(child.props?.style)
|
||||
? child.props.style
|
||||
: [child.props.style || {}]),
|
||||
{
|
||||
borderTopLeftRadius: i > 0 ? 0 : undefined,
|
||||
borderTopRightRadius: i > 0 ? 0 : undefined,
|
||||
borderBottomLeftRadius: i < total - 1 ? 0 : undefined,
|
||||
borderBottomRightRadius: i < total - 1 ? 0 : undefined,
|
||||
borderBottomWidth: i < total - 1 ? 0 : undefined,
|
||||
},
|
||||
],
|
||||
})}
|
||||
</React.Fragment>
|
||||
) : null
|
||||
})}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import React from 'react'
|
||||
import {View, TextInput, TextInputProps, TextStyle} from 'react-native'
|
||||
|
||||
import {useTheme, atoms, web, tokens} from '#/alf'
|
||||
|
||||
type Props = Omit<TextInputProps, 'placeholder'> & {
|
||||
placeholder: string
|
||||
hasError?: boolean
|
||||
icon?: React.FunctionComponent<any>
|
||||
}
|
||||
|
||||
export function InputText({hasError, icon: Icon, ...props}: Props) {
|
||||
const t = useTheme()
|
||||
const [state, setState] = React.useState({
|
||||
hovered: false,
|
||||
focused: false,
|
||||
})
|
||||
|
||||
const onHoverIn = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
hovered: true,
|
||||
}))
|
||||
}, [setState])
|
||||
const onHoverOut = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
hovered: false,
|
||||
}))
|
||||
}, [setState])
|
||||
const onFocus = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
focused: true,
|
||||
}))
|
||||
}, [setState])
|
||||
const onBlur = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
focused: false,
|
||||
}))
|
||||
}, [setState])
|
||||
|
||||
const {inputStyles, iconStyles} = React.useMemo(() => {
|
||||
const input: TextStyle[] = []
|
||||
const icon: TextStyle[] = []
|
||||
|
||||
if (Icon) {
|
||||
input.push({
|
||||
paddingLeft: 40,
|
||||
})
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
input.push({
|
||||
borderColor: tokens.color.red_200,
|
||||
})
|
||||
icon.push({
|
||||
color: tokens.color.red_400,
|
||||
})
|
||||
}
|
||||
|
||||
if (state.hovered || state.focused) {
|
||||
input.push({
|
||||
borderColor: t.atoms.border_contrast_500.borderColor,
|
||||
})
|
||||
|
||||
if (hasError) {
|
||||
input.push({
|
||||
borderColor: tokens.color.red_500,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {inputStyles: input, iconStyles: icon}
|
||||
}, [t, state, hasError, Icon])
|
||||
|
||||
return (
|
||||
<View style={[atoms.relative, atoms.w_full]}>
|
||||
<TextInput
|
||||
{...props}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
{...web({
|
||||
onMouseEnter: onHoverIn,
|
||||
onMouseLeave: onHoverOut,
|
||||
})}
|
||||
placeholderTextColor={t.atoms.text_contrast_500.color}
|
||||
style={[
|
||||
t.name === 'dark' ? t.atoms.bg_contrast_100 : t.atoms.bg,
|
||||
atoms.w_full,
|
||||
atoms.px_lg,
|
||||
atoms.py_md,
|
||||
atoms.rounded_sm,
|
||||
t.atoms.border,
|
||||
t.atoms.text,
|
||||
{borderWidth: 2},
|
||||
web({
|
||||
paddingTop: atoms.pt_md.paddingTop - 1,
|
||||
}),
|
||||
...inputStyles,
|
||||
...(Array.isArray(props.style) ? props.style : [props.style]),
|
||||
]}
|
||||
/>
|
||||
|
||||
{Icon && (
|
||||
<Icon
|
||||
style={[
|
||||
atoms.absolute,
|
||||
atoms.inset_0,
|
||||
{color: t.atoms.border_contrast_500.borderColor},
|
||||
{
|
||||
left: atoms.px_md.paddingLeft,
|
||||
right: 'auto',
|
||||
width: 20,
|
||||
marginVertical: 'auto',
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
...iconStyles,
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react'
|
||||
import {StyleSheet} from 'react-native'
|
||||
import Svg, {
|
||||
Path,
|
||||
Defs,
|
||||
@@ -19,7 +20,8 @@ type Props = {
|
||||
export const Logo = React.forwardRef(function LogoImpl(props: Props, ref) {
|
||||
const {fill, ...rest} = props
|
||||
const gradient = fill === 'sky'
|
||||
const _fill = gradient ? 'url(#sky)' : fill || colors.blue3
|
||||
const styles = StyleSheet.flatten(props.style)
|
||||
const _fill = gradient ? 'url(#sky)' : fill || styles?.color || colors.blue3
|
||||
// @ts-ignore it's fiiiiine
|
||||
const size = parseInt(rest.width || 32)
|
||||
return (
|
||||
@@ -29,7 +31,7 @@ export const Logo = React.forwardRef(function LogoImpl(props: Props, ref) {
|
||||
ref={ref}
|
||||
viewBox="0 0 64 57"
|
||||
{...rest}
|
||||
style={{width: size, height: size * ratio}}>
|
||||
style={[{width: size, height: size * ratio}, styles]}>
|
||||
{gradient && (
|
||||
<Defs>
|
||||
<LinearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
|
||||
|
||||
@@ -9,6 +9,8 @@ import {atoms as a, useTheme, useBreakpoints, ThemeProvider as Alf} from '#/alf'
|
||||
import {Button, ButtonText} from '#/view/com/Button'
|
||||
import {Link} from '#/view/com/Link'
|
||||
import {Text, H1, H2, H3, H4, H5, H6} from '#/view/com/Typography'
|
||||
import {InputText} from '#/view/com/forms/InputText'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
|
||||
function ThemeSelector() {
|
||||
const setColorMode = useSetColorMode()
|
||||
@@ -212,6 +214,16 @@ export function Buttons() {
|
||||
)
|
||||
}
|
||||
|
||||
function Forms() {
|
||||
return (
|
||||
<View style={[a.gap_md, a.align_start]}>
|
||||
<InputText placeholder="Type here" />
|
||||
<InputText placeholder="Type here" icon={Logo} />
|
||||
<InputText hasError placeholder="Type here" icon={Logo} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export function DebugScreen() {
|
||||
const t = useTheme()
|
||||
|
||||
@@ -221,6 +233,7 @@ export function DebugScreen() {
|
||||
<View style={[a.p_xl, a.gap_xxl, {paddingBottom: 200}]}>
|
||||
<ThemeSelector />
|
||||
|
||||
<Forms />
|
||||
<Buttons />
|
||||
|
||||
<Alf theme="light">
|
||||
|
||||
Reference in New Issue
Block a user