diff --git a/.eslintrc.js b/.eslintrc.js index 7c7037ca..668c47a2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,10 +10,12 @@ module.exports = { tsconfigRootDir: __dirname, }, extends: ['@pluralsh/eslint-config-typescript', 'prettier'], + plugins: ['prettier'], globals: { JSX: true, }, rules: { + 'prettier/prettier': 'error', '@typescript-eslint/consistent-type-exports': 'error', '@typescript-eslint/consistent-type-imports': [ 'error', diff --git a/package.json b/package.json index 3f02269c..8074e467 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@markdoc/markdoc": "0.4.0", "@markdoc/next.js": "0.2.2", "@open-draft/until": "2.1.0", - "@pluralsh/design-system": "3.23.0", + "@pluralsh/design-system": "3.48.0", "@react-types/shared": "3.22.0", "@tanstack/react-table": "8.10.7", "@tanstack/react-virtual": "3.0.1", @@ -111,6 +111,7 @@ "eslint-plugin-import": "2.29.1", "eslint-plugin-import-newlines": "1.3.4", "eslint-plugin-jsx-a11y": "6.8.0", + "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", "husky": "8.0.3", diff --git a/pages/about.tsx b/pages/about.tsx index 8368db7d..6d2ad5d0 100644 --- a/pages/about.tsx +++ b/pages/about.tsx @@ -10,7 +10,7 @@ import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' import { TextLimiter } from '@src/components/layout/TextLimiter' import { TeamSection } from '@src/components/page-sections/TeamSection' import { CenteredSectionHead } from '@src/components/SectionHeads' -import { Cta } from '@src/components/Typography' +import { ResponsiveText } from '@src/components/Typography' import { getTeamMembers } from '@src/data/getTeamMembers' import { type TeamMemberFragment } from '@src/generated/graphqlDirectus' import { cn as classNames } from '@src/utils/cn' @@ -49,27 +49,11 @@ export default function About({ - -

- We are building a flexible, scalable solution to application - delivery. -

-
-
- - -

- At Plural, we believe that there is a better way to solve - the third major constraint—distributed systems operational - cost—that benefits OSS developers and DevOps teams alike. -

- - Read more - -
+

+ Our mission is to democratize elite DevOps capabilities by + simplifing tooling complexities, fostering a ZeroOps world + that accelerates software development. +

@@ -108,29 +92,36 @@ export default function About({ 'bg-fill-zero', 'flex flex-col', 'gap-y-xxxxlarge py-xxxxlarge', - 'md:gap-y-xxxxxlarge md:py-xxxxxlarge', - 'xxl:gap-y-xxxxxxlarge xxl:py-xxxxxxlarge', + 'md:gap-y-large md:py-xxxxxlarge', + 'xxl:py-xxxxxxlarge', 'text-text' )} > - - We are a dynamic and innovative company that specializes in - creating meaningful connections and fostering collaboration. - At Plural, we believe in the power of diversity and inclusion, - recognizing that when different perspectives come together, - incredible things happen. -

- } - className="mb-xxxxlarge text-center" - /> + + Who we are + + + We are a dynamic and innovative company that specializes in + creating meaningful connections and fostering collaboration. At + Plural, we believe in the power of diversity and inclusion, + recognizing that when different perspectives come together, + incredible things happen. + + The Plural team standing together on a sidewalk in the French Quarter of New Orleans.
@@ -138,7 +129,6 @@ export default function About({ preHeading="Our company values" heading="As a driven and cohesive team, we share a common mission to build something unique." - intro={

How we stay connected as a team

} className="mb-xxxxlarge text-center" /> - -

- At Plural, kindness and respect are fundamental to our - culture. We foster a supportive and inclusive environment - where everyone is treated with empathy, dignity, and - respect. We believe in the power of positive interactions - and aim to uplift and encourage one another, both within - our team and the wider community. -

-

We are dedicated to building an inclusive platform that @@ -187,6 +167,16 @@ mission to build something unique." succeed.

+ +

+ We have a passion for excellence and continuously strive + to deliver the highest quality in everything we do. We are + committed to providing outstanding products, services, and + experiences to our community. We encourage innovation, + embrace challenges, and consistently seek ways to improve + and exceed expectations. +

+
@@ -197,6 +187,16 @@ mission to build something unique." 'columns:gap-y-xxlarge' )} > + +

+ At Plural, kindness and respect are fundamental to our + culture. We foster a supportive and inclusive environment + where everyone is treated with empathy, dignity, and + respect. We believe in the power of positive interactions + and aim to uplift and encourage one another, both within + our team and the wider community. +

+

We have a passion for excellence and continuously strive @@ -207,24 +207,15 @@ mission to build something unique." and exceed expectations.

- -

- We believe in the power of open-mindedness and embracing - new possibilities. We encourage curiosity, creativity, and - a willingness to explore uncharted territories. We foster - an environment that embraces diverse ideas, encourages - constructive feedback, and values continuous learning. We - are open to new perspectives and always ready to embark on - exciting adventures. -

-

- By embracing these values, we aim to build a vibrant and - thriving community where developers can collaborate, - learn, and grow together. We are committed to making a - positive impact and empowering individuals to achieve - their goals. -

-
+ + By embracing these values, we aim to build a vibrant and + thriving community where developers can collaborate, learn, + and grow together. We are committed to making a positive + impact and empowering individuals to achieve their goals. +
diff --git a/pages/contact-sales.tsx b/pages/contact-sales.tsx index 95f85ea2..57d22137 100644 --- a/pages/contact-sales.tsx +++ b/pages/contact-sales.tsx @@ -1,4 +1,3 @@ -import { ColorModeProvider } from '@pluralsh/design-system' import Head from 'next/head' import Script from 'next/script' @@ -7,9 +6,6 @@ import { GradientBG } from '@src/components/layout/GradientBG' import { HeaderPad } from '@src/components/layout/HeaderPad' import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' -import { HubspotForm } from '../src/components/HubspotForm' -import { StandardPageWidth } from '../src/components/layout/LayoutHelpers' - import { ContactHeader } from './contact' export default function Index() { @@ -25,20 +21,13 @@ export default function Index() { as={GradientBG} size="cover" position="top middle" - image="/images/gradients/gradient-bg-4.jpg" + image="/images/gradients/gradient-bg-12.png" > - -
- - - -
-
) } diff --git a/pages/contact.tsx b/pages/contact.tsx index 885a8b3c..e06b8805 100644 --- a/pages/contact.tsx +++ b/pages/contact.tsx @@ -1,5 +1,6 @@ -import { ColorModeProvider } from '@pluralsh/design-system' +import { Button } from '@pluralsh/design-system' import Head from 'next/head' +import Link from 'next/link' import Script from 'next/script' import { clsx } from 'clsx' @@ -33,7 +34,7 @@ export function ContactHeader({ )} > - + {title} - - - - {subtitle} + + Want to learn more about pricing? + + + + +
@@ -78,21 +96,13 @@ export default function Index() { as={GradientBG} size="cover" position="top middle" - image="/images/gradients/gradient-bg-4.jpg" + image="/images/gradients/gradient-bg-12.png" > - -
- - - -
-
) } diff --git a/pages/index.tsx b/pages/index.tsx index 5d220eba..c4a6ee3e 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,47 +1,24 @@ -import { - type ComponentProps, - type ReactElement, - type ReactNode, - cloneElement, - useRef, -} from 'react' +import { type ComponentProps, useRef, useState } from 'react' -import { - Button, - CloudIcon, - ClusterIcon, - ColorModeProvider, - GitMergeIcon, - LogsIcon, - PadlockLockedIcon, -} from '@pluralsh/design-system' +import { Button, CloseIcon } from '@pluralsh/design-system' import { type InferGetStaticPropsType } from 'next' import Link from 'next/link' import { until } from '@open-draft/until' -import { - type Variants, - motion, - useInView, - useScroll, - useTransform, -} from 'framer-motion' -import styled, { useTheme } from 'styled-components' +import { type Variants, motion } from 'framer-motion' +import styled from 'styled-components' // @ts-expect-error import useMobileDetect from 'use-mobile-detect-hook' import { directusClient } from '@src/apollo-client' -import { mqs } from '@src/breakpoints' -import { ArticleCardNoBorder } from '@src/components/ArticleCard' -import { CompanyLogosSection } from '@src/components/CompanyLogos' +import { BareModal } from '@src/components/BareModal' import { FooterVariant } from '@src/components/FooterFull' import { GradientBG } from '@src/components/layout/GradientBG' import { HeaderPad } from '@src/components/layout/HeaderPad' -import { LearnAboutPluralSection } from '@src/components/LearnAboutPluralSection' +import ArticleSection from '@src/components/page-sections/articleSection' +import { QuoteSection } from '@src/components/page-sections/QuoteSection' import { HomePageHero } from '@src/components/PageHeros' -import { TestimonialsSection } from '@src/components/QuoteCards' import { CenteredSectionHead } from '@src/components/SectionHeads' -import { ShadowedCard } from '@src/components/ShadowedCard' import { getTinyRepos } from '@src/data/getRepos' import { getStacks } from '@src/data/getStacks' import { getStackTabData } from '@src/data/getStackTabData' @@ -54,29 +31,18 @@ import { cn as classNames } from '@src/utils/cn' import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' import { normalizeQuotes } from '@src/utils/normalizeQuotes' -import { - StandardPageSection, - StandardPageWidth, -} from '../src/components/layout/LayoutHelpers' +import { StandardPageWidth } from '../src/components/layout/LayoutHelpers' import { HomepageFeaturesSection } from '../src/components/page-sections/HomepageFeaturesSection' import { combineErrors } from '../src/utils/combineErrors' const HeroImagesSC = styled.div(({ theme: _theme }) => { - const baseWidth = 1432 - const baseHeight = 683 + const baseWidth = 1147 return { - transformStyle: 'preserve-3d', - perspective: '1200px', transformOrigin: 'center', - transform: 'rotateY(-00deg) rotateX(0deg) rotateZ(0deg)', - position: 'relative', width: '100%', aspectRatio: '2 / 1', - '& *': { - transformStyle: 'preserve-3d', - }, '.heroImg': { position: 'absolute', pointerEvents: 'none', @@ -87,74 +53,44 @@ const HeroImagesSC = styled.div(({ theme: _theme }) => { }, }, '.heroImg1': { - width: `${(512 * 100) / baseWidth}%`, - left: `${(960 * 100) / baseWidth}%`, - top: `${(160 * 100) / baseHeight}%`, - '.endTransform': { - transform: [ - 'rotateY(-10deg)', - // 'rotateX(0deg)', - // 'rotateZ(0deg)', - 'translateZ(00px)', - 'translateX(-2%)', - 'translateY(-10px)', - 'scale(1.07)', - ].join(' '), + width: `80%`, + maxWidth: baseWidth, + left: `50%`, + top: `0`, + transform: 'translateX(-50%)', + '&::after': { + content: `''`, + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + boxShadow: 'inset 0px -200px 600px rgba(0,0,0,0.3)', + pointerEvents: 'none', }, }, '.heroImg2': { - width: `${(1200 * 100) / baseWidth}%`, - left: `${(-20 * 100) / baseWidth}%`, - top: `${(-10 * 100) / baseHeight}%`, - '.endTransform': { - transform: [ - 'rotateY(10deg)', - // 'rotateX(0deg)', - // 'rotateZ(0deg)', - 'translateZ(-100px)', - 'translateX(2%)', - 'scale(0.98)', - ].join(' '), - }, + width: `30%`, + left: `5%`, + top: `16%`, + maxWidth: 413, }, '.heroImg3': { - width: `${(840 * 100) / baseWidth}%`, - left: `${(563 * 100) / baseWidth}%`, - top: `${(300 * 100) / baseHeight}%`, - '.endTransform': { - transform: [ - 'rotateY(-5deg)', - // 'rotateX(0deg)', - // 'rotateZ(0deg)', - 'translateZ(100px)', - 'translateX(-4%)', - 'translateY(-2%)', - 'scale(0.90)', - ].join(' '), - }, + width: `32%`, + right: `8%`, + top: `-7%`, + maxWidth: 468, + overflow: 'hidden', + borderRadius: _theme.borderRadiuses.large, }, } }) -const MotionDiv = styled(motion.div)(({ theme: _ }) => ({ - // position: 'absolute', - // top: 0, - // right: 0, - // bottom: 0, - // left: 0, - // transformOrigin: '100% 50% -300px', - // // transformStyle: 'flat', - // perspective: PERSPECTIVE, - opacity: 0, -})) - const heroVariants = ({ delay = 0 }: { delay: number }): Variants => { const start = { - translateZ: 350, opacity: 0, } const end = { - translateZ: 0, opacity: 1, } @@ -181,35 +117,18 @@ const heroVariants = ({ delay = 0 }: { delay: number }): Variants => { } } -function HeroIn({ - children, - inView, - className, - delay, - scrollYProgress, - parallax, -}) { +function HeroIn({ children, className, delay }) { const variants = heroVariants({ delay }) - const translateY = useTransform( - scrollYProgress, - [0, 1], - [`${20 * parallax}%`, `${-20 * parallax}%`] - ) const isMobile = useMobileDetect().isMobile() return ( -
- - {children} - -
+ {children}
) } @@ -217,14 +136,8 @@ function HeroIn({ function HeroImages({ ...props }: ComponentProps) { const ref = useRef(null) - const inView = useInView(ref, { once: true, margin: '-80px 0px -40%' }) const stagger = 0.25 - const { scrollYProgress } = useScroll({ - target: ref, - offset: ['start end', 'end start'], - }) - return ( ) { > - + - + - + ) } -const BuildSecurelyCardSC = styled(ShadowedCard)(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - gap: '', - textAlign: 'center', - ...theme.partials.text.body2Bold, - color: theme.colors['text-light'], - '& > *': { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - minHeight: 120, - paddingLeft: theme.spacing.medium, - paddingRight: theme.spacing.medium, - maxWidth: 240, - marginLeft: 'auto', - marginRight: 'auto', - '&:first-child': { - paddingTop: theme.spacing.xlarge, - }, - '&:last-child': { - paddingBottom: theme.spacing.xlarge, - }, - }, -})) - -function BuildSecurelyCard({ - icon, - heading, - ...props -}: { - icon: ReactElement - heading: ReactNode -} & ComponentProps) { - const theme = useTheme() - const iconClone = cloneElement(icon, { - size: 48, - color: theme.colors['icon-primary'], - }) - - return ( - -
{iconClone}
-
{heading}
-
- ) -} - -const BuildSecurelyGridSC = styled.div(({ theme }) => ({ - display: 'grid', - gap: theme.spacing.medium, - gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', - textWrap: 'balance', - [mqs.xs]: { - gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', - '& > *': { - '&:nth-child(n + 5)': { - gridColumn: 'span 2', - }, - }, - }, - [mqs.md]: { - gridTemplateColumns: 'repeat(6, minmax(0, 1fr))', - '& > *': { - '&, &:nth-child(n)': { - gridColumn: 'span 2', - }, - '&:nth-child(n+4)': { - gridColumn: 'span 3', - }, - }, - }, - [mqs.lg]: { - gridTemplateColumns: 'repeat(5, minmax(0, 1fr))', - '& > *': { - '&, &:nth-child(n)': { - gridColumn: 'span 1', - }, - }, - }, -})) - -function BuildSecurely() { - return ( -
- - Secure and scalable pull-based architecture. A single pane of glass - to understand and maintain complex Kubernetes fleets. -
- } - /> - - } - heading="Self-hosted and secure in your cloud" - /> - } - heading="Multi-cloud and multi-cluster support" - /> - } - heading="Build release pipelines with no scripts" - /> - } - heading="Fully customizable with resources defined in Git" - /> - } - heading="Full visibility into your service and cluster fleet" - /> - - - ) -} - -const CARD_LAYOUTS = [ - [{ size: 'medium', reverse: false }], - [ - { size: 'medium', reverse: false }, - { size: 'medium', reverse: false }, - ], - [ - { size: 'medium', reverse: false }, - { size: 'medium', reverse: false }, - { size: 'medium', reverse: false }, - ], - [ - { size: 'medium', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - ], - [ - { size: 'medium', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'medium', reverse: true }, - ], - [ - { size: 'medium', reverse: false }, - { size: 'medium', reverse: true }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'medium', reverse: false }, - ], - [ - { size: 'medium', reverse: false }, - { size: 'medium', reverse: true }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'medium', reverse: false }, - { size: 'medium', reverse: true }, - ], - [ - { size: 'medium', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'small', reverse: false }, - { size: 'medium', reverse: true }, - ], -] as const - export default function Index({ - quotes, - // featuredQuote, - // buildStackTabs, articleCards, - globalProps, }: InferGetStaticPropsType) { + const [showVideo, setShowVideo] = useState(false) + return ( <> Self-hosted Kubernetes fleet management} + heading={<>Managing Kubernetes can be a cluster—} description={
- Manage and orchestrate your Kubernetes clusters from a single, - intuitive interface. Accelerate your DevOps pipeline with - automated deployment workflows, and enforce compliance - requirements with cluster-wide, granular security policies. + Plural reduces cluster upgrade cycles from months to hours at + enterprise scale with streamlined dependency management.
} ctas={ @@ -472,82 +208,111 @@ export default function Index({ } /> -
+
+ + setShowVideo(false)} + closeButton={false} + className="mx-auto flex w-[90%] items-center justify-center" + style={{ height: 'fit-content', overflow: 'visible' }} + > +
+ +