Skip to content

Instantly share code, notes, and snippets.

@markosmk
Created February 21, 2025 05:20
Show Gist options
  • Save markosmk/53326c804b2d6598a848320bb378363b to your computer and use it in GitHub Desktop.
Save markosmk/53326c804b2d6598a848320bb378363b to your computer and use it in GitHub Desktop.
esto lo hice para poder expandir una seccion de forma animada en altura, tomando tambien el card y boton de shadcn, el hook esta separado del card-expandable, porque tambien se puede usar con otra seccion que no sea un card
import * as React from 'react';
import { Card } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { useExpandable } from '@/hooks/use-expandable';
interface CardExpandableProps {
minHeight: number;
children: React.ReactNode;
}
export function CardExpandable({
minHeight,
children
}: CardExpandableProps): JSX.Element {
const {
isExpanded,
setIsExpanded,
contentHeight,
contentRef,
showExpandButton
} = useExpandable(minHeight);
if (!showExpandButton) {
return (
<Card className="relative mt-3 overflow-hidden">
<div ref={contentRef}>{children}</div>
</Card>
);
}
return (
<Card className="relative mt-3 overflow-hidden pb-12">
<div
ref={contentRef}
style={{ height: isExpanded ? `${contentHeight}px` : `${minHeight}px` }}
className="transition-[height] duration-300 ease-in-out"
>
{children}
</div>
{!isExpanded && (
<div className="absolute bottom-12 left-0 right-0 h-20 bg-gradient-to-t from-card to-transparent" />
)}
<div className="absolute bottom-0 left-0 right-0 flex justify-center bg-card p-2">
<Button
variant="outline"
size="sm"
onClick={() => setIsExpanded(!isExpanded)}
>
{isExpanded ? 'Ver menos' : 'Ver completo'}
</Button>
</div>
</Card>
);
}
import * as React from 'react';
export function useExpandable(minHeight: number) {
const [isExpanded, setIsExpanded] = React.useState(false);
const [contentHeight, setContentHeight] = React.useState(minHeight);
const [showExpandButton, setShowExpandButton] = React.useState(true);
const contentRef = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
if (contentRef.current) {
const contentScrollHeight = contentRef.current.scrollHeight;
setContentHeight(contentRef.current.scrollHeight);
setShowExpandButton(contentScrollHeight > minHeight);
}
}, [minHeight]);
return {
isExpanded,
setIsExpanded,
contentHeight,
contentRef,
showExpandButton
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment