simplify component structure and improve layout responsiveness

This commit is contained in:
Seth Van Niekerk 2026-04-10 15:17:01 -04:00
parent 2573928e2a
commit e8e1560106
No known key found for this signature in database
GPG key ID: E86ACA677312A675
4 changed files with 19 additions and 41 deletions

View file

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useState } from 'react';
import {
ActionIcon,
Avatar,
@ -143,19 +143,6 @@ const AvailablePluginCard = ({ plugin, appVersion, multiRepo = false, autoOpenDe
plugin.latest_version && plugin.installed_version &&
compareVersions(plugin.latest_version, plugin.installed_version) < 0;
const descContainerRef = useRef(null);
const [descLines, setDescLines] = useState(3);
useEffect(() => {
const el = descContainerRef.current;
if (!el) return;
const obs = new ResizeObserver(() => {
const lh = parseFloat(getComputedStyle(el).lineHeight) || 22;
setDescLines(Math.max(1, Math.min(3, Math.floor(el.clientHeight / lh))));
});
obs.observe(el);
return () => obs.disconnect();
}, []);
const doInstall = (params) => {
if (plugin.deprecated) {
setPendingDeprecatedInstall(params);
@ -291,7 +278,7 @@ const AvailablePluginCard = ({ plugin, appVersion, multiRepo = false, autoOpenDe
style={{
display: 'flex',
flexDirection: 'column',
height: 220,
minHeight: 220,
...(multiRepo && plugin.is_official_repo ? { borderColor: '#0e6459' } : {}),
}}
>
@ -311,7 +298,9 @@ const AvailablePluginCard = ({ plugin, appVersion, multiRepo = false, autoOpenDe
</Text>
<Group gap={6} align="center" wrap="nowrap">
{plugin.author && (
<Text size="xs" c="dimmed">by {plugin.author}</Text>
<Text size="xs" c="dimmed" truncate style={{ minWidth: 0, maxWidth: '100%' }}>
{plugin.author}
</Text>
)}
<StatusBadge
status={plugin.install_status}
@ -333,14 +322,14 @@ const AvailablePluginCard = ({ plugin, appVersion, multiRepo = false, autoOpenDe
</Group>
<Box style={{ flex: 1, minHeight: 0, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
<div ref={descContainerRef} style={{ flex: 1, minHeight: 0, overflow: 'hidden' }}>
<Text size="sm" c="dimmed" lineClamp={descLines}>
<div style={{ overflow: 'hidden' }}>
<Text size="sm" c="dimmed" lineClamp={3} mb={0}>
{plugin.description}
</Text>
</div>
<Stack gap={4} style={{ flexShrink: 0 }}>
<Group gap="xs" wrap="wrap">
<Stack gap={2} mt="auto" pt={4} style={{ flexShrink: 0 }}>
<Group gap="xs" wrap="wrap">
{plugin.latest_version && (
<Badge size="xs" variant="default">
<span style={{ opacity: 0.5, marginRight: 4 }}>LATEST</span>

View file

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useState } from 'react';
import { showNotification } from '../../utils/notificationUtils.js';
import { Field } from '../Field.jsx';
import {
@ -129,18 +129,6 @@ const PluginCard = ({
const [installing, setInstalling] = useState(false);
const [uninstalling] = useState(false);
const descContainerRef = useRef(null);
const [descLines, setDescLines] = useState(3);
useEffect(() => {
const el = descContainerRef.current;
if (!el) return;
const obs = new ResizeObserver(() => {
const lh = parseFloat(getComputedStyle(el).lineHeight) || 22;
setDescLines(Math.max(1, Math.min(3, Math.floor(el.clientHeight / lh))));
});
obs.observe(el);
return () => obs.disconnect();
}, []);
const installPlugin = usePluginStore((s) => s.installPlugin);
// Keep local enabled state in sync with props
@ -391,10 +379,11 @@ const PluginCard = ({
<Text
size="xs"
c="dimmed"
truncate
onClick={isManaged ? () => openModal('details') : undefined}
style={isManaged ? { cursor: 'pointer' } : undefined}
style={{ minWidth: 0, maxWidth: '100%', ...(isManaged ? { cursor: 'pointer' } : {}) }}
>
by {plugin.author}
{plugin.author}
</Text>
)}
{plugin.help_url && (
@ -466,9 +455,9 @@ const PluginCard = ({
</Group>
</Group>
{/* Description — flex: 1 pushes bottom content down */}
<div ref={descContainerRef} style={{ flex: 1, minHeight: 0, overflow: 'hidden' }}>
<Text size="sm" c="dimmed" lineClamp={descLines} mb="xs">
{/* Description */}
<div style={{ overflow: 'hidden' }}>
<Text size="sm" c="dimmed" lineClamp={3} mb={0}>
{plugin.description}
</Text>
</div>
@ -483,7 +472,7 @@ const PluginCard = ({
)}
{/* Bottom metadata pills */}
<Stack gap={4} style={{ flexShrink: 0 }}>
<Stack gap={2} mt="auto" pt={4} style={{ flexShrink: 0 }}>
<Group gap="xs" wrap="wrap">
<Badge size="xs" variant="default">
<span style={{ opacity: 0.5, marginRight: 4 }}>VERSION</span>

View file

@ -403,7 +403,7 @@ export default function PluginBrowsePage() {
{!loading && filteredPlugins.length > 0 && (
<>
<SimpleGrid
cols={{ base: 1, sm: 2, lg: 3 }}
cols={{ base: 1, md: 2, xl: 3 }}
spacing="md"
>
{paginatedPlugins.map((p) => (

View file

@ -144,7 +144,7 @@ const PluginsList = ({ onRequestDelete, onRequireTrust, onRequestConfirm }) => {
{filteredPlugins.length > 0 && (
<SimpleGrid
cols={{ base: 1, sm: 2, lg: 3 }}
cols={{ base: 1, md: 2, xl: 3 }}
spacing="md"
>
<ErrorBoundary>