mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 14:44:48 +00:00
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:
@@ -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" />
|
||||
|
||||
@@ -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')}
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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'
|
||||
|
||||
80
packages/ui/src/progressive-blur/index.tsx
Normal file
80
packages/ui/src/progressive-blur/index.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user