11<template >
2- <div class =" flex h-full min-h- [430px] flex-col bg-white rounded-lg overflow-hidden" >
2+ <div class =" flex h-[430px] flex-col bg-white rounded-lg overflow-hidden" >
33 <div
44 class =" flex-shrink-0 flex justify-center items-center w-full h-[178px] bg-white"
55 >
5858
5959 <div
6060 v-if =" tool.description"
61- ref =" descriptionContainerRef"
6261 class =" flex-grow min-h-0"
63- :class =" { 'overflow-hidden': needShowMore && !showMore }"
6462 >
6563 <div
66- ref =" descriptionRef"
67- class =" relative flex-grow text-slate-500 text-[16px] leading-[22px] mb-2 overflow-hidden"
68- style =" height : auto "
64+ class =" relative flex-grow text-slate-500 text-[16px] leading-[22px] mb-2"
6965 >
70- <div v-html =" formatMultiline(tool.description)" />
66+ <div v-html =" formatMultiline(showMore ? tool.description : getCollapsedText(tool.description) )" />
7167
7268 <div
73- v-if =" needShowMore "
69+ v-if =" isCollapsible(tool.description) "
7470 class =" flex justify-end bottom-0 right-0 bg-white pl-0.5 text-dark-blue"
75- :class =" { absolute: !showMore, 'w-full': showMore }"
71+ :class =" { absolute: !showMore }"
7672 >
7773 <button @click =" onToggleShowMore" >
7874 {{ showMore ? 'Show less' : '... Show more' }}
@@ -111,9 +107,8 @@ export default {
111107 },
112108 data () {
113109 return {
114- descriptionHeight: ' auto' ,
115- needShowMore: true ,
116110 showMore: false ,
111+ previewMaxChars: 190 ,
117112 };
118113 },
119114 methods: {
@@ -130,46 +125,20 @@ export default {
130125 const normalized = String (value).replace (/ \r\n ? / g , ' \n ' );
131126 return this .escapeHtml (normalized).replace (/ \n / g , ' <br>' );
132127 },
133- computeDescriptionHeight () {
134- const containerEl = this .$refs .descriptionContainerRef ;
135- const descriptionEl = this .$refs .descriptionRef ;
136- if (! containerEl || ! descriptionEl) {
137- return ;
128+ getCollapsedText (value = ' ' ) {
129+ const normalized = String (value).replace (/ \s + / g , ' ' ).trim ();
130+ if (normalized .length <= this .previewMaxChars ) {
131+ return normalized;
138132 }
139133
140- const maxHeight = containerEl .clientHeight ;
141- const rows = Math .floor (maxHeight / 22 );
142- descriptionEl .style .height = ' auto' ;
143- this .descriptionHeight = ' auto' ;
144-
145- this .needShowMore = descriptionEl .offsetHeight > maxHeight;
146- if (descriptionEl .offsetHeight > maxHeight) {
147- descriptionEl .style .height = ` ${ rows * 22 } px` ;
148- this .descriptionHeight = ` ${ rows * 22 } px` ;
149- } else {
150- this .showMore = false ;
151- }
134+ return ` ${ normalized .slice (0 , this .previewMaxChars ).trimEnd ()} ...` ;
135+ },
136+ isCollapsible (value = ' ' ) {
137+ const normalized = String (value).replace (/ \s + / g , ' ' ).trim ();
138+ return normalized .length > this .previewMaxChars ;
152139 },
153140 onToggleShowMore () {
154- const descriptionEl = this .$refs .descriptionRef ;
155- if (! descriptionEl) {
156- return ;
157- }
158-
159141 this .showMore = ! this .showMore ;
160- if (! this .showMore ) {
161- descriptionEl .style .height = this .descriptionHeight ;
162- } else {
163- descriptionEl .style .height = ' auto' ;
164- }
165- },
166- },
167- mounted : function () {
168- if (this .tool .description ) {
169- this .computeDescriptionHeight ();
170- } else {
171- this .needShowMore = false ;
172- this .showMore = false ;
173142 }
174143 },
175144};
0 commit comments