feat: enhance PageHeader and PageHeaderRight components with improved styling and layout

- Added LinearBlur effect to the PageHeader for a refined visual appearance.
- Updated PageHeaderRight to use background styles instead of borders for a modern look.
- Adjusted ViewModeSegment styling to maintain consistency across components.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2025-11-30 13:24:20 +08:00
parent a9703f34dc
commit 2a7336cd6b
5 changed files with 96 additions and 7 deletions

View File

@@ -41,9 +41,9 @@ export const PageHeaderRight = () => {
(gallerySetting.selectedRatings !== null ? 1 : 0)
return (
<div className="flex items-center gap-1 rounded-lg bg-white/5 lg:gap-1.5">
<div className="flex items-center gap-1 lg:gap-1.5">
{/* Action Buttons */}
<div className="border-border flex items-center gap-1 rounded-lg border-[0.5px]">
<div className="bg-material-medium/40 flex items-center gap-1 rounded-lg">
<ActionIconButton
icon="i-mingcute-search-line"
title={t('action.search.unified.title')}
@@ -81,7 +81,7 @@ export const PageHeaderRight = () => {
{/* Auth Section - Only show when useCloud is true */}
{injectConfig.useCloud && (
<div className="border-border flex items-center gap-1 rounded-full border-[0.5px]">
<div className="bg-material-medium/40 flex items-center gap-1 rounded-lg">
{sessionUser ? <UserMenuButton user={sessionUser} /> : <LoginButton />}
</div>
)}
@@ -106,7 +106,7 @@ const DesktopViewButton = ({
<DropdownMenuTrigger asChild>
<button
type="button"
className="relative flex size-7 items-center justify-center rounded text-white/60 transition-all duration-200 hover:bg-white/10 hover:text-white lg:size-8"
className="relative flex size-7 items-center justify-center rounded-full text-white/60 transition-all duration-200 hover:bg-white/10 hover:text-white lg:size-8"
title={title}
>
<i className={`${icon} text-sm lg:text-base`} />
@@ -187,7 +187,7 @@ const LoginButton = () => {
<DropdownMenuTrigger asChild>
<button
type="button"
className="relative flex size-7 items-center justify-center rounded-full text-white/60 transition-all duration-200 hover:bg-white/10 hover:text-white lg:size-8"
className="relative flex size-7 items-center justify-center rounded text-white/60 transition-all duration-200 hover:bg-white/10 hover:text-white lg:size-8"
title={t('action.login')}
>
<i className="i-lucide-log-in text-sm lg:text-base" />

View File

@@ -15,7 +15,7 @@ export const ViewModeSegment = () => {
}
return (
<div className="border-border relative flex h-7 items-center gap-0.5 rounded-lg border-[0.5px] bg-white/5 p-0.5 lg:h-8 lg:gap-1 lg:p-1">
<div className="bg-material-medium/40 relative flex h-7 items-center gap-0.5 rounded-lg p-0.5 lg:h-8 lg:gap-1 lg:p-1">
<button
type="button"
onClick={() => handleViewModeChange('masonry')}

View File

@@ -1,3 +1,5 @@
import { LinearBlur } from '@afilmory/ui'
import { PageHeaderCenter } from './PageHeaderCenter'
import { PageHeaderLeft } from './PageHeaderLeft'
import { PageHeaderRight } from './PageHeaderRight'
@@ -11,7 +13,13 @@ interface PageHeaderProps {
export const PageHeader = ({ dateRange, location, showDateRange }: PageHeaderProps) => {
return (
<header className="fixed top-0 right-0 left-0 z-100 border-b border-white/5 bg-black/80 backdrop-blur-xl">
<header className="fixed top-0 right-0 left-0 z-100">
<LinearBlur
className="pointer-events-none absolute inset-x-0 z-[-1] h-15"
tint="var(--color-background)"
strength={128}
side="top"
/>
<div className="flex h-12 items-center justify-between gap-2 px-3 lg:h-12 lg:gap-3 lg:px-4">
<PageHeaderLeft />
<PageHeaderCenter dateRange={dateRange} location={location} showDateRange={showDateRange} />

View File

@@ -14,6 +14,7 @@ export * from './lazy-image'
export * from './mobile-tab'
export * from './modal'
export * from './portal'
export * from './progressive-blur'
export * from './prompts'
export * from './scroll-areas'
export * from './segment'

View File

@@ -0,0 +1,80 @@
import * as React from 'react'
interface LinearBlurProps extends React.HTMLAttributes<HTMLDivElement> {
strength?: number
steps?: number
falloffPercentage?: number
tint?: string
side?: 'left' | 'right' | 'top' | 'bottom'
}
const oppositeSide = {
left: 'right',
right: 'left',
top: 'bottom',
bottom: 'top',
}
export function LinearBlur({
strength = 64,
steps = 8,
falloffPercentage = 100,
tint = 'transparent',
side = 'top',
...props
}: LinearBlurProps) {
const actualSteps = Math.max(1, steps)
const step = falloffPercentage / actualSteps
const factor = 0.5
const base = Math.pow(strength / factor, 1 / (actualSteps - 1))
const mainPercentage = 100 - falloffPercentage
const getBackdropFilter = (i: number) => `blur(${factor * base ** (actualSteps - i - 1)}px)`
return (
<div
{...props}
style={{
// This has to be set on the top level element to prevent pointer events
pointerEvents: 'none',
transformOrigin: side,
...props.style,
}}
>
<div className="absolute z-0 size-full">
{/* Full blur at 100-falloffPercentage% */}
{actualSteps > 1 && (
<div
className="absolute inset-0 z-[2]"
style={{
mask: `linear-gradient(to ${oppositeSide[side]}, rgba(0, 0, 0, 1) ${mainPercentage}%, rgba(0, 0, 0, 1) ${mainPercentage + step}%, rgba(0, 0, 0, 0) ${mainPercentage + step * 2}%)`,
backdropFilter: getBackdropFilter(1),
WebkitBackdropFilter: getBackdropFilter(1),
}}
/>
)}
{actualSteps > 2 &&
Array.from({ length: actualSteps - 2 }).map((_, i) => (
<div
key={i}
className="absolute inset-0"
style={{
zIndex: i + 2,
mask: `linear-gradient(to ${oppositeSide[side]},rgba(0, 0, 0, 0) ${mainPercentage + i * step}%,rgba(0, 0, 0, 1) ${mainPercentage + (i + 1) * step}%,rgba(0, 0, 0, 1) ${mainPercentage + (i + 2) * step}%,rgba(0, 0, 0, 0) ${mainPercentage + (i + 3) * step}%)`,
backdropFilter: getBackdropFilter(i + 2),
WebkitBackdropFilter: getBackdropFilter(i + 2),
}}
/>
))}
<div
className="absolute -top-full left-0 size-full"
style={{ boxShadow: `0 0 60px ${tint}, 0 0 100px ${tint}` }}
/>
</div>
</div>
)
}