@@ -11,10 +11,61 @@ const { lang, params } = useData();
1111const props = defineProps ([" module" ]);
1212const repo = computed (() => new Repository (params .value .url ));
1313
14-
1514const timestamp = computed (() => props .module .timestamp );
1615const module = computed (() => props .module );
1716
17+ // Label types enum
18+ const LabelType = {
19+ LICENSE : " LICENSE" ,
20+ ANTIFEATURES : " ANTIFEATURES" ,
21+ CATEGORY : " CATEGORY" ,
22+ METAMODULE : " METAMODULE" ,
23+ };
24+
25+ // Labels to show logic
26+ const labelsToShow = computed (() => {
27+ const labels = [];
28+
29+ if (module .value .license ) {
30+ labels .push ({
31+ type: LabelType .LICENSE ,
32+ text: module .value .license ,
33+ icon: " tag" ,
34+ style: " default" ,
35+ });
36+ }
37+
38+ if (module .value .track ? .antifeatures ) {
39+ labels .push ({
40+ type: LabelType .ANTIFEATURES ,
41+ text: " Anti-Features" ,
42+ icon: " alert-triangle" ,
43+ style: " warning" ,
44+ });
45+ }
46+
47+ if (module .value .categories ? .length > 0 ) {
48+ labels .push ({
49+ type: LabelType .CATEGORY ,
50+ text: module .value .categories [0 ],
51+ icon: " category" ,
52+ style: " secondary" ,
53+ });
54+ }
55+
56+ if (module .value .metamodule && (module .value .metamodule == " true" || module .value .metamodule == " 1" )) {
57+ labels .push ({
58+ type: LabelType .METAMODULE ,
59+ text: " META" ,
60+ style: " success" ,
61+ });
62+ }
63+
64+ return labels;
65+ });
66+
67+ const hasLabels = computed (() => labelsToShow .value .length > 0 );
68+
1869const getLastUpdated = () => {
1970 if (! timestamp .value ) {
2071 return " Invalid date" ;
@@ -37,55 +88,39 @@ const getLastUpdated = () => {
3788 < article : class = " $style.box" >
3889 < h2 : class = " $style.title" : id= " module.id" > {{ module .name }}< / h2>
3990 < span : class = " $style.author" > {{ module .version }} ({{ module .versionCode }}) by {{ module .author }}< / span>
40- <span :class =" $style.details" >{{ module.description }}</span >
41- <ul :class =" $style.moduleMetaContainer" >
42- <li :class =" $style.moduleMeta" v-if =" module.size" >
43- <svg :class =" $style.moduleMetaIcon" xmlns =" http://www.w3.org/2000/svg" width =" 24" height =" 24" viewBox =" 0 0 24 24" >
44- <g fill =" none" stroke =" currentColor" stroke-linecap =" round" stroke-linejoin =" round" stroke-width =" 2" >
45- <path d =" M6 20.735A2 2 0 0 1 5 19V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2h-1" />
46- <path
47- d =" M11 17a2 2 0 0 1 2 2v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a2 2 0 0 1 2-2m0-12h-1m3 2h-1m-1 2h-1m3 2h-1m-1 2h-1m3 2h-1"
48- />
49- </g >
50- </svg >
51- {{ toFormattedFileSize(module.size) }}
52- </li >
53- <li :class =" $style.moduleMeta" v-if =" module.categories" >
54- <svg :class =" $style.moduleMetaIcon" xmlns =" http://www.w3.org/2000/svg" width =" 24" height =" 24" viewBox =" 0 0 24 24" >
55- <path
56- fill =" none"
57- stroke =" currentColor"
58- stroke-linecap =" round"
59- stroke-linejoin =" round"
60- stroke-width =" 2"
61- d =" M4 4h6v6H4zm10 0h6v6h-6zM4 14h6v6H4zm10 3a3 3 0 1 0 6 0a3 3 0 1 0-6 0"
62- />
63- </svg >
64- {{ module.categories[0] }}
65- </li >
66- <li :class =" $style.moduleMeta" v-if =" module.track.antifeatures" >
67- <svg :class =" $style.moduleMetaIcon" xmlns =" http://www.w3.org/2000/svg" width =" 24" height =" 24" viewBox =" 0 0 24 24" >
68- <path
69- fill =" none"
70- stroke =" currentColor"
71- stroke-linecap =" round"
72- stroke-linejoin =" round"
73- stroke-width =" 2"
74- d =" M12 9v4m-1.637-9.409L2.257 17.125a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636-2.87L13.637 3.59a1.914 1.914 0 0 0-3.274 0zM12 16h.01"
75- />
91+ < span : class = " $style.lastUpdated" v- if = " module.timestamp" >
92+ {{ getLastUpdated () }}
93+ < span : class = " $style.stars" v- if = " module.stars" >
94+ < span> β’< / span>
95+ < svg xmlns= " http://www.w3.org/2000/svg" width= " 12" height= " 12" viewBox= " 0 0 24 24" >
96+ < use : href= " `/assets/icons/star.svg`" >< / use>
7697 < / svg>
77- Anti-Features
78- </li >
79- <li :class =" $style.moduleMeta" v-if =" module.timestamp" >
80- <svg :class =" $style.moduleMetaIcon" xmlns =" http://www.w3.org/2000/svg" width =" 24" height =" 24" viewBox =" 0 0 24 24" >
81- <g fill =" none" stroke =" currentColor" stroke-linecap =" round" stroke-linejoin =" round" stroke-width =" 2" >
82- <path d =" M3 12a9 9 0 1 0 18 0a9 9 0 0 0-18 0" />
83- <path d =" M12 7v5l3 3" />
84- </g >
98+ < span> {{ module .stars }}< / span>
99+ < / span>
100+ < / span>
101+
102+ < span : class = " $style.details" > {{ module .description }}< / span>
103+
104+ <!-- Labels -->
105+ < div v- if = " hasLabels" : class = " $style.labelsContainer" >
106+ < div
107+ v- for = " label in labelsToShow"
108+ : key= " label.type"
109+ : class = " [$style.label, $style[`label${label.style.charAt(0).toUpperCase() + label.style.slice(1)}`]]"
110+ >
111+ < svg
112+ v- if = " label.icon"
113+ : class = " $style.labelIcon"
114+ xmlns= " http://www.w3.org/2000/svg"
115+ width= " 16"
116+ height= " 16"
117+ viewBox= " 0 0 24 24"
118+ >
119+ < use : href= " `/assets/icons/${label.icon}.svg`" >< / use>
85120 < / svg>
86- {{ getLastUpdated() }}
87- </li >
88- </ul >
121+ < span : class = " $style.labelText " > {{ label . text }}< / span >
122+ < / div >
123+ < / div >
89124 < / article>
90125 < / article>
91126 < / div>
@@ -134,6 +169,22 @@ const getLastUpdated = () => {
134169 color: var (-- vp- badge- tip- text);
135170}
136171
172+ .lastUpdated {
173+ flex- grow: 1 ;
174+ line- height: 24px ;
175+ font- size: 13px ;
176+ font- weight: 500 ;
177+ color: var (-- vp- c- gray- 1 );
178+ }
179+
180+ .stars {
181+ display: inline- flex;
182+ align- items: center;
183+ gap: 4px ;
184+ margin- left: 6px ;
185+ color: var (-- vp- c- yellow- 5 );
186+ }
187+
137188.details {
138189 flex- grow: 1 ;
139190 padding- top: 8px ;
@@ -151,26 +202,95 @@ const getLastUpdated = () => {
151202 object- fit: cover;
152203}
153204
154- .moduleMeta {
155- align-items : center ;
156- align-self : end ;
205+ .moduleMetaContainer {
206+ color: var (-- vp- c- text- 3 );
207+ margin: 0px ! important;
208+ padding: 0px ! important;
209+ padding- top: 20px ! important;
210+ }
211+
212+ /* Labels Section */
213+ .labelsContainer {
157214 display: flex;
158- line-height : 20px ;
159- word-break : break-word ;
215+ flex- wrap: wrap;
216+ gap: 6px ;
217+ margin- top: 6px ;
218+ padding- top: 8px ;
160219}
161220
162- .moduleMetaIcon {
221+ .label {
222+ display: inline- flex;
223+ align- items: center;
224+ gap: 4px ;
225+ padding: 4px 8px ;
226+ border- radius: 12px ;
227+ font- size: 12px ;
228+ font- weight: 600 ;
229+ white- space: nowrap;
230+ transition: all 0 .2s ease;
231+ border: 1px solid transparent;
232+ }
233+
234+ .label : hover {
235+ transform: scale (1.05 );
236+ }
237+
238+ .labelIcon {
239+ width: 14px ;
240+ height: 14px ;
163241 flex- shrink: 0 ;
164- width : 20px ;
165- line-height : 20px ;
166- margin-right : 4px ;
167- height : 20px ;
168242}
169243
170- .moduleMetaContainer {
171- color : var (--vp-c-text-3 );
172- margin : 0px !important ;
173- padding : 0px !important ;
174- padding-top : 20px !important ;
244+ .labelText {
245+ font- weight: 600 ;
246+ }
247+
248+ /* Label Variants */
249+ .labelDefault {
250+ background: var (-- vp- c- bg);
251+ color: var (-- vp- c- text- 1 );
252+ border- color: var (-- vp- c- border);
253+ }
254+
255+ .labelSuccess {
256+ background: rgba (34 , 197 , 94 , 0.1 );
257+ color: #16a34a ;
258+ border- color: rgba (34 , 197 , 94 , 0.3 );
259+ }
260+
261+ .labelWarning {
262+ background: rgba (245 , 158 , 11 , 0.1 );
263+ color: #d97706;
264+ border- color: rgba (245 , 158 , 11 , 0.3 );
265+ }
266+
267+ .labelError {
268+ background: rgba (239 , 68 , 68 , 0.1 );
269+ color: #dc2626;
270+ border- color: rgba (239 , 68 , 68 , 0.3 );
271+ }
272+
273+ .labelSecondary {
274+ background: var (-- vp- c- brand- soft);
275+ color: var (-- vp- c- brand- 1 );
276+ border- color: var (-- vp- c- brand- soft);
277+ }
278+
279+ @media (max - width : 768px ) {
280+ .label {
281+ padding: 1px 4px ;
282+ font- size: 9px ;
283+ }
284+
285+ .labelIcon {
286+ width: 12px ;
287+ height: 12px ;
288+ }
289+ }
290+
291+ @media (max - width : 480px ) {
292+ .labelsContainer {
293+ gap: 4px ;
294+ }
175295}
176296< / style>
0 commit comments