From 129a1b1a21745487485730e826fa2fb5b550fed8 Mon Sep 17 00:00:00 2001 From: overcuriousity Date: Thu, 17 Jul 2025 14:57:35 +0200 Subject: [PATCH] layout improvements --- src/components/ToolCard.astro | 4 +- src/components/ToolMatrix.astro | 622 ++++++++++++++++++-------------- src/pages/index.astro | 28 +- src/styles/global.css | 169 ++++++++- 4 files changed, 532 insertions(+), 291 deletions(-) diff --git a/src/components/ToolCard.astro b/src/components/ToolCard.astro index 60614d1..a6a36fb 100644 --- a/src/components/ToolCard.astro +++ b/src/components/ToolCard.astro @@ -29,7 +29,7 @@ const hasValidProjectUrl = tool.projectUrl !== undefined && const hasKnowledgebase = tool.knowledgebase === true; // Determine card styling based on hosting status (derived from projectUrl) -const cardClass = hasValidProjectUrl ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card'); +const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card'); ---
@@ -79,7 +79,7 @@ const cardClass = hasValidProjectUrl ? 'card card-hosted' : (tool.license !== 'P
-
+
{tool.tags.map(tag => ( {tag} ))} diff --git a/src/components/ToolMatrix.astro b/src/components/ToolMatrix.astro index 035b323..c453001 100644 --- a/src/components/ToolMatrix.astro +++ b/src/components/ToolMatrix.astro @@ -8,82 +8,59 @@ const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml'); const yamlContent = await fs.readFile(yamlPath, 'utf8'); const data = load(yamlContent) as any; -const tools = data.tools; const domains = data.domains; -const phases = data.phases.filter((p: any) => p.id !== 'collaboration-general'); // Exclude from matrix +const phases = data.phases; +const tools = data.tools; -// Filter collaboration tools (tools with "collaboration-general" phase) +// Separate collaboration tools from domain-specific tools const collaborationTools = tools.filter((tool: any) => tool.phases && tool.phases.includes('collaboration-general') ); -// Filter regular tools for matrix (excluding collaboration-only tools from matrix display) -const matrixTools = tools.filter((tool: any) => { - if (!tool.phases || tool.phases.length === 0) return false; - // Include if has non-collaboration phases and non-empty domains - const hasRegularPhases = tool.phases.some((phase: string) => phase !== 'collaboration-general'); - const hasDomains = tool.domains && tool.domains.length > 0; - return hasRegularPhases && hasDomains; -}); +const domainTools = tools.filter((tool: any) => + !tool.phases || !tool.phases.includes('collaboration-general') +); -// Also include collaboration tools in matrix if they have domains and regular phases -const collaborationToolsInMatrix = collaborationTools.filter((tool: any) => { - const hasRegularPhases = tool.phases && tool.phases.some((phase: string) => phase !== 'collaboration-general'); - const hasDomains = tool.domains && tool.domains.length > 0; - return hasRegularPhases && hasDomains; +// Create matrix structure for domain-specific tools only +const matrix: Record> = {}; +domains.forEach((domain: any) => { + matrix[domain.id] = {}; + phases.filter((phase: any) => phase.id !== 'collaboration-general').forEach((phase: any) => { + matrix[domain.id][phase.id] = domainTools.filter((tool: any) => + tool.domains && tool.domains.includes(domain.id) && tool.phases && tool.phases.includes(phase.id) + ); + }); }); - -// Combine for matrix display -const allMatrixTools = [...matrixTools, ...collaborationToolsInMatrix]; --- - - - - \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index f20260f..3139e6f 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -78,7 +78,7 @@ const tools = data.tools;
-
+
{tools.map((tool: any) => ( ))} @@ -352,16 +352,16 @@ function createToolCard(tool) { cardDiv.style.cursor = 'pointer'; cardDiv.onclick = () => (window as any).showToolDetails(tool.name); - // Create button HTML based on hosting status + // Create responsive button HTML let buttonHTML; if (hasValidProjectUrl) { - // Two buttons for tools we're hosting + // Two buttons for tools we're hosting - responsive layout buttonHTML = ` -
- + @@ -369,28 +369,28 @@ function createToolCard(tool) { } else { // Single button for tools we're not hosting buttonHTML = ` - + Software-Homepage `; } cardDiv.innerHTML = ` -
-

${tool.name}

-
+
+

${tool.name}

+
${hasValidProjectUrl ? 'Self-Hosted' : ''} ${tool.license !== 'Proprietary' ? 'Open Source' : ''} ${hasKnowledgebase ? 'Infos 📖' : ''}
-

+

${tool.description}

-
+
@@ -401,7 +401,7 @@ function createToolCard(tool) {
-
+
@@ -411,7 +411,7 @@ function createToolCard(tool) {
-
+
diff --git a/src/styles/global.css b/src/styles/global.css index 565f46c..d5c6a6e 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -136,6 +136,8 @@ nav { position: sticky; top: 0; z-index: 100; + width: 100%; + overflow-x: hidden; /* Prevent horizontal overflow */ } .nav-wrapper { @@ -143,12 +145,18 @@ nav { align-items: center; justify-content: space-between; padding: 1rem 0; + width: 100%; + max-width: 1280px; + margin: 0 auto; + padding-left: 1rem; + padding-right: 1rem; } .nav-brand { display: flex; align-items: center; gap: 0.5rem; + flex-shrink: 0; /* Prevent brand from shrinking */ } .nav-logo { @@ -159,15 +167,20 @@ nav { .nav-links { display: flex; align-items: center; - gap: 5rem; + gap: 2rem; /* Reduced from 5rem */ list-style: none; + margin: 0; + padding: 0; + flex-wrap: wrap; /* Allow wrapping on very small screens */ } .nav-link { color: var(--color-text); font-weight: 500; transition: color 0.2s ease; - font-size: 1.2rem; + font-size: 1rem; /* Reduced from 1.2rem */ + white-space: nowrap; /* Prevent text wrapping */ + flex-shrink: 0; } .nav-link:hover { @@ -296,11 +309,20 @@ input[type="checkbox"] { box-shadow: 0 0 0 1px var(--color-hosted); } +/* Adjust gradient for different card types */ +.card-hosted .tool-tags-container::after { + background: linear-gradient(to bottom, transparent 0%, var(--color-hosted-bg) 80%); +} + .card-oss { background-color: var(--color-oss-bg); border-color: var(--color-oss); } +.card-oss .tool-tags-container::after { + background: linear-gradient(to bottom, transparent 0%, var(--color-oss-bg) 80%); +} + /* Grid and Layout */ .grid { display: grid; @@ -323,6 +345,19 @@ input[type="checkbox"] { grid-template-columns: repeat(4, minmax(0, 1fr)); } +/* NEW: Auto-responsive grid classes */ +.grid-auto-fit { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 1rem; +} + +.grid-auto-fit-small { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1rem; +} + /* Tool Matrix */ .matrix-wrapper { overflow-x: auto; @@ -421,6 +456,37 @@ input[type="checkbox"] { box-shadow: inset 0 0 0 1px rgb(59 130 246 / 40%); } +/* Tool Card Description Truncation - 4 lines max */ +.tool-card .text-muted { + display: -webkit-box !important; + -webkit-line-clamp: 4; + line-clamp: 4; + -webkit-box-orient: vertical; + overflow: hidden !important; + line-height: 1.4; + max-height: calc(1.4em * 4); +} + +/* Tool Card Tags Truncation - 3 lines max (uses height approach since we need flex) */ +.tool-card .tool-tags-container { + max-height: calc(1.5em * 3 + 0.5rem) !important; /* 3 lines + gap space */ + overflow: hidden !important; + position: relative; +} + +/* Add subtle fade for truncated tags */ +.tool-card .tool-tags-container::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 1.2em; + background: linear-gradient(to bottom, transparent 0%, var(--color-bg) 80%); + pointer-events: none; +} + + .tool-chip { display: inline-block; padding: 0.25rem 0.5rem; @@ -1007,22 +1073,42 @@ footer { } /* Responsive Design */ -@media (width: 768px) { +@media (width <= 1200px) { + .grid-cols-4 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} + +@media (width <= 900px) { + .grid-cols-3, + .grid-cols-4 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (width <= 768px) { .grid-cols-2 { grid-template-columns: 1fr; } - .grid-cols-3 { grid-template-columns: 1fr; } - .grid-cols-4 { grid-template-columns: 1fr; } + .nav-wrapper { + padding-left: 0.75rem; + padding-right: 0.75rem; + } + .nav-links { gap: 1rem; } + + .nav-link { + font-size: 0.875rem; + } h1 { font-size: 2rem; @@ -1143,13 +1229,21 @@ footer { } } -@media (width: 600px) { - .phase-tools { - grid-template-columns: 1fr !important; - } -} -@media (width: 640px) { + +@media (width <= 640px) { + .grid-cols-2, + .grid-cols-3, + .grid-cols-4 { + grid-template-columns: 1fr; + } + + .grid, + .grid-auto-fit, + .grid-auto-fit-small { + gap: 0.75rem; + } + .phase-buttons { justify-content: center; } @@ -1167,9 +1261,35 @@ footer { .tag-cloud.expanded { max-height: 800px; } + + .nav-wrapper { + padding-left: 0.5rem; + padding-right: 0.5rem; + flex-direction: column; + gap: 1rem; + padding-top: 0.75rem; + padding-bottom: 0.75rem; + } + + .nav-links { + gap: 0.75rem; + justify-content: center; + width: 100%; + } + + .nav-link { + font-size: 0.8125rem; + padding: 0.25rem 0.5rem; + } } -@media (width: 480px) { +@media (width <= 600px) { + .phase-tools { + grid-template-columns: 1fr !important; + } +} + +@media (width <= 480px) { .phase-buttons { flex-direction: column; gap: 0.375rem; @@ -1199,6 +1319,31 @@ footer { .phase-tools { grid-template-columns: 1fr; } + + .nav-wrapper { + gap: 0.75rem; + } + + .nav-links { + gap: 0.5rem; + flex-wrap: wrap; + justify-content: center; + } + + .nav-link { + font-size: 0.75rem; + padding: 0.25rem 0.375rem; + } + + .nav-brand h1 { + font-size: 1.25rem; /* Smaller brand text on very small screens */ + } + + .grid, + .grid-auto-fit, + .grid-auto-fit-small { + gap: 0.5rem; + } } /* AI Interface Container */