add glassy effect to headers
This commit is contained in:
@@ -240,7 +240,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
|||||||
}
|
}
|
||||||
} else if (variant === 'ghost') {
|
} else if (variant === 'ghost') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push(t.atoms.bg)
|
baseStyles.push(a.bg_transparent)
|
||||||
hoverStyles.push({
|
hoverStyles.push({
|
||||||
backgroundColor: t.palette.primary_100,
|
backgroundColor: t.palette.primary_100,
|
||||||
})
|
})
|
||||||
@@ -271,7 +271,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
|||||||
}
|
}
|
||||||
} else if (variant === 'ghost') {
|
} else if (variant === 'ghost') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push(t.atoms.bg)
|
baseStyles.push(a.bg_transparent)
|
||||||
hoverStyles.push({
|
hoverStyles.push({
|
||||||
backgroundColor: t.palette.contrast_25,
|
backgroundColor: t.palette.contrast_25,
|
||||||
})
|
})
|
||||||
@@ -308,7 +308,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
|||||||
}
|
}
|
||||||
} else if (variant === 'ghost') {
|
} else if (variant === 'ghost') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push(t.atoms.bg)
|
baseStyles.push(a.bg_transparent)
|
||||||
hoverStyles.push({
|
hoverStyles.push({
|
||||||
backgroundColor: t.palette.contrast_25,
|
backgroundColor: t.palette.contrast_25,
|
||||||
})
|
})
|
||||||
@@ -351,7 +351,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
|||||||
}
|
}
|
||||||
} else if (variant === 'ghost') {
|
} else if (variant === 'ghost') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push(t.atoms.bg)
|
baseStyles.push(a.bg_transparent)
|
||||||
hoverStyles.push({
|
hoverStyles.push({
|
||||||
backgroundColor: t.palette.negative_100,
|
backgroundColor: t.palette.negative_100,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import {View} from 'react-native'
|
||||||
|
|
||||||
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GlassyBackdrop component
|
||||||
|
* On web, it applies a backdrop filter to create a glassy effect.
|
||||||
|
* On native and non-safari mobile web, it's just a solid color.
|
||||||
|
*/
|
||||||
|
export function GlassyBackdrop() {
|
||||||
|
const t = useTheme()
|
||||||
|
return <View style={[a.absolute, a.inset_0, t.atoms.bg]} />
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import {View} from 'react-native'
|
||||||
|
|
||||||
|
import {isAndroidWeb} from '#/lib/browser'
|
||||||
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GlassyBackdrop component
|
||||||
|
* On web, it applies a backdrop filter to create a glassy effect.
|
||||||
|
* On native and non-safari mobile web, it's just a solid color.
|
||||||
|
*/
|
||||||
|
export function GlassyBackdrop() {
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
if (isAndroidWeb) {
|
||||||
|
return <View style={[a.absolute, a.inset_0, t.atoms.bg]} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View style={[a.absolute, a.inset_0, t.atoms.bg, {opacity: 0.9}]} />
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.absolute,
|
||||||
|
a.inset_0,
|
||||||
|
a.pointer_events_none,
|
||||||
|
{backdropFilter: 'blur(16px)'},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
} from '#/components/Layout/const'
|
} from '#/components/Layout/const'
|
||||||
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {GlassyBackdrop} from './GlassyBackdrop'
|
||||||
|
|
||||||
export function Outer({
|
export function Outer({
|
||||||
children,
|
children,
|
||||||
@@ -56,7 +57,7 @@ export function Outer({
|
|||||||
a.flex_row,
|
a.flex_row,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.gap_sm,
|
a.gap_sm,
|
||||||
sticky && web([a.sticky, {top: 0}, a.z_10, t.atoms.bg]),
|
sticky && web([a.sticky, {top: 0}, a.z_10]),
|
||||||
gutters,
|
gutters,
|
||||||
platform({
|
platform({
|
||||||
native: [a.pb_xs, {minHeight: 48}],
|
native: [a.pb_xs, {minHeight: 48}],
|
||||||
@@ -71,6 +72,7 @@ export function Outer({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
|
{sticky && <GlassyBackdrop />}
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -131,11 +133,7 @@ export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
|
|||||||
shape="square"
|
shape="square"
|
||||||
onPress={onPressBack}
|
onPress={onPressBack}
|
||||||
hitSlop={HITSLOP_30}
|
hitSlop={HITSLOP_30}
|
||||||
style={[
|
style={[{marginLeft: -BUTTON_VISUAL_ALIGNMENT_OFFSET}, style]}
|
||||||
{marginLeft: -BUTTON_VISUAL_ALIGNMENT_OFFSET},
|
|
||||||
a.bg_transparent,
|
|
||||||
style,
|
|
||||||
]}
|
|
||||||
{...props}>
|
{...props}>
|
||||||
<ButtonIcon icon={ArrowLeft} size="lg" />
|
<ButtonIcon icon={ArrowLeft} size="lg" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -182,8 +182,7 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Layout.Center
|
<Layout.Center style={[a.z_10, web([a.sticky, a.z_10, {top: 0}])]}>
|
||||||
style={[t.atoms.bg, a.z_10, web([a.sticky, a.z_10, {top: 0}])]}>
|
|
||||||
<Layout.Header.Outer>
|
<Layout.Header.Outer>
|
||||||
<Layout.Header.BackButton />
|
<Layout.Header.BackButton />
|
||||||
<Layout.Header.Content align="left">
|
<Layout.Header.Content align="left">
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ function HomeHeaderLayoutDesktopAndTablet({
|
|||||||
)}
|
)}
|
||||||
{tabBarAnchor}
|
{tabBarAnchor}
|
||||||
<Layout.Center
|
<Layout.Center
|
||||||
style={[a.sticky, a.z_10, a.align_center, t.atoms.bg, {top: 0}]}
|
style={[a.sticky, a.z_10, a.align_center, {top: 0}]}
|
||||||
onLayout={e => {
|
onLayout={e => {
|
||||||
headerHeight.set(e.nativeEvent.layout.height)
|
headerHeight.set(e.nativeEvent.layout.height)
|
||||||
}}>
|
}}>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {emitSoftReset} from '#/state/events'
|
|||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||||
import {Logo} from '#/view/icons/Logo'
|
import {Logo} from '#/view/icons/Logo'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, native, useTheme} from '#/alf'
|
||||||
import {ButtonIcon} from '#/components/Button'
|
import {ButtonIcon} from '#/components/Button'
|
||||||
import {Hashtag_Stroke2_Corner0_Rounded as FeedsIcon} from '#/components/icons/Hashtag'
|
import {Hashtag_Stroke2_Corner0_Rounded as FeedsIcon} from '#/components/icons/Hashtag'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
@@ -35,7 +35,7 @@ export function HomeHeaderLayoutMobile({
|
|||||||
style={[
|
style={[
|
||||||
a.fixed,
|
a.fixed,
|
||||||
a.z_10,
|
a.z_10,
|
||||||
t.atoms.bg,
|
native(t.atoms.bg),
|
||||||
{
|
{
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export interface TabBarProps {
|
|||||||
onPressSelected?: (index: number) => void
|
onPressSelected?: (index: number) => void
|
||||||
dragProgress: SharedValue<number>
|
dragProgress: SharedValue<number>
|
||||||
dragState: SharedValue<'idle' | 'dragging' | 'settling'>
|
dragState: SharedValue<'idle' | 'dragging' | 'settling'>
|
||||||
|
glassEffect?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const ITEM_PADDING = 10
|
const ITEM_PADDING = 10
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {useCallback, useEffect, useRef} from 'react'
|
|||||||
import {type ScrollView, StyleSheet, View} from 'react-native'
|
import {type ScrollView, StyleSheet, View} from 'react-native'
|
||||||
|
|
||||||
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
|
import {GlassyBackdrop} from '#/components/Layout/Header/GlassyBackdrop'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {PressableWithHover} from '../util/PressableWithHover'
|
import {PressableWithHover} from '../util/PressableWithHover'
|
||||||
import {DraggableScrollView} from './DraggableScrollView'
|
import {DraggableScrollView} from './DraggableScrollView'
|
||||||
@@ -15,6 +16,7 @@ export interface TabBarProps {
|
|||||||
|
|
||||||
onSelect?: (index: number) => void
|
onSelect?: (index: number) => void
|
||||||
onPressSelected?: (index: number) => void
|
onPressSelected?: (index: number) => void
|
||||||
|
glassEffect?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// How much of the previous/next item we're showing
|
// How much of the previous/next item we're showing
|
||||||
@@ -27,6 +29,7 @@ export function TabBar({
|
|||||||
items,
|
items,
|
||||||
onSelect,
|
onSelect,
|
||||||
onPressSelected,
|
onPressSelected,
|
||||||
|
glassEffect = true,
|
||||||
}: TabBarProps) {
|
}: TabBarProps) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const scrollElRef = useRef<ScrollView>(null)
|
const scrollElRef = useRef<ScrollView>(null)
|
||||||
@@ -92,8 +95,9 @@ export function TabBar({
|
|||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
testID={testID}
|
testID={testID}
|
||||||
style={[t.atoms.bg, styles.outer]}
|
style={[styles.outer, !glassEffect && t.atoms.bg]}
|
||||||
accessibilityRole="tablist">
|
accessibilityRole="tablist">
|
||||||
|
{glassEffect && <GlassyBackdrop />}
|
||||||
<DraggableScrollView
|
<DraggableScrollView
|
||||||
testID={`${testID}-selector`}
|
testID={`${testID}-selector`}
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
|
|||||||
Reference in New Issue
Block a user