Add subtle hover to all components except feed
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
import {View} from 'react-native'
|
||||||
|
|
||||||
|
import {atoms as a, useTheme, type ViewStyleProp} from '#/alf'
|
||||||
|
|
||||||
|
export function SubtleHover({style, hover}: ViewStyleProp & {hover: boolean}) {
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
let opacity: number
|
||||||
|
switch (t.name) {
|
||||||
|
case 'dark':
|
||||||
|
opacity = 0.4
|
||||||
|
break
|
||||||
|
case 'dim':
|
||||||
|
opacity = 0.45
|
||||||
|
break
|
||||||
|
case 'light':
|
||||||
|
opacity = 0.5
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.absolute,
|
||||||
|
a.inset_0,
|
||||||
|
a.pointer_events_none,
|
||||||
|
a.transition_opacity,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
style,
|
||||||
|
{opacity: hover ? opacity : 0},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -52,6 +52,7 @@ import {StarterPack} from '#/components/icons/StarterPack'
|
|||||||
import {UserCircle_Stroke2_Corner0_Rounded as Person} from '#/components/icons/UserCircle'
|
import {UserCircle_Stroke2_Corner0_Rounded as Person} from '#/components/icons/UserCircle'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as ProfileCard from '#/components/ProfileCard'
|
import * as ProfileCard from '#/components/ProfileCard'
|
||||||
|
import {SubtleHover} from '#/components/SubtleHover'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import * as ModuleHeader from './components/ModuleHeader'
|
import * as ModuleHeader from './components/ModuleHeader'
|
||||||
import {
|
import {
|
||||||
@@ -69,33 +70,26 @@ function LoadMore({item}: {item: ExploreScreenItems & {type: 'loadMore'}}) {
|
|||||||
onPress={item.onLoadMore}
|
onPress={item.onLoadMore}
|
||||||
style={[a.relative, a.w_full]}>
|
style={[a.relative, a.w_full]}>
|
||||||
{({hovered, pressed}) => (
|
{({hovered, pressed}) => (
|
||||||
<View
|
<>
|
||||||
style={[
|
<SubtleHover hover={hovered || pressed} />
|
||||||
a.flex_1,
|
<View
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_center,
|
|
||||||
a.px_lg,
|
|
||||||
a.py_md,
|
|
||||||
a.gap_sm,
|
|
||||||
(hovered || pressed) && t.atoms.bg_contrast_25,
|
|
||||||
]}>
|
|
||||||
<Text
|
|
||||||
style={[
|
style={[
|
||||||
a.leading_snug,
|
a.flex_1,
|
||||||
hovered ? t.atoms.text : t.atoms.text_contrast_medium,
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.justify_center,
|
||||||
|
a.px_lg,
|
||||||
|
a.py_md,
|
||||||
|
a.gap_sm,
|
||||||
]}>
|
]}>
|
||||||
{item.message}
|
<Text style={[a.leading_snug]}>{item.message}</Text>
|
||||||
</Text>
|
{item.isLoadingMore ? (
|
||||||
{item.isLoadingMore ? (
|
<Loader size="sm" />
|
||||||
<Loader size="sm" />
|
) : (
|
||||||
) : (
|
<ChevronDownIcon size="sm" style={t.atoms.text_contrast_medium} />
|
||||||
<ChevronDownIcon
|
)}
|
||||||
size="sm"
|
</View>
|
||||||
style={hovered ? t.atoms.text : t.atoms.text_contrast_medium}
|
</>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {PlusSmall_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus
|
|||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||||
import {useStarterPackLink} from '#/components/StarterPack/StarterPackCard'
|
import {useStarterPackLink} from '#/components/StarterPack/StarterPackCard'
|
||||||
|
import {SubtleHover} from '#/components/SubtleHover'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
@@ -48,75 +49,80 @@ export function StarterPackCard({
|
|||||||
.map(item => item.subject)
|
.map(item => item.subject)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<Link
|
||||||
style={[
|
to={link.to}
|
||||||
a.w_full,
|
label={link.label}
|
||||||
a.p_lg,
|
onHoverIn={link.precache}
|
||||||
a.gap_md,
|
onPress={link.precache}>
|
||||||
a.border,
|
{s => (
|
||||||
a.rounded_sm,
|
<>
|
||||||
a.overflow_hidden,
|
<SubtleHover hover={s.hovered || s.pressed} />
|
||||||
t.atoms.border_contrast_low,
|
|
||||||
]}>
|
|
||||||
<View aria-hidden style={[a.absolute, a.inset_0, a.z_40]}>
|
|
||||||
<Link
|
|
||||||
to={link.to}
|
|
||||||
label={link.label}
|
|
||||||
style={[a.absolute, a.inset_0]}
|
|
||||||
onHoverIn={link.precache}
|
|
||||||
onPress={link.precache}>
|
|
||||||
<View />
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<AvatarStack
|
<View
|
||||||
profiles={profiles ?? []}
|
style={[
|
||||||
numPending={profileCount}
|
a.w_full,
|
||||||
total={view.list?.listItemCount}
|
a.p_lg,
|
||||||
/>
|
a.gap_md,
|
||||||
|
a.border,
|
||||||
|
a.rounded_sm,
|
||||||
|
a.overflow_hidden,
|
||||||
|
t.atoms.border_contrast_low,
|
||||||
|
]}>
|
||||||
|
<AvatarStack
|
||||||
|
profiles={profiles ?? []}
|
||||||
|
numPending={profileCount}
|
||||||
|
total={view.list?.listItemCount}
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.w_full,
|
a.w_full,
|
||||||
a.flex_row,
|
a.flex_row,
|
||||||
a.align_start,
|
a.align_start,
|
||||||
a.gap_lg,
|
a.gap_lg,
|
||||||
web({
|
web({
|
||||||
position: 'static',
|
position: 'static',
|
||||||
zIndex: 'unset',
|
zIndex: 'unset',
|
||||||
}),
|
}),
|
||||||
]}>
|
]}>
|
||||||
<View style={[a.flex_1]}>
|
<View style={[a.flex_1]}>
|
||||||
<Text
|
<Text
|
||||||
emoji
|
emoji
|
||||||
style={[a.text_md, a.font_bold, a.leading_snug]}
|
style={[a.text_md, a.font_bold, a.leading_snug]}
|
||||||
numberOfLines={1}>
|
numberOfLines={1}>
|
||||||
{view.record.name}
|
{view.record.name}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
emoji
|
emoji
|
||||||
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}
|
style={[
|
||||||
numberOfLines={1}>
|
a.text_sm,
|
||||||
{view.creator?.did === currentAccount?.did
|
a.leading_snug,
|
||||||
? _(msg`By you`)
|
t.atoms.text_contrast_medium,
|
||||||
: _(msg`By ${sanitizeHandle(view.creator.handle, '@')}`)}
|
]}
|
||||||
</Text>
|
numberOfLines={1}>
|
||||||
</View>
|
{view.creator?.did === currentAccount?.did
|
||||||
<Link
|
? _(msg`By you`)
|
||||||
to={link.to}
|
: _(msg`By ${sanitizeHandle(view.creator.handle, '@')}`)}
|
||||||
label={link.label}
|
</Text>
|
||||||
onHoverIn={link.precache}
|
</View>
|
||||||
onPress={link.precache}
|
<Link
|
||||||
variant="solid"
|
to={link.to}
|
||||||
color="secondary"
|
label={link.label}
|
||||||
size="small"
|
onHoverIn={link.precache}
|
||||||
style={[a.z_50]}>
|
onPress={link.precache}
|
||||||
<ButtonText>
|
variant="solid"
|
||||||
<Trans>Open pack</Trans>
|
color="secondary"
|
||||||
</ButtonText>
|
size="small"
|
||||||
</Link>
|
style={[a.z_50]}>
|
||||||
</View>
|
<ButtonText>
|
||||||
</View>
|
<Trans>Open pack</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {atoms as a} from '#/alf'
|
|||||||
import {Button} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
import * as ProfileCard from '#/components/ProfileCard'
|
import * as ProfileCard from '#/components/ProfileCard'
|
||||||
import {boostInterests, Tabs} from '#/components/ProgressGuide/FollowDialog'
|
import {boostInterests, Tabs} from '#/components/ProgressGuide/FollowDialog'
|
||||||
|
import {SubtleHover} from '#/components/SubtleHover'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
@@ -133,10 +134,7 @@ let Tab = ({
|
|||||||
a.py_sm,
|
a.py_sm,
|
||||||
a.border,
|
a.border,
|
||||||
active || hovered || pressed || focused
|
active || hovered || pressed || focused
|
||||||
? [
|
? [t.atoms.bg_contrast_25, t.atoms.border_contrast_medium]
|
||||||
t.atoms.bg_contrast_25,
|
|
||||||
{borderColor: t.atoms.bg_contrast_25.backgroundColor},
|
|
||||||
]
|
|
||||||
: [t.atoms.bg, t.atoms.border_contrast_low],
|
: [t.atoms.bg, t.atoms.border_contrast_low],
|
||||||
]}>
|
]}>
|
||||||
<Text
|
<Text
|
||||||
@@ -187,48 +185,50 @@ let SuggestedProfileCard = ({
|
|||||||
)
|
)
|
||||||
}}>
|
}}>
|
||||||
{s => (
|
{s => (
|
||||||
<View
|
<>
|
||||||
style={[
|
<SubtleHover hover={s.hovered || s.pressed} />
|
||||||
a.flex_1,
|
<View
|
||||||
a.w_full,
|
style={[
|
||||||
a.py_lg,
|
a.flex_1,
|
||||||
a.px_lg,
|
a.w_full,
|
||||||
a.border_t,
|
a.py_lg,
|
||||||
t.atoms.border_contrast_low,
|
a.px_lg,
|
||||||
(s.hovered || s.pressed) && [t.atoms.bg_contrast_25],
|
a.border_t,
|
||||||
]}>
|
t.atoms.border_contrast_low,
|
||||||
<ProfileCard.Outer>
|
]}>
|
||||||
<ProfileCard.Header>
|
<ProfileCard.Outer>
|
||||||
<ProfileCard.Avatar
|
<ProfileCard.Header>
|
||||||
profile={profile}
|
<ProfileCard.Avatar
|
||||||
moderationOpts={moderationOpts}
|
profile={profile}
|
||||||
/>
|
moderationOpts={moderationOpts}
|
||||||
<ProfileCard.NameAndHandle
|
/>
|
||||||
profile={profile}
|
<ProfileCard.NameAndHandle
|
||||||
moderationOpts={moderationOpts}
|
profile={profile}
|
||||||
/>
|
moderationOpts={moderationOpts}
|
||||||
<ProfileCard.FollowButton
|
/>
|
||||||
profile={profile}
|
<ProfileCard.FollowButton
|
||||||
moderationOpts={moderationOpts}
|
profile={profile}
|
||||||
withIcon={false}
|
moderationOpts={moderationOpts}
|
||||||
logContext="ExploreSuggestedAccounts"
|
withIcon={false}
|
||||||
onFollow={() => {
|
logContext="ExploreSuggestedAccounts"
|
||||||
logger.metric(
|
onFollow={() => {
|
||||||
'suggestedUser:follow',
|
logger.metric(
|
||||||
{
|
'suggestedUser:follow',
|
||||||
logContext: 'Explore',
|
{
|
||||||
location: 'Card',
|
logContext: 'Explore',
|
||||||
recId,
|
location: 'Card',
|
||||||
position,
|
recId,
|
||||||
},
|
position,
|
||||||
{statsig: true},
|
},
|
||||||
)
|
{statsig: true},
|
||||||
}}
|
)
|
||||||
/>
|
}}
|
||||||
</ProfileCard.Header>
|
/>
|
||||||
<ProfileCard.Description profile={profile} numberOfLines={2} />
|
</ProfileCard.Header>
|
||||||
</ProfileCard.Outer>
|
<ProfileCard.Description profile={profile} numberOfLines={2} />
|
||||||
</View>
|
</ProfileCard.Outer>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</ProfileCard.Link>
|
</ProfileCard.Link>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {type Props as SVGIconProps} from '#/components/icons/common'
|
|||||||
import {Flame_Stroke2_Corner1_Rounded as FlameIcon} from '#/components/icons/Flame'
|
import {Flame_Stroke2_Corner1_Rounded as FlameIcon} from '#/components/icons/Flame'
|
||||||
import {Trending3_Stroke2_Corner1_Rounded as TrendingIcon} from '#/components/icons/Trending'
|
import {Trending3_Stroke2_Corner1_Rounded as TrendingIcon} from '#/components/icons/Trending'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
|
import {SubtleHover} from '#/components/SubtleHover'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
const TOPIC_COUNT = 5
|
const TOPIC_COUNT = 5
|
||||||
@@ -92,15 +93,8 @@ export function TrendRow({
|
|||||||
PressableComponent={Pressable}>
|
PressableComponent={Pressable}>
|
||||||
{({hovered, pressed}) => (
|
{({hovered, pressed}) => (
|
||||||
<>
|
<>
|
||||||
<View
|
<SubtleHover hover={hovered || pressed} />
|
||||||
style={[
|
<View style={[gutters, a.w_full, a.py_lg, a.flex_row, a.gap_2xs]}>
|
||||||
gutters,
|
|
||||||
a.w_full,
|
|
||||||
a.py_lg,
|
|
||||||
a.flex_row,
|
|
||||||
a.gap_2xs,
|
|
||||||
(hovered || pressed) && t.atoms.bg_contrast_25,
|
|
||||||
]}>
|
|
||||||
<View style={[a.flex_1, a.gap_xs]}>
|
<View style={[a.flex_1, a.gap_xs]}>
|
||||||
<View style={[a.flex_row]}>
|
<View style={[a.flex_row]}>
|
||||||
<Text
|
<Text
|
||||||
|
|||||||
Reference in New Issue
Block a user