@@ -12,6 +12,8 @@ import ExtensionForkDialog from './extension-fork-dialog';
1212import { useDeleteExtensionMutation } from '@/redux/services/extensions/extensionsApi' ;
1313import { toast } from 'sonner' ;
1414
15+ const MAX_DESCRIPTION_CHARS = 90 ;
16+
1517interface ExtensionCardProps {
1618 extension : Extension ;
1719 onInstall ?: ( extension : Extension ) => void ;
@@ -23,6 +25,7 @@ export function ExtensionCard({ extension, onInstall, onViewDetails }: Extension
2325 const [ forkOpen , setForkOpen ] = React . useState ( false ) ;
2426 const [ confirmOpen , setConfirmOpen ] = React . useState ( false ) ;
2527 const [ deleteExtension ] = useDeleteExtensionMutation ( ) ;
28+ const [ expanded , setExpanded ] = React . useState ( false ) ;
2629
2730 const onDelete = async ( ) => {
2831 try {
@@ -80,7 +83,17 @@ export function ExtensionCard({ extension, onInstall, onViewDetails }: Extension
8083 </ div >
8184
8285 < CardDescription className = "text-sm leading-relaxed text-muted-foreground" >
83- { extension . description }
86+ { expanded || extension . description . length <= MAX_DESCRIPTION_CHARS
87+ ? extension . description
88+ : `${ extension . description . slice ( 0 , MAX_DESCRIPTION_CHARS ) } …` }
89+ { extension . description . length > MAX_DESCRIPTION_CHARS && (
90+ < button
91+ className = "ml-2 text-primary hover:underline text-sm"
92+ onClick = { ( ) => setExpanded ( ( v ) => ! v ) }
93+ >
94+ { expanded ? ( t ( 'common.readLess' ) || 'Read less' ) : ( t ( 'common.readMore' ) || 'Read more' ) }
95+ </ button >
96+ ) }
8497 </ CardDescription >
8598 < div className = "flex gap-2 pt-6 justify-start" >
8699 < Button
0 commit comments