mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 22:48:17 +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)
|
(gallerySetting.selectedRatings !== null ? 1 : 0)
|
||||||
|
|
||||||
return (
|
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 */}
|
{/* 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
|
<ActionIconButton
|
||||||
icon="i-mingcute-search-line"
|
icon="i-mingcute-search-line"
|
||||||
title={t('action.search.unified.title')}
|
title={t('action.search.unified.title')}
|
||||||
@@ -81,7 +81,7 @@ export const PageHeaderRight = () => {
|
|||||||
|
|
||||||
{/* Auth Section - Only show when useCloud is true */}
|
{/* Auth Section - Only show when useCloud is true */}
|
||||||
{injectConfig.useCloud && (
|
{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 />}
|
{sessionUser ? <UserMenuButton user={sessionUser} /> : <LoginButton />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -106,7 +106,7 @@ const DesktopViewButton = ({
|
|||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="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}
|
title={title}
|
||||||
>
|
>
|
||||||
<i className={`${icon} text-sm lg:text-base`} />
|
<i className={`${icon} text-sm lg:text-base`} />
|
||||||
@@ -187,7 +187,7 @@ const LoginButton = () => {
|
|||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="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')}
|
title={t('action.login')}
|
||||||
>
|
>
|
||||||
<i className="i-lucide-log-in text-sm lg:text-base" />
|
<i className="i-lucide-log-in text-sm lg:text-base" />
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export const ViewModeSegment = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleViewModeChange('masonry')}
|
onClick={() => handleViewModeChange('masonry')}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { LinearBlur } from '@afilmory/ui'
|
||||||
|
|
||||||
import { PageHeaderCenter } from './PageHeaderCenter'
|
import { PageHeaderCenter } from './PageHeaderCenter'
|
||||||
import { PageHeaderLeft } from './PageHeaderLeft'
|
import { PageHeaderLeft } from './PageHeaderLeft'
|
||||||
import { PageHeaderRight } from './PageHeaderRight'
|
import { PageHeaderRight } from './PageHeaderRight'
|
||||||
@@ -11,7 +13,13 @@ interface PageHeaderProps {
|
|||||||
|
|
||||||
export const PageHeader = ({ dateRange, location, showDateRange }: PageHeaderProps) => {
|
export const PageHeader = ({ dateRange, location, showDateRange }: PageHeaderProps) => {
|
||||||
return (
|
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">
|
<div className="flex h-12 items-center justify-between gap-2 px-3 lg:h-12 lg:gap-3 lg:px-4">
|
||||||
<PageHeaderLeft />
|
<PageHeaderLeft />
|
||||||
<PageHeaderCenter dateRange={dateRange} location={location} showDateRange={showDateRange} />
|
<PageHeaderCenter dateRange={dateRange} location={location} showDateRange={showDateRange} />
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export * from './lazy-image'
|
|||||||
export * from './mobile-tab'
|
export * from './mobile-tab'
|
||||||
export * from './modal'
|
export * from './modal'
|
||||||
export * from './portal'
|
export * from './portal'
|
||||||
|
export * from './progressive-blur'
|
||||||
export * from './prompts'
|
export * from './prompts'
|
||||||
export * from './scroll-areas'
|
export * from './scroll-areas'
|
||||||
export * from './segment'
|
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