diff --git a/landing/competitor-comparison.css b/landing/competitor-comparison.css index 8ef63569c..b9de33787 100644 --- a/landing/competitor-comparison.css +++ b/landing/competitor-comparison.css @@ -1,55 +1,76 @@ .competitorComparisonSection { display: flex; flex-direction: column; align-items: center; padding: 48px 16px; } .headerText { color: var(--white-80); text-align: center; margin-bottom: 72px; } .competitorsContainer { overflow: hidden; display: flex; justify-content: space-between; column-gap: 16px; padding: 16px 32px; background-color: var(--comparison-cards); border-radius: 16px; width: 560px; max-width: 90vw; } .logoContainer { display: flex; flex-direction: column; align-items: center; position: relative; } .competitorLogo { opacity: 0.35; } .competitorLogo:hover { opacity: 1; cursor: pointer; } .activeCompetitorLogo { opacity: 1; transform: translateY(-2px); } .bump { width: 80%; height: 4px; border-top-left-radius: 16px; border-top-right-radius: 16px; background-color: var(--violet-dark-100); position: absolute; bottom: -16px; } + +.featureCardsContainer { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 40px; + margin-top: 48px; +} + +/* 2*16(padding) + 3*432(cards) + 2*40(gap) */ +@media screen and (max-width: 1408px) { + .featureCardsContainer { + grid-template-columns: repeat(2, 1fr); + } +} + +/* 2*16(padding) + 2*432(cards) + 40(gap) */ +@media screen and (max-width: 936px) { + .featureCardsContainer { + grid-template-columns: repeat(1, 1fr); + } +} diff --git a/landing/competitor-comparison.react.js b/landing/competitor-comparison.react.js index f6ad36e83..0e982dcfe 100644 --- a/landing/competitor-comparison.react.js +++ b/landing/competitor-comparison.react.js @@ -1,59 +1,94 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; +import { useModalContext } from 'lib/components/modal-provider.react.js'; + import css from './competitor-comparison.css'; +import { + competitorData, + type Competitor, + type FeatureComparison, +} from './competitor-data.js'; +import CompetitorFeatureCard from './competitor-feature-card.react.js'; import CompetitorLogo from './competitor-logo.react.js'; +import FeatureModal from './feature-modal.react.js'; import typography from './typography.css'; const competitors = [ 'signal', 'keybase', 'telegram', 'discord', 'slack', 'matrix', ]; function CompetitorComparison(): React.Node { + const { pushModal } = useModalContext(); + const [selectedCompetitorID, setSelectedCompetitorID] = React.useState('signal'); + const onFeatureCardClick = React.useCallback( + (competitor: Competitor, feature: FeatureComparison) => { + pushModal(); + }, + [pushModal], + ); + const competitorSelector = React.useMemo( () => competitors.map(competitor => { const competitorLogoClassName = classNames({ [css.competitorLogo]: true, [css.activeCompetitorLogo]: selectedCompetitorID === competitor, }); const bumpClassName = classNames({ [css.bump]: selectedCompetitorID === competitor, }); return (
setSelectedCompetitorID(competitor)} >
); }), [selectedCompetitorID], ); + const featureCards = React.useMemo(() => { + const selectedCompetitor = competitorData[selectedCompetitorID]; + + return selectedCompetitor.featureComparison.map(feature => ( + onFeatureCardClick(selectedCompetitor, feature)} + /> + )); + }, [onFeatureCardClick, selectedCompetitorID]); + const headerClassName = classNames([typography.heading1, css.headerText]); return (

See how Comm is different

{competitorSelector}
+
{featureCards}
); } export default CompetitorComparison;