feat(website): Create customer testimonials section, add scrollbar styling (#6252)

Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
This commit is contained in:
Patti
2024-08-14 22:29:18 -07:00
committed by GitHub
parent 272e4b2bcd
commit b2b663aba4
8 changed files with 202 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -27,4 +27,49 @@
*:is(code) {
@apply overflow-x-auto rounded text-sm;
}
/* For WebKit browsers (Chrome, Safari) */
.dark-scroll::-webkit-scrollbar {
width: 12px; /* Adjust the width of the scrollbar */
}
.dark-scroll::-webkit-scrollbar-button {
height: 0;
width: 0;
display: none;
}
.dark-scroll::-webkit-scrollbar-thumb {
background-color: #666; /* White color at 20% opacity */
border-radius: 10px; /* Optional: Rounds the corners of the scrollbar thumb */
}
.dark-scroll::-webkit-scrollbar-track {
background-color: #222; /* White color at 40% opacity */
border-radius: 10px; /* Optional: Rounds the corners of the scrollbar track */
}
/* For Firefox */
* .dark-scroll {
scrollbar-width: thin;
scrollbar-color: #666 #222;
}
.dark-scroll::-ms-scrollbar {
width: 12px; /* Adjust the width of the scrollbar */
}
.dark-scroll::-ms-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.2); /* White color at 20% opacity */
border-radius: 10px; /* Optional: Rounds the corners of the scrollbar thumb */
}
.dark-scroll::-ms-scrollbar-track {
background-color: rgba(255, 255, 255, 0.4); /* White color at 40% opacity */
border-radius: 10px; /* Optional: Rounds the corners of the scrollbar track */
}
.dark-scroll::-ms-scrollbar-button {
display: none;
}
}

View File

