Created
February 21, 2025 05:20
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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