Skip to content

Commit

Permalink
✨ Competitor Hover Descriptions (#2224)
Browse files Browse the repository at this point in the history
* add-hover-descriptions

* content changes

* sizing fixes

* Update components/blocks/CompareBox.tsx

Co-authored-by: Isaac Lombard [SSW] <[email protected]>

* refresh lock

* lg screen tool tips

* sm and md views

* ui fixes w/ betty

* extendable to extensible

* add comment on functioj

---------

Co-authored-by: Isaac Lombard [SSW] <[email protected]>
  • Loading branch information
joshbermanssw and isaaclombardssw authored Oct 29, 2024
1 parent f684048 commit 4ea2c24
Show file tree
Hide file tree
Showing 4 changed files with 34,428 additions and 82 deletions.
1 change: 1 addition & 0 deletions components/blocks/CompareBox.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const compareBoxTemplate: Template = {
description:
'The text inside the description will NOT be displayed anywhere, this is just to elaborate on the criteria itself for our own users.',
},

],
},
{
Expand Down
167 changes: 94 additions & 73 deletions components/blocks/CompareBox.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import React, { useState, useEffect, useRef } from 'react'
import { FaCircle } from 'react-icons/fa'
import Slider from 'react-slick'
import 'slick-carousel/slick/slick.css'
import 'slick-carousel/slick/slick-theme.css'
import css from 'styled-jsx/css'
import Image from 'next/image'
import React, { useState, useEffect, useRef } from 'react';
import { FaCircle } from 'react-icons/fa';
import Slider from 'react-slick';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import css from 'styled-jsx/css';
import Image from 'next/image';
import { tinaField } from 'tinacms/dist/react';
import { IoMdInformationCircleOutline } from 'react-icons/io';


//Function to use alpha values to create a background gradient with any input hex colour
function hexToRgba(hex, alpha) {
let r = parseInt(hex.slice(1, 3), 16)
let g = parseInt(hex.slice(3, 5), 16)
let b = parseInt(hex.slice(5, 7), 16)
return `rgba(${r}, ${g}, ${b}, ${alpha})`
let r = parseInt(hex.slice(1, 3), 16);
let g = parseInt(hex.slice(3, 5), 16);
let b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

const commonHeightStyle = {
height: '50px',
marginBottom: '8px',
lineHeight: '16px',
}
};

const CompanyItem = ({ company, onClick }) => {
if (company.isHidden) {
return null
return null;
}

return (
Expand All @@ -48,27 +52,44 @@ const CompanyItem = ({ company, onClick }) => {
<div className="lg:text-xl md:text-sm text-xs">{company.headline}</div>
</span>
</div>
)
}
);
};

const CriteriaCard = ({ criteriaItems }) => {
const [hoveredItem, setHoveredItem] = useState(null);

return (
<div className="criteria-card rounded-lg">
{/* This empty div acts as a spacer to offset the start point of the criteria list. */}
<div className="criteria-card rounded-lg relative">
<div key={0} className="py-3 flex" style={commonHeightStyle} />
{criteriaItems.map((item, idx) => (
<div key={idx} className="py-3 flex" style={commonHeightStyle}>
<h3 className="sm:leading-[10px] md:font-semibold lg:font-semibold sm:font-normal lg:text-lg md:text-sm sm:text-xs">
{item.criteria}
<div key={idx} className="py-3 flex relative" style={commonHeightStyle}>
<h3
data-tina-field={tinaField(item, 'criteria')}
className="sm:leading-[10px] md:font-semibold lg:font-semibold sm:font-normal lg:text-lg md:text-sm sm:text-xs flex items-center"
>
<span>{item.criteria}</span>
</h3>
<div className="relative content-center ml-auto lg:ml-0">
<IoMdInformationCircleOutline
className="ml-1 text-orange-500 text-xl"
onMouseEnter={() => setHoveredItem(idx)}
onMouseLeave={() => setHoveredItem(null)}
/>
{hoveredItem === idx && (
<div className="ml-0.5 shadow-[0px_0px_25px_10px_rgba(0,0,0,0.1)] absolute left-1/2 transform -translate-x-1/2 mt-2 bg-white text-sm p-2 rounded-lg z-10 xl:w-[300px] w-[150px] break-words text-center">
<div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full w-0 h-0 border-l-8 border-l-transparent border-r-8 border-r-transparent border-b-8 border-b-white"></div>
{item.description}
</div>
)}
</div>
</div>
))}
</div>
)
}
);
};

const CompanyCard = ({ company }) => {
const baseColor = company.backgroundColor || '#000000'
const baseColor = company.backgroundColor || '#000000';
return (
<div className="rounded-lg flex flex-col items-center w-full company-card">
<div
Expand Down Expand Up @@ -123,19 +144,19 @@ const CompanyCard = ({ company }) => {
))}
</div>
</div>
)
}
);
};

interface CompareBoxBlockProps {
data: any
index: number
data: any;
index: number;
}

