Add Prompt, Dialog refinement, mobile refinement
This commit is contained in:
@@ -5,6 +5,7 @@ import * as themes from '#/alf/themes'
|
|||||||
export * as tokens from '#/alf/tokens'
|
export * as tokens from '#/alf/tokens'
|
||||||
export {atoms} from '#/alf/atoms'
|
export {atoms} from '#/alf/atoms'
|
||||||
export * from '#/alf/util/platform'
|
export * from '#/alf/util/platform'
|
||||||
|
export * from '#/alf/util/flatten'
|
||||||
|
|
||||||
type BreakpointName = keyof typeof breakpoints
|
type BreakpointName = keyof typeof breakpoints
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,36 @@ export const lightPalette = {
|
|||||||
primary: tokens.color.blue_500,
|
primary: tokens.color.blue_500,
|
||||||
positive: tokens.color.green_500,
|
positive: tokens.color.green_500,
|
||||||
negative: tokens.color.red_500,
|
negative: tokens.color.red_500,
|
||||||
|
|
||||||
|
contrast_0: tokens.color.gray_0,
|
||||||
|
contrast_100: tokens.color.gray_100,
|
||||||
|
contrast_200: tokens.color.gray_200,
|
||||||
|
contrast_300: tokens.color.gray_300,
|
||||||
|
contrast_400: tokens.color.gray_400,
|
||||||
|
contrast_500: tokens.color.gray_500,
|
||||||
|
contrast_600: tokens.color.gray_600,
|
||||||
|
contrast_700: tokens.color.gray_700,
|
||||||
|
contrast_800: tokens.color.gray_800,
|
||||||
|
contrast_900: tokens.color.gray_900,
|
||||||
|
contrast_1000: tokens.color.gray_1000,
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const darkPalette: Palette = {
|
export const darkPalette: Palette = {
|
||||||
primary: tokens.color.blue_500,
|
primary: tokens.color.blue_500,
|
||||||
positive: tokens.color.green_400,
|
positive: tokens.color.green_400,
|
||||||
negative: tokens.color.red_400,
|
negative: tokens.color.red_400,
|
||||||
|
|
||||||
|
contrast_0: tokens.color.gray_1000,
|
||||||
|
contrast_100: tokens.color.gray_900,
|
||||||
|
contrast_200: tokens.color.gray_800,
|
||||||
|
contrast_300: tokens.color.gray_700,
|
||||||
|
contrast_400: tokens.color.gray_600,
|
||||||
|
contrast_500: tokens.color.gray_500,
|
||||||
|
contrast_600: tokens.color.gray_400,
|
||||||
|
contrast_700: tokens.color.gray_300,
|
||||||
|
contrast_800: tokens.color.gray_200,
|
||||||
|
contrast_900: tokens.color.gray_100,
|
||||||
|
contrast_1000: tokens.color.gray_0,
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const light = {
|
export const light = {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import {StyleSheet} from 'react-native'
|
||||||
|
|
||||||
|
export const flatten = StyleSheet.flatten
|
||||||
@@ -284,13 +284,7 @@ export function ButtonText({
|
|||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
{...rest}
|
{...rest}
|
||||||
style={[
|
style={[atoms.font_semibold, atoms.text_center, ...textStyles, style]}>
|
||||||
atoms.flex_1,
|
|
||||||
atoms.font_semibold,
|
|
||||||
atoms.text_center,
|
|
||||||
...textStyles,
|
|
||||||
style,
|
|
||||||
]}>
|
|
||||||
{children}
|
{children}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,5 +15,9 @@ export function useDialogControl() {
|
|||||||
close: () => {},
|
close: () => {},
|
||||||
})
|
})
|
||||||
|
|
||||||
return control
|
return {
|
||||||
|
ref: control,
|
||||||
|
open: () => control.current.open(),
|
||||||
|
close: () => control.current.close(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ import {
|
|||||||
} from '#/view/com/Dialog/types'
|
} from '#/view/com/Dialog/types'
|
||||||
import {Context} from '#/view/com/Dialog/context'
|
import {Context} from '#/view/com/Dialog/context'
|
||||||
|
|
||||||
export {useDialogControl} from '#/view/com/Dialog/context'
|
export {useDialogControl, useDialogContext} from '#/view/com/Dialog/context'
|
||||||
|
export * from '#/view/com/Dialog/types'
|
||||||
|
|
||||||
export function Outer({
|
export function Outer({
|
||||||
|
children,
|
||||||
control,
|
control,
|
||||||
onClose,
|
onClose,
|
||||||
children,
|
nativeOptions,
|
||||||
}: React.PropsWithChildren<DialogOuterProps>) {
|
}: React.PropsWithChildren<DialogOuterProps>) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const sheet = React.useRef<BottomSheet>(null)
|
const sheet = React.useRef<BottomSheet>(null)
|
||||||
@@ -32,7 +34,7 @@ export function Outer({
|
|||||||
}, [onClose])
|
}, [onClose])
|
||||||
|
|
||||||
useImperativeHandle(
|
useImperativeHandle(
|
||||||
control,
|
control.ref,
|
||||||
() => ({
|
() => ({
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
@@ -45,13 +47,14 @@ export function Outer({
|
|||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<BottomSheet
|
<BottomSheet
|
||||||
ref={sheet}
|
|
||||||
index={-1}
|
|
||||||
snapPoints={['90%']}
|
snapPoints={['90%']}
|
||||||
enablePanDownToClose
|
enablePanDownToClose
|
||||||
keyboardBehavior="extend"
|
keyboardBehavior="extend"
|
||||||
backgroundStyle={{backgroundColor: 'transparent'}}
|
|
||||||
android_keyboardInputMode="adjustResize"
|
android_keyboardInputMode="adjustResize"
|
||||||
|
{...(nativeOptions?.sheet || {})}
|
||||||
|
ref={sheet}
|
||||||
|
index={-1}
|
||||||
|
backgroundStyle={{backgroundColor: 'transparent'}}
|
||||||
backdropComponent={props => (
|
backdropComponent={props => (
|
||||||
<BottomSheetBackdrop
|
<BottomSheetBackdrop
|
||||||
appearsOnIndex={0}
|
appearsOnIndex={0}
|
||||||
@@ -61,28 +64,37 @@ export function Outer({
|
|||||||
)}
|
)}
|
||||||
handleIndicatorStyle={{backgroundColor: t.palette.primary}}
|
handleIndicatorStyle={{backgroundColor: t.palette.primary}}
|
||||||
handleStyle={{display: 'none'}}
|
handleStyle={{display: 'none'}}
|
||||||
onChange={() => {}}
|
|
||||||
onClose={onClose}>
|
onClose={onClose}>
|
||||||
<Context.Provider value={context}>{children}</Context.Provider>
|
<Context.Provider value={context}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.absolute,
|
||||||
|
a.inset_0,
|
||||||
|
t.atoms.bg,
|
||||||
|
{
|
||||||
|
borderTopLeftRadius: 40,
|
||||||
|
borderTopRightRadius: 40,
|
||||||
|
height: Dimensions.get('window').height * 2,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</Context.Provider>
|
||||||
</BottomSheet>
|
</BottomSheet>
|
||||||
</Portal>
|
</Portal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO a11y props here, or is that handled by the sheet?
|
||||||
export function Inner(props: DialogInnerProps) {
|
export function Inner(props: DialogInnerProps) {
|
||||||
const t = useTheme()
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
|
||||||
a.inset_0,
|
|
||||||
a.p_lg,
|
a.p_lg,
|
||||||
a.pt_xxl,
|
a.pt_xxl,
|
||||||
t.atoms.bg,
|
|
||||||
{
|
{
|
||||||
borderTopLeftRadius: 40,
|
borderTopLeftRadius: 40,
|
||||||
borderTopRightRadius: 40,
|
borderTopRightRadius: 40,
|
||||||
height: Dimensions.get('window').height * 2,
|
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
{props.children}
|
{props.children}
|
||||||
@@ -101,7 +113,7 @@ export function Handle() {
|
|||||||
t.atoms.bg_contrast_200,
|
t.atoms.bg_contrast_200,
|
||||||
{
|
{
|
||||||
top: 12,
|
top: 12,
|
||||||
width: 80,
|
width: 50,
|
||||||
height: 6,
|
height: 6,
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import {Button} from '#/view/com/Button'
|
|||||||
import {DialogOuterProps, DialogInnerProps} from '#/view/com/Dialog/types'
|
import {DialogOuterProps, DialogInnerProps} from '#/view/com/Dialog/types'
|
||||||
import {Context, useDialogContext} from '#/view/com/Dialog/context'
|
import {Context, useDialogContext} from '#/view/com/Dialog/context'
|
||||||
|
|
||||||
export {useDialogControl} from '#/view/com/Dialog/context'
|
export {useDialogControl, useDialogContext} from '#/view/com/Dialog/context'
|
||||||
|
export * from '#/view/com/Dialog/types'
|
||||||
|
|
||||||
const stopPropagation = (e: any) => e.stopPropagation()
|
const stopPropagation = (e: any) => e.stopPropagation()
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ export function Outer({
|
|||||||
}, [onClose, setIsOpen])
|
}, [onClose, setIsOpen])
|
||||||
|
|
||||||
useImperativeHandle(
|
useImperativeHandle(
|
||||||
control,
|
control.ref,
|
||||||
() => ({
|
() => ({
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
@@ -58,7 +59,12 @@ export function Outer({
|
|||||||
return () => document.removeEventListener('keydown', handler)
|
return () => document.removeEventListener('keydown', handler)
|
||||||
}, [isOpen, close])
|
}, [isOpen, close])
|
||||||
|
|
||||||
const context = React.useMemo(() => ({close}), [close])
|
const context = React.useMemo(
|
||||||
|
() => ({
|
||||||
|
close,
|
||||||
|
}),
|
||||||
|
[close],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -111,12 +117,19 @@ export function Outer({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Inner({children, style}: DialogInnerProps) {
|
export function Inner({
|
||||||
|
children,
|
||||||
|
style,
|
||||||
|
accessibilityLabelledBy,
|
||||||
|
accessibilityDescribedBy,
|
||||||
|
}: DialogInnerProps) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
return (
|
return (
|
||||||
<FocusScope loop enabled trapped>
|
<FocusScope loop enabled trapped>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
|
aria-labelledby={accessibilityLabelledBy}
|
||||||
|
aria-describedby={accessibilityDescribedBy}
|
||||||
aria-role="dialog"
|
aria-role="dialog"
|
||||||
// @ts-ignore web only -prf
|
// @ts-ignore web only -prf
|
||||||
onClick={stopPropagation}
|
onClick={stopPropagation}
|
||||||
@@ -128,9 +141,10 @@ export function Inner({children, style}: DialogInnerProps) {
|
|||||||
a.relative,
|
a.relative,
|
||||||
a.rounded_md,
|
a.rounded_md,
|
||||||
a.w_full,
|
a.w_full,
|
||||||
|
a.border,
|
||||||
gtMobile ? a.p_xl : a.p_lg,
|
gtMobile ? a.p_xl : a.p_lg,
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
{maxWidth: 600},
|
{maxWidth: 600, borderColor: t.palette.contrast_300},
|
||||||
...(Array.isArray(style) ? style : [style || {}]),
|
...(Array.isArray(style) ? style : [style || {}]),
|
||||||
]}>
|
]}>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type {ViewStyle} from 'react-native'
|
import type {ViewStyle, AccessibilityProps} from 'react-native'
|
||||||
|
import {BottomSheetProps} from '@gorhom/bottom-sheet'
|
||||||
|
|
||||||
|
type A11yProps = Required<AccessibilityProps>
|
||||||
|
|
||||||
export type DialogContextProps = {
|
export type DialogContextProps = {
|
||||||
close: () => void
|
close: () => void
|
||||||
@@ -11,8 +14,20 @@ export type DialogControlProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type DialogOuterProps = {
|
export type DialogOuterProps = {
|
||||||
control: React.RefObject<DialogControlProps>
|
control: {
|
||||||
|
ref: React.RefObject<DialogControlProps>
|
||||||
|
open: (index?: number) => void
|
||||||
|
close: () => void
|
||||||
|
}
|
||||||
onClose?: () => void
|
onClose?: () => void
|
||||||
|
nativeOptions?: {
|
||||||
|
sheet?: Omit<BottomSheetProps, 'children'>
|
||||||
|
}
|
||||||
|
webOptions?: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DialogInnerProps = React.PropsWithChildren<{style?: ViewStyle}>
|
export type DialogInnerProps = React.PropsWithChildren<{
|
||||||
|
style?: ViewStyle
|
||||||
|
accessibilityLabelledBy: A11yProps['aria-labelledby']
|
||||||
|
accessibilityDescribedBy: string
|
||||||
|
}>
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View, PressableProps, LayoutChangeEvent} from 'react-native'
|
||||||
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
|
||||||
|
import {useTheme, atoms as a} from '#/alf'
|
||||||
|
import {H2, P} from '#/view/com/Typography'
|
||||||
|
import {Button} from '#/view/com/Button'
|
||||||
|
|
||||||
|
import * as Dialog from '#/view/com/Dialog'
|
||||||
|
|
||||||
|
export {useDialogControl as usePromptControl} from '#/view/com/Dialog'
|
||||||
|
|
||||||
|
const Context = React.createContext<{
|
||||||
|
titleId: string
|
||||||
|
descriptionId: string
|
||||||
|
}>({
|
||||||
|
titleId: '',
|
||||||
|
descriptionId: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
export function Outer({
|
||||||
|
children,
|
||||||
|
control,
|
||||||
|
}: React.PropsWithChildren<{
|
||||||
|
control: Dialog.DialogOuterProps['control']
|
||||||
|
}>) {
|
||||||
|
const insets = useSafeAreaInsets()
|
||||||
|
const titleId = React.useId()
|
||||||
|
const descriptionId = React.useId()
|
||||||
|
const [defaultSnapPoints, setDefaultSnapPoints] = React.useState<
|
||||||
|
string | number
|
||||||
|
>('25%')
|
||||||
|
|
||||||
|
const context = React.useMemo(
|
||||||
|
() => ({titleId, descriptionId}),
|
||||||
|
[titleId, descriptionId],
|
||||||
|
)
|
||||||
|
|
||||||
|
const measureDefaultSnapPoint = React.useCallback(
|
||||||
|
(e: LayoutChangeEvent) => {
|
||||||
|
setDefaultSnapPoints(e.nativeEvent.layout.height + insets.bottom + 50)
|
||||||
|
},
|
||||||
|
[insets, setDefaultSnapPoints],
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog.Outer
|
||||||
|
control={control}
|
||||||
|
nativeOptions={{
|
||||||
|
sheet: {
|
||||||
|
snapPoints: [defaultSnapPoints],
|
||||||
|
},
|
||||||
|
}}>
|
||||||
|
<Context.Provider value={context}>
|
||||||
|
<View onLayout={measureDefaultSnapPoint}>
|
||||||
|
<Dialog.Inner
|
||||||
|
accessibilityLabelledBy={titleId}
|
||||||
|
accessibilityDescribedBy={descriptionId}
|
||||||
|
style={{width: 'auto', maxWidth: 400}}>
|
||||||
|
<Dialog.Handle />
|
||||||
|
{children}
|
||||||
|
</Dialog.Inner>
|
||||||
|
</View>
|
||||||
|
</Context.Provider>
|
||||||
|
</Dialog.Outer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Title({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const t = useTheme()
|
||||||
|
const {titleId} = React.useContext(Context)
|
||||||
|
return (
|
||||||
|
<H2
|
||||||
|
nativeID={titleId}
|
||||||
|
style={[a.font_semibold, t.atoms.text_contrast_700, a.pb_sm]}>
|
||||||
|
{children}
|
||||||
|
</H2>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Description({children}: React.PropsWithChildren<{}>) {
|
||||||
|
const t = useTheme()
|
||||||
|
const {descriptionId} = React.useContext(Context)
|
||||||
|
return (
|
||||||
|
<P nativeID={descriptionId} style={[t.atoms.text_contrast_700, a.pb_lg]}>
|
||||||
|
{children}
|
||||||
|
</P>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Actions({children}: React.PropsWithChildren<{}>) {
|
||||||
|
return (
|
||||||
|
<View style={[a.w_full, a.flex_row, a.gap_sm, a.justify_end]}>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Cancel({
|
||||||
|
children,
|
||||||
|
}: React.PropsWithChildren<{onPress?: PressableProps['onPress']}>) {
|
||||||
|
const {close} = Dialog.useDialogContext()
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="secondary"
|
||||||
|
size="small"
|
||||||
|
accessibilityLabel="Cancel"
|
||||||
|
accessibilityHint="Cancel this action"
|
||||||
|
onPress={close}>
|
||||||
|
{children}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Action({
|
||||||
|
children,
|
||||||
|
onPress,
|
||||||
|
}: React.PropsWithChildren<{onPress?: () => void}>) {
|
||||||
|
const {close} = Dialog.useDialogContext()
|
||||||
|
const handleOnPress = React.useCallback(() => {
|
||||||
|
close()
|
||||||
|
onPress?.()
|
||||||
|
}, [close, onPress])
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
accessibilityLabel="Confirm"
|
||||||
|
accessibilityHint="Confirm this action"
|
||||||
|
onPress={handleOnPress}>
|
||||||
|
{children}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Text as RNText, TextProps} from 'react-native'
|
import {Text as RNText, TextProps} from 'react-native'
|
||||||
import {useTheme, atoms, web} from '#/alf'
|
|
||||||
|
import {useTheme, atoms, web, flatten} from '#/alf'
|
||||||
|
|
||||||
export function Text({style, ...rest}: TextProps) {
|
export function Text({style, ...rest}: TextProps) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -18,7 +19,7 @@ export function H1({style, ...rest}: TextProps) {
|
|||||||
<RNText
|
<RNText
|
||||||
{...attr}
|
{...attr}
|
||||||
{...rest}
|
{...rest}
|
||||||
style={[atoms.text_xl, atoms.font_bold, t.atoms.text, style]}
|
style={[atoms.text_xl, atoms.font_bold, t.atoms.text, flatten(style)]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -34,7 +35,7 @@ export function H2({style, ...rest}: TextProps) {
|
|||||||
<RNText
|
<RNText
|
||||||
{...attr}
|
{...attr}
|
||||||
{...rest}
|
{...rest}
|
||||||
style={[atoms.text_lg, atoms.font_bold, t.atoms.text, style]}
|
style={[atoms.text_lg, atoms.font_bold, t.atoms.text, flatten(style)]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -50,7 +51,7 @@ export function H3({style, ...rest}: TextProps) {
|
|||||||
<RNText
|
<RNText
|
||||||
{...attr}
|
{...attr}
|
||||||
{...rest}
|
{...rest}
|
||||||
style={[atoms.text_md, atoms.font_bold, t.atoms.text, style]}
|
style={[atoms.text_md, atoms.font_bold, t.atoms.text, flatten(style)]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,7 @@ export function H4({style, ...rest}: TextProps) {
|
|||||||
<RNText
|
<RNText
|
||||||
{...attr}
|
{...attr}
|
||||||
{...rest}
|
{...rest}
|
||||||
style={[atoms.text_sm, atoms.font_bold, t.atoms.text, style]}
|
style={[atoms.text_sm, atoms.font_bold, t.atoms.text, flatten(style)]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,7 @@ export function H5({style, ...rest}: TextProps) {
|
|||||||
<RNText
|
<RNText
|
||||||
{...attr}
|
{...attr}
|
||||||
{...rest}
|
{...rest}
|
||||||
style={[atoms.text_xs, atoms.font_bold, t.atoms.text, style]}
|
style={[atoms.text_xs, atoms.font_bold, t.atoms.text, flatten(style)]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -98,7 +99,26 @@ export function H6({style, ...rest}: TextProps) {
|
|||||||
<RNText
|
<RNText
|
||||||
{...attr}
|
{...attr}
|
||||||
{...rest}
|
{...rest}
|
||||||
style={[atoms.text_xxs, atoms.font_bold, t.atoms.text, style]}
|
style={[atoms.text_xxs, atoms.font_bold, t.atoms.text, flatten(style)]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function P({style, ...rest}: TextProps) {
|
||||||
|
const t = useTheme()
|
||||||
|
const attr =
|
||||||
|
web({
|
||||||
|
role: 'paragraph',
|
||||||
|
}) || {}
|
||||||
|
const _style = flatten(style)
|
||||||
|
const lineHeight =
|
||||||
|
(_style?.lineHeight || atoms.text_md.lineHeight) *
|
||||||
|
atoms.leading_normal.lineHeight
|
||||||
|
return (
|
||||||
|
<RNText
|
||||||
|
{...attr}
|
||||||
|
{...rest}
|
||||||
|
style={[atoms.text_md, t.atoms.text, _style, {lineHeight}]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,32 +8,39 @@ import * as tokens from '#/alf/tokens'
|
|||||||
import {atoms as a, useTheme, useBreakpoints, ThemeProvider as Alf} from '#/alf'
|
import {atoms as a, useTheme, useBreakpoints, ThemeProvider as Alf} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/view/com/Button'
|
import {Button, ButtonText} from '#/view/com/Button'
|
||||||
import {Link} from '#/view/com/Link'
|
import {Link} from '#/view/com/Link'
|
||||||
import {Text, H1, H2, H3, H4, H5, H6} from '#/view/com/Typography'
|
import {Text, H1, H2, H3, H4, H5, H6, P} from '#/view/com/Typography'
|
||||||
import {InputText} from '#/view/com/forms/InputText'
|
import {InputText} from '#/view/com/forms/InputText'
|
||||||
import {InputDate, utils} from '#/view/com/forms/InputDate'
|
import {InputDate, utils} from '#/view/com/forms/InputDate'
|
||||||
import {Logo} from '#/view/icons/Logo'
|
import {Logo} from '#/view/icons/Logo'
|
||||||
import * as Dialog from '#/view/com/Dialog'
|
import * as Dialog from '#/view/com/Dialog'
|
||||||
|
import * as Prompt from '#/view/com/Prompt'
|
||||||
|
|
||||||
function ThemeSelector() {
|
function ThemeSelector() {
|
||||||
const setColorMode = useSetColorMode()
|
const setColorMode = useSetColorMode()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.flex_row, a.gap_md]}>
|
<View style={[a.flex_row, a.align_start, a.gap_md]}>
|
||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
|
accessibilityLabel='Set theme to "system"'
|
||||||
|
accessibilityHint="Set theme to system default"
|
||||||
onPress={() => setColorMode('system')}>
|
onPress={() => setColorMode('system')}>
|
||||||
System
|
System
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
|
accessibilityLabel='Set theme to "system"'
|
||||||
|
accessibilityHint="Set theme to system default"
|
||||||
onPress={() => setColorMode('light')}>
|
onPress={() => setColorMode('light')}>
|
||||||
Light
|
Light
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
|
accessibilityLabel='Set theme to "system"'
|
||||||
|
accessibilityHint="Set theme to system default"
|
||||||
onPress={() => setColorMode('dark')}>
|
onPress={() => setColorMode('dark')}>
|
||||||
Dark
|
Dark
|
||||||
</Button>
|
</Button>
|
||||||
@@ -319,39 +326,58 @@ function Forms() {
|
|||||||
|
|
||||||
function Dialogs() {
|
function Dialogs() {
|
||||||
const control = Dialog.useDialogControl()
|
const control = Dialog.useDialogControl()
|
||||||
|
const prompt = Prompt.usePromptControl()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
onPress={() => control.current.open()}
|
onPress={() => control.open()}
|
||||||
accessibilityLabel="Open basic dialog"
|
accessibilityLabel="Open basic dialog"
|
||||||
accessibilityHint="Open basic dialog">
|
accessibilityHint="Open basic dialog">
|
||||||
Open basic dialog
|
Open basic dialog
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="negative"
|
||||||
|
size="small"
|
||||||
|
onPress={() => prompt.open()}
|
||||||
|
accessibilityLabel="Open prompt"
|
||||||
|
accessibilityHint="Open prompt">
|
||||||
|
Open prompt
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Prompt.Outer control={prompt}>
|
||||||
|
<Prompt.Title>Are you sure?</Prompt.Title>
|
||||||
|
<Prompt.Description>
|
||||||
|
This action cannot be undone. This action cannot be undone. This
|
||||||
|
action cannot be undone.
|
||||||
|
</Prompt.Description>
|
||||||
|
<Prompt.Actions>
|
||||||
|
<Prompt.Cancel>Cancel</Prompt.Cancel>
|
||||||
|
<Prompt.Action>Confirm</Prompt.Action>
|
||||||
|
</Prompt.Actions>
|
||||||
|
</Prompt.Outer>
|
||||||
|
|
||||||
<Dialog.Outer control={control}>
|
<Dialog.Outer control={control}>
|
||||||
<Dialog.Inner style={{width: 'auto'}}>
|
<Dialog.Inner
|
||||||
|
accessibilityLabelledBy="dialog-title"
|
||||||
|
accessibilityDescribedBy="dialog-description">
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<View style={[a.gap_md]}>
|
<View style={[a.gap_md]}>
|
||||||
<Button
|
<H3 nativeID="dialog-title">Dialog</H3>
|
||||||
type="primary"
|
<P nativeID="dialog-description">Description</P>
|
||||||
size="small"
|
<View style={[a.flex_row, a.justify_end]}>
|
||||||
onPress={() => control.current.close()}
|
<Button
|
||||||
accessibilityLabel="Open basic dialog"
|
type="primary"
|
||||||
accessibilityHint="Open basic dialog">
|
size="small"
|
||||||
Close basic dialog
|
onPress={() => control.close()}
|
||||||
</Button>
|
accessibilityLabel="Open basic dialog"
|
||||||
<View style={{height: 100}} />
|
accessibilityHint="Open basic dialog">
|
||||||
<Button
|
Close basic dialog
|
||||||
type="secondary"
|
</Button>
|
||||||
size="small"
|
</View>
|
||||||
onPress={() => control.current.close()}
|
|
||||||
accessibilityLabel="Open basic dialog"
|
|
||||||
accessibilityHint="Open basic dialog">
|
|
||||||
Some other control
|
|
||||||
</Button>
|
|
||||||
</View>
|
</View>
|
||||||
</Dialog.Inner>
|
</Dialog.Inner>
|
||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
|
|||||||
Reference in New Issue
Block a user