mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 21:10:12 +02:00
Migrate to Mantine v8 and Design Changes (#961)
* mantine v8 migration * various design changes and improvements
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
import { Flex, FlexProps } from '@mantine/core';
|
||||
import { AnimatePresence, motion, Variants } from 'framer-motion';
|
||||
import { ReactNode, useRef } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useShouldPadTitlebar, useTheme } from '/@/renderer/hooks';
|
||||
import { useWindowSettings } from '/@/renderer/store/settings.store';
|
||||
import { Platform } from '/@/shared/types/types';
|
||||
|
||||
const Container = styled(motion(Flex))<{
|
||||
$height?: string;
|
||||
$position?: string;
|
||||
}>`
|
||||
position: ${(props) => props.$position || 'relative'};
|
||||
z-index: 190;
|
||||
width: 100%;
|
||||
height: ${(props) => props.$height || '65px'};
|
||||
background: var(--titlebar-bg);
|
||||
`;
|
||||
|
||||
const Header = styled(motion.div)<{
|
||||
$isDraggable?: boolean;
|
||||
$isHidden?: boolean;
|
||||
$padRight?: boolean;
|
||||
}>`
|
||||
position: relative;
|
||||
z-index: 15;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-right: ${(props) => (props.$padRight ? '140px' : '1rem')};
|
||||
pointer-events: ${(props) => (props.$isHidden ? 'none' : 'auto')};
|
||||
user-select: ${(props) => (props.$isHidden ? 'none' : 'auto')};
|
||||
-webkit-app-region: ${(props) => props.$isDraggable && 'drag'};
|
||||
|
||||
button {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
input {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
`;
|
||||
|
||||
const BackgroundImage = styled.div<{ $background: string }>`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: ${(props) => props.$background || 'var(--titlebar-bg)'};
|
||||
`;
|
||||
|
||||
const BackgroundImageOverlay = styled.div<{ theme: 'dark' | 'light' }>`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: ${(props) =>
|
||||
props.theme === 'light'
|
||||
? 'linear-gradient(rgba(255, 255, 255, 25%), rgba(255, 255, 255, 25%))'
|
||||
: 'linear-gradient(rgba(0, 0, 0, 50%), rgba(0, 0, 0, 50%))'};
|
||||
`;
|
||||
|
||||
export interface PageHeaderProps
|
||||
extends Omit<FlexProps, 'onAnimationStart' | 'onDrag' | 'onDragEnd' | 'onDragStart'> {
|
||||
animated?: boolean;
|
||||
backgroundColor?: string;
|
||||
children?: ReactNode;
|
||||
height?: string;
|
||||
isHidden?: boolean;
|
||||
position?: string;
|
||||
}
|
||||
|
||||
const TitleWrapper = styled(motion.div)`
|
||||
position: absolute;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const variants: Variants = {
|
||||
animate: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
duration: 0.3,
|
||||
ease: 'easeIn',
|
||||
},
|
||||
},
|
||||
exit: { opacity: 0 },
|
||||
initial: { opacity: 0 },
|
||||
};
|
||||
|
||||
export const PageHeader = ({
|
||||
animated,
|
||||
backgroundColor,
|
||||
children,
|
||||
height,
|
||||
isHidden,
|
||||
position,
|
||||
...props
|
||||
}: PageHeaderProps) => {
|
||||
const ref = useRef(null);
|
||||
const padRight = useShouldPadTitlebar();
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container
|
||||
$height={height}
|
||||
$position={position}
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<Header
|
||||
$isDraggable={windowBarStyle === Platform.WEB}
|
||||
$isHidden={isHidden}
|
||||
$padRight={padRight}
|
||||
>
|
||||
<AnimatePresence initial={animated ?? false}>
|
||||
<TitleWrapper
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
initial="initial"
|
||||
variants={variants}
|
||||
>
|
||||
{children}
|
||||
</TitleWrapper>
|
||||
</AnimatePresence>
|
||||
</Header>
|
||||
{backgroundColor && (
|
||||
<>
|
||||
<BackgroundImage $background={backgroundColor || 'var(--titlebar-bg)'} />
|
||||
<BackgroundImageOverlay theme={theme as 'dark' | 'light'} />
|
||||
</>
|
||||
)}
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 190;
|
||||
width: 100%;
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
.header {
|
||||
position: relative;
|
||||
z-index: 15;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-right: 1rem;
|
||||
pointer-events: auto;
|
||||
user-select: auto;
|
||||
-webkit-app-region: drag;
|
||||
|
||||
button {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
input {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
}
|
||||
|
||||
.header.pad-right {
|
||||
margin-right: 140px;
|
||||
}
|
||||
|
||||
.header.hidden {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.header.is-draggable {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
.background-image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--theme-colors-background);
|
||||
}
|
||||
|
||||
.background-image-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.background-image-overlay.light {
|
||||
background: linear-gradient(rgb(255 255 255 / 25%), rgb(255 255 255 / 25%));
|
||||
}
|
||||
|
||||
.background-image-overlay.dark {
|
||||
background: linear-gradient(rgb(0 0 0 / 50%), rgb(0 0 0 / 50%));
|
||||
}
|
||||
|
||||
.title-wrapper {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.title-wrapper.hidden {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import clsx from 'clsx';
|
||||
import { AnimatePresence, motion, Variants } from 'motion/react';
|
||||
import { CSSProperties, ReactNode, useRef } from 'react';
|
||||
|
||||
import styles from './page-header.module.css';
|
||||
|
||||
import { useShouldPadTitlebar } from '/@/renderer/hooks';
|
||||
import { useWindowSettings } from '/@/renderer/store/settings.store';
|
||||
import { useAppTheme } from '/@/renderer/themes/use-app-theme';
|
||||
import { Flex, FlexProps } from '/@/shared/components/flex/flex';
|
||||
import { Platform } from '/@/shared/types/types';
|
||||
|
||||
export interface PageHeaderProps
|
||||
extends Omit<FlexProps, 'onAnimationStart' | 'onDrag' | 'onDragEnd' | 'onDragStart'> {
|
||||
animated?: boolean;
|
||||
backgroundColor?: string;
|
||||
children?: ReactNode;
|
||||
height?: string;
|
||||
isHidden?: boolean;
|
||||
position?: string;
|
||||
}
|
||||
|
||||
const variants: Variants = {
|
||||
animate: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
duration: 0.3,
|
||||
ease: 'easeIn',
|
||||
},
|
||||
},
|
||||
exit: { opacity: 0 },
|
||||
initial: { opacity: 0 },
|
||||
};
|
||||
|
||||
export const PageHeader = ({
|
||||
animated,
|
||||
backgroundColor = 'var(--theme-colors-background)',
|
||||
children,
|
||||
height,
|
||||
isHidden,
|
||||
position,
|
||||
...props
|
||||
}: PageHeaderProps) => {
|
||||
const ref = useRef(null);
|
||||
const padRight = useShouldPadTitlebar();
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
const { mode } = useAppTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
className={styles.container}
|
||||
ref={ref}
|
||||
style={{ height, position: position as CSSProperties['position'] }}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className={clsx(styles.header, {
|
||||
[styles.hidden]: isHidden,
|
||||
[styles.isDraggable]: windowBarStyle === Platform.WEB,
|
||||
[styles.padRight]: padRight,
|
||||
})}
|
||||
>
|
||||
<AnimatePresence initial={animated ?? false}>
|
||||
<motion.div
|
||||
animate="animate"
|
||||
className={styles.titleWrapper}
|
||||
exit="exit"
|
||||
initial="initial"
|
||||
variants={variants}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
{backgroundColor && (
|
||||
<>
|
||||
<div
|
||||
className={styles.backgroundImage}
|
||||
style={{
|
||||
background: backgroundColor,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={clsx(styles.backgroundImageOverlay, {
|
||||
[styles.dark]: mode === 'dark',
|
||||
[styles.light]: mode === 'light',
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user