Link updates, add atoms

This commit is contained in:
Eric Bailey
2024-02-16 10:55:50 -06:00
parent 1b992d5d6b
commit 677c4abece
3 changed files with 77 additions and 18 deletions
+36
View File
@@ -122,6 +122,9 @@ export const atoms = {
flex_shrink: { flex_shrink: {
flexShrink: 1, flexShrink: 1,
}, },
justify_start: {
justifyContent: 'flex-start',
},
justify_center: { justify_center: {
justifyContent: 'center', justifyContent: 'center',
}, },
@@ -140,10 +143,31 @@ export const atoms = {
align_end: { align_end: {
alignItems: 'flex-end', alignItems: 'flex-end',
}, },
self_auto: {
alignSelf: 'auto',
},
self_start: {
alignSelf: 'flex-start',
},
self_end: {
alignSelf: 'flex-end',
},
self_center: {
alignSelf: 'center',
},
self_stretch: {
alignSelf: 'stretch',
},
self_baseline: {
alignSelf: 'baseline',
},
/* /*
* Text * Text
*/ */
text_left: {
textAlign: 'left',
},
text_center: { text_center: {
textAlign: 'center', textAlign: 'center',
}, },
@@ -195,10 +219,16 @@ export const atoms = {
font_bold: { font_bold: {
fontWeight: tokens.fontWeight.semibold, fontWeight: tokens.fontWeight.semibold,
}, },
italic: {
fontStyle: 'italic',
},
/* /*
* Border * Border
*/ */
border_0: {
borderWidth: 0,
},
border: { border: {
borderWidth: 1, borderWidth: 1,
}, },
@@ -208,6 +238,12 @@ export const atoms = {
border_b: { border_b: {
borderBottomWidth: 1, borderBottomWidth: 1,
}, },
border_l: {
borderLeftWidth: 1,
},
border_r: {
borderRightWidth: 1,
},
/* /*
* Shadow * Shadow
+32 -14
View File
@@ -13,7 +13,7 @@ import {sanitizeUrl} from '@braintree/sanitize-url'
import {useInteractionState} from '#/components/hooks/useInteractionState' import {useInteractionState} from '#/components/hooks/useInteractionState'
import {isWeb} from '#/platform/detection' import {isWeb} from '#/platform/detection'
import {useTheme, web, flatten, TextStyleProp} from '#/alf' import {useTheme, web, flatten, TextStyleProp, atoms as a} from '#/alf'
import {Button, ButtonProps} from '#/components/Button' import {Button, ButtonProps} from '#/components/Button'
import {AllNavigatorParams, NavigationProp} from '#/lib/routes/types' import {AllNavigatorParams, NavigationProp} from '#/lib/routes/types'
import { import {
@@ -35,6 +35,8 @@ type BaseLinkProps = Pick<
Parameters<typeof useLinkProps<AllNavigatorParams>>[0], Parameters<typeof useLinkProps<AllNavigatorParams>>[0],
'to' 'to'
> & { > & {
testID?: string
/** /**
* The React Navigation `StackAction` to perform when the link is pressed. * The React Navigation `StackAction` to perform when the link is pressed.
*/ */
@@ -46,6 +48,13 @@ type BaseLinkProps = Pick<
* Note: atm this only works for `InlineLink`s with a string child. * Note: atm this only works for `InlineLink`s with a string child.
*/ */
warnOnMismatchingTextChild?: boolean warnOnMismatchingTextChild?: boolean
/**
* Callback for when the link is pressed.
*
* DO NOT use this for navigation, that's what the `to` prop is for.
*/
onPress?: (e: GestureResponderEvent) => void
} }
export function useLink({ export function useLink({
@@ -53,6 +62,7 @@ export function useLink({
displayText, displayText,
action = 'push', action = 'push',
warnOnMismatchingTextChild, warnOnMismatchingTextChild,
onPress: outerOnPress,
}: BaseLinkProps & { }: BaseLinkProps & {
displayText: string displayText: string
}) { }) {
@@ -66,6 +76,8 @@ export function useLink({
const onPress = React.useCallback( const onPress = React.useCallback(
(e: GestureResponderEvent) => { (e: GestureResponderEvent) => {
outerOnPress?.(e)
const requiresWarning = Boolean( const requiresWarning = Boolean(
warnOnMismatchingTextChild && warnOnMismatchingTextChild &&
displayText && displayText &&
@@ -132,6 +144,7 @@ export function useLink({
displayText, displayText,
closeModal, closeModal,
openModal, openModal,
outerOnPress,
], ],
) )
@@ -143,15 +156,11 @@ export function useLink({
} }
export type LinkProps = Omit<BaseLinkProps, 'warnOnMismatchingTextChild'> & export type LinkProps = Omit<BaseLinkProps, 'warnOnMismatchingTextChild'> &
Omit<ButtonProps, 'style' | 'onPress' | 'disabled' | 'label'> & { Omit<ButtonProps, 'onPress' | 'disabled' | 'label'> & {
/** /**
* Label for a11y. Defaults to the href. * Label for a11y. Defaults to the href.
*/ */
label?: string label?: string
/**
* Web-only attribute. Sets `download` attr on web.
*/
download?: string
} }
/** /**
@@ -166,19 +175,21 @@ export function Link({
children, children,
to, to,
action = 'push', action = 'push',
download, onPress: outerOnPress,
...rest ...rest
}: LinkProps) { }: LinkProps) {
const {href, isExternal, onPress} = useLink({ const {href, isExternal, onPress} = useLink({
to, to,
displayText: typeof children === 'string' ? children : '', displayText: typeof children === 'string' ? children : '',
action, action,
onPress: outerOnPress,
}) })
return ( return (
<Button <Button
label={href} label={href}
{...rest} {...rest}
style={[a.justify_start, flatten(rest.style)]}
role="link" role="link"
accessibilityRole="link" accessibilityRole="link"
href={href} href={href}
@@ -187,7 +198,6 @@ export function Link({
hrefAttrs: { hrefAttrs: {
target: isExternal ? 'blank' : undefined, target: isExternal ? 'blank' : undefined,
rel: isExternal ? 'noopener noreferrer' : undefined, rel: isExternal ? 'noopener noreferrer' : undefined,
download,
}, },
dataSet: { dataSet: {
// default to no underline, apply this ourselves // default to no underline, apply this ourselves
@@ -215,6 +225,7 @@ export function InlineLink({
action = 'push', action = 'push',
warnOnMismatchingTextChild, warnOnMismatchingTextChild,
style, style,
onPress: outerOnPress,
...rest ...rest
}: InlineLinkProps) { }: InlineLinkProps) {
const t = useTheme() const t = useTheme()
@@ -224,13 +235,20 @@ export function InlineLink({
displayText: stringChildren ? children : '', displayText: stringChildren ? children : '',
action, action,
warnOnMismatchingTextChild, warnOnMismatchingTextChild,
onPress: outerOnPress,
}) })
const {
state: hovered,
onIn: onHoverIn,
onOut: onHoverOut,
} = useInteractionState()
const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
const { const {
state: pressed, state: pressed,
onIn: onPressIn, onIn: onPressIn,
onOut: onPressOut, onOut: onPressOut,
} = useInteractionState() } = useInteractionState()
const flattenedStyle = flatten(style)
return ( return (
<TouchableWithoutFeedback <TouchableWithoutFeedback
@@ -245,14 +263,16 @@ export function InlineLink({
{...rest} {...rest}
style={[ style={[
{color: t.palette.primary_500}, {color: t.palette.primary_500},
(focused || pressed) && { (hovered || focused || pressed) && {
outline: 0, outline: 0,
textDecorationLine: 'underline', textDecorationLine: 'underline',
textDecorationColor: t.palette.primary_500, textDecorationColor: flattenedStyle.color ?? t.palette.primary_500,
}, },
flatten(style), flattenedStyle,
]} ]}
role="link" role="link"
onMouseEnter={onHoverIn}
onMouseLeave={onHoverOut}
accessibilityRole="link" accessibilityRole="link"
href={href} href={href}
{...web({ {...web({
@@ -260,9 +280,7 @@ export function InlineLink({
target: isExternal ? 'blank' : undefined, target: isExternal ? 'blank' : undefined,
rel: isExternal ? 'noopener noreferrer' : undefined, rel: isExternal ? 'noopener noreferrer' : undefined,
}, },
dataSet: stringChildren dataSet: {
? {}
: {
// default to no underline, apply this ourselves // default to no underline, apply this ourselves
noUnderline: '1', noUnderline: '1',
}, },
+6 -1
View File
@@ -19,9 +19,14 @@ export function Links() {
style={[a.text_md]}> style={[a.text_md]}>
External External
</InlineLink> </InlineLink>
<InlineLink to="https://bsky.social" style={[a.text_md]}> <InlineLink to="https://bsky.social" style={[a.text_md, t.atoms.text]}>
<H3>External with custom children</H3> <H3>External with custom children</H3>
</InlineLink> </InlineLink>
<InlineLink
to="https://bsky.social"
style={[a.text_md, t.atoms.text_contrast_low]}>
External with custom children
</InlineLink>
<InlineLink <InlineLink
to="https://bsky.social" to="https://bsky.social"
warnOnMismatchingTextChild warnOnMismatchingTextChild