AtomAI
AtomAI is a premium AI-powered SaaS template designed to be a modern, world-class website, suitable for startups, SaaS, and AI-related businesses.
<hr> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script> <style> .container { max-width: 900px; margin: 0 auto; padding: 20px; } .chart-container { background-color: #fff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); overflow: hidden; } .chart-area { width: 100%; height: 520px; position: relative; } .legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 32px; padding: 0 20px 15px 20px; } .legend-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 32px; margin-bottom: 12px; } .legend-item { display: flex; align-items: center; cursor: pointer; transition: opacity 0.2s ease; } .legend-icon { width: 20px; height: 20px; border-radius: 50%; margin-right: 10px; } .legend-text { font-size: 1.1rem; transition: font-weight 0.2s ease; } .note { text-align: center; font-size: 0.875rem; color: #6b7280; margin-top: 4px; padding-bottom: 12px; } /* Radar Chart Styles */ .radar-chart { width: 100%; height: 100%; } .radar-circle { fill: none; stroke: #6b7280; stroke-width: 1.5; } .radar-axis { stroke: #6b7280; stroke-width: 1.5; } .radar-area { fill-opacity: 0; stroke-width: 3; } .radar-area.highlighted { stroke-width: 6; } .radar-area.faded { stroke-width: 2; opacity: 0.25; } .radar-label { font-size: 13px; fill: #9ca3af; } .radar-value { font-size: 13px; font-weight: 600; fill: #4b5563; } /* Tooltip Styles */ .tooltip { position: absolute; background: white; padding: 8px 12px; border-radius: 4px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); font-size: 14px; pointer-events: none; opacity: 0; transition: opacity 0.2s; z-index: 10; border: 1px solid #e5e7eb; } .tooltip-title { font-weight: 600; margin-bottom: 4px; color: #374151; } .tooltip-value { margin: 2px 0; } </style> <div class="container"> <div class="chart-container"> <div class="chart-area" id="radar-chart-container"></div> <hr> <div class="note"> Click on a vendor name to highlight their scores. </div> <div class="legend" id="chart-legend"> <!-- Legend will be dynamically generated --> </div> </div> </div> <div id="tooltip" class="tooltip"></div> <script> // Tools Array with distinct colors for each extension const tools = [ { name: 'Magical', color: '#4F46E5', favicon: '' }, { name: 'LastPass', color: '#10B981', favicon: '' }, { name: 'RoboForm', color: '#F59E0B', favicon: '' }, { name: 'Dashlane', color: '#EC4899', favicon: '' }, { name: 'Form Filler', color: '#6366F1', favicon: '' }, { name: 'Lightning Autofill', color: '#DC2626', favicon: '' }, { name: 'QuickForm', color: '#7C3AED', favicon: '' }, { name: 'Autofill by Google', color: '#2563EB', favicon: '' }, { name: 'Simple Form Fill', color: '#059669', favicon: '' } ]; // Categories for comparison const categories = [ 'Ease of Use', 'Password Management', 'Cross-Platform Sync', 'Custom Templates', 'Data Security', 'Privacy Focus' ]; // Data for each category and tool const toolData = [ { category: 'Ease of Use', 'Magical': 96, 'LastPass': 88, 'RoboForm': 82, 'Dashlane': 85, 'Form Filler': 92, 'Lightning Autofill': 78, 'QuickForm': 91, 'Autofill by Google': 89, 'Simple Form Fill': 86, fullMark: 100 }, { category: 'Password Management', 'Magical': 75, 'LastPass': 95, 'RoboForm': 92, 'Dashlane': 94, 'Form Filler': 65, 'Lightning Autofill': 70, 'QuickForm': 68, 'Autofill by Google': 72, 'Simple Form Fill': 60, fullMark: 100 }, { category: 'Cross-Platform Sync', 'Magical': 91, 'LastPass': 94, 'RoboForm': 87, 'Dashlane': 92, 'Form Filler': 70, 'Lightning Autofill': 75, 'QuickForm': 80, 'Autofill by Google': 90, 'Simple Form Fill': 68, fullMark: 100 }, { category: 'Custom Templates', 'Magical': 94, 'LastPass': 76, 'RoboForm': 89, 'Dashlane': 82, 'Form Filler': 80, 'Lightning Autofill': 85, 'QuickForm': 88, 'Autofill by Google': 65, 'Simple Form Fill': 83, fullMark: 100 }, { category: 'Data Security', 'Magical': 88, 'LastPass': 96, 'RoboForm': 89, 'Dashlane': 93, 'Form Filler': 70, 'Lightning Autofill': 86, 'QuickForm': 83, 'Autofill by Google': 90, 'Simple Form Fill': 72, fullMark: 100 }, { category: 'Privacy Focus', 'Magical': 87, 'LastPass': 82, 'RoboForm': 84, 'Dashlane': 78, 'Form Filler': 75, 'Lightning Autofill': 93, 'QuickForm': 90, 'Autofill by Google': 75, 'Simple Form Fill': 85, fullMark: 100 } ]; // Variables for tracking state let highlightedTool = null; // D3.js radar chart implementation function createRadarChart() { // Get the container dimensions const container = document.getElementById('radar-chart-container'); const width = container.clientWidth; const height = container.clientHeight; const margin = { top: 40, right: 80, bottom: 40, left: 80 }; // Calculate the center and radius of the radar chart const centerX = width / 2; const centerY = height / 2; const radius = Math.min(width - margin.left - margin.right, height - margin.top - margin.bottom) / 2; // Create the SVG element const svg = d3.select('#radar-chart-container') .append('svg') .attr('width', width) .attr('height', height) .attr('class', 'radar-chart'); // Create a group element for the radar chart, centered in the SVG const g = svg.append('g') .attr('transform', `translate(${centerX}, ${centerY})`); // Angle scale - maps categories to angles const angleSlice = Math.PI * 2 / categories.length; // Value scale (radial) const valueScale = d3.scaleLinear() .domain([40, 100]) // Min and max values .range([0, radius]); // Create the circles for the radar grid const circles = [40, 60, 80, 100]; circles.forEach(value => { g.append('circle') .attr('r', valueScale(value)) .attr('class', 'radar-circle'); }); // Create the radial axes categories.forEach((category, i) => { const angle = i * angleSlice; const line = [ [0, 0], [radius * Math.sin(angle), -radius * Math.cos(angle)] ]; g.append('path') .datum(line) .attr('class', 'radar-axis') .attr('d', d3.line()); // Add the category labels g.append('text') .attr('class', 'radar-label') .attr('x', (radius + 25) * Math.sin(angle)) .attr('y', -(radius + 25) * Math.cos(angle)) .attr('text-anchor', (i === 0 || i === categories.length / 2) ? 'middle' : (i < categories.length / 2 ? 'start' : 'end')) .attr('dominant-baseline', 'middle') .text(category); }); // Add value labels to one axis circles.forEach(value => { g.append('text') .attr('class', 'radar-value') .attr('x', 0) .attr('y', -valueScale(value)) .attr('text-anchor', 'middle') .attr('dominant-baseline', 'middle') .text(value); }); // Create data points for each tool and category tools.forEach(tool => { const dataPoints = categories.map((category, i) => { const categoryData = toolData.find(d => d.category === category); const value = categoryData[tool.name]; const angle = i * angleSlice; return { x: valueScale(value) * Math.sin(angle), y: -valueScale(value) * Math.cos(angle), value: value, category: category }; }); // Close the path by duplicating the first point dataPoints.push(dataPoints[0]); // Create the path g.append('path') .datum(dataPoints) .attr('class', 'radar-area') .attr('d', d3.line() .x(d => d.x) .y(d => d.y)) .attr('stroke', tool.color) .attr('stroke-width', 3) .attr('fill', 'none') .attr('data-tool', tool.name); }); // Create the tooltip const tooltip = d3.select('#tooltip'); // Create radar data points for tooltip interactions tools.forEach(tool => { categories.forEach((category, i) => { const categoryData = toolData.find(d => d.category === category); const value = categoryData[tool.name]; const angle = i * angleSlice; const x = valueScale(value) * Math.sin(angle); const y = -valueScale(value) * Math.cos(angle); g.append('circle') .attr('cx', x) .attr('cy', y) .attr('r', 5) .attr('fill', 'transparent') .attr('stroke', 'transparent') .attr('data-tool', tool.name) .attr('data-category', category) .attr('data-value', value) .on('mouseover', function(event) { const tool = d3.select(this).attr('data-tool'); const category = d3.select(this).attr('data-category'); const value = d3.select(this).attr('data-value'); tooltip.html(` <div class="tooltip-title">${category}</div> <div class="tooltip-value" style="color: ${tools.find(t => t.name === tool).color}">${tool}: ${value}</div> `); tooltip .style('left', `${event.pageX + 10}px`) .style('top', `${event.pageY + 10}px`) .style('opacity', 1); }) .on('mouseout', function() { tooltip.style('opacity', 0); }); }); }); } // Create legend and handle interactions function createLegend() { const legendContainer = document.getElementById('chart-legend'); // Create first row with first 3 tools const firstRow = document.createElement('div'); firstRow.className = 'legend-row'; legendContainer.appendChild(firstRow); tools.slice(0, 3).forEach(tool => { const legendItem = document.createElement('div'); legendItem.className = 'legend-item'; legendItem.setAttribute('data-tool', tool.name); let iconElement; if (tool.favicon && tool.favicon.trim() !== '') { // Use favicon if available iconElement = document.createElement('img'); iconElement.src = tool.favicon; iconElement.alt = `${tool.name} icon`; iconElement.className = 'legend-icon'; iconElement.style.width = '20px'; iconElement.style.height = '20px'; } else { // Use colored circle as fallback iconElement = document.createElement('div'); iconElement.className = 'legend-icon'; iconElement.style.backgroundColor = tool.color; } const textElement = document.createElement('span'); textElement.className = 'legend-text'; textElement.style.color = tool.color; textElement.textContent = tool.name; legendItem.appendChild(iconElement); legendItem.appendChild(textElement); firstRow.appendChild(legendItem); // Add click handler legendItem.addEventListener('click', () => { handleToolClick(tool.name); }); }); // Create second row with remaining tools const secondRow = document.createElement('div'); secondRow.className = 'legend-row'; legendContainer.appendChild(secondRow); tools.slice(3).forEach(tool => { const legendItem = document.createElement('div'); legendItem.className = 'legend-item'; legendItem.setAttribute('data-tool', tool.name); let iconElement; if (tool.favicon && tool.favicon.trim() !== '') { // Use favicon if available iconElement = document.createElement('img'); iconElement.src = tool.favicon; iconElement.alt = `${tool.name} icon`; iconElement.className = 'legend-icon'; iconElement.style.width = '20px'; iconElement.style.height = '20px'; } else { // Use colored circle as fallback iconElement = document.createElement('div'); iconElement.className = 'legend-icon'; iconElement.style.backgroundColor = tool.color; } const textElement = document.createElement('span'); textElement.className = 'legend-text'; textElement.style.color = tool.color; textElement.textContent = tool.name; legendItem.appendChild(iconElement); legendItem.appendChild(textElement); secondRow.appendChild(legendItem); // Add click handler legendItem.addEventListener('click', () => { handleToolClick(tool.name); }); }); } // Handle tool highlight/unhighlight function handleToolClick(toolName) { if (highlightedTool === toolName) { // If already highlighted, unhighlight highlightedTool = null; updateHighlighting(); } else { // Highlight the selected tool highlightedTool = toolName; updateHighlighting(); } } // Update the highlighting based on the selected tool function updateHighlighting() { // Update radar areas const radarAreas = document.querySelectorAll('.radar-area'); radarAreas.forEach(area => { const tool = area.getAttribute('data-tool'); if (highlightedTool === null) { // Reset all to normal area.classList.remove('highlighted', 'faded'); area.style.strokeWidth = '3px'; area.style.opacity = '1'; } else if (tool === highlightedTool) { // Highlight the selected tool area.classList.add('highlighted'); area.classList.remove('faded'); area.style.strokeWidth = '6px'; area.style.opacity = '1'; } else { // Fade other tools area.classList.remove('highlighted'); area.classList.add('faded'); area.style.strokeWidth = '2px'; area.style.opacity = '0.25'; } }); // Update legend items const legendItems = document.querySelectorAll('.legend-item'); legendItems.forEach(item => { const tool = item.getAttribute('data-tool'); const textElement = item.querySelector('.legend-text'); const iconElement = item.querySelector('.legend-icon'); if (highlightedTool === null) { // Reset all to normal item.style.opacity = '1'; textElement.style.fontWeight = 'normal'; iconElement.style.border = 'none'; iconElement.style.boxShadow = 'none'; } else if (tool === highlightedTool) { // Highlight the selected tool item.style.opacity = '1'; textElement.style.fontWeight = 'bold'; iconElement.style.border = `2px solid ${tools.find(t => t.name === tool).color}`; iconElement.style.boxShadow = '0 0 0 2px rgba(0,0,0,0.1)'; } else { // Fade other tools item.style.opacity = '0.5'; textElement.style.fontWeight = 'normal'; iconElement.style.border = 'none'; iconElement.style.boxShadow = 'none'; } }); } // Initialize the chart and legend document.addEventListener('DOMContentLoaded', function() { createRadarChart(); createLegend(); }); </script
Client
Framer Template
Service Provided
Web Design, Web Development



The Goal:
The primary goal of AtomAI is to provide businesses with an intuitive and cutting-edge SaaS template, seamlessly blending advanced features with sleek design. Designed for AI-related startups and enterprises, AtomAI empowers users to create world-class websites with ease.
1


The Challenge:
AtomAI is built to help businesses launch powerful, AI-driven websites effortlessly. This modern SaaS template combines innovation with sleek design, offering advanced features tailored for AI startups and enterprises. With AtomAI, creating a world-class online presence has never been easier.
2


The Result
In conclusion, AtomAI stands as the ultimate solution for AI-focused businesses and startups seeking a modern, professional, and feature-rich SaaS template. With its intuitive design, seamless functionality, and flexibility, AtomAI empowers users to craft stunning, high-performance websites that captivate audiences and drive growth.
3

