style consolidation

This commit is contained in:
overcuriousity 2025-07-25 16:10:27 +02:00
parent 6e5ea011e0
commit 78dc47d218
3 changed files with 179 additions and 172 deletions

View File

@ -38,10 +38,10 @@ const hasValidProjectUrl = tool.projectUrl !== undefined &&
const hasKnowledgebase = tool.knowledgebase === true; const hasKnowledgebase = tool.knowledgebase === true;
// Determine card styling based on type and hosting status // Determine card styling based on type and hosting status
const cardClass = isConcept ? 'card card-concept tool-card' : const cardClass = isConcept ? 'card card-concept tool-card cursor-pointer' :
isMethod ? 'card card-method tool-card' : isMethod ? 'card card-method tool-card cursor-pointer' :
hasValidProjectUrl ? 'card card-hosted tool-card' : hasValidProjectUrl ? 'card card-hosted tool-card cursor-pointer' :
(tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card'); (tool.license !== 'Proprietary' ? 'card card-oss tool-card cursor-pointer' : 'card tool-card cursor-pointer');
// ENHANCED: Data attributes for filtering // ENHANCED: Data attributes for filtering
const toolDataAttributes = { const toolDataAttributes = {
@ -60,92 +60,92 @@ const toolDataAttributes = {
<div <div
class={cardClass} class={cardClass}
{...toolDataAttributes} {...toolDataAttributes}
style="cursor: pointer;"
onclick={`window.showToolDetails('${tool.name}')`} onclick={`window.showToolDetails('${tool.name}')`}
> >
<!-- Card Header with Fixed Height --> <!-- Card Header with Fixed Height -->
<div class="tool-card-header"> <div class="tool-card-header">
<h3> <h3>
{tool.icon && <span style="margin-right: 0.5rem; font-size: 1.125rem;">{tool.icon}</span>} {tool.icon && <span class="mr-2 text-lg">{tool.icon}</span>}
{tool.name} {tool.name}
</h3> </h3>
<div class="tool-card-badges"> <div class="tool-card-badges">
<!-- Only show CC24-Server and Knowledgebase badges --> <!-- Only show CC24-Server and Knowledgebase badges -->
{!isMethod && hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>} {!isMethod && hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>}
{hasKnowledgebase && <span class="badge badge-error">📖</span>} {hasKnowledgebase && <span class="badge badge-error">📖</span>}
<ShareButton toolName={tool.name} context="card" size="small" /> <ShareButton toolName={tool.name} context="card" size="small" />
</div> </div>
</div>
<!-- Description - Truncated to 2 lines -->
<p class="text-muted">
{tool.description}
</p>
<!-- Metadata - Compact Icons with Better Alignment -->
<div class="tool-card-metadata flex items-center gap-4 mb-3" style="line-height: 1;">
<div class="metadata-item flex items-center gap-2 text-xs text-secondary flex-shrink-1 min-w-0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="flex-shrink-0">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<line x1="9" y1="9" x2="15" y2="9"></line>
<line x1="9" y1="15" x2="15" y2="15"></line>
</svg>
<span class="overflow-hidden min-w-0" style="text-overflow: ellipsis; white-space: nowrap;">
{tool.platforms.slice(0, 2).join(', ')}{tool.platforms.length > 2 ? '...' : ''}
</span>
</div> </div>
<!-- Description - Truncated to 2 lines --> <div class="metadata-item flex items-center gap-2 text-xs text-secondary flex-shrink-1 min-w-0">
<p class="text-muted"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="flex-shrink-0">
{tool.description} <circle cx="12" cy="12" r="10"></circle>
</p> <path d="M12 6v6l4 2"></path>
</svg>
<!-- Metadata - Compact Icons with Better Alignment --> <span class="overflow-hidden min-w-0" style="text-overflow: ellipsis; white-space: nowrap;">
<div class="tool-card-metadata" style="display: flex; align-items: center; gap: 1rem; margin-bottom: 0.75rem; line-height: 1;"> {tool.skillLevel}
<div class="metadata-item" style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: var(--color-text-secondary); flex-shrink: 1; min-width: 0;"> </span>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="flex-shrink: 0;">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<line x1="9" y1="9" x2="15" y2="9"></line>
<line x1="9" y1="15" x2="15" y2="15"></line>
</svg>
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;">
{tool.platforms.slice(0, 2).join(', ')}{tool.platforms.length > 2 ? '...' : ''}
</span>
</div>
<div class="metadata-item" style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: var(--color-text-secondary); flex-shrink: 1; min-width: 0;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="flex-shrink: 0;">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 6v6l4 2"></path>
</svg>
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;">
{tool.skillLevel}
</span>
</div>
<div class="metadata-item" style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: var(--color-text-secondary); flex-shrink: 1; min-width: 0;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="flex-shrink: 0;">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
</svg>
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;">
{isConcept ? 'Konzept' : isMethod ? 'Methode' : tool.license === 'Proprietary' ? 'Prop.' : tool.license?.split(' ')[0]}
</span>
</div>
</div> </div>
<!-- Tags - Two Lines with Fade --> <div class="metadata-item flex items-center gap-2 text-xs text-secondary flex-shrink-1 min-w-0">
<div class="tool-tags-container"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="flex-shrink-0">
{tool.tags.slice(0, 8).map(tag => ( <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<span class="tag">{tag}</span> <polyline points="14 2 14 8 20 8"></polyline>
))} </svg>
<span class="overflow-hidden min-w-0" style="text-overflow: ellipsis; white-space: nowrap;">
{isConcept ? 'Konzept' : isMethod ? 'Methode' : tool.license === 'Proprietary' ? 'Prop.' : tool.license?.split(' ')[0]}
</span>
</div> </div>
</div>
<!-- Buttons - Fixed at Bottom (NO EDIT BUTTONS - Available in modals) -->
<div class="tool-card-buttons" onclick="event.stopPropagation();"> <!-- Tags - Two Lines with Fade -->
{isConcept ? ( <div class="tool-tags-container">
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button" style="background-color: var(--color-concept); border-color: var(--color-concept);"> {tool.tags.slice(0, 8).map(tag => (
Mehr erfahren <span class="tag">{tag}</span>
))}
</div>
<!-- Buttons - Fixed at Bottom (NO EDIT BUTTONS - Available in modals) -->
<div class="tool-card-buttons" onclick="event.stopPropagation();">
{isConcept ? (
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button" style="background-color: var(--color-concept); border-color: var(--color-concept);">
Mehr erfahren
</a>
) : isMethod ? (
<a href={tool.projectUrl || tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button" style="background-color: var(--color-method); border-color: var(--color-method);">
Zur Methode
</a>
) : hasValidProjectUrl ? (
<div class="button-row">
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
Homepage
</a> </a>
) : isMethod ? ( <a href={tool.projectUrl} target="_blank" rel="noopener noreferrer" class="btn btn-primary">
<a href={tool.projectUrl || tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button" style="background-color: var(--color-method); border-color: var(--color-method);"> Zugreifen
Zur Methode
</a> </a>
) : hasValidProjectUrl ? ( </div>
<div class="button-row"> ) : (
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary"> <a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button">
Homepage Software-Homepage
</a> </a>
<a href={tool.projectUrl} target="_blank" rel="noopener noreferrer" class="btn btn-primary"> )}
Zugreifen </div>
</a> </div>
</div>
) : (
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button">
Software-Homepage
</a>
)}
</div>
</div> </div>

View File

@ -2,8 +2,6 @@
import { getToolsData } from '../utils/dataService.js'; import { getToolsData } from '../utils/dataService.js';
import ShareButton from './ShareButton.astro'; import ShareButton from './ShareButton.astro';
// Load tools data // Load tools data
const data = await getToolsData(); const data = await getToolsData();
@ -37,17 +35,17 @@ domains.forEach((domain: any) => {
<div id="matrix-container" class="matrix-wrapper" style="display: none;"> <div id="matrix-container" class="matrix-wrapper" style="display: none;">
<!-- Domain-Agnostic Software Sections --> <!-- Domain-Agnostic Software Sections -->
{domainAgnosticTools.map((sectionData: any, index: number) => ( {domainAgnosticTools.map((sectionData: any, index: number) => (
<div id={`domain-agnostic-section-${sectionData.section.id}`} class="card collaboration-section-collapsed" style="margin-bottom: 1.5rem; border-left: 4px solid var(--color-accent);"> <div id={`domain-agnostic-section-${sectionData.section.id}`} class="card collaboration-section-collapsed mb-6 border-l-4" style="border-left-color: var(--color-accent);">
<div class="collaboration-header" onclick={`toggleDomainAgnosticSection('${sectionData.section.id}')`} style="cursor: pointer; display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.1rem;"> <div class="collaboration-header cursor-pointer flex items-center gap-3" onclick={`toggleDomainAgnosticSection('${sectionData.section.id}')`} style="margin-bottom: 0.1rem;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--color-accent)" stroke-width="2" style="margin-right: 0.5rem;"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--color-accent)" stroke-width="2" class="mr-2">
<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/> <path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
<circle cx="8.5" cy="7" r="4"/> <circle cx="8.5" cy="7" r="4"/>
<line x1="20" y1="8" x2="20" y2="14"/> <line x1="20" y1="8" x2="20" y2="14"/>
<line x1="23" y1="11" x2="17" y2="11"/> <line x1="23" y1="11" x2="17" y2="11"/>
</svg> </svg>
<h3 style="margin: 0; color: var(--color-accent); font-size: 1.125rem;"> <h3 class="m-0 text-lg" style="color: var(--color-accent);">
{sectionData.section.name} {sectionData.section.name}
<span id={`count-${sectionData.section.id}`} class="badge" style="background-color: var(--color-text-secondary); color: var(--color-bg); margin-left: 0.5rem; font-size: 0.75rem;"> <span id={`count-${sectionData.section.id}`} class="badge text-xs" style="background-color: var(--color-text-secondary); color: var(--color-bg); margin-left: 0.5rem;">
{sectionData.tools.length} {sectionData.tools.length}
</span> </span>
</h3> </h3>
@ -65,14 +63,14 @@ domains.forEach((domain: any) => {
tool.projectUrl !== "" && tool.projectUrl !== "" &&
tool.projectUrl.trim() !== ""; tool.projectUrl.trim() !== "";
return ( return (
<div class={`collaboration-tool-compact ${hasValidProjectUrl ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`} <div class={`collaboration-tool-compact cursor-pointer ${hasValidProjectUrl ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`}
onclick={`window.showToolDetails('${tool.name}')`}> onclick={`window.showToolDetails('${tool.name}')`}>
<div class="tool-compact-header"> <div class="tool-compact-header">
<h4 style="margin: 0; font-size: 0.875rem; font-weight: 600;"> <h4 class="m-0 text-sm font-semibold">
{tool.icon && <span style="margin-right: 0.5rem;">{tool.icon}</span>} {tool.icon && <span class="mr-2">{tool.icon}</span>}
{tool.name} {tool.name}
</h4> </h4>
<div style="display: flex; gap: 0.25rem;"> <div class="flex gap-1">
{hasValidProjectUrl && <span class="badge badge--mini badge-primary">CC24-Server</span>} {hasValidProjectUrl && <span class="badge badge--mini badge-primary">CC24-Server</span>}
{tool.knowledgebase === true && <span class="badge badge--mini badge-error">📖</span>} {tool.knowledgebase === true && <span class="badge badge--mini badge-error">📖</span>}
</div> </div>
@ -80,7 +78,7 @@ domains.forEach((domain: any) => {
<p class="text-muted"> <p class="text-muted">
{tool.description} {tool.description}
</p> </p>
<div style="display: flex; gap: 0.75rem; font-size: 0.6875rem; color: var(--color-text-secondary);"> <div class="flex gap-3 text-xs" style="color: var(--color-text-secondary);">
<span>{tool.platforms.join(', ')}</span> <span>{tool.platforms.join(', ')}</span>
<span>•</span> <span>•</span>
<span>{tool.skillLevel}</span> <span>{tool.skillLevel}</span>
@ -95,7 +93,7 @@ domains.forEach((domain: any) => {
<!-- DFIR Tools Matrix --> <!-- DFIR Tools Matrix -->
<div id="dfir-matrix-section"> <div id="dfir-matrix-section">
<h2 style="margin-bottom: 1rem; color: var(--color-text);">MATRIX</h2> <h2 class="mb-4" style="color: var(--color-text);">MATRIX</h2>
<table class="matrix-table"> <table class="matrix-table">
<thead> <thead>
<tr> <tr>
@ -128,7 +126,7 @@ domains.forEach((domain: any) => {
title={`${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`} title={`${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`}
> >
{tool.name} {tool.name}
{tool.knowledgebase === true && <span style="margin-left: 0.25rem; font-size: 0.6875rem;">📖</span>} {tool.knowledgebase === true && <span class="text-xs" style="margin-left: 0.25rem;">📖</span>}
</span> </span>
); );
})} })}
@ -146,9 +144,9 @@ domains.forEach((domain: any) => {
<!-- Primary Modal --> <!-- Primary Modal -->
<div class="tool-details" id="tool-details-primary"> <div class="tool-details" id="tool-details-primary">
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;"> <div class="flex justify-between items-start mb-4">
<h2 id="tool-name-primary" style="margin: 0;">Tool Name</h2> <h2 id="tool-name-primary" class="m-0">Tool Name</h2>
<div style="display: flex; align-items: center; gap: 0.5rem;"> <div class="flex items-center gap-2">
<div id="share-button-primary" style="display: none;"> <div id="share-button-primary" style="display: none;">
<!-- Share button will be populated by JavaScript --> <!-- Share button will be populated by JavaScript -->
</div> </div>
@ -166,20 +164,20 @@ domains.forEach((domain: any) => {
<p id="tool-description-primary" class="text-muted"></p> <p id="tool-description-primary" class="text-muted"></p>
<div id="tool-badges-primary" style="display: flex; gap: 0.5rem; margin-bottom: 1rem;"></div> <div id="tool-badges-primary" class="flex gap-2 mb-4"></div>
<div id="tool-metadata-primary" style="margin-bottom: 1rem;"></div> <div id="tool-metadata-primary" class="mb-4"></div>
<div id="tool-tags-primary" style="margin-bottom: 1rem;"></div> <div id="tool-tags-primary" class="mb-4"></div>
<div id="tool-links-primary" style="display: flex; gap: 0.5rem; flex-direction: column;"></div> <div id="tool-links-primary" class="flex flex-col gap-2"></div>
</div> </div>
<!-- Secondary Modal --> <!-- Secondary Modal -->
<div class="tool-details" id="tool-details-secondary"> <div class="tool-details" id="tool-details-secondary">
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;"> <div class="flex justify-between items-start mb-4">
<h2 id="tool-name-secondary" style="margin: 0;">Tool Name</h2> <h2 id="tool-name-secondary" class="m-0">Tool Name</h2>
<div style="display: flex; align-items: center; gap: 0.5rem;"> <div class="flex items-center gap-2">
<div id="share-button-secondary" style="display: none;"> <div id="share-button-secondary" style="display: none;">
<!-- Share button will be populated by JavaScript --> <!-- Share button will be populated by JavaScript -->
</div> </div>
@ -197,13 +195,13 @@ domains.forEach((domain: any) => {
<p id="tool-description-secondary" class="text-muted"></p> <p id="tool-description-secondary" class="text-muted"></p>
<div id="tool-badges-secondary" style="display: flex; gap: 0.5rem; margin-bottom: 1rem;"></div> <div id="tool-badges-secondary" class="flex gap-2 mb-4"></div>
<div id="tool-metadata-secondary" style="margin-bottom: 1rem;"></div> <div id="tool-metadata-secondary" class="mb-4"></div>
<div id="tool-tags-secondary" style="margin-bottom: 1rem;"></div> <div id="tool-tags-secondary" class="mb-4"></div>
<div id="tool-links-secondary" style="display: flex; gap: 0.5rem; flex-direction: column;"></div> <div id="tool-links-secondary" class="flex flex-col gap-2"></div>
</div> </div>
<script define:vars={{ toolsData: tools, domainAgnosticSoftware, domainAgnosticTools }}> <script define:vars={{ toolsData: tools, domainAgnosticSoftware, domainAgnosticTools }}>
@ -284,11 +282,6 @@ domains.forEach((domain: any) => {
} }
} }
// ===== SHARING FUNCTIONALITY =====
// REMOVED: createToolSlug function - now using window.createToolSlug
// REMOVED: findTool function - now using window.findToolByIdentifier
// Generate share URLs // Generate share URLs
function generateShareURL(toolName, view, modal = null) { function generateShareURL(toolName, view, modal = null) {
const toolSlug = window.createToolSlug(toolName); const toolSlug = window.createToolSlug(toolName);
@ -345,10 +338,18 @@ domains.forEach((domain: any) => {
backdrop = document.createElement('div'); backdrop = document.createElement('div');
backdrop.id = 'share-modal-backdrop'; backdrop.id = 'share-modal-backdrop';
backdrop.style.cssText = ` backdrop.style.cssText = `
position: fixed; top: 0; left: 0; right: 0; bottom: 0; position: fixed;
background: rgba(0, 0, 0, 0.5); z-index: 9999; top: 0;
display: flex; align-items: center; justify-content: center; left: 0;
opacity: 0; transition: opacity 0.2s ease; right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.2s ease;
`; `;
document.body.appendChild(backdrop); document.body.appendChild(backdrop);
} }
@ -356,21 +357,27 @@ domains.forEach((domain: any) => {
// Create share dialog // Create share dialog
const dialog = document.createElement('div'); const dialog = document.createElement('div');
dialog.style.cssText = ` dialog.style.cssText = `
background: var(--color-bg); border: 1px solid var(--color-border); background-color: var(--color-bg);
border-radius: 0.75rem; padding: 1.5rem; max-width: 400px; width: 90%; border: 1px solid var(--color-border);
box-shadow: var(--shadow-lg); transform: scale(0.9); transition: transform 0.2s ease; border-radius: 0.5rem;
padding: 1.5rem;
max-width: 28rem;
width: 90%;
box-shadow: var(--shadow-lg);
transform: scale(0.9);
transition: transform 0.2s ease;
`; `;
dialog.innerHTML = ` dialog.innerHTML = `
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem;">
<h3 style="margin: 0; color: var(--color-primary);"> <h3 style="margin: 0; color: var(--color-primary); display: flex; align-items: center;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem; vertical-align: middle;"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/> <circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/> <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
</svg> </svg>
${toolName} teilen ${toolName} teilen
</h3> </h3>
<button id="close-share-dialog" style="background: none; border: none; cursor: pointer; padding: 0.25rem;color: var(--color-text-secondary)"> <button id="close-share-dialog" class="btn-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/> <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
</svg> </svg>
@ -378,44 +385,54 @@ domains.forEach((domain: any) => {
</div> </div>
<div style="display: flex; flex-direction: column; gap: 0.75rem;"> <div style="display: flex; flex-direction: column; gap: 0.75rem;">
<button class="share-option-btn" data-url="${generateShareURL(toolName, 'grid')}" <button class="share-option-btn" data-url="${generateShareURL(toolName, 'grid')}" style="display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--color-border); border-radius: 0.5rem; background-color: var(--color-bg); cursor: pointer; transition: var(--transition-fast); text-align: left; width: 100%;" onmouseover="this.style.backgroundColor='var(--color-bg-secondary)'" onmouseout="this.style.backgroundColor='var(--color-bg)'">
style="display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--color-border); border-radius: 0.5rem; background: var(--color-bg); cursor: pointer; transition: var(--transition-fast); text-align: left; width: 100%;"> <div style="width: 2rem; height: 2rem; background-color: var(--color-primary); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center;">
<div style="width: 32px; height: 32px; background: var(--color-primary); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/> <rect x="3" y="3" width="7" height="7"/>
<rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/> <rect x="14" y="3" width="7" height="7"/>
<rect x="14" y="14" width="7" height="7"/>
<rect x="3" y="14" width="7" height="7"/>
</svg> </svg>
</div> </div>
<div> <div>
<div style="font-weight: 500; margin-bottom: 0.25rem;color: var(--color-text-secondary)">Kachelansicht</div> <div style="font-weight: 500; margin-bottom: 0.25rem; color: var(--color-text);">Kachelansicht</div>
<div style="font-size: 0.8125rem; color: var(--color-text-secondary);">Scrollt zur Karte in der Übersicht</div> <div style="font-size: 0.875rem; color: var(--color-text-secondary);">Scrollt zur Karte in der Übersicht</div>
</div> </div>
</button> </button>
<button class="share-option-btn" data-url="${generateShareURL(toolName, 'matrix')}" <button class="share-option-btn" data-url="${generateShareURL(toolName, 'matrix')}" style="display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--color-border); border-radius: 0.5rem; background-color: var(--color-bg); cursor: pointer; transition: var(--transition-fast); text-align: left; width: 100%;" onmouseover="this.style.backgroundColor='var(--color-bg-secondary)'" onmouseout="this.style.backgroundColor='var(--color-bg)'">
style="display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--color-border); border-radius: 0.5rem; background: var(--color-bg); cursor: pointer; transition: var(--transition-fast); text-align: left; width: 100%;"> <div style="width: 2rem; height: 2rem; background-color: var(--color-accent); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center;">
<div style="width: 32px; height: 32px; background: var(--color-accent); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<path d="M3 3h7v7H3zM14 3h7v7h-7zM14 14h7v7h-7zM3 14h7v7H3z"/> <rect x="3" y="3" width="4" height="4"/>
<rect x="10" y="3" width="4" height="4"/>
<rect x="17" y="3" width="4" height="4"/>
<rect x="3" y="10" width="4" height="4"/>
<rect x="10" y="10" width="4" height="4"/>
<rect x="17" y="10" width="4" height="4"/>
<rect x="3" y="17" width="4" height="4"/>
<rect x="10" y="17" width="4" height="4"/>
<rect x="17" y="17" width="4" height="4"/>
</svg> </svg>
</div> </div>
<div> <div>
<div style="font-weight: 500; margin-bottom: 0.25rem;color: var(--color-text-secondary)">Matrix-Ansicht</div> <div style="font-weight: 500; margin-bottom: 0.25rem; color: var(--color-text);">Matrix-Ansicht</div>
<div style="font-size: 0.8125rem; color: var(--color-text-secondary);">Zeigt Tool-Position in der Matrix</div> <div style="font-size: 0.875rem; color: var(--color-text-secondary);">Zeigt Tool-Position in der Matrix</div>
</div> </div>
</button> </button>
<button class="share-option-btn" data-url="${generateShareURL(toolName, 'modal', 'primary')}" <button class="share-option-btn" data-url="${generateShareURL(toolName, 'modal', 'primary')}" style="display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--color-border); border-radius: 0.5rem; background-color: var(--color-bg); cursor: pointer; transition: var(--transition-fast); text-align: left; width: 100%;" onmouseover="this.style.backgroundColor='var(--color-bg-secondary)'" onmouseout="this.style.backgroundColor='var(--color-bg)'">
style="display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--color-border); border-radius: 0.5rem; background: var(--color-bg); cursor: pointer; transition: var(--transition-fast); text-align: left; width: 100%;"> <div style="width: 2rem; height: 2rem; background-color: var(--color-warning); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center;">
<div style="width: 32px; height: 32px; background: var(--color-warning); border-radius: 0.25rem; display: flex; align-items: center; justify-content: center;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/> <polyline points="14 2 14 8 20 8"/>
<line x1="16" y1="13" x2="8" y2="13"/>
<line x1="16" y1="17" x2="8" y2="17"/>
<polyline points="10 9 9 9 8 9"/>
</svg> </svg>
</div> </div>
<div> <div>
<div style="font-weight: 500; margin-bottom: 0.25rem;color: var(--color-text-secondary)">Tool-Details</div> <div style="font-weight: 500; margin-bottom: 0.25rem; color: var(--color-text);">Tool-Details</div>
<div style="font-size: 0.8125rem; color: var(--color-text-secondary);">Öffnet Detail-Fenster direkt</div> <div style="font-size: 0.875rem; color: var(--color-text-secondary);">Öffnet Detail-Fenster direkt</div>
</div> </div>
</button> </button>
</div> </div>
@ -448,16 +465,6 @@ domains.forEach((domain: any) => {
// Share option handlers // Share option handlers
dialog.querySelectorAll('.share-option-btn').forEach(btn => { dialog.querySelectorAll('.share-option-btn').forEach(btn => {
btn.addEventListener('mouseover', () => {
btn.style.backgroundColor = 'var(--color-bg-secondary)';
btn.style.borderColor = 'var(--color-primary)';
});
btn.addEventListener('mouseout', () => {
btn.style.backgroundColor = 'var(--color-bg)';
btn.style.borderColor = 'var(--color-border)';
});
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
const url = btn.getAttribute('data-url'); const url = btn.getAttribute('data-url');
copyToClipboard(url, btn); copyToClipboard(url, btn);
@ -498,7 +505,7 @@ domains.forEach((domain: any) => {
} }
// Update modal content // Update modal content
const iconHtml = tool.icon ? `<span style="margin-right: 0.75rem; font-size: 1.5rem;">${tool.icon}</span>` : ''; const iconHtml = tool.icon ? `<span class="mr-3 text-xl">${tool.icon}</span>` : '';
elements.name.innerHTML = `${iconHtml}${tool.name}`; elements.name.innerHTML = `${iconHtml}${tool.name}`;
elements.description.textContent = tool.description; elements.description.textContent = tool.description;
@ -524,7 +531,7 @@ domains.forEach((domain: any) => {
const domainsText = domains.length > 0 ? domains.join(', ') : 'Domain-agnostic'; const domainsText = domains.length > 0 ? domains.join(', ') : 'Domain-agnostic';
const phasesText = phases.join(', '); const phasesText = phases.join(', ');
let metadataHTML = `<div style="display: grid; gap: 0.5rem;">`; let metadataHTML = `<div class="grid gap-2">`;
if (!isConcept) { if (!isConcept) {
metadataHTML += ` metadataHTML += `
@ -547,7 +554,7 @@ domains.forEach((domain: any) => {
// Tags and Related Concepts // Tags and Related Concepts
const tags = tool.tags || []; const tags = tool.tags || [];
let tagsHTML = ` let tagsHTML = `
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem;"> <div class="flex flex-wrap gap-1">
${tags.map(tag => `<span class="tag">${tag}</span>`).join('')} ${tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
</div> </div>
`; `;
@ -558,14 +565,14 @@ domains.forEach((domain: any) => {
const conceptLinks = relatedConcepts.map(conceptName => { const conceptLinks = relatedConcepts.map(conceptName => {
const concept = toolsData.find(t => t.name === conceptName && t.type === 'concept'); const concept = toolsData.find(t => t.name === conceptName && t.type === 'concept');
if (concept) { if (concept) {
return `<button class="tag" style="cursor: pointer; background-color: var(--color-concept-bg); border: 1px solid var(--color-concept); color: var(--color-concept); transition: var(--transition-fast); margin: 0.125rem;" return `<button class="tag cursor-pointer" style="background-color: var(--color-concept-bg); border: 1px solid var(--color-concept); color: var(--color-concept); transition: var(--transition-fast);"
onclick="event.stopPropagation(); window.showToolDetails('${conceptName}', 'secondary')" onclick="event.stopPropagation(); window.showToolDetails('${conceptName}', 'secondary')"
onmouseover="this.style.backgroundColor='var(--color-concept)'; this.style.color='white';" onmouseover="this.style.backgroundColor='var(--color-concept)'; this.style.color='white';"
onmouseout="this.style.backgroundColor='var(--color-concept-bg)'; this.style.color='var(--color-concept)';"> onmouseout="this.style.backgroundColor='var(--color-concept-bg)'; this.style.color='var(--color-concept)';">
${conceptName} ${conceptName}
</button>`; </button>`;
} }
return `<span class="tag" style="background-color: var(--color-bg-tertiary); color: var(--color-text-secondary); margin: 0.125rem;">${conceptName}</span>`; return `<span class="tag" style="background-color: var(--color-bg-tertiary); color: var(--color-text-secondary);">${conceptName}</span>`;
}).join(''); }).join('');
// Check if mobile device // Check if mobile device
@ -573,18 +580,18 @@ domains.forEach((domain: any) => {
const collapseOnMobile = isMobile && relatedConcepts.length > 2; const collapseOnMobile = isMobile && relatedConcepts.length > 2;
tagsHTML += ` tagsHTML += `
<div style="margin-top: 1rem;"> <div class="mt-4">
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem;"> <div class="flex items-center gap-2 mb-2">
<strong style="color: var(--color-text);">Verwandte Konzepte:</strong> <strong style="color: var(--color-text);">Verwandte Konzepte:</strong>
${collapseOnMobile ? ` ${collapseOnMobile ? `
<button id="concepts-toggle-${modalType}" <button id="concepts-toggle-${modalType}"
onclick="this.nextElementSibling.style.display = this.nextElementSibling.style.display === 'none' ? 'block' : 'none'; this.textContent = this.textContent === '▼' ? '▲' : '▼';" onclick="this.nextElementSibling.style.display = this.nextElementSibling.style.display === 'none' ? 'block' : 'none'; this.textContent = this.textContent === '▼' ? '▲' : '▼';"
style="background: none; border: 1px solid var(--color-border); border-radius: 0.25rem; padding: 0.25rem 0.5rem; cursor: pointer; font-size: 0.75rem;"> class="btn-icon text-xs">
</button> </button>
` : ''} ` : ''}
</div> </div>
<div ${collapseOnMobile ? 'style="display: none;"' : ''} style="display: flex; flex-wrap: wrap; gap: 0.25rem;"> <div ${collapseOnMobile ? 'style="display: none;"' : ''} class="flex flex-wrap gap-1">
${conceptLinks} ${conceptLinks}
</div> </div>
</div> </div>
@ -598,30 +605,30 @@ domains.forEach((domain: any) => {
if (isConcept) { if (isConcept) {
linksHTML += ` linksHTML += `
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%; background-color: var(--color-concept); border-color: var(--color-concept);"> <a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary w-full" style="background-color: var(--color-concept); border-color: var(--color-concept);">
Mehr erfahren Mehr erfahren
</a> </a>
`; `;
} else if (isMethod) { } else if (isMethod) {
linksHTML += ` linksHTML += `
<a href="${tool.projectUrl || tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%; background-color: var(--color-method); border-color: var(--color-method);"> <a href="${tool.projectUrl || tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary w-full" style="background-color: var(--color-method); border-color: var(--color-method);">
Zur Methode Zur Methode
</a> </a>
`; `;
} else if (hasValidProjectUrl) { } else if (hasValidProjectUrl) {
linksHTML += ` linksHTML += `
<div style="display: flex; gap: 0.5rem;"> <div class="flex gap-2">
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;"> <a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary flex-1">
Homepage Homepage
</a> </a>
<a href="${tool.projectUrl}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="flex: 1;"> <a href="${tool.projectUrl}" target="_blank" rel="noopener noreferrer" class="btn btn-primary flex-1">
Zugreifen Zugreifen
</a> </a>
</div> </div>
`; `;
} else { } else {
linksHTML += ` linksHTML += `
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;"> <a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary w-full">
Software-Homepage Software-Homepage
</a> </a>
`; `;
@ -630,8 +637,8 @@ domains.forEach((domain: any) => {
if (tool.knowledgebase === true) { if (tool.knowledgebase === true) {
const kbId = window.createToolSlug(tool.name); const kbId = window.createToolSlug(tool.name);
linksHTML += ` linksHTML += `
<a href="/knowledgebase#kb-${kbId}" class="btn btn-secondary" style="width: 100%; margin-top: 0.5rem;"> <a href="/knowledgebase#kb-${kbId}" class="btn btn-secondary w-full mt-2">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="mr-2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/> <polyline points="14 2 14 8 20 8"/>
<line x1="16" y1="13" x2="8" y2="13"/> <line x1="16" y1="13" x2="8" y2="13"/>
@ -728,7 +735,6 @@ domains.forEach((domain: any) => {
if (shareButtonSecondary) shareButtonSecondary.style.display = 'none'; if (shareButtonSecondary) shareButtonSecondary.style.display = 'none';
if (contributeButtonSecondary) contributeButtonSecondary.style.display = 'none'; if (contributeButtonSecondary) contributeButtonSecondary.style.display = 'none';
} }
// ... rest of existing code
} else if (modalType === 'primary' && primaryModal) { } else if (modalType === 'primary' && primaryModal) {
primaryModal.classList.remove('active'); primaryModal.classList.remove('active');
const shareButtonPrimary = document.getElementById('share-button-primary'); const shareButtonPrimary = document.getElementById('share-button-primary');

View File

@ -1738,6 +1738,7 @@ This will literally assault the user's retinas. They'll need sunglasses to look
.flex-wrap { flex-wrap: wrap; } .flex-wrap { flex-wrap: wrap; }
.flex-1 { flex: 1; } .flex-1 { flex: 1; }
.flex-shrink-0 { flex-shrink: 0; } .flex-shrink-0 { flex-shrink: 0; }
.flex-shrink-1 { flex-shrink: 1; }
/* Alignment */ /* Alignment */
.items-center { align-items: center; } .items-center { align-items: center; }