mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 04:50:12 +02:00
optimize library headers (#1374)
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
grid-template-areas: 'image info';
|
||||
grid-template-rows: auto;
|
||||
grid-template-columns: 225px minmax(0, 1fr);
|
||||
align-items: center;
|
||||
align-items: flex-end;
|
||||
justify-items: start;
|
||||
height: auto;
|
||||
min-height: 340px;
|
||||
@@ -98,7 +98,7 @@
|
||||
.title {
|
||||
display: flex;
|
||||
margin: var(--theme-spacing-sm) 0;
|
||||
font-size: clamp(2rem, 3.5dvw, 3.25rem);
|
||||
font-size: clamp(1.75rem, 3dvw, 2.75rem);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,12 @@ import { Link } from 'react-router';
|
||||
import styles from './library-header.module.css';
|
||||
|
||||
import {
|
||||
PlayLastTextButton,
|
||||
PlayNextTextButton,
|
||||
PlayTextButton,
|
||||
WideShuffleButton,
|
||||
} from '/@/renderer/features/shared/components/play-button';
|
||||
import { LONG_PRESS_PLAY_BEHAVIOR } from '/@/renderer/features/shared/components/play-button-group';
|
||||
import { usePlayButtonClick } from '/@/renderer/features/shared/hooks/use-play-button-click';
|
||||
import { useIsMutatingCreateFavorite } from '/@/renderer/features/shared/mutations/create-favorite-mutation';
|
||||
import { useIsMutatingDeleteFavorite } from '/@/renderer/features/shared/mutations/delete-favorite-mutation';
|
||||
import { useIsMutatingRating } from '/@/renderer/features/shared/mutations/set-rating-mutation';
|
||||
@@ -20,6 +23,7 @@ import { Image } from '/@/shared/components/image/image';
|
||||
import { Rating } from '/@/shared/components/rating/rating';
|
||||
import { Text } from '/@/shared/components/text/text';
|
||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||
import { Play } from '/@/shared/types/types';
|
||||
|
||||
interface LibraryHeaderProps {
|
||||
children?: ReactNode;
|
||||
@@ -145,36 +149,36 @@ export const LibraryHeader = forwardRef(
|
||||
|
||||
const calculateTitleSize = (title: string) => {
|
||||
const titleLength = title.length;
|
||||
let baseSize = '3.5dvw';
|
||||
let baseSize = '3dvw';
|
||||
|
||||
if (titleLength > 20) {
|
||||
baseSize = '3dvw';
|
||||
}
|
||||
|
||||
if (titleLength > 30) {
|
||||
baseSize = '2.75dvw';
|
||||
}
|
||||
|
||||
if (titleLength > 40) {
|
||||
baseSize = '2.5dvw';
|
||||
}
|
||||
|
||||
if (titleLength > 50) {
|
||||
if (titleLength > 30) {
|
||||
baseSize = '2.25dvw';
|
||||
}
|
||||
|
||||
if (titleLength > 60) {
|
||||
if (titleLength > 40) {
|
||||
baseSize = '2dvw';
|
||||
}
|
||||
|
||||
return `clamp(2rem, ${baseSize}, 3.25rem)`;
|
||||
if (titleLength > 50) {
|
||||
baseSize = '1.875dvw';
|
||||
}
|
||||
|
||||
if (titleLength > 60) {
|
||||
baseSize = '1.75dvw';
|
||||
}
|
||||
|
||||
return `clamp(1.75rem, ${baseSize}, 2.75rem)`;
|
||||
};
|
||||
|
||||
interface LibraryHeaderMenuProps {
|
||||
favorite?: boolean;
|
||||
onFavorite?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
onMore?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
onPlay?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
onPlay?: (type: Play) => void;
|
||||
onRating?: (rating: number) => void;
|
||||
onShuffle?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
rating?: number;
|
||||
@@ -186,7 +190,6 @@ export const LibraryHeaderMenu = ({
|
||||
onMore,
|
||||
onPlay,
|
||||
onRating,
|
||||
onShuffle,
|
||||
rating,
|
||||
}: LibraryHeaderMenuProps) => {
|
||||
const isMutatingRating = useIsMutatingRating();
|
||||
@@ -194,11 +197,43 @@ export const LibraryHeaderMenu = ({
|
||||
const isMutatingDeleteFavorite = useIsMutatingDeleteFavorite();
|
||||
const isMutatingFavorite = isMutatingCreateFavorite || isMutatingDeleteFavorite;
|
||||
|
||||
const handlePlayNow = usePlayButtonClick({
|
||||
onClick: () => {
|
||||
onPlay?.(Play.NOW);
|
||||
},
|
||||
onLongPress: () => {
|
||||
onPlay?.(LONG_PRESS_PLAY_BEHAVIOR[Play.NOW]);
|
||||
},
|
||||
});
|
||||
|
||||
const handlePlayNext = usePlayButtonClick({
|
||||
onClick: () => {
|
||||
onPlay?.(Play.NEXT);
|
||||
},
|
||||
onLongPress: () => {
|
||||
onPlay?.(LONG_PRESS_PLAY_BEHAVIOR[Play.NEXT]);
|
||||
},
|
||||
});
|
||||
|
||||
const handlePlayLast = usePlayButtonClick({
|
||||
onClick: () => {
|
||||
onPlay?.(Play.LAST);
|
||||
},
|
||||
onLongPress: () => {
|
||||
onPlay?.(LONG_PRESS_PLAY_BEHAVIOR[Play.LAST]);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={styles.libraryHeaderMenu}>
|
||||
<Group wrap="nowrap">
|
||||
{onPlay && <PlayTextButton onClick={onPlay} />}
|
||||
{onShuffle && <WideShuffleButton onClick={onShuffle} />}
|
||||
{onPlay && <PlayTextButton {...handlePlayNow.handlers} {...handlePlayNow.props} />}
|
||||
{onPlay && (
|
||||
<PlayNextTextButton {...handlePlayNext.handlers} {...handlePlayNext.props} />
|
||||
)}
|
||||
{onPlay && (
|
||||
<PlayLastTextButton {...handlePlayLast.handlers} {...handlePlayLast.props} />
|
||||
)}
|
||||
</Group>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
{onRating && (
|
||||
|
||||
@@ -50,10 +50,26 @@
|
||||
padding-left: var(--theme-spacing-xl);
|
||||
background: white;
|
||||
border-radius: var(--theme-radius-xl);
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
|
||||
&[data-variant='subtle'] {
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus-visible {
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wide-text-button.unthemed {
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
|
||||
&[data-variant='subtle'] {
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
}
|
||||
|
||||
@mixin light {
|
||||
background: black;
|
||||
|
||||
@@ -62,8 +78,11 @@
|
||||
fill: white;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: lighten(black, 10%);
|
||||
&[data-variant='subtle']:hover,
|
||||
&[data-variant='subtle']:active,
|
||||
&[data-variant='subtle']:focus-visible {
|
||||
background: lighten(black, 10%) !important;
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +94,11 @@
|
||||
fill: black;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: darken(white, 20%);
|
||||
&[data-variant='subtle']:hover,
|
||||
&[data-variant='subtle']:active,
|
||||
&[data-variant='subtle']:focus-visible {
|
||||
background: darken(white, 20%) !important;
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,14 +112,16 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
|
||||
svg {
|
||||
color: black;
|
||||
fill: black;
|
||||
}
|
||||
}
|
||||
|
||||
.no-fill {
|
||||
fill: none !important;
|
||||
}
|
||||
|
||||
.play-button {
|
||||
all: unset;
|
||||
display: flex;
|
||||
|
||||
@@ -4,12 +4,14 @@ import { forwardRef, memo } from 'react';
|
||||
|
||||
import styles from './play-button.module.css';
|
||||
|
||||
import { PlayTooltip } from '/@/renderer/features/shared/components/play-button-group';
|
||||
import { usePlayButtonClick } from '/@/renderer/features/shared/hooks/use-play-button-click';
|
||||
import { ActionIcon, ActionIconProps } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Button, ButtonProps } from '/@/shared/components/button/button';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { AppIcon, Icon } from '/@/shared/components/icon/icon';
|
||||
import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||
import { Play } from '/@/shared/types/types';
|
||||
|
||||
export interface DefaultPlayButtonProps extends ActionIconProps {
|
||||
size?: number | string;
|
||||
@@ -36,14 +38,18 @@ export const DefaultPlayButton = forwardRef<HTMLButtonElement, DefaultPlayButton
|
||||
|
||||
DefaultPlayButton.displayName = 'DefaultPlayButton';
|
||||
|
||||
interface TextPlayButtonProps extends ButtonProps {}
|
||||
interface TextPlayButtonProps extends ButtonProps {
|
||||
onLongPress?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
showTooltip?: boolean;
|
||||
}
|
||||
|
||||
export const PlayTextButton = ({
|
||||
className,
|
||||
showTooltip = true,
|
||||
variant = 'default',
|
||||
...props
|
||||
}: TextPlayButtonProps) => {
|
||||
return (
|
||||
const button = (
|
||||
<Button
|
||||
className={clsx(styles.wideTextButton, className, {
|
||||
[styles.unthemed]: variant !== 'filled',
|
||||
@@ -57,12 +63,64 @@ export const PlayTextButton = ({
|
||||
>
|
||||
{props.children || (
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<Icon fill="default" icon="mediaPlay" size="lg" />
|
||||
<Icon icon="mediaPlay" size="lg" />
|
||||
{t('player.play', { postProcess: 'sentenceCase' })}
|
||||
</Group>
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
|
||||
const hasLongPress = Boolean(
|
||||
props.onLongPress || (props as any).onMouseDown || (props as any).onTouchStart,
|
||||
);
|
||||
|
||||
if (hasLongPress && showTooltip) {
|
||||
return <PlayTooltip type={Play.NOW}>{button}</PlayTooltip>;
|
||||
}
|
||||
|
||||
return button;
|
||||
};
|
||||
|
||||
export const PlayNextTextButton = ({ ...props }: TextPlayButtonProps) => {
|
||||
const button = (
|
||||
<PlayTextButton {...props} showTooltip={false}>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<Icon className={styles.noFill} icon="mediaPlayNext" size="lg" />
|
||||
{t('player.addNext', { postProcess: 'sentenceCase' })}
|
||||
</Group>
|
||||
</PlayTextButton>
|
||||
);
|
||||
|
||||
const hasLongPress = Boolean(
|
||||
props.onLongPress || (props as any).onMouseDown || (props as any).onTouchStart,
|
||||
);
|
||||
|
||||
if (hasLongPress) {
|
||||
return <PlayTooltip type={Play.NEXT}>{button}</PlayTooltip>;
|
||||
}
|
||||
|
||||
return button;
|
||||
};
|
||||
|
||||
export const PlayLastTextButton = ({ ...props }: TextPlayButtonProps) => {
|
||||
const button = (
|
||||
<PlayTextButton {...props} showTooltip={false}>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<Icon className={styles.noFill} icon="mediaPlayLast" size="lg" />
|
||||
{t('player.addLast', { postProcess: 'sentenceCase' })}
|
||||
</Group>
|
||||
</PlayTextButton>
|
||||
);
|
||||
|
||||
const hasLongPress = Boolean(
|
||||
props.onLongPress || (props as any).onMouseDown || (props as any).onTouchStart,
|
||||
);
|
||||
|
||||
if (hasLongPress) {
|
||||
return <PlayTooltip type={Play.LAST}>{button}</PlayTooltip>;
|
||||
}
|
||||
|
||||
return button;
|
||||
};
|
||||
|
||||
export const WideShuffleButton = ({ ...props }: TextPlayButtonProps) => {
|
||||
|
||||
Reference in New Issue
Block a user