Reorg
This commit is contained in:
+4
-1
@@ -41,7 +41,10 @@ import {
|
||||
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
|
||||
import * as persisted from '#/state/persisted'
|
||||
import {Splash} from '#/Splash'
|
||||
import {Provider as PortalProvider, Outlet as PortalOutlet} from '#/view/com/Portal'
|
||||
import {
|
||||
Provider as PortalProvider,
|
||||
Outlet as PortalOutlet,
|
||||
} from '#/components/Portal'
|
||||
|
||||
SplashScreen.preventAutoHideAsync()
|
||||
|
||||
|
||||
+4
-1
@@ -30,7 +30,10 @@ import {
|
||||
} from 'state/session'
|
||||
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
|
||||
import * as persisted from '#/state/persisted'
|
||||
import {Provider as PortalProvider, Outlet as PortalOutlet} from '#/view/com/Portal'
|
||||
import {
|
||||
Provider as PortalProvider,
|
||||
Outlet as PortalOutlet,
|
||||
} from '#/components/Portal'
|
||||
|
||||
function InnerApp() {
|
||||
const {isInitialLoad, currentAccount} = useSession()
|
||||
|
||||
+79
-13
@@ -8,11 +8,8 @@ export type ReadonlyPalette = typeof lightPalette
|
||||
export type Palette = Mutable<ReadonlyPalette>
|
||||
|
||||
export const lightPalette = {
|
||||
white: '#FFFFFF',
|
||||
black: '#080B12',
|
||||
primary: tokens.color.blue_500,
|
||||
positive: tokens.color.green_500,
|
||||
negative: tokens.color.red_500,
|
||||
white: tokens.color.white,
|
||||
black: tokens.color.black,
|
||||
|
||||
contrast_25: tokens.color.gray_25,
|
||||
contrast_50: tokens.color.gray_50,
|
||||
@@ -25,14 +22,47 @@ export const lightPalette = {
|
||||
contrast_700: tokens.color.gray_700,
|
||||
contrast_800: tokens.color.gray_800,
|
||||
contrast_900: tokens.color.gray_900,
|
||||
|
||||
primary_25: tokens.color.blue_25,
|
||||
primary_50: tokens.color.blue_50,
|
||||
primary_100: tokens.color.blue_100,
|
||||
primary_200: tokens.color.blue_200,
|
||||
primary_300: tokens.color.blue_300,
|
||||
primary_400: tokens.color.blue_400,
|
||||
primary_500: tokens.color.blue_500,
|
||||
primary_600: tokens.color.blue_600,
|
||||
primary_700: tokens.color.blue_700,
|
||||
primary_800: tokens.color.blue_800,
|
||||
primary_900: tokens.color.blue_900,
|
||||
|
||||
positive_25: tokens.color.green_25,
|
||||
positive_50: tokens.color.green_50,
|
||||
positive_100: tokens.color.green_100,
|
||||
positive_200: tokens.color.green_200,
|
||||
positive_300: tokens.color.green_300,
|
||||
positive_400: tokens.color.green_400,
|
||||
positive_500: tokens.color.green_500,
|
||||
positive_600: tokens.color.green_600,
|
||||
positive_700: tokens.color.green_700,
|
||||
positive_800: tokens.color.green_800,
|
||||
positive_900: tokens.color.green_900,
|
||||
|
||||
negative_25: tokens.color.red_25,
|
||||
negative_50: tokens.color.red_50,
|
||||
negative_100: tokens.color.red_100,
|
||||
negative_200: tokens.color.red_200,
|
||||
negative_300: tokens.color.red_300,
|
||||
negative_400: tokens.color.red_400,
|
||||
negative_500: tokens.color.red_500,
|
||||
negative_600: tokens.color.red_600,
|
||||
negative_700: tokens.color.red_700,
|
||||
negative_800: tokens.color.red_800,
|
||||
negative_900: tokens.color.red_900,
|
||||
} as const
|
||||
|
||||
export const darkPalette: Palette = {
|
||||
white: '#FFFFFF',
|
||||
black: '#080B12',
|
||||
primary: tokens.color.blue_500,
|
||||
positive: tokens.color.green_500,
|
||||
negative: tokens.color.red_500,
|
||||
white: tokens.color.white,
|
||||
black: tokens.color.black,
|
||||
|
||||
contrast_25: tokens.color.gray_900,
|
||||
contrast_50: tokens.color.gray_800,
|
||||
@@ -45,6 +75,42 @@ export const darkPalette: Palette = {
|
||||
contrast_700: tokens.color.gray_100,
|
||||
contrast_800: tokens.color.gray_50,
|
||||
contrast_900: tokens.color.gray_25,
|
||||
|
||||
primary_25: tokens.color.blue_25,
|
||||
primary_50: tokens.color.blue_50,
|
||||
primary_100: tokens.color.blue_100,
|
||||
primary_200: tokens.color.blue_200,
|
||||
primary_300: tokens.color.blue_300,
|
||||
primary_400: tokens.color.blue_400,
|
||||
primary_500: tokens.color.blue_500,
|
||||
primary_600: tokens.color.blue_600,
|
||||
primary_700: tokens.color.blue_700,
|
||||
primary_800: tokens.color.blue_800,
|
||||
primary_900: tokens.color.blue_900,
|
||||
|
||||
positive_25: tokens.color.green_25,
|
||||
positive_50: tokens.color.green_50,
|
||||
positive_100: tokens.color.green_100,
|
||||
positive_200: tokens.color.green_200,
|
||||
positive_300: tokens.color.green_300,
|
||||
positive_400: tokens.color.green_400,
|
||||
positive_500: tokens.color.green_500,
|
||||
positive_600: tokens.color.green_600,
|
||||
positive_700: tokens.color.green_700,
|
||||
positive_800: tokens.color.green_800,
|
||||
positive_900: tokens.color.green_900,
|
||||
|
||||
negative_25: tokens.color.red_25,
|
||||
negative_50: tokens.color.red_50,
|
||||
negative_100: tokens.color.red_100,
|
||||
negative_200: tokens.color.red_200,
|
||||
negative_300: tokens.color.red_300,
|
||||
negative_400: tokens.color.red_400,
|
||||
negative_500: tokens.color.red_500,
|
||||
negative_600: tokens.color.red_600,
|
||||
negative_700: tokens.color.red_700,
|
||||
negative_800: tokens.color.red_800,
|
||||
negative_900: tokens.color.red_900,
|
||||
} as const
|
||||
|
||||
export const light = {
|
||||
@@ -52,7 +118,7 @@ export const light = {
|
||||
palette: lightPalette,
|
||||
atoms: {
|
||||
text: {
|
||||
color: tokens.color.gray_900,
|
||||
color: lightPalette.black,
|
||||
},
|
||||
text_contrast_600: {
|
||||
color: lightPalette.contrast_600,
|
||||
@@ -110,7 +176,7 @@ export const dim: Theme = {
|
||||
color: darkPalette.contrast_400,
|
||||
},
|
||||
text_inverted: {
|
||||
color: darkPalette.contrast_900,
|
||||
color: darkPalette.black,
|
||||
},
|
||||
bg: {
|
||||
backgroundColor: darkPalette.contrast_25,
|
||||
@@ -156,7 +222,7 @@ export const dark: Theme = {
|
||||
color: darkPalette.contrast_400,
|
||||
},
|
||||
text_inverted: {
|
||||
color: tokens.color.gray_900,
|
||||
color: darkPalette.black,
|
||||
},
|
||||
bg: {
|
||||
backgroundColor: darkPalette.black,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
export const color = {
|
||||
white: '#FFFFFF',
|
||||
black: '#080B12',
|
||||
|
||||
gray_25: `#FCFCFD`,
|
||||
gray_50: `#F9FAFB`,
|
||||
gray_100: `#F3F4F6`,
|
||||
|
||||
@@ -0,0 +1,434 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
Pressable,
|
||||
Text,
|
||||
PressableProps,
|
||||
TextProps,
|
||||
ViewStyle,
|
||||
AccessibilityProps,
|
||||
} from 'react-native'
|
||||
|
||||
import {useTheme, atoms, tokens, web, native} from '#/alf'
|
||||
|
||||
export type ButtonVariant = 'solid' | 'outline' | 'ghost'
|
||||
export type ButtonColor = 'primary' | 'secondary' | 'negative'
|
||||
export type ButtonSize = 'small' | 'large'
|
||||
export type VariantProps = {
|
||||
/**
|
||||
* The style variation of the button
|
||||
*/
|
||||
variant?: ButtonVariant
|
||||
/**
|
||||
* The color of the button
|
||||
*/
|
||||
color?: ButtonColor
|
||||
/**
|
||||
* The size of the button
|
||||
*/
|
||||
size?: ButtonSize
|
||||
}
|
||||
|
||||
export type ButtonProps = Omit<
|
||||
PressableProps,
|
||||
'children' | 'style' | 'accessibilityLabel' | 'accessibilityHint'
|
||||
> &
|
||||
VariantProps & {
|
||||
children:
|
||||
| ((props: {
|
||||
state: {
|
||||
pressed: boolean
|
||||
hovered: boolean
|
||||
focused: boolean
|
||||
}
|
||||
props: VariantProps & {
|
||||
disabled?: boolean
|
||||
}
|
||||
}) => React.ReactNode)
|
||||
| React.ReactNode
|
||||
| string
|
||||
accessibilityLabel: Required<AccessibilityProps>['accessibilityLabel']
|
||||
accessibilityHint: Required<AccessibilityProps>['accessibilityHint']
|
||||
}
|
||||
export type ButtonTextProps = TextProps & VariantProps & {disabled?: boolean}
|
||||
|
||||
export function Button({
|
||||
children,
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
accessibilityLabel,
|
||||
accessibilityHint,
|
||||
disabled = false,
|
||||
...rest
|
||||
}: ButtonProps) {
|
||||
const t = useTheme()
|
||||
const [state, setState] = React.useState({
|
||||
pressed: false,
|
||||
hovered: false,
|
||||
focused: false,
|
||||
})
|
||||
|
||||
const onPressIn = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
pressed: true,
|
||||
}))
|
||||
}, [setState])
|
||||
const onPressOut = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
pressed: false,
|
||||
}))
|
||||
}, [setState])
|
||||
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 {baseStyles, hoverStyles} = React.useMemo(() => {
|
||||
const baseStyles: ViewStyle[] = []
|
||||
const hoverStyles: ViewStyle[] = []
|
||||
const light = t.name === 'light'
|
||||
|
||||
if (color === 'primary') {
|
||||
if (variant === 'solid') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({
|
||||
backgroundColor: t.palette.primary_500,
|
||||
})
|
||||
hoverStyles.push({
|
||||
backgroundColor: t.palette.primary_600,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
backgroundColor: t.palette.primary_700,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'outline') {
|
||||
baseStyles.push(atoms.border, t.atoms.bg, {
|
||||
borderWidth: 1,
|
||||
})
|
||||
|
||||
if (!disabled) {
|
||||
baseStyles.push(atoms.border, {
|
||||
borderColor: tokens.color.blue_500,
|
||||
})
|
||||
hoverStyles.push(atoms.border, {
|
||||
backgroundColor: light
|
||||
? t.palette.primary_100
|
||||
: t.palette.primary_900,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push(atoms.border, {
|
||||
borderColor: light ? tokens.color.blue_200 : tokens.color.blue_900,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'ghost') {
|
||||
if (!disabled) {
|
||||
baseStyles.push(t.atoms.bg)
|
||||
hoverStyles.push({
|
||||
backgroundColor: light
|
||||
? t.palette.primary_100
|
||||
: t.palette.primary_900,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (color === 'secondary') {
|
||||
if (variant === 'solid') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({
|
||||
backgroundColor: light
|
||||
? tokens.color.gray_200
|
||||
: tokens.color.gray_800,
|
||||
})
|
||||
hoverStyles.push({
|
||||
backgroundColor: light
|
||||
? tokens.color.gray_300
|
||||
: tokens.color.gray_900,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
backgroundColor: light
|
||||
? tokens.color.gray_300
|
||||
: tokens.color.gray_900,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'outline') {
|
||||
baseStyles.push(atoms.border, t.atoms.bg, {
|
||||
borderWidth: 1,
|
||||
})
|
||||
|
||||
if (!disabled) {
|
||||
baseStyles.push(atoms.border, {
|
||||
borderColor: light ? tokens.color.gray_500 : tokens.color.gray_500,
|
||||
})
|
||||
hoverStyles.push(atoms.border, t.atoms.bg_contrast_50)
|
||||
} else {
|
||||
baseStyles.push(atoms.border, {
|
||||
borderColor: light ? tokens.color.gray_200 : tokens.color.gray_800,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'ghost') {
|
||||
if (!disabled) {
|
||||
baseStyles.push(t.atoms.bg)
|
||||
hoverStyles.push({
|
||||
backgroundColor: light
|
||||
? tokens.color.gray_100
|
||||
: tokens.color.gray_800,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (color === 'negative') {
|
||||
if (variant === 'solid') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({
|
||||
backgroundColor: t.palette.negative_500,
|
||||
})
|
||||
hoverStyles.push({
|
||||
backgroundColor: t.palette.negative_600,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
backgroundColor: t.palette.negative_700,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'outline') {
|
||||
baseStyles.push(atoms.border, t.atoms.bg, {
|
||||
borderWidth: 1,
|
||||
})
|
||||
|
||||
if (!disabled) {
|
||||
baseStyles.push(atoms.border, {
|
||||
borderColor: t.palette.negative_600,
|
||||
})
|
||||
hoverStyles.push(atoms.border, {
|
||||
backgroundColor: light ? t.palette.negative_50 : '#2D0614', // darker red
|
||||
})
|
||||
} else {
|
||||
baseStyles.push(atoms.border, {
|
||||
borderColor: light
|
||||
? t.palette.negative_200
|
||||
: t.palette.negative_900,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'ghost') {
|
||||
if (!disabled) {
|
||||
baseStyles.push(t.atoms.bg)
|
||||
hoverStyles.push({
|
||||
backgroundColor: light ? t.palette.negative_50 : '#2D0614', // darker red
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (size === 'large') {
|
||||
baseStyles.push(
|
||||
{paddingVertical: 15},
|
||||
atoms.px_2xl,
|
||||
atoms.rounded_sm,
|
||||
atoms.gap_sm,
|
||||
)
|
||||
} else if (size === 'small') {
|
||||
baseStyles.push(
|
||||
{paddingVertical: 9},
|
||||
atoms.px_md,
|
||||
atoms.rounded_sm,
|
||||
atoms.gap_xs,
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
baseStyles,
|
||||
hoverStyles,
|
||||
}
|
||||
}, [t, variant, color, size, disabled])
|
||||
|
||||
const childProps = React.useMemo(
|
||||
() => ({
|
||||
state,
|
||||
props: {
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
disabled: disabled || false,
|
||||
},
|
||||
}),
|
||||
[state, variant, color, size, disabled],
|
||||
)
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
role="button"
|
||||
{...rest}
|
||||
aria-label={accessibilityLabel}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityHint={accessibilityHint}
|
||||
disabled={disabled || false}
|
||||
accessibilityState={{
|
||||
disabled: disabled || false,
|
||||
}}
|
||||
style={[
|
||||
atoms.flex_row,
|
||||
atoms.align_center,
|
||||
...baseStyles,
|
||||
...(state.hovered ? hoverStyles : []),
|
||||
]}
|
||||
onPressIn={onPressIn}
|
||||
onPressOut={onPressOut}
|
||||
onHoverIn={onHoverIn}
|
||||
onHoverOut={onHoverOut}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}>
|
||||
{typeof children === 'string' ? (
|
||||
<ButtonText
|
||||
variant={variant}
|
||||
color={color}
|
||||
size={size}
|
||||
disabled={disabled || false}>
|
||||
{children}
|
||||
</ButtonText>
|
||||
) : typeof children === 'function' ? (
|
||||
children(childProps)
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
|
||||
export function ButtonText({
|
||||
children,
|
||||
style,
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
disabled,
|
||||
...rest
|
||||
}: ButtonTextProps) {
|
||||
const t = useTheme()
|
||||
|
||||
const textStyles = React.useMemo(() => {
|
||||
const baseStyles = []
|
||||
const light = t.name === 'light'
|
||||
|
||||
if (color === 'primary') {
|
||||
if (variant === 'solid') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({color: t.palette.white})
|
||||
} else {
|
||||
baseStyles.push({color: t.palette.white, opacity: 0.5})
|
||||
}
|
||||
} else if (variant === 'outline') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({
|
||||
color: light ? t.palette.primary_600 : t.palette.primary_500,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({color: t.palette.primary_600, opacity: 0.5})
|
||||
}
|
||||
} else if (variant === 'ghost') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({color: t.palette.primary_600})
|
||||
} else {
|
||||
baseStyles.push({color: t.palette.primary_600, opacity: 0.5})
|
||||
}
|
||||
}
|
||||
} else if (color === 'secondary') {
|
||||
if (variant === 'solid') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({
|
||||
color: light ? tokens.color.gray_700 : tokens.color.gray_100,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
color: light ? tokens.color.gray_400 : tokens.color.gray_700,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'outline') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({
|
||||
color: light ? tokens.color.gray_600 : tokens.color.gray_300,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
color: light ? tokens.color.gray_400 : tokens.color.gray_700,
|
||||
})
|
||||
}
|
||||
} else if (variant === 'ghost') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({
|
||||
color: light ? tokens.color.gray_600 : tokens.color.gray_300,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
color: light ? tokens.color.gray_400 : tokens.color.gray_600,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (color === 'negative') {
|
||||
if (variant === 'solid') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({color: t.palette.white})
|
||||
} else {
|
||||
baseStyles.push({color: t.palette.white, opacity: 0.5})
|
||||
}
|
||||
} else if (variant === 'outline') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({color: t.palette.negative_500})
|
||||
} else {
|
||||
baseStyles.push({color: t.palette.negative_500, opacity: 0.5})
|
||||
}
|
||||
} else if (variant === 'ghost') {
|
||||
if (!disabled) {
|
||||
baseStyles.push({color: t.palette.negative_500})
|
||||
} else {
|
||||
baseStyles.push({color: t.palette.negative_500, opacity: 0.5})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (size === 'large') {
|
||||
baseStyles.push(
|
||||
atoms.text_md,
|
||||
web({paddingBottom: 1}),
|
||||
native({marginTop: 2}),
|
||||
)
|
||||
} else {
|
||||
baseStyles.push(
|
||||
atoms.text_md,
|
||||
web({paddingBottom: 1}),
|
||||
native({marginTop: 2}),
|
||||
)
|
||||
}
|
||||
|
||||
return baseStyles
|
||||
}, [t, variant, color, size, disabled])
|
||||
|
||||
return (
|
||||
<Text
|
||||
{...rest}
|
||||
style={[atoms.font_bold, atoms.text_center, ...textStyles, style]}>
|
||||
{children}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import {DialogContextProps, DialogControlProps} from '#/view/com/Dialog/types'
|
||||
import {DialogContextProps, DialogControlProps} from '#/components/Dialog/types'
|
||||
|
||||
export const Context = React.createContext<DialogContextProps>({
|
||||
close: () => {},
|
||||
@@ -3,17 +3,17 @@ import {View, Dimensions} from 'react-native'
|
||||
import BottomSheet, {BottomSheetBackdrop} from '@gorhom/bottom-sheet'
|
||||
|
||||
import {useTheme, atoms as a} from '#/alf'
|
||||
import {Portal} from '#/view/com/Portal'
|
||||
import {Portal} from '#/components/Portal'
|
||||
|
||||
import {
|
||||
DialogOuterProps,
|
||||
DialogControlProps,
|
||||
DialogInnerProps,
|
||||
} from '#/view/com/Dialog/types'
|
||||
import {Context} from '#/view/com/Dialog/context'
|
||||
} from '#/components/Dialog/types'
|
||||
import {Context} from '#/components/Dialog/context'
|
||||
|
||||
export {useDialogControl, useDialogContext} from '#/view/com/Dialog/context'
|
||||
export * from '#/view/com/Dialog/types'
|
||||
export {useDialogControl, useDialogContext} from '#/components/Dialog/context'
|
||||
export * from '#/components/Dialog/types'
|
||||
|
||||
export function Outer({
|
||||
children,
|
||||
@@ -62,7 +62,7 @@ export function Outer({
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
handleIndicatorStyle={{backgroundColor: t.palette.primary}}
|
||||
handleIndicatorStyle={{backgroundColor: t.palette.primary_500}}
|
||||
handleStyle={{display: 'none'}}
|
||||
onClose={onClose}>
|
||||
<Context.Provider value={context}>
|
||||
@@ -4,15 +4,15 @@ import {FocusScope} from '@tamagui/focus-scope'
|
||||
import Animated, {FadeInDown, FadeIn} from 'react-native-reanimated'
|
||||
|
||||
import {useTheme, atoms as a, useBreakpoints, web} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {Portal} from '#/view/com/Portal'
|
||||
import {Button} from '#/view/com/Button'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {Portal} from '#/components/Portal'
|
||||
import {Button} from '#/components/Button'
|
||||
|
||||
import {DialogOuterProps, DialogInnerProps} from '#/view/com/Dialog/types'
|
||||
import {Context, useDialogContext} from '#/view/com/Dialog/context'
|
||||
import {DialogOuterProps, DialogInnerProps} from '#/components/Dialog/types'
|
||||
import {Context, useDialogContext} from '#/components/Dialog/context'
|
||||
|
||||
export {useDialogControl, useDialogContext} from '#/view/com/Dialog/context'
|
||||
export * from '#/view/com/Dialog/types'
|
||||
export {useDialogControl, useDialogContext} from '#/components/Dialog/context'
|
||||
export * from '#/components/Dialog/types'
|
||||
|
||||
const stopPropagation = (e: any) => e.stopPropagation()
|
||||
|
||||
@@ -15,7 +15,7 @@ import {sanitizeUrl} from '@braintree/sanitize-url'
|
||||
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {useTheme, web} from '#/alf'
|
||||
import {Button, ButtonProps} from '#/view/com/Button'
|
||||
import {Button, ButtonProps} from '#/components/Button'
|
||||
import {AllNavigatorParams, NavigationProp} from '#/lib/routes/types'
|
||||
import {
|
||||
convertBskyAppUrlIfNeeded,
|
||||
@@ -157,10 +157,10 @@ export function Link({
|
||||
<Text
|
||||
style={[
|
||||
style,
|
||||
{color: t.palette.primary},
|
||||
{color: t.palette.primary_500},
|
||||
state.hovered && {
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationColor: t.palette.primary,
|
||||
textDecorationColor: t.palette.primary_500,
|
||||
},
|
||||
]}>
|
||||
{children as string}
|
||||
@@ -3,12 +3,12 @@ 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 {H2, P} from '#/components/Typography'
|
||||
import {Button} from '#/components/Button'
|
||||
|
||||
import * as Dialog from '#/view/com/Dialog'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
|
||||
export {useDialogControl as usePromptControl} from '#/view/com/Dialog'
|
||||
export {useDialogControl as usePromptControl} from '#/components/Dialog'
|
||||
|
||||
const Context = React.createContext<{
|
||||
titleId: string
|
||||
@@ -102,7 +102,8 @@ export function Cancel({
|
||||
const {close} = Dialog.useDialogContext()
|
||||
return (
|
||||
<Button
|
||||
type="secondary"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="small"
|
||||
accessibilityLabel="Cancel"
|
||||
accessibilityHint="Cancel this action"
|
||||
@@ -123,7 +124,8 @@ export function Action({
|
||||
}, [close, onPress])
|
||||
return (
|
||||
<Button
|
||||
type="primary"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="small"
|
||||
accessibilityLabel="Confirm"
|
||||
accessibilityHint="Confirm this action"
|
||||
+5
-5
@@ -6,16 +6,16 @@ import DateTimePicker, {
|
||||
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {useTheme, atoms, tokens} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {useInteractionState} from '#/view/com/util/hooks/useInteractionState'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||
|
||||
import {InputDateProps} from '#/view/com/forms/InputDate/types'
|
||||
import {InputDateProps} from '#/components/forms/InputDate/types'
|
||||
import {
|
||||
localizeDate,
|
||||
toSimpleDateString,
|
||||
} from '#/view/com/forms/InputDate/utils'
|
||||
} from '#/components/forms/InputDate/utils'
|
||||
|
||||
export * as utils from '#/view/com/forms/InputDate/utils'
|
||||
export * as utils from '#/components/forms/InputDate/utils'
|
||||
|
||||
export function InputDate({
|
||||
value: initialValue,
|
||||
@@ -5,11 +5,11 @@ import DateTimePicker, {
|
||||
} from '@react-native-community/datetimepicker'
|
||||
|
||||
import {useTheme, atoms} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {toSimpleDateString} from '#/view/com/forms/InputDate/utils'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {toSimpleDateString} from '#/components/forms/InputDate/utils'
|
||||
|
||||
import {InputDateProps} from '#/view/com/forms/InputDate/types'
|
||||
export * as utils from '#/view/com/forms/InputDate/utils'
|
||||
import {InputDateProps} from '#/components/forms/InputDate/types'
|
||||
export * as utils from '#/components/forms/InputDate/utils'
|
||||
|
||||
/**
|
||||
* Date-only input. Accepts a date in the format YYYY-MM-DD, and reports date
|
||||
+5
-5
@@ -5,13 +5,13 @@ import {unstable_createElement} from 'react-native-web'
|
||||
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {useTheme, atoms, tokens} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {useInteractionState} from '#/view/com/util/hooks/useInteractionState'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||
|
||||
import {InputDateProps} from '#/view/com/forms/InputDate/types'
|
||||
import {toSimpleDateString} from '#/view/com/forms/InputDate/utils'
|
||||
import {InputDateProps} from '#/components/forms/InputDate/types'
|
||||
import {toSimpleDateString} from '#/components/forms/InputDate/utils'
|
||||
|
||||
export * as utils from '#/view/com/forms/InputDate/utils'
|
||||
export * as utils from '#/components/forms/InputDate/utils'
|
||||
|
||||
export function InputDate({
|
||||
label,
|
||||
@@ -1,6 +1,6 @@
|
||||
import {TextInputProps} from 'react-native'
|
||||
|
||||
import {BaseProps} from '#/view/com/forms/types'
|
||||
import {BaseProps} from '#/components/forms/types'
|
||||
|
||||
export type InputDateProps = BaseProps & {
|
||||
/**
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
} from 'react-native'
|
||||
|
||||
import {useTheme, atoms, web, tokens} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {useInteractionState} from '#/view/com/util/hooks/useInteractionState'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||
|
||||
import {BaseProps} from '#/view/com/forms/types'
|
||||
import {BaseProps} from '#/components/forms/types'
|
||||
|
||||
type Props = BaseProps &
|
||||
Omit<TextInputProps, 'placeholder'> & {
|
||||
@@ -1,297 +0,0 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
Pressable,
|
||||
Text,
|
||||
PressableProps,
|
||||
TextProps,
|
||||
ViewStyle,
|
||||
AccessibilityProps,
|
||||
} from 'react-native'
|
||||
|
||||
import {useTheme, atoms, tokens, web, native} from '#/alf'
|
||||
|
||||
export type ButtonType = 'primary' | 'secondary' | 'negative'
|
||||
export type ButtonSize = 'small' | 'large'
|
||||
export type VariantProps = {
|
||||
/**
|
||||
* The presentation styles of the button
|
||||
*/
|
||||
type?: ButtonType
|
||||
/**
|
||||
* The size of the button
|
||||
*/
|
||||
size?: ButtonSize
|
||||
}
|
||||
|
||||
export type ButtonProps = Omit<
|
||||
PressableProps,
|
||||
'children' | 'style' | 'accessibilityLabel' | 'accessibilityHint'
|
||||
> &
|
||||
VariantProps & {
|
||||
children:
|
||||
| ((props: {
|
||||
state: {
|
||||
pressed: boolean
|
||||
hovered: boolean
|
||||
focused: boolean
|
||||
}
|
||||
props: VariantProps & {
|
||||
disabled?: boolean
|
||||
}
|
||||
}) => React.ReactNode)
|
||||
| React.ReactNode
|
||||
| string
|
||||
accessibilityLabel: Required<AccessibilityProps>['accessibilityLabel']
|
||||
accessibilityHint: Required<AccessibilityProps>['accessibilityHint']
|
||||
}
|
||||
export type ButtonTextProps = TextProps & VariantProps & {disabled?: boolean}
|
||||
|
||||
export function Button({
|
||||
children,
|
||||
type,
|
||||
size,
|
||||
accessibilityLabel,
|
||||
accessibilityHint,
|
||||
disabled = false,
|
||||
...rest
|
||||
}: ButtonProps) {
|
||||
const [state, setState] = React.useState({
|
||||
pressed: false,
|
||||
hovered: false,
|
||||
focused: false,
|
||||
})
|
||||
|
||||
const onPressIn = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
pressed: true,
|
||||
}))
|
||||
}, [setState])
|
||||
const onPressOut = React.useCallback(() => {
|
||||
setState(s => ({
|
||||
...s,
|
||||
pressed: false,
|
||||
}))
|
||||
}, [setState])
|
||||
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 {baseStyles, hoverStyles} = React.useMemo(() => {
|
||||
const baseStyles: ViewStyle[] = []
|
||||
const hoverStyles: ViewStyle[] = []
|
||||
|
||||
switch (type) {
|
||||
case 'primary': {
|
||||
if (disabled) {
|
||||
baseStyles.push({
|
||||
backgroundColor: tokens.color.blue_200,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
backgroundColor: tokens.color.blue_500,
|
||||
})
|
||||
hoverStyles.push({
|
||||
backgroundColor: tokens.color.blue_600,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'secondary': {
|
||||
if (disabled) {
|
||||
baseStyles.push({
|
||||
backgroundColor: tokens.color.gray_200,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
backgroundColor: tokens.color.gray_300,
|
||||
})
|
||||
hoverStyles.push({
|
||||
backgroundColor: tokens.color.gray_400,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'negative': {
|
||||
if (disabled) {
|
||||
baseStyles.push({
|
||||
backgroundColor: tokens.color.red_400,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
backgroundColor: tokens.color.red_500,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 'large': {
|
||||
baseStyles.push(
|
||||
{paddingVertical: 15},
|
||||
atoms.px_2xl,
|
||||
atoms.rounded_sm,
|
||||
atoms.gap_sm,
|
||||
)
|
||||
break
|
||||
}
|
||||
case 'small': {
|
||||
baseStyles.push(
|
||||
{paddingVertical: 9},
|
||||
atoms.px_md,
|
||||
atoms.rounded_sm,
|
||||
atoms.gap_xs,
|
||||
)
|
||||
break
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return {
|
||||
baseStyles,
|
||||
hoverStyles,
|
||||
}
|
||||
}, [type, size, disabled])
|
||||
|
||||
const childProps = React.useMemo(
|
||||
() => ({
|
||||
state,
|
||||
props: {
|
||||
type,
|
||||
size,
|
||||
disabled: disabled || false,
|
||||
},
|
||||
}),
|
||||
[state, type, size, disabled],
|
||||
)
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
role="button"
|
||||
{...rest}
|
||||
aria-label={accessibilityLabel}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityHint={accessibilityHint}
|
||||
disabled={disabled || false}
|
||||
accessibilityState={{
|
||||
disabled: disabled || false,
|
||||
}}
|
||||
style={[
|
||||
atoms.flex_row,
|
||||
atoms.align_center,
|
||||
...baseStyles,
|
||||
...(state.hovered ? hoverStyles : []),
|
||||
]}
|
||||
onPressIn={onPressIn}
|
||||
onPressOut={onPressOut}
|
||||
onHoverIn={onHoverIn}
|
||||
onHoverOut={onHoverOut}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}>
|
||||
{typeof children === 'string' ? (
|
||||
<ButtonText type={type} size={size} disabled={disabled || false}>
|
||||
{children}
|
||||
</ButtonText>
|
||||
) : typeof children === 'function' ? (
|
||||
children(childProps)
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
|
||||
export function ButtonText({
|
||||
children,
|
||||
style,
|
||||
type,
|
||||
size,
|
||||
disabled,
|
||||
...rest
|
||||
}: ButtonTextProps) {
|
||||
const t = useTheme()
|
||||
|
||||
const textStyles = React.useMemo(() => {
|
||||
const baseStyles = []
|
||||
|
||||
switch (type) {
|
||||
case 'primary': {
|
||||
baseStyles.push({color: tokens.color.white})
|
||||
break
|
||||
}
|
||||
case 'secondary': {
|
||||
if (disabled) {
|
||||
baseStyles.push({
|
||||
color: tokens.color.gray_400,
|
||||
})
|
||||
} else {
|
||||
baseStyles.push({
|
||||
color: tokens.color.gray_800,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'negative': {
|
||||
baseStyles.push({
|
||||
color: tokens.color.white,
|
||||
})
|
||||
break
|
||||
}
|
||||
default:
|
||||
baseStyles.push(t.atoms.text)
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 'small': {
|
||||
baseStyles.push(
|
||||
atoms.text_md,
|
||||
web({paddingBottom: 1}),
|
||||
native({marginTop: 2}),
|
||||
)
|
||||
break
|
||||
}
|
||||
case 'large': {
|
||||
baseStyles.push(
|
||||
atoms.text_md,
|
||||
web({paddingBottom: 1}),
|
||||
native({marginTop: 2}),
|
||||
)
|
||||
break
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return baseStyles
|
||||
}, [t, type, size, disabled])
|
||||
|
||||
return (
|
||||
<Text
|
||||
{...rest}
|
||||
style={[atoms.font_bold, atoms.text_center, ...textStyles, style]}>
|
||||
{children}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a, useTheme, useBreakpoints} from '#/alf'
|
||||
import {Text, H3} from '#/view/com/Typography'
|
||||
import {Text, H3} from '#/components/Typography'
|
||||
|
||||
export function Breakpoints() {
|
||||
const t = useTheme()
|
||||
|
||||
@@ -1,120 +1,42 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonText} from '#/view/com/Button'
|
||||
import {Link} from '#/view/com/Link'
|
||||
import {Text, H3} from '#/view/com/Typography'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Button, ButtonVariant, ButtonColor} from '#/components/Button'
|
||||
import {H1} from '#/components/Typography'
|
||||
|
||||
export function Buttons() {
|
||||
const t = useTheme()
|
||||
|
||||
return (
|
||||
<View style={[a.gap_md, a.align_start]}>
|
||||
<Button
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something">
|
||||
Unstyled button
|
||||
</Button>
|
||||
<View style={[a.gap_md]}>
|
||||
<H1>Buttons</H1>
|
||||
|
||||
<Button
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something">
|
||||
{({state}) => (
|
||||
<View style={[a.p_md, a.rounded_full, t.atoms.bg_contrast_300]}>
|
||||
<Text>Entirely custom button, state: {JSON.stringify(state)}</Text>
|
||||
<View style={[a.flex_row, a.gap_md, a.align_start]}>
|
||||
{['primary', 'secondary', 'negative'].map(color => (
|
||||
<View key={color} style={[a.gap_md, a.align_start]}>
|
||||
{['solid', 'outline', 'ghost'].map(variant => (
|
||||
<React.Fragment key={variant}>
|
||||
<Button
|
||||
variant={variant as ButtonVariant}
|
||||
color={color as ButtonColor}
|
||||
size="large"
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something">
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
disabled
|
||||
variant={variant as ButtonVariant}
|
||||
color={color as ButtonColor}
|
||||
size="large"
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something">
|
||||
Button
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
type="primary"
|
||||
size="large">
|
||||
Default button
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
type="primary"
|
||||
size="large"
|
||||
disabled>
|
||||
Default button (disabled)
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
type="primary"
|
||||
size="large">
|
||||
{({props}) => (
|
||||
<>
|
||||
<FontAwesomeIcon icon={['fas', 'plus']} size={12} />
|
||||
<ButtonText {...props}>Default with an icon</ButtonText>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
type="secondary"
|
||||
size="small">
|
||||
Small button
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
type="secondary"
|
||||
size="small"
|
||||
disabled>
|
||||
Small button (disabled)
|
||||
</Button>
|
||||
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://blueskyweb.xyz"
|
||||
warnOnMismatchingTextChild
|
||||
style={[a.text_md]}>
|
||||
External
|
||||
</Link>
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://blueskyweb.xyz"
|
||||
style={[a.text_md]}>
|
||||
<H3>External with custom children</H3>
|
||||
</Link>
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://blueskyweb.xyz"
|
||||
warnOnMismatchingTextChild
|
||||
style={[a.text_md]}>
|
||||
https://blueskyweb.xyz
|
||||
</Link>
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://bsky.app/profile/bsky.app"
|
||||
warnOnMismatchingTextChild
|
||||
style={[a.text_md]}>
|
||||
Internal
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
type="primary"
|
||||
size="large"
|
||||
to="https://bsky.app/profile/bsky.app">
|
||||
{({props}) => <ButtonText {...props}>Link as a button</ButtonText>}
|
||||
</Link>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Button} from '#/view/com/Button'
|
||||
import {H3, P} from '#/view/com/Typography'
|
||||
import * as Dialog from '#/view/com/Dialog'
|
||||
import * as Prompt from '#/view/com/Prompt'
|
||||
import {Button} from '#/components/Button'
|
||||
import {H3, P} from '#/components/Typography'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
|
||||
export function Dialogs() {
|
||||
const control = Dialog.useDialogControl()
|
||||
@@ -14,7 +14,8 @@ export function Dialogs() {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
type="secondary"
|
||||
variant="outline"
|
||||
color="secondary"
|
||||
size="small"
|
||||
onPress={() => control.open()}
|
||||
accessibilityLabel="Open basic dialog"
|
||||
@@ -23,7 +24,8 @@ export function Dialogs() {
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="negative"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="small"
|
||||
onPress={() => prompt.open()}
|
||||
accessibilityLabel="Open prompt"
|
||||
@@ -53,7 +55,8 @@ export function Dialogs() {
|
||||
<P nativeID="dialog-description">Description</P>
|
||||
<View style={[a.flex_row, a.justify_end]}>
|
||||
<Button
|
||||
type="primary"
|
||||
variant="outline"
|
||||
color="primary"
|
||||
size="small"
|
||||
onPress={() => control.close()}
|
||||
accessibilityLabel="Open basic dialog"
|
||||
|
||||
@@ -2,9 +2,9 @@ import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {InputText} from '#/view/com/forms/InputText'
|
||||
import {InputDate, utils} from '#/view/com/forms/InputDate'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {InputText} from '#/components/forms/InputText'
|
||||
import {InputDate, utils} from '#/components/forms/InputDate'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
|
||||
export function Forms() {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {ButtonText} from '#/components/Button'
|
||||
import {Link} from '#/components/Link'
|
||||
import {H1, H3} from '#/components/Typography'
|
||||
|
||||
export function Links() {
|
||||
return (
|
||||
<View style={[a.gap_md, a.align_start]}>
|
||||
<H1>Links</H1>
|
||||
|
||||
<View style={[a.gap_md, a.align_start]}>
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://blueskyweb.xyz"
|
||||
warnOnMismatchingTextChild
|
||||
style={[a.text_md]}>
|
||||
External
|
||||
</Link>
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://blueskyweb.xyz"
|
||||
style={[a.text_md]}>
|
||||
<H3>External with custom children</H3>
|
||||
</Link>
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://blueskyweb.xyz"
|
||||
warnOnMismatchingTextChild
|
||||
style={[a.text_md]}>
|
||||
https://blueskyweb.xyz
|
||||
</Link>
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
to="https://bsky.app/profile/bsky.app"
|
||||
warnOnMismatchingTextChild
|
||||
style={[a.text_md]}>
|
||||
Internal
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
accessibilityLabel="Click here"
|
||||
accessibilityHint="Opens something"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="large"
|
||||
to="https://bsky.app/profile/bsky.app">
|
||||
{({props}) => <ButtonText {...props}>Link as a button</ButtonText>}
|
||||
</Link>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -2,62 +2,62 @@ import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {Text, H1} from '#/components/Typography'
|
||||
|
||||
export function Spacing() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<View>
|
||||
<View style={[a.gap_md]}>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>2xs (2px)</Text>
|
||||
<View style={[a.flex_1, a.pt_2xs, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.gap_md]}>
|
||||
<H1>Spacing</H1>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>xs (4px)</Text>
|
||||
<View style={[a.flex_1, a.pt_xs, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>2xs (2px)</Text>
|
||||
<View style={[a.flex_1, a.pt_2xs, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>sm (8px)</Text>
|
||||
<View style={[a.flex_1, a.pt_sm, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>xs (4px)</Text>
|
||||
<View style={[a.flex_1, a.pt_xs, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>md (12px)</Text>
|
||||
<View style={[a.flex_1, a.pt_md, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>sm (8px)</Text>
|
||||
<View style={[a.flex_1, a.pt_sm, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>lg (16px)</Text>
|
||||
<View style={[a.flex_1, a.pt_lg, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>md (12px)</Text>
|
||||
<View style={[a.flex_1, a.pt_md, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>xl (20px)</Text>
|
||||
<View style={[a.flex_1, a.pt_xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>lg (16px)</Text>
|
||||
<View style={[a.flex_1, a.pt_lg, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>2xl (24px)</Text>
|
||||
<View style={[a.flex_1, a.pt_2xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>xl (20px)</Text>
|
||||
<View style={[a.flex_1, a.pt_xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>3xl (28px)</Text>
|
||||
<View style={[a.flex_1, a.pt_3xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>2xl (24px)</Text>
|
||||
<View style={[a.flex_1, a.pt_2xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>4xl (32px)</Text>
|
||||
<View style={[a.flex_1, a.pt_4xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>3xl (28px)</Text>
|
||||
<View style={[a.flex_1, a.pt_3xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>5xl (40px)</Text>
|
||||
<View style={[a.flex_1, a.pt_5xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>4xl (32px)</Text>
|
||||
<View style={[a.flex_1, a.pt_4xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<Text style={{width: 80}}>5xl (40px)</Text>
|
||||
<View style={[a.flex_1, a.pt_5xl, t.atoms.bg_contrast_300]} />
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Text} from '#/view/com/Typography'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {Palette} from './Palette'
|
||||
|
||||
export function Theming() {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Text, H1, H2, H3, H4, H5, H6, P} from '#/view/com/Typography'
|
||||
import {Text, H1, H2, H3, H4, H5, H6, P} from '#/components/Typography'
|
||||
|
||||
export function Typography() {
|
||||
return (
|
||||
<>
|
||||
<View style={[a.gap_md]}>
|
||||
<H1>H1 Heading</H1>
|
||||
<H2>H2 Heading</H2>
|
||||
<H3>H3 Heading</H3>
|
||||
@@ -24,6 +25,6 @@ export function Typography() {
|
||||
<Text style={[a.text_sm]}>atoms.text_sm</Text>
|
||||
<Text style={[a.text_xs]}>atoms.text_xs</Text>
|
||||
<Text style={[a.text_2xs]}>atoms.text_2xs</Text>
|
||||
</>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@ import {CenteredView, ScrollView} from '#/view/com/util/Views'
|
||||
|
||||
import {atoms as a, useTheme, ThemeProvider} from '#/alf'
|
||||
import {useSetColorMode} from '#/state/shell'
|
||||
import {Button} from '#/view/com/Button'
|
||||
import {Button} from '#/components/Button'
|
||||
|
||||
import {Theming} from './Theming'
|
||||
import {Typography} from './Typography'
|
||||
import {Spacing} from './Spacing'
|
||||
import {Buttons} from './Buttons'
|
||||
import {Links} from './Links'
|
||||
import {Forms} from './Forms'
|
||||
import {Dialogs} from './Dialogs'
|
||||
import {Breakpoints} from './Breakpoints'
|
||||
@@ -21,10 +22,11 @@ export function Storybook() {
|
||||
return (
|
||||
<ScrollView>
|
||||
<CenteredView style={[t.atoms.bg]}>
|
||||
<View style={[a.p_xl, a.gap_2xl, {paddingBottom: 200}]}>
|
||||
<View style={[a.p_xl, a.gap_5xl, {paddingBottom: 200}]}>
|
||||
<View style={[a.flex_row, a.align_start, a.gap_md]}>
|
||||
<Button
|
||||
type="secondary"
|
||||
variant="outline"
|
||||
color="primary"
|
||||
size="small"
|
||||
accessibilityLabel='Set theme to "system"'
|
||||
accessibilityHint="Set theme to system default"
|
||||
@@ -32,7 +34,8 @@ export function Storybook() {
|
||||
System
|
||||
</Button>
|
||||
<Button
|
||||
type="secondary"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="small"
|
||||
accessibilityLabel='Set theme to "system"'
|
||||
accessibilityHint="Set theme to system default"
|
||||
@@ -40,7 +43,8 @@ export function Storybook() {
|
||||
Light
|
||||
</Button>
|
||||
<Button
|
||||
type="secondary"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="small"
|
||||
accessibilityLabel='Set theme to "system"'
|
||||
accessibilityHint="Set theme to system default"
|
||||
@@ -62,6 +66,7 @@ export function Storybook() {
|
||||
<Typography />
|
||||
<Spacing />
|
||||
<Buttons />
|
||||
<Links />
|
||||
<Forms />
|
||||
<Dialogs />
|
||||
<Breakpoints />
|
||||
|
||||
Reference in New Issue
Block a user