export function CompareBoxBlock({ data, index }: CompareBoxBlockProps) {
const [companies, setCompanies] = useState([])
const [userInteracted, setUserInteracted] = useState(false)
const [maxActive, setMaxActive] = useState(4)
const sliderRef = useRef(null)
const [companies, setCompanies] = useState([]);
const [userInteracted, setUserInteracted] = useState(false);
const [maxActive, setMaxActive] = useState(4);
const sliderRef = useRef(null);

useEffect(() => {
if (data && data.companies) {
Expand All @@ -144,83 +165,83 @@ export function CompareBoxBlock({ data, index }: CompareBoxBlockProps) {
...company,
isHidden: company.headline === 'TinaCMS',
active: idx === 0 ? true : company.active,
}
};
data.criteriaItems.forEach((criteria, idx) => {
updatedCompany[`criteria${idx + 1}`] =
updatedCompany[`criteria${idx + 1}`] || false
})
return updatedCompany
})
setCompanies(updatedCompanies)
updatedCompany[`criteria${idx + 1}`] || false;
});
return updatedCompany;
});
setCompanies(updatedCompanies);
}
}, [data])
}, [data]);

useEffect(() => {
if (userInteracted) return
if (userInteracted) return;

let currentIndex = 1
let currentIndex = 1;
const interval = setInterval(() => {
setCompanies((prevCompanies) => {
const newCompanies = prevCompanies.map((company, idx) => ({
...company,
active: idx === 0 ? true : idx === currentIndex,
}))
}));
if (sliderRef.current) {
sliderRef.current.slickGoTo(currentIndex - 1)
sliderRef.current.slickGoTo(currentIndex - 1);
}
currentIndex = (currentIndex + 1) % prevCompanies.length
if (currentIndex === 0) currentIndex = 1
return newCompanies
})
}, 3000)
currentIndex = (currentIndex + 1) % prevCompanies.length;
if (currentIndex === 0) currentIndex = 1;
return newCompanies;
});
}, 3000);

return () => clearInterval(interval)
}, [userInteracted])
return () => clearInterval(interval);
}, [userInteracted]);

useEffect(() => {
const updateMaxActive = () => {
const width = window.innerWidth
const width = window.innerWidth;
if (width < 600) {
setMaxActive(2)
setMaxActive(2);
} else if (width < 1024) {
setMaxActive(3)
setMaxActive(3);
} else {
setMaxActive(4)
setMaxActive(4);
}
}
};

updateMaxActive()
window.addEventListener('resize', updateMaxActive)
updateMaxActive();
window.addEventListener('resize', updateMaxActive);

return () => window.removeEventListener('resize', updateMaxActive)
}, [])
return () => window.removeEventListener('resize', updateMaxActive);
}, []);

const toggleActive = (companyIdx) => {
setUserInteracted(true)
setUserInteracted(true);

setCompanies((prevCompanies) => {
const activeCompanies = prevCompanies.filter((company) => company.active)
const activeCompaniesCount = activeCompanies.length
const company = prevCompanies[companyIdx]
const activeCompanies = prevCompanies.filter((company) => company.active);
const activeCompaniesCount = activeCompanies.length;
const company = prevCompanies[companyIdx];

if (company.isHidden) {
return prevCompanies
return prevCompanies;
}

if (!company.active && activeCompaniesCount >= maxActive) {
const firstActiveIdx = prevCompanies.findIndex(
(comp) => comp.active && !comp.isHidden && comp.headline !== 'TinaCMS'
)
);
if (firstActiveIdx !== -1) {
prevCompanies[firstActiveIdx].active = false
prevCompanies[firstActiveIdx].active = false;
}
}

return prevCompanies.map((company, idx) =>
idx === companyIdx ? { ...company, active: !company.active } : company
)
})
}
);
});
};

const settings = {
dots: false,
Expand Down Expand Up @@ -267,7 +288,7 @@ export function CompareBoxBlock({ data, index }: CompareBoxBlockProps) {
},
},
],
}
};

return (
<div className="md:px-10 lg:px-10 rounded-lg">
Expand Down Expand Up @@ -338,12 +359,12 @@ export function CompareBoxBlock({ data, index }: CompareBoxBlockProps) {
`}</style>
</div>
</div>
)
);
}

const styles = css`
.criteria-card {
width: 300px; /* Increase width as needed */
width: 300px;
}
.company-card {
Expand All @@ -358,6 +379,6 @@ const styles = css`
transform: translateY(0);
}
}
`
`;

export default CompareBoxBlock
export default CompareBoxBlock;
26 changes: 17 additions & 9 deletions content/blocksPages/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -244,32 +244,40 @@
{
"criteriaItems": [
{
"criteria": "Open Source Front-end"
"criteria": "Open Source Front-end",
"description": "A CMS which is transparent, extensible and community driven"
},
{
"criteria": "Content API"
"criteria": "Content API",
"description": "Query your data, wherever, whenever"
},
{
"criteria": "Git-based Content Management "
"criteria": "Git-based Content Management ",
"description": "Get all the benefits of the GitHub editing workflow directly from your site - Pull requests, branching, version control"
},
{
"criteria": "GitHub Contributions"
"criteria": "GitHub Contributions",
"description": "Editors get GitHub contributions when they make changes"
},
{
"criteria": "Markdown Support",
"description": ""
"description": "Store your content in a simple and lightweight format with Markdown"
},
{
"criteria": "Visual Editing Capabilities "
"criteria": "Visual Editing Capabilities ",
"description": "See your changes on your site as you make them"
},
{
"criteria": "Local Development Workflow "
"criteria": "Local Development Workflow ",
"description": "Develop your site locally within your favourite IDE"
},
{
"criteria": "Free Option"
"criteria": "Free Option",
"description": "An option to use the CMS for free, forever"
},
{
"criteria": "Self-hosted Option"
"criteria": "Self-hosted Option",
"description": "Option to self-host"
}
],
"companies": [
Expand Down
Loading

0 comments on commit 4ea2c24

Please sign in to comment.