fix: card thumbnails, search/sort sizing, link styling, management buttons
- install-index.html: contain thumbnails instead of cropping, add title overlay on cards, fix search bar min-width, constrain sort dropdown - install-detail.html: fix link colors for both themes, prevent icon underline on hover, replace "Already Installed" with management buttons (Open, Config, README, License, Info, Delete) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TerminallyLazy committed
Mar 3, 2026 at 23:43 UTC
e7f9456b071021667c31ded563575865894b0e4e
2 files changed
+141
-26
plugins/plugin_installer/webui/install-detail.html
+100
-5
@@ -50,9 +50,55 @@
50
51
<div class="pi-detail-actions">
52
<template x-if="$store.pluginInstallStore.selectedPlugin.installed">
53
- <button class="button" disabled>
54
- <span class="icon material-symbols-outlined">check</span> Already Installed
55
- </button>
53
+ <div>
54
+ <div class="pi-installed-badge-row">
55
+ <span class="material-symbols-outlined pi-installed-check">check_circle</span>
56
+ <span class="pi-installed-label">Installed</span>
57
+ </div>
58
+
59
+ <div x-show="$store.pluginInstallStore.installedPluginInfoLoading" class="pi-loading-inline">
60
+ Loading plugin info...
61
+ </div>
62
+
63
+ <template x-if="$store.pluginInstallStore.installedPluginInfo">
64
+ <div class="pi-manage-actions">
65
+ <template x-if="$store.pluginInstallStore.installedPluginInfo.has_main_screen">
66
+ <button type="button" class="button"
67
+ @click="$store.pluginInstallStore.manageOpenPlugin()">
68
+ <span class="icon material-symbols-outlined">dashboard</span> Open
69
+ </button>
70
+ </template>
71
+ <template x-if="$store.pluginInstallStore.installedPluginInfo.has_config_screen">
72
+ <button type="button" class="button"
73
+ @click="$store.pluginInstallStore.manageOpenConfig()">
74
+ <span class="icon material-symbols-outlined">settings</span> Config
75
+ </button>
76
+ </template>
77
+ <template x-if="$store.pluginInstallStore.installedPluginInfo.has_readme">
78
+ <button type="button" class="button"
79
+ @click="$store.pluginInstallStore.manageOpenDoc('readme')">
80
+ <span class="icon material-symbols-outlined">description</span> README
81
+ </button>
82
+ </template>
83
+ <template x-if="$store.pluginInstallStore.installedPluginInfo.has_license">
84
+ <button type="button" class="button"
85
+ @click="$store.pluginInstallStore.manageOpenDoc('license')">
86
+ <span class="icon material-symbols-outlined">gavel</span> License
87
+ </button>
88
+ </template>
89
+ <button type="button" class="button"
90
+ @click="$store.pluginInstallStore.manageOpenInfo()">
91
+ <span class="icon material-symbols-outlined">info</span> Info
92
+ </button>
93
+ <template x-if="$store.pluginInstallStore.installedPluginInfo.is_custom">
94
+ <button type="button" class="button cancel"
95
+ @click="$confirmClick($event, () => $store.pluginInstallStore.manageDeletePlugin())">
96
+ <span class="icon material-symbols-outlined">delete</span> Delete
97
+ </button>
98
+ </template>
99
+ </div>
100
+ </template>
101
+ </div>
102
</template>
103
<template x-if="!$store.pluginInstallStore.selectedPlugin.installed">
104
<button class="button confirm"
@@ -112,11 +158,11 @@
158
.pi-detail-thumb img {
159
width: 100%;
160
height: 100%;
115
- object-fit: cover;
161
+ object-fit: contain;
162
}
163
164
.pi-detail-placeholder {
119
- font-size: 3rem;
165
+ font-size: 4rem;
166
color: var(--color-text-muted);
167
}
168
@@ -177,6 +223,16 @@
223
224
.pi-link:hover {
225
text-decoration: underline;
226
+ text-underline-offset: 2px;
227
+ }
228
+
229
+ .pi-link .material-symbols-outlined {
230
+ text-decoration: none;
231
+ color: var(--color-highlight);
232
+ }
233
+
234
+ .pi-link:hover .material-symbols-outlined {
235
+ text-decoration: none;
236
}
237
238
.pi-detail-actions {
@@ -220,6 +276,45 @@
276
font-family: var(--font-family-code);
277
}
278
279
+ .pi-installed-badge-row {
280
+ display: flex;
281
+ align-items: center;
282
+ gap: 0.4rem;
283
+ margin-bottom: 0.75rem;
284
+ }
285
+
286
+ .pi-installed-check {
287
+ font-size: 1.3rem;
288
+ color: #22c55e;
289
+ }
290
+
291
+ .pi-installed-label {
292
+ font-weight: 600;
293
+ font-size: 0.95rem;
294
+ color: #22c55e;
295
+ }
296
+
297
+ .pi-manage-actions {
298
+ display: flex;
299
+ flex-wrap: wrap;
300
+ gap: 0.5rem;
301
+ }
302
+
303
+ .pi-manage-actions .button {
304
+ padding: 0.3rem 0.6rem;
305
+ font-size: 0.9rem;
306
+ }
307
+
308
+ .pi-manage-actions .button .icon {
309
+ font-size: 1.1rem;
310
+ }
311
+
312
+ .pi-loading-inline {
313
+ font-size: 0.85rem;
314
+ color: var(--color-text-secondary);
315
+ padding: 0.5rem 0;
316
+ }
317
+
318
@media (max-width: 500px) {
319
.pi-detail-header {
320
flex-direction: column;
plugins/plugin_installer/webui/install-index.html
+41
-21
@@ -18,8 +18,8 @@
18
placeholder="Search plugins...">
19
<select class="pi-sort-select"
20
x-model="$store.pluginInstallStore.sortBy">
21
- <option value="stars">Sort by Stars</option>
22
- <option value="name">Sort by Name</option>
21
+ <option value="stars">Stars</option>
22
+ <option value="name">Name</option>
23
</select>
24
</div>
25
@@ -44,14 +44,14 @@
44
<template x-if="!plugin.thumbnail">
45
<span class="material-symbols-outlined pi-card-placeholder">extension</span>
46
</template>
47
- </div>
48
- <div class="pi-card-body">
49
- <div class="pi-card-title">
50
- <span x-text="plugin.title || plugin.key"></span>
47
+ <div class="pi-card-thumb-overlay">
48
+ <span class="pi-card-thumb-title" x-text="plugin.title || plugin.key"></span>
49
<template x-if="plugin.installed">
50
<span class="pi-badge-installed">Installed</span>
51
</template>
52
</div>
53
+ </div>
54
+ <div class="pi-card-body">
55
<div class="pi-card-desc" x-text="$store.pluginInstallStore.truncate(plugin.description, 100)"></div>
56
</div>
57
<div class="pi-card-footer">
@@ -100,6 +100,7 @@
100
101
.pi-search-input {
102
flex: 1;
103
+ min-width: 0;
104
padding: 0.5rem 0.75rem;
105
border: 1px solid var(--color-border);
106
border-radius: 4px;
@@ -109,6 +110,8 @@
110
}
111
112
.pi-sort-select {
113
+ max-width: 140px;
114
+ flex-shrink: 0;
115
padding: 0.5rem;
116
border: 1px solid var(--color-border);
117
border-radius: 4px;
@@ -141,46 +144,63 @@
144
145
.pi-card-thumb {
146
width: 100%;
144
- height: 120px;
147
+ height: 140px;
148
overflow: hidden;
149
display: flex;
150
align-items: center;
151
justify-content: center;
152
background: var(--color-panel);
153
+ position: relative;
154
}
155
156
.pi-card-thumb img {
157
width: 100%;
158
height: 100%;
155
- object-fit: cover;
159
+ object-fit: contain;
160
+ padding: 0.5rem;
161
}
162
163
.pi-card-placeholder {
159
- font-size: 3rem;
164
+ font-size: 4.5rem;
165
color: var(--color-text-muted);
166
}
167
163
- .pi-card-body {
164
- padding: 0.6rem 0.75rem;
165
- flex: 1;
166
- }
167
-
168
- .pi-card-title {
169
- font-weight: 600;
170
- font-size: 0.95rem;
168
+ .pi-card-thumb-overlay {
169
+ position: absolute;
170
+ bottom: 0;
171
+ left: 0;
172
+ right: 0;
173
+ padding: 0.4rem 0.6rem;
174
+ background: rgba(0, 0, 0, 0.55);
175
display: flex;
176
align-items: center;
177
gap: 0.4rem;
174
- flex-wrap: wrap;
178
+ }
179
+
180
+ .pi-card-thumb-title {
181
+ font-weight: 600;
182
+ font-size: 0.85rem;
183
+ color: #fff;
184
+ white-space: nowrap;
185
+ overflow: hidden;
186
+ text-overflow: ellipsis;
187
+ flex: 1;
188
+ min-width: 0;
189
}
190
191
.pi-badge-installed {
178
- font-size: 0.7rem;
192
+ font-size: 0.65rem;
193
font-weight: 600;
194
padding: 0.1rem 0.4rem;
195
border-radius: 3px;
182
- background: rgba(34,197,94,0.2);
183
- color: #22c55e;
196
+ background: rgba(34,197,94,0.3);
197
+ color: #4ade80;
198
+ flex-shrink: 0;
199
+ }
200
+
201
+ .pi-card-body {
202
+ padding: 0.5rem 0.75rem;
203
+ flex: 1;
204
}
205
206
.pi-card-desc {