@@ -35,6 +35,7 @@ import ComplianceDiagram from "@/components/Animations/ComplianceDiagram";
import SimpleArchitecture from "@/components/Animations/SimpleArchitecture";
import { manrope } from "@/lib/fonts";
import "@/styles/hero.css";
import CustomerTestimonials from "@/components/CustomerTestimonials";
import FeatureCards from "@/components/FeatureCards";
import SingleFeature from "@/components/SingleFeature";
@@ -116,6 +117,8 @@ export default function Page() {
</div>
</section>
<CustomerTestimonials />
{/* Feature section 2: Achieve compliance in minutes, not weeks. */}
<section className="bg-white py-20 md:py-16">
<div className="sm:mx-auto px-4 mb-4 md:mb-8 text-3xl md:text-4xl lg:text-5xl text-pretty text-center">

View File

@@ -0,0 +1,45 @@
import type { CustomFlowbiteTheme } from "flowbite-react";
import { Carousel as FlowbiteCarousel } from "flowbite-react";
const theme: CustomFlowbiteTheme["carousel"] = {
root: {
base: "relative h-full w-full",
leftControl:
"absolute left-0 bottom-4 flex items-end justify-center px-4 focus:outline-none",
rightControl:
"absolute right-0 bottom-4 flex items-end justify-center px-4 focus:outline-none",
},
indicators: {
active: {
off: "bg-white/50 hover:bg-white dark:bg-gray-800/50 dark:hover:bg-gray-800",
on: "bg-white dark:bg-gray-800",
},
base: "h-3 w-3 rounded-full",
wrapper: "absolute bottom-7 left-1/2 flex -translate-x-1/2 space-x-3",
},
item: {
base: "absolute left-1/2 block w-full -translate-x-1/2",
wrapper: {
off: "w-full flex-shrink-0 transform cursor-default snap-center",
on: "w-full flex-shrink-0 transform cursor-grab snap-center",
},
},
control: {
base: "inline-flex h-8 w-8 items-center justify-center rounded-full bg-white/30 group-hover:bg-white/50 group-focus:outline-none group-focus:ring-4 group-focus:ring-white dark:bg-gray-800/30 dark:group-hover:bg-gray-800/60 dark:group-focus:ring-gray-800/70 sm:h-10 sm:w-10",
icon: "h-5 w-5 text-white dark:text-gray-800 sm:h-6 sm:w-6",
},
scrollContainer: {
base: "flex h-full snap-mandatory overflow-y-hidden overflow-x-scroll scroll-smooth rounded-lg",
snap: "snap-x",
},
};
export default function Carousel({ children }: { children: React.ReactNode }) {
return (
<div className="h-96 rounded-2xl text-neutral-50 bg-[#1B1B1D]">
<FlowbiteCarousel slideInterval={10000} pauseOnHover theme={theme}>
{children}
</FlowbiteCarousel>
</div>
);
}

View File

@@ -0,0 +1,109 @@
import Carousel from "@/components/Carousel";
import Image from "next/image";
import Link from "next/link";
import { HiArrowLeft, HiArrowRight } from "react-icons/hi2";
import { FaHeart } from "react-icons/fa";
import { manrope } from "@/lib/fonts";
const customerData = [
{
desc: `When producing live broadcasts for Fortune 500 companies security is of
the utmost importance. We therefore selected Firezone for its robust
WireGuard-based architecture. The flexible policy system and simple &
clean user experience make Firezone the best fitting product for us in
the market after trying several other solutions like Tailscale, OpenVPN,
and Nebula.`,
authorName: "Robert Buisman",
authorImage: "/images/portrait-robert-buisman.png",
authorTitle: "CEO, NOMOBO",
},
{
desc: `Firezone's easy-to-setup, sleek, and simple interface makes management
effortless. It perfectly met our zero-trust security needs without the
complexity found in other products we tested.`,
authorName: "Mark Sim",
authorImage: "/images/portrait-mark-sim.jpg",
authorTitle: "Technical Account Manager, Beakon",
},
{
desc: `After comparing Tailscale, we ultimately chose Firezone to secure access
to our data warehouses. Firezone's ease of configuration and robust
policy-based access system made it the clear choice for our needs.`,
authorName: "James Winegar",
authorImage: "/images/portrait-james-winegar.png",
authorTitle: "CEO, Corrdyn",
},
{
desc: `At Strong Compute, we have been using Firezone for over 3 years and it
is still the most stable and best VPN solution we tested for remote access.`,
authorName: "Cian Byrne",
authorImage: "/images/portrait-cian-byrne.jpg",
authorTitle: "Founding Engineer, Strong Compute",
},
];
interface TestimonialBoxProps {
desc: string;
authorImage: string;
authorName: string;
authorTitle: string;
}
const TestimonialBox = ({
desc,
authorImage,
authorName,
authorTitle,
}: TestimonialBoxProps) => {
return (
<div className="h-full px-8 md:px-16 py-8 md:py-12">
<div className="mb-4 md:mb-8">
<p className="text-md md:text-lg tracking-wide font-light mb-2 md:mb-6 break-keep italic">
"{desc}"
</p>
</div>
<div className="flex gap-4 items-center">
<Image
src={authorImage}
alt="author portrait"
width={128}
height={128}
className="w-10 h-10 sm:h-12 sm:h-12 md:h-16 md:w-16 rounded-full"
/>
<div>
<p className="text-md md:text-lg">{authorName}</p>
<p className="text-sm md:text-md font-light">{authorTitle}</p>
</div>
</div>
</div>
);
};
export default function CustomerTestimonials() {
return (
<section className="bg-neutral-950 py-24 px-8 md:px-0">
<div className="max-w-screen-md mx-auto">
<h3
className={`text-white text-3xl leading-5 md:text-4xl lg:text-5xl tracking-tight font-medium inline-block text-left mb-4 ${manrope.className}`}
>
Customers{" "}
<FaHeart className="text-red-500 w-12 h-12 mx-1 inline-block" /> us
</h3>
<p className="text-neutral-500 text-sm md:text-md font-light mb-8">
(and we love them back)
</p>
<Carousel>
{customerData.map((item, index) => (
<TestimonialBox
key={index}
authorTitle={item.authorTitle}
desc={item.desc}
authorImage={item.authorImage}
authorName={item.authorName}
/>
))}
</Carousel>
</div>
</section>
);
}