add new spoiler component

This commit is contained in:
jeffvli
2025-12-05 01:35:54 -08:00
parent 40af5fb945
commit 83886ed4ba
3 changed files with 22 additions and 38 deletions
@@ -363,7 +363,11 @@ export const AlbumDetailContent = () => {
return ( return (
<div className={styles.contentContainer} ref={ref}> <div className={styles.contentContainer} ref={ref}>
<div className={styles.detailContainer}> <div className={styles.detailContainer}>
{comment && <Spoiler maxHeight={75}>{replaceURLWithHTMLLinks(comment)}</Spoiler>} {comment && (
<Spoiler hideLabel={true} maxHeight={32} showLabel={true}>
{replaceURLWithHTMLLinks(comment)}
</Spoiler>
)}
<div className={styles.contentLayout}> <div className={styles.contentLayout}>
<div className={styles.songsColumn}> <div className={styles.songsColumn}>
{detailQuery?.data?.songs && detailQuery.data.songs.length > 0 && ( {detailQuery?.data?.songs && detailQuery.data.songs.length > 0 && (
@@ -8,18 +8,13 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
text-align: justify; cursor: pointer;
} }
.spoiler:not(.is-expanded).can-expand::after { .control {
position: absolute;
bottom: 0;
left: 0;
width: 100%; width: 100%;
height: 100%; padding: var(--theme-spacing-md) 0;
pointer-events: none; color: var(--theme-colors-foreground);
content: '';
background: linear-gradient(to top, var(--theme-colors-background) 10%, transparent 60%);
} }
.spoiler.can-expand { .spoiler.can-expand {
+13 -28
View File
@@ -1,42 +1,27 @@
import clsx from 'clsx'; import { Spoiler as MantineSpoiler, SpoilerProps as MantineSpoilerProps } from '@mantine/core';
import { HTMLAttributes, ReactNode, useRef, useState } from 'react'; import { ReactNode, useState } from 'react';
import styles from './spoiler.module.css'; import styles from './spoiler.module.css';
import { Text } from '/@/shared/components/text/text'; import { Icon } from '/@/shared/components/icon/icon';
import { useIsOverflow } from '/@/shared/hooks/use-is-overflow';
interface SpoilerProps extends HTMLAttributes<HTMLDivElement> { interface SpoilerProps extends MantineSpoilerProps {
children?: ReactNode; children?: ReactNode;
defaultOpened?: boolean;
maxHeight?: number;
} }
export const Spoiler = ({ children, defaultOpened, maxHeight, ...props }: SpoilerProps) => { export const Spoiler = ({ children, ...props }: SpoilerProps) => {
const ref = useRef(null); const [expanded, setExpanded] = useState(false);
const isOverflow = useIsOverflow(ref);
const [isExpanded, setIsExpanded] = useState(!!defaultOpened);
const spoilerClassNames = clsx(styles.spoiler, {
[styles.canExpand]: isOverflow,
[styles.isExpanded]: isExpanded,
});
const handleToggleExpand = () => {
setIsExpanded((val) => !val);
};
return ( return (
<Text <MantineSpoiler
className={spoilerClassNames} classNames={{ content: styles.spoiler, control: styles.control }}
onClick={handleToggleExpand} expanded={expanded}
ref={ref}
role="button"
style={{ maxHeight: maxHeight ?? '100px', whiteSpace: 'pre-wrap' }}
tabIndex={-1}
{...props} {...props}
hideLabel={<Icon icon="arrowUpS" size="lg" />}
onClick={() => setExpanded(!expanded)}
showLabel={<Icon icon="arrowDownS" size="lg" />}
> >
{children} {children}
</Text> </MantineSpoiler>
); );
}; };