[Assembly] Consul on Kubernetes Page (#11047)
* Start new page * reset * Consul on Kubernetes - Features List Section (#11078) * Fix conflicts * Start adding and placing content * Add a lot of styling and background image * Looking like design. Before adding more global styles * Work on editing styles * Move imports and switch to flex * Add more styles and bottom left background image * Fix conflicts * Fix styles on mobile * Change images path in public * Updates from code review - Move data and update styles * Convert to tsx and add types * Change button props to get desired styling without using css * Remove margin on mobile * Consul On Kubernetes - Hero (#11089) * Start hero section * Increase max sizes for container * Minor Edits * Use g-grid-container * Edit video styles and test * Rename component * Start moving global styles over * Move hero styles to locl * Remove composes g-hero * Fix flex basis on media * Add display flex to media * Clean up some styles * Consul On Kubernetes - Block List (#11114) * Start block list * Enter data and start styles * Get all images in and update styles * Move data and convert to ts * Add comment in page * Consul On Kubernetes - Side by Side Section (#11122) * Start block list * Enter data and start styles * Get all images in and update styles * Start side by side * Add content and more styles * Some more styles * Add styles for text and titles * Edit styles and clean * Fix spacing between button and text in overview * Delete public folder * Fix images in block on page * remove extra file * Fix classnames import * Use fragment * Consul On Kubernetes - Docs List Component (#11150) * Add docs list component * Add docs list content * Change type declaration * Remove unecessary style * Use fragment * Change icons * Consul On Kubernetes - Card List & Get Started Section (#11168) * Start card list component * Begin adding content * Start wrapper styles * Add more styles for card * Fix style * Edit styles * Use next Link * Add minor formatting * Make entire card a link * Add transition * Change import * Use svg instead of button and make target blank * Move wrapper div to component and add classname prop, use color variable for border * Change min of card in grid * Less pxels for min * Update copy * Consul on Kubernetes Content (#11179) * Add content so far * Add hero content and switch video to embed - needs editing * Add overview and docs links * Use iframe in hero and style * Remove = null on prop * Add learn tutorials content so far * Change learn tutorials content * Change placeholder learn content * Add requested copy updates * Align numbers * Consul on Kubernetes Content & Design Updates (#11217) * Update docs icons * Update learn cards * Update challenges icon * Video poster pending * New image * Add split up background images * Looking pretty good * Fix up background image * Add more styles * Add meta description and new feature images * Revert img change * Fix up images and replace poster * Switch to grid * Move images * Clean up styles * Change hero button text * Update styles for hero video * Update youtube url * Use gray variable * Consul on Kubernetes Metadata (#11219) * Add meta data for sharing * Test * Test 2 * Add meta title * Update share image * CHange name * Test * Test again * Use relative url * Swap urls for hero ctas * Update tutorial card to be uniform * Change overview button text * Resolve conflicts and fix dependencies
|
@ -0,0 +1,29 @@
|
|||
import s from './style.module.css'
|
||||
|
||||
interface Block {
|
||||
title: string
|
||||
description: string
|
||||
image: string
|
||||
}
|
||||
|
||||
interface BlockListProps {
|
||||
blocks: Block[]
|
||||
}
|
||||
|
||||
export default function BlockList({ blocks }: BlockListProps) {
|
||||
return (
|
||||
<div className={s.blocksContainer}>
|
||||
{blocks.map(({ image, title, description }) => (
|
||||
<div key={title} className={s.block}>
|
||||
<div className={s.imageContainer}>
|
||||
<img src={image} alt={title} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className={s.title}>{title}</h3>
|
||||
<p className={s.description}>{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
.blocksContainer {
|
||||
display: grid;
|
||||
row-gap: 64px;
|
||||
|
||||
& .block {
|
||||
display: flex;
|
||||
|
||||
& .imageContainer {
|
||||
margin-right: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
composes: g-type-display-5 from global;
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
composes: g-type-body-small from global;
|
||||
margin: 0;
|
||||
color: var(--gray-2);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import s from './style.module.css'
|
||||
|
||||
interface Card {
|
||||
heading: string
|
||||
description: string
|
||||
url: string
|
||||
eyebrow: string
|
||||
}
|
||||
|
||||
interface CardListProps {
|
||||
title: string
|
||||
cards: Card[]
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default function CardList({ title, cards, className }: CardListProps) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<h3 className={s.title}>{title}</h3>
|
||||
<div className={s.cardsWrapper}>
|
||||
{cards.map(({ heading, description, url, eyebrow }) => (
|
||||
<a
|
||||
href={url}
|
||||
key={eyebrow}
|
||||
className={s.card}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<div className={s.cardContent}>
|
||||
<span className={s.eyebrow}>{eyebrow}</span>
|
||||
<span className={s.heading}>{heading}</span>
|
||||
<p className={s.description}>{description}</p>
|
||||
</div>
|
||||
<img
|
||||
src={require('@hashicorp/mktg-logos/product/consul/logomark/color.svg')}
|
||||
alt="consul-icon"
|
||||
className={s.icon}
|
||||
/>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
.cardsWrapper {
|
||||
display: grid;
|
||||
column-gap: 40px;
|
||||
row-gap: 40px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(218px, 1fr));
|
||||
|
||||
& .card {
|
||||
border: 1px solid var(--gray-5);
|
||||
box-shadow: 0 2px 3px rgba(37, 41, 55, 0.08);
|
||||
border-radius: 1px;
|
||||
transition: box-shadow 0.25s, transform 0.25s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 24px 24px 28px;
|
||||
justify-content: space-between;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 16px 28px rgba(37, 38, 45, 0.12);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
& .cardContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
& .icon {
|
||||
width: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
composes: g-type-display-3 from global;
|
||||
margin-top: 0;
|
||||
margin-bottom: 46px;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
composes: g-type-label from global;
|
||||
color: var(--gray-2);
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.heading {
|
||||
composes: g-type-display-6 from global;
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.description {
|
||||
composes: g-type-body from global;
|
||||
color: var(--gray-1);
|
||||
margin-top: 0;
|
||||
margin-bottom: 17px;
|
||||
}
|
After Width: | Height: | Size: 247 KiB |
After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 249 KiB |
|
@ -0,0 +1,98 @@
|
|||
import Button from '@hashicorp/react-button'
|
||||
import ReactPlayer from 'react-player'
|
||||
import s from './style.module.css'
|
||||
|
||||
interface Cta {
|
||||
url: string
|
||||
text: string
|
||||
}
|
||||
|
||||
interface ConsulOnKubernetesHeroProps {
|
||||
title: string
|
||||
description: string
|
||||
ctas: Cta[]
|
||||
video: {
|
||||
src: string
|
||||
poster: string
|
||||
}
|
||||
}
|
||||
|
||||
export default function ConsulOnKubernetesHero({
|
||||
title,
|
||||
description,
|
||||
ctas,
|
||||
video,
|
||||
}: ConsulOnKubernetesHeroProps) {
|
||||
return (
|
||||
<div className={s.ckHero}>
|
||||
<div className={s.contentWrapper}>
|
||||
<div className={s.headline}>
|
||||
<h1 className={s.title}>{title}</h1>
|
||||
<p className={s.description}>{description}</p>
|
||||
<div className={s.buttons}>
|
||||
{ctas.map(({ text, url }, idx) => (
|
||||
<Button
|
||||
key={text}
|
||||
theme={{
|
||||
brand: 'consul',
|
||||
variant: idx === 0 ? 'primary' : 'tertiary-neutral',
|
||||
background: 'dark',
|
||||
}}
|
||||
linkType={idx === 0 ? null : 'inbound'}
|
||||
url={url}
|
||||
title={text}
|
||||
className={s.button}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.media}>
|
||||
<img
|
||||
src={require('./images/bg-top.svg')}
|
||||
alt="background top"
|
||||
className={s.bgTop}
|
||||
/>
|
||||
<img
|
||||
src={require('./images/bg-right.svg')}
|
||||
alt="background right"
|
||||
className={s.bgRight}
|
||||
/>
|
||||
<img
|
||||
src={require('./images/bg-dots.svg')}
|
||||
alt="background bottom"
|
||||
className={s.bgBottom}
|
||||
/>
|
||||
<img
|
||||
src={require('./images/bg-dots.svg')}
|
||||
alt="background left"
|
||||
className={s.bgLeft}
|
||||
/>
|
||||
<div className={s.video}>
|
||||
<ReactPlayer
|
||||
playing
|
||||
light={video.poster}
|
||||
url={video.src}
|
||||
width="100%"
|
||||
height="100%"
|
||||
controls
|
||||
className={s.player}
|
||||
playIcon={
|
||||
<svg
|
||||
aria-label="Play video"
|
||||
width="72"
|
||||
height="72"
|
||||
viewBox="0 0 72 72"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="72" height="72" rx="36" fill="#F85C94" />
|
||||
<path d="M56 36L26 53.3205L26 18.6795L56 36Z" fill="white" />
|
||||
</svg>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
.ckHero {
|
||||
background-color: var(--black);
|
||||
color: var(--white);
|
||||
padding-top: 130px;
|
||||
padding-bottom: 142px;
|
||||
overflow: hidden;
|
||||
|
||||
@media (--medium) {
|
||||
padding-top: 78px;
|
||||
padding-bottom: 104px;
|
||||
}
|
||||
|
||||
@media (--small) {
|
||||
padding-top: 56px;
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
.contentWrapper {
|
||||
--columns: 1;
|
||||
|
||||
column-gap: 32px;
|
||||
composes: g-grid-container from global;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
|
||||
row-gap: 48px;
|
||||
|
||||
@media (--medium-up) {
|
||||
--columns: 12;
|
||||
}
|
||||
|
||||
& .headline {
|
||||
text-align: center;
|
||||
grid-column: 1 / -1;
|
||||
margin: 0 auto;
|
||||
|
||||
@media (--large) {
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
grid-column: 1 / 6;
|
||||
}
|
||||
|
||||
& .buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@media (--large) {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
& .button:not(:last-of-type) {
|
||||
margin-right: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .media {
|
||||
position: relative;
|
||||
grid-column: 1 / -1;
|
||||
|
||||
@media (--medium) {
|
||||
grid-column: 3 / 11;
|
||||
}
|
||||
|
||||
@media (--large) {
|
||||
grid-column: 7 / -1;
|
||||
}
|
||||
|
||||
& > div {
|
||||
border: 1px var(--gray-3) solid;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
& .video {
|
||||
background-color: var(--black);
|
||||
position: relative;
|
||||
padding-top: 56.25%;
|
||||
width: 100%;
|
||||
|
||||
& .player {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
& div {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
& iframe {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
& > * {
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
composes: g-type-display-1 from global;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
composes: g-type-body-large from global;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 40px;
|
||||
color: var(--gray-5);
|
||||
max-width: 500px;
|
||||
|
||||
@media (--large) {
|
||||
max-width: 385px;
|
||||
}
|
||||
}
|
||||
|
||||
.backgroundImage {
|
||||
height: auto;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.bgTop {
|
||||
composes: backgroundImage;
|
||||
left: auto;
|
||||
right: 0;
|
||||
top: -130px;
|
||||
display: none;
|
||||
width: 75%;
|
||||
|
||||
@media (--large) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.bgRight {
|
||||
composes: backgroundImage;
|
||||
top: 20%;
|
||||
left: 99.5%;
|
||||
}
|
||||
|
||||
.bgBottom {
|
||||
composes: backgroundImage;
|
||||
width: auto;
|
||||
top: 80%;
|
||||
left: 8%;
|
||||
}
|
||||
|
||||
.bgLeft {
|
||||
composes: backgroundImage;
|
||||
width: auto;
|
||||
top: 86px;
|
||||
left: -77px;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
import Button from '@hashicorp/react-button'
|
||||
import s from './style.module.css'
|
||||
interface Doc {
|
||||
icon: {
|
||||
src: string
|
||||
alt: string
|
||||
}
|
||||
description: string
|
||||
cta: {
|
||||
text: string
|
||||
url: string
|
||||
}
|
||||
}
|
||||
|
||||
interface DocsListProps {
|
||||
title: string
|
||||
docs: Doc[]
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default function DocsList({ title, docs, className }: DocsListProps) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<h3 className={s.title}>{title}</h3>
|
||||
<div className={s.docsList}>
|
||||
{docs.map(({ icon, description, cta }) => (
|
||||
<div key={cta.text}>
|
||||
<div className={s.image}>
|
||||
<img src={icon.src} alt={icon.alt} />
|
||||
</div>
|
||||
<p className={s.description}>{description}</p>
|
||||
<Button
|
||||
key="stable"
|
||||
url={cta.url}
|
||||
title={cta.text}
|
||||
linkType="inbound"
|
||||
theme={{
|
||||
variant: 'tertiary',
|
||||
brand: 'neutral',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
.docsList {
|
||||
display: grid;
|
||||
row-gap: 48px;
|
||||
}
|
||||
|
||||
.title {
|
||||
composes: g-type-display-3 from global;
|
||||
margin-top: 0;
|
||||
margin-bottom: 46px;
|
||||
}
|
||||
|
||||
.image {
|
||||
border: 1px solid var(--gray-5);
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
composes: g-body from global;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 24px;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import { ReactNode } from 'react'
|
||||
import Button from '@hashicorp/react-button'
|
||||
import s from './style.module.css'
|
||||
|
||||
interface InfoSection {
|
||||
heading: string
|
||||
content: ReactNode
|
||||
}
|
||||
|
||||
interface Cta {
|
||||
text: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface FeatureProps {
|
||||
number: number
|
||||
title: string
|
||||
subtitle: string
|
||||
infoSections: InfoSection[]
|
||||
cta: Cta
|
||||
image: string
|
||||
}
|
||||
|
||||
export default function Feature({
|
||||
number,
|
||||
title,
|
||||
subtitle,
|
||||
infoSections,
|
||||
cta,
|
||||
image,
|
||||
}: FeatureProps) {
|
||||
return (
|
||||
<div className={s.featureContainer}>
|
||||
<div className={s.imageContainer}>
|
||||
<img src={image} alt={title} />
|
||||
</div>
|
||||
<div className={s.featureTextContainer}>
|
||||
<div className={s.listNumber}>
|
||||
<span>{number}</span>
|
||||
</div>
|
||||
<div className={s.featureText}>
|
||||
<h3 className={s.featureTitle}>{title}</h3>
|
||||
<p className={s.featureSubtitle}>{subtitle}</p>
|
||||
<div className={s.infoSection}>
|
||||
{infoSections.map(({ heading, content }) => (
|
||||
<div key={heading}>
|
||||
<h4 className={s.infoTitle}>{heading}</h4>
|
||||
{content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
title={cta.text}
|
||||
url={cta.url}
|
||||
linkType="inbound"
|
||||
theme={{
|
||||
variant: 'tertiary-neutral',
|
||||
background: 'dark',
|
||||
}}
|
||||
className={s.ctaButton}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
After Width: | Height: | Size: 254 KiB |
After Width: | Height: | Size: 497 KiB |
|
@ -0,0 +1,28 @@
|
|||
import Feature from './feature'
|
||||
import s from './style.module.css'
|
||||
import { FeatureProps } from './feature'
|
||||
|
||||
interface FeaturesListProps {
|
||||
title: string
|
||||
features: Omit<FeatureProps, 'number'>[]
|
||||
}
|
||||
|
||||
export default function FeaturesList({ title, features }: FeaturesListProps) {
|
||||
return (
|
||||
<div
|
||||
className={s.featureListContainer}
|
||||
style={{
|
||||
backgroundImage: `url(${require('./images/top-right-design.svg')}), url(${require('./images/bottom-left-design.svg')})`,
|
||||
}}
|
||||
>
|
||||
<div className={s.contentWrapper}>
|
||||
<h2 className={s.title}>{title}</h2>
|
||||
<div className={s.featuresContainer}>
|
||||
{features.map((feature, i) => (
|
||||
<Feature {...feature} number={i + 1} key={feature.title} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
.featureListContainer {
|
||||
background-color: #000;
|
||||
padding-top: 128px;
|
||||
background-position: right top, left bottom;
|
||||
background-repeat: no-repeat;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.contentWrapper {
|
||||
composes: g-grid-container from global;
|
||||
}
|
||||
|
||||
.featureContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
& .featureTextContainer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
& .imageContainer {
|
||||
max-width: 490px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 40px;
|
||||
|
||||
& img {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (--large) {
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
|
||||
& .featureTextContainer {
|
||||
margin-right: 60px;
|
||||
}
|
||||
|
||||
& .featureText {
|
||||
max-width: 488px;
|
||||
}
|
||||
|
||||
& .imageContainer {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.featuresContainer {
|
||||
padding-top: 157px;
|
||||
padding-bottom: 394px;
|
||||
display: grid;
|
||||
row-gap: 120px;
|
||||
}
|
||||
|
||||
.title {
|
||||
composes: g-type-display-1 from global;
|
||||
max-width: 488px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.listNumber {
|
||||
composes: g-type-display-5 from global;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
background-color: var(--consul);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 64px;
|
||||
margin-top: 10px;
|
||||
|
||||
@media (--small) {
|
||||
margin-right: 30px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.featureTitle {
|
||||
composes: g-type-display-2 from global;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.featureSubtitle {
|
||||
composes: g-type-body-large from global;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.infoTitle {
|
||||
composes: g-type-display-5 from global;
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.infoSection {
|
||||
composes: g-type-body from global;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 40px;
|
||||
display: grid;
|
||||
row-gap: 24px;
|
||||
|
||||
& p,
|
||||
& ul {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { ReactNode } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import s from './style.module.css'
|
||||
|
||||
interface SideBySideProps {
|
||||
left: ReactNode
|
||||
right: ReactNode
|
||||
}
|
||||
|
||||
export default function SideBySide({ left, right }: SideBySideProps) {
|
||||
return (
|
||||
<div className={s.sideBySide}>
|
||||
<div className={classNames(s.sideWrapper, s.leftSide)}>
|
||||
<div className={s.side}>{left}</div>
|
||||
</div>
|
||||
<div className={classNames(s.sideWrapper, s.rightSide)}>
|
||||
<div className={s.side}>{right}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
.sideBySide {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@media (--large) {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
& .sideWrapper {
|
||||
padding: 105px 0;
|
||||
width: 100%;
|
||||
|
||||
@media (--large) {
|
||||
width: 50%;
|
||||
padding-bottom: 176px;
|
||||
}
|
||||
|
||||
&.leftSide {
|
||||
background: var(--consul-secondary);
|
||||
|
||||
@media (--large) {
|
||||
padding-left: 48px;
|
||||
padding-right: 104px;
|
||||
}
|
||||
}
|
||||
|
||||
&.rightSide {
|
||||
@media (--large) {
|
||||
padding-right: 48px;
|
||||
padding-left: 75px;
|
||||
}
|
||||
}
|
||||
|
||||
& .side {
|
||||
margin: 0 auto;
|
||||
|
||||
@media (--small) {
|
||||
max-width: 616px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
@media (--medium) {
|
||||
max-width: 944px;
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
@media (--large) {
|
||||
margin: 0;
|
||||
max-width: 490px;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child .side {
|
||||
@media (--large) {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ export default function ConsulSubnav() {
|
|||
|
||||
{ text: 'Download', url: '/downloads' },
|
||||
{
|
||||
text: 'Try Cloud',
|
||||
text: 'Try HCP Consul',
|
||||
url:
|
||||
'https://cloud.hashicorp.com/?utm_source=consul_io&utm_content=top_nav_consul',
|
||||
},
|
||||
|
|
|
@ -48,7 +48,8 @@
|
|||
"nuka-carousel": "4.7.7",
|
||||
"react": "^17.0.2",
|
||||
"react-device-detect": "1.17.0",
|
||||
"react-dom": "^17.0.2"
|
||||
"react-dom": "^17.0.2",
|
||||
"react-player": "^2.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hashicorp/platform-cli": "^1.2.0",
|
||||
|
@ -11045,6 +11046,11 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/load-script": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
|
||||
"integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
|
||||
},
|
||||
"node_modules/loader-runner": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
|
||||
|
@ -11772,6 +11778,11 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/memoize-one": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||
},
|
||||
"node_modules/memory-fs": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||
|
@ -14936,6 +14947,34 @@
|
|||
"react": "^16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-player": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.9.0.tgz",
|
||||
"integrity": "sha512-jNUkTfMmUhwPPAktAdIqiBcVUKsFKrVGH6Ocutj6535CNfM91yrvWxHg6fvIX8Y/fjYUPoejddwh7qboNV9vGA==",
|
||||
"dependencies": {
|
||||
"deepmerge": "^4.0.0",
|
||||
"load-script": "^1.0.0",
|
||||
"memoize-one": "^5.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-player/node_modules/deepmerge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-player/node_modules/react-fast-compare": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||
|
@ -28569,6 +28608,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"load-script": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
|
||||
"integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
|
||||
},
|
||||
"loader-runner": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
|
||||
|
@ -29115,6 +29159,11 @@
|
|||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||
},
|
||||
"memoize-one": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||
},
|
||||
"memory-fs": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||
|
@ -31619,6 +31668,30 @@
|
|||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"react-player": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.9.0.tgz",
|
||||
"integrity": "sha512-jNUkTfMmUhwPPAktAdIqiBcVUKsFKrVGH6Ocutj6535CNfM91yrvWxHg6fvIX8Y/fjYUPoejddwh7qboNV9vGA==",
|
||||
"requires": {
|
||||
"deepmerge": "^4.0.0",
|
||||
"load-script": "^1.0.0",
|
||||
"memoize-one": "^5.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"deepmerge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
|
||||
},
|
||||
"react-fast-compare": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-refresh": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||
|
|
|
@ -44,7 +44,8 @@
|
|||
"nuka-carousel": "4.7.7",
|
||||
"react": "^17.0.2",
|
||||
"react-device-detect": "1.17.0",
|
||||
"react-dom": "^17.0.2"
|
||||
"react-dom": "^17.0.2",
|
||||
"react-player": "^2.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hashicorp/platform-cli": "^1.2.0",
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<svg width="81" height="80" viewBox="0 0 81 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M0.955078 0H80.9551V80H0.955078V0Z" fill="white"/>
|
||||
<path d="M46.4551 7H9.45508C8.62665 7 7.95508 7.67157 7.95508 8.5V45.5C7.95508 46.3284 8.62665 47 9.45508 47H46.4551C47.2835 47 47.9551 46.3284 47.9551 45.5V8.5C47.9551 7.67157 47.2835 7 46.4551 7Z" fill="white" fill-opacity="0.8"/>
|
||||
<path d="M46.4551 7H9.45508C8.62665 7 7.95508 7.67157 7.95508 8.5V45.5C7.95508 46.3284 8.62665 47 9.45508 47H46.4551C47.2835 47 47.9551 46.3284 47.9551 45.5V8.5C47.9551 7.67157 47.2835 7 46.4551 7Z" fill="url(#paint0_linear)" fill-opacity="0.6"/>
|
||||
<path d="M33.9551 33H73.9551V73H33.9551V33Z" fill="#D1EBFF"/>
|
||||
<path d="M21.2626 54.1919C22.5426 52.2779 22.8036 49.9399 21.9336 47.8389C21.0636 45.7389 19.1996 44.2039 16.9676 43.8209C16.7978 43.7781 16.6435 43.6881 16.5228 43.5612C16.4021 43.4342 16.3199 43.2757 16.2856 43.1039C16.053 41.0778 16.0362 39.0326 16.2356 37.0029C16.2413 36.9281 16.2561 36.8542 16.2796 36.7829C16.3866 36.4799 16.6116 36.2099 16.8696 36.1709C19.1586 35.7609 20.9836 34.2359 21.8666 32.1019C22.7486 29.9679 22.4686 27.6229 21.2056 25.6859C21.0036 25.3839 21.0646 24.9749 21.2726 24.7349C22.5306 23.1369 23.9746 21.6159 25.6846 20.3689C25.8301 20.2717 26.0002 20.2178 26.1752 20.2135C26.3501 20.2093 26.5226 20.2549 26.6726 20.3449C28.5876 21.6279 30.9226 21.8909 33.0206 21.0219C35.1186 20.1529 36.6506 18.2879 37.0306 16.0549C37.073 15.885 37.1628 15.7307 37.2896 15.6099C37.4164 15.4892 37.5749 15.407 37.7466 15.3729C39.771 15.1421 41.8142 15.1273 43.8416 15.3289C43.9165 15.3346 43.9904 15.3493 44.0616 15.3729C44.3636 15.4809 44.6346 15.7059 44.6736 15.9649C45.0836 18.2549 46.6096 20.0849 48.7436 20.9699C50.8756 21.8549 53.2186 21.5769 55.1536 20.3139C55.4536 20.1129 55.8636 20.1739 56.1036 20.3819C57.7006 21.6419 59.2206 23.0889 60.4686 24.8019C60.5662 24.9476 60.6204 25.118 60.6248 25.2933C60.6292 25.4686 60.5837 25.6415 60.4936 25.7919C59.3176 27.5859 59.0776 29.9919 59.9476 32.0929C60.8176 34.1929 62.6826 35.7279 64.9146 36.1109C65.2576 36.1999 65.5246 36.4739 65.5946 36.8289C65.8286 38.8469 65.8446 40.8809 65.6456 42.9289C65.6399 43.0038 65.6251 43.0776 65.6016 43.1489C65.4946 43.4519 65.2706 43.7229 65.0116 43.7609C62.7236 44.1709 60.8976 45.6959 60.0146 47.8309C59.1326 49.9639 59.4126 52.3089 60.6756 54.2469C60.8776 54.5479 60.8166 54.9569 60.6086 55.1969C59.3506 56.7949 57.9076 58.3169 56.1966 59.5629C55.9296 59.7419 55.5466 59.7869 55.2956 59.6479C55.2336 59.6139 55.1786 59.5679 55.1186 59.5309C54.1862 58.9502 53.129 58.5995 52.0343 58.5077C50.9396 58.4159 49.8388 58.5856 48.8226 59.0029C46.7246 59.8719 45.1926 61.7369 44.8126 63.9709C44.7699 64.1404 44.68 64.2943 44.5532 64.4147C44.4265 64.5351 44.2681 64.617 44.0966 64.6509C42.0723 64.8821 40.0291 64.8972 38.0016 64.6959C37.9268 64.6902 37.8529 64.6754 37.7816 64.6519C37.4796 64.5449 37.2086 64.3199 37.1696 64.0599C36.7856 61.8359 35.2336 59.9399 33.0996 59.0559C32.2843 58.7134 31.4094 58.5355 30.525 58.5322C29.6407 58.5289 28.7645 58.7005 27.9466 59.0369C27.5536 59.1999 27.1216 59.4559 26.6896 59.7109C26.3896 59.9129 25.9796 59.8509 25.6746 59.6709C24.0776 58.4099 22.5566 56.9629 21.3096 55.2499C21.1146 54.9459 21.0826 54.4979 21.2626 54.1919Z" fill="url(#paint1_linear)"/>
|
||||
<path d="M51.3159 32.4646V38.1161M51.3159 38.1161H45.6644M51.3159 38.1161L46.9454 34.0093C45.9331 32.9965 44.6807 32.2566 43.3051 31.8587C41.9295 31.4608 40.4755 31.4179 39.0788 31.7339C37.6821 32.0499 36.3882 32.7146 35.3179 33.6659L34.4025 34.6847L33.1159 36.7137M30.5938 47.5353V41.8838M30.5938 41.8838H36.2452M30.5938 41.8838L34.9642 45.9905C35.9766 47.0033 37.229 47.7432 38.6046 48.1411C39.9802 48.539 41.4342 48.582 42.8309 48.2659C44.2276 47.9499 45.5214 47.2852 46.5918 46.3339C47.6621 45.3826 48.474 44.1756 48.9517 42.8257" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="47.9551" y1="7" x2="4.39808" y2="42.655" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#DC477D"/>
|
||||
<stop offset="0.583" stop-color="#D4BCD9"/>
|
||||
<stop offset="0.938" stop-color="#D1EBFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="47.3136" y1="63.3389" x2="49.3236" y2="11.6229" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#DC477D"/>
|
||||
<stop offset="0.359" stop-color="#DC477D" stop-opacity="0.96"/>
|
||||
<stop offset="0.703" stop-color="#DC477D" stop-opacity="0.88"/>
|
||||
<stop offset="1" stop-color="#DC477D" stop-opacity="0.7"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0">
|
||||
<rect width="80" height="80" fill="white" transform="translate(0.955078)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
|
@ -0,0 +1,23 @@
|
|||
<svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="80" height="80" fill="white"/>
|
||||
<path d="M73.5 31H32.5C31.6716 31 31 31.6716 31 32.5V73.5C31 74.3284 31.6716 75 32.5 75H73.5C74.3284 75 75 74.3284 75 73.5V32.5C75 31.6716 74.3284 31 73.5 31Z" fill="url(#paint0_linear)" fill-opacity="0.25"/>
|
||||
<path d="M63.5 21H22.5C21.6716 21 21 21.6716 21 22.5V63.5C21 64.3284 21.6716 65 22.5 65H63.5C64.3284 65 65 64.3284 65 63.5V22.5C65 21.6716 64.3284 21 63.5 21Z" fill="url(#paint1_linear)" fill-opacity="0.75"/>
|
||||
<path d="M47.5 5H6.5C5.67157 5 5 5.67157 5 6.5V47.5C5 48.3284 5.67157 49 6.5 49H47.5C48.3284 49 49 48.3284 49 47.5V6.5C49 5.67157 48.3284 5 47.5 5Z" fill="url(#paint2_linear)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.75 17C17.2312 17 16 18.2312 16 19.75V31.0004C16 31.0004 16 31.0003 16 31.0004V34.25C16 35.7688 17.2312 37 18.75 37H35.25C36.7688 37 38 35.7688 38 34.25V19.75C38 18.2312 36.7688 17 35.25 17H18.75ZM17.5 31.3529V34.25C17.5 34.9404 18.0596 35.5 18.75 35.5H23L23 34.75C23 34.3358 23.3358 34 23.75 34C24.1642 34 24.5 34.3358 24.5 34.75V35.5H29.5V34.75C29.5 34.3358 29.8358 34 30.25 34C30.6642 34 31 34.3358 31 34.75V35.5H35.25C35.9404 35.5 36.5 34.9404 36.5 34.25V19.75C36.5 19.0596 35.9404 18.5 35.25 18.5H18.75C18.0596 18.5 17.5 19.0596 17.5 19.75V29.4058L23.5067 24.4347C23.5472 24.3995 23.591 24.3689 23.6374 24.3433C23.7145 24.3007 23.7971 24.2728 23.8812 24.2594C24.004 24.2396 24.1326 24.2501 24.2555 24.2947C24.2874 24.3063 24.3187 24.32 24.349 24.3359L29.9208 27.1219L33.55 24.4C33.8814 24.1514 34.3515 24.2186 34.6 24.55C34.8486 24.8813 34.7814 25.3514 34.45 25.6L30.4626 28.5905C30.3495 28.679 30.2131 28.733 30.0711 28.7467C29.9623 28.7571 29.8501 28.7439 29.7425 28.7044C29.7113 28.6931 29.6807 28.6796 29.651 28.664L24.1017 25.8894L17.5 31.3529Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="75" y1="31" x2="24" y2="82.5" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.130208" stop-color="#D1EBFF"/>
|
||||
<stop offset="1" stop-color="#DC477D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="65" y1="21" x2="8.5" y2="77.5" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.130208" stop-color="#D1EBFF"/>
|
||||
<stop offset="1" stop-color="#DC477D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear" x1="24.2" y1="49" x2="44.047" y2="5.903" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#DC477D"/>
|
||||
<stop offset="0.359" stop-color="#DC477D" stop-opacity="0.96"/>
|
||||
<stop offset="0.703" stop-color="#DC477D" stop-opacity="0.88"/>
|
||||
<stop offset="1" stop-color="#DC477D" stop-opacity="0.7"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,33 @@
|
|||
<svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M0 0H80V80H0V0Z" fill="white"/>
|
||||
<path d="M47.5 5H6.5C5.67157 5 5 5.67157 5 6.5V47.5C5 48.3284 5.67157 49 6.5 49H47.5C48.3284 49 49 48.3284 49 47.5V6.5C49 5.67157 48.3284 5 47.5 5Z" fill="white" fill-opacity="0.8"/>
|
||||
<path d="M47.5 5H6.5C5.67157 5 5 5.67157 5 6.5V47.5C5 48.3284 5.67157 49 6.5 49H47.5C48.3284 49 49 48.3284 49 47.5V6.5C49 5.67157 48.3284 5 47.5 5Z" fill="url(#paint0_linear)" fill-opacity="0.3"/>
|
||||
<path d="M57.5 15H16.5C15.6716 15 15 15.6716 15 16.5V57.5C15 58.3284 15.6716 59 16.5 59H57.5C58.3284 59 59 58.3284 59 57.5V16.5C59 15.6716 58.3284 15 57.5 15Z" fill="white" fill-opacity="0.8"/>
|
||||
<path d="M57.5 15H16.5C15.6716 15 15 15.6716 15 16.5V57.5C15 58.3284 15.6716 59 16.5 59H57.5C58.3284 59 59 58.3284 59 57.5V16.5C59 15.6716 58.3284 15 57.5 15Z" fill="url(#paint1_linear)" fill-opacity="0.6"/>
|
||||
<path d="M67.5 25H26.5C25.6716 25 25 25.6716 25 26.5V67.5C25 68.3284 25.6716 69 26.5 69H67.5C68.3284 69 69 68.3284 69 67.5V26.5C69 25.6716 68.3284 25 67.5 25Z" fill="url(#paint2_linear)"/>
|
||||
<path d="M47 51.25C47.4142 51.25 47.75 51.5858 47.75 52V54C47.75 54.4142 47.4142 54.75 47 54.75C46.5858 54.75 46.25 54.4142 46.25 54V52C46.25 51.5858 46.5858 51.25 47 51.25Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M41 45.1035V41.75C41 40.2129 41.6415 38.7466 42.7704 37.6714C43.8982 36.5974 45.4202 36 47 36C48.5798 36 50.1018 36.5974 51.2296 37.6714C52.3585 38.7466 53 40.2129 53 41.75V45.1035C54.1543 45.43 55 46.4912 55 47.75V55.25C55 56.7688 53.7688 58 52.25 58H41.75C40.2312 58 39 56.7688 39 55.25V47.75C39 46.4912 39.8457 45.43 41 45.1035ZM43.8049 38.7576C44.6464 37.9562 45.795 37.5 47 37.5C48.205 37.5 49.3536 37.9562 50.1951 38.7576C51.0352 39.5577 51.5 40.635 51.5 41.75V45H42.5V41.75C42.5 40.635 42.9648 39.5577 43.8049 38.7576ZM52.25 46.5H41.75C41.0596 46.5 40.5 47.0596 40.5 47.75V55.25C40.5 55.9404 41.0596 56.5 41.75 56.5H52.25C52.9404 56.5 53.5 55.9404 53.5 55.25V47.75C53.5 47.0596 52.9404 46.5 52.25 46.5Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="49" y1="5" x2="1.088" y2="44.221" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#DC477D"/>
|
||||
<stop offset="0.583" stop-color="#D4BCD9"/>
|
||||
<stop offset="0.938" stop-color="#D1EBFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="59" y1="15" x2="11.088" y2="54.221" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#DC477D"/>
|
||||
<stop offset="0.583" stop-color="#D4BCD9"/>
|
||||
<stop offset="0.938" stop-color="#D1EBFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear" x1="44.2" y1="69" x2="64.047" y2="25.903" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#DC477D"/>
|
||||
<stop offset="0.359" stop-color="#DC477D" stop-opacity="0.96"/>
|
||||
<stop offset="0.703" stop-color="#DC477D" stop-opacity="0.88"/>
|
||||
<stop offset="1" stop-color="#DC477D" stop-opacity="0.7"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0">
|
||||
<rect width="80" height="80" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 112 KiB |
|
@ -0,0 +1,326 @@
|
|||
import ReactHead from '@hashicorp/react-head'
|
||||
import Button from '@hashicorp/react-button'
|
||||
import ConsulOnKubernetesHero from 'components/consul-on-kubernetes-hero'
|
||||
import FeaturesList from 'components/features-list'
|
||||
import BlockList from 'components/block-list'
|
||||
import SideBySide from 'components/side-by-side'
|
||||
import CardList from 'components/card-list'
|
||||
import DocsList from 'components/docs-list'
|
||||
import s from './style.module.css'
|
||||
|
||||
export default function ConsulOnKubernetesPage() {
|
||||
const pageDescription =
|
||||
'Consul is a robust service mesh for discovering and securely connecting applications on Kubernetes.'
|
||||
const pageTitle = 'Consul on Kubernetes'
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ReactHead
|
||||
title={pageTitle}
|
||||
pageName={pageTitle}
|
||||
description={pageDescription}
|
||||
image="/img/consul-on-kubernetes-share-image.png"
|
||||
twitterCard="summary_large_image"
|
||||
>
|
||||
<meta name="og:title" property="og:title" content={pageTitle} />
|
||||
<meta name="twitter:title" content={pageTitle} />
|
||||
<meta name="twitter:description" content={pageDescription} />
|
||||
<meta name="author" content="@HashiCorp" />
|
||||
</ReactHead>
|
||||
|
||||
<ConsulOnKubernetesHero
|
||||
title="Consul on Kubernetes"
|
||||
description="A robust service mesh for discovering and securely connecting applications on Kubernetes."
|
||||
ctas={[
|
||||
{
|
||||
text: 'Try HCP Consul',
|
||||
url:
|
||||
'https://portal.cloud.hashicorp.com/?utm_source=docs&utm_content=consul_on_kubernetes_landing',
|
||||
},
|
||||
{
|
||||
text: 'Install Consul on Kubernetes',
|
||||
url: '/docs/k8s/installation/install',
|
||||
},
|
||||
]}
|
||||
video={{
|
||||
src: 'https://www.youtube.com/watch?v=Eyszp_apaEU',
|
||||
poster: require('./images/hero/poster.png'),
|
||||
}}
|
||||
/>
|
||||
|
||||
<section>
|
||||
<SideBySide
|
||||
left={
|
||||
<>
|
||||
<h2 className={s.sideBySideTitle}>Overview</h2>
|
||||
<p className={s.leftSideText}>
|
||||
Kubernetes and service mesh tend to go hand and hand.
|
||||
Organizations that adopt Kubernetes are looking for a way to
|
||||
automate, secure, and observe the connections between pods and
|
||||
clusters. Consul and Kubernetes provide a scalable and highly
|
||||
resilient platform for microservices. Consul supports any
|
||||
Kubernetes runtime including hosted solutions like EKS, AKS,
|
||||
GKE, and OpenShift.
|
||||
<br />
|
||||
<br />
|
||||
Need help managing Consul on AWS? HCP Consul supports Amazon
|
||||
Elastic Kubernetes Service (EKS). Get started today.
|
||||
</p>
|
||||
<Button
|
||||
title="Install Consul on Kubernetes"
|
||||
url="/docs/k8s/installation/install"
|
||||
theme={{
|
||||
brand: 'consul',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
right={
|
||||
<>
|
||||
<h2 className={s.sideBySideTitle}>Challenges</h2>
|
||||
<BlockList
|
||||
blocks={[
|
||||
{
|
||||
title: 'Multi-cluster',
|
||||
description:
|
||||
'Organizations typically prefer to utilize a more distributed model for Kubernetes deployments. Rather than maintain a single cluster, they connect multiple environments for testing, staging, and production purposes.',
|
||||
image: require('./images/blocks/multi-cluster.svg'),
|
||||
},
|
||||
{
|
||||
title: 'Connecting Kubernetes to non-Kubernetes',
|
||||
description:
|
||||
'Creating consistency when connecting Kubernetes to non-Kubernetes environments can be challenging, workflows need additional automation to accommodate many virtual machines or containers.',
|
||||
image: require('./images/blocks/connecting.svg'),
|
||||
},
|
||||
{
|
||||
title: 'Securing Kubernetes networking',
|
||||
description:
|
||||
'Securing Kubernetes networking with multiple layers of network policies can be challenging. Organizations need to apply policies at both the application layer and network layer to ensure consistent security.',
|
||||
image: require('./images/blocks/securing.svg'),
|
||||
},
|
||||
{
|
||||
title: 'Kubernetes monitoring',
|
||||
description:
|
||||
"Obtaining insights into what's happening inside the cluster and the overall health of the cluster. In addition, security issues and vulnerabilities need to be properly tracked.",
|
||||
image: require('./images/blocks/monitoring.svg'),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<FeaturesList
|
||||
title="Why Consul on Kubernetes"
|
||||
features={[
|
||||
{
|
||||
title: 'Multi-platform',
|
||||
subtitle:
|
||||
'Support both Kubernetes and non-Kubernetes workloads on any runtime',
|
||||
infoSections: [
|
||||
{
|
||||
heading: 'Why it matters',
|
||||
content: (
|
||||
<p>
|
||||
You can connect almost any application to any runtime.
|
||||
Consul supports virtual machines and containers across
|
||||
just about any platform.
|
||||
</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
heading: 'Features',
|
||||
content: (
|
||||
<ul>
|
||||
<li>Run thousands of nodes with low latency</li>
|
||||
<li>Support any Kubernetes distribution</li>
|
||||
<li>
|
||||
Work across Kubernetes & non-Kubernetes Environments
|
||||
</li>
|
||||
</ul>
|
||||
),
|
||||
},
|
||||
],
|
||||
cta: {
|
||||
text: 'Start tutorial',
|
||||
url:
|
||||
'https://learn.hashicorp.com/tutorials/consul/kubernetes-deployment-guide?in=consul/kubernetes',
|
||||
},
|
||||
image: require('./images/features/multi-platform.svg'),
|
||||
},
|
||||
{
|
||||
title: 'Kube-native workflow',
|
||||
subtitle:
|
||||
'Use Consul’s Custom Resource Definitions (CRDs) to interact with Kubernetes',
|
||||
infoSections: [
|
||||
{
|
||||
heading: 'Why it matters',
|
||||
content: (
|
||||
<p>
|
||||
Reduce Application deployment times using a workflows not
|
||||
technologies approach and Kube native tools instead of
|
||||
manual scripts
|
||||
</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
heading: 'Features',
|
||||
content: (
|
||||
<ul>
|
||||
<li>Layer 7 Traffic</li>
|
||||
<li>Ingress/Egress through Gateways</li>
|
||||
<li>Custom Resource Definitions</li>
|
||||
</ul>
|
||||
),
|
||||
},
|
||||
],
|
||||
cta: {
|
||||
text: 'Start tutorial',
|
||||
url:
|
||||
'https://learn.hashicorp.com/tutorials/consul/kubernetes-custom-resource-definitions?in=consul/kubernetes',
|
||||
},
|
||||
image: require('./images/features/workflow.svg'),
|
||||
},
|
||||
{
|
||||
title: 'Observable',
|
||||
subtitle:
|
||||
'Use built in UI and enable Kubernetes metrics via helm configuration',
|
||||
infoSections: [
|
||||
{
|
||||
heading: 'Why it matters',
|
||||
content: (
|
||||
<p>
|
||||
Provide enhanced observability using Kubernetes tools or
|
||||
use third party solutions to monitor Kubernetes
|
||||
performance
|
||||
</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
heading: 'Features',
|
||||
content: (
|
||||
<ul>
|
||||
<li>Built in UI metrics</li>
|
||||
<li>APM integrations (Prometheus, Datadog, etc.)</li>
|
||||
</ul>
|
||||
),
|
||||
},
|
||||
],
|
||||
cta: {
|
||||
text: 'Start tutorial',
|
||||
url:
|
||||
'https://learn.hashicorp.com/tutorials/consul/kubernetes-layer7-observability?in=consul/kubernetes',
|
||||
},
|
||||
image: require('./images/features/observable.svg'),
|
||||
},
|
||||
{
|
||||
title: 'Secure',
|
||||
subtitle:
|
||||
'Offload security concerns from applications based on application security policies. With HCP, security is enabled by default.',
|
||||
infoSections: [
|
||||
{
|
||||
heading: 'Why it matters',
|
||||
content: (
|
||||
<p>
|
||||
You can connect almost any application to any runtime.
|
||||
Consul supports virtual machines and containers across
|
||||
just about any platform.
|
||||
</p>
|
||||
),
|
||||
},
|
||||
{
|
||||
heading: 'Features',
|
||||
content: (
|
||||
<ul>
|
||||
<li>
|
||||
Encryption & Authorization (mTLS) using certificates for
|
||||
service identity
|
||||
</li>
|
||||
<li>Access Controls (ACLs) & Namespaces</li>
|
||||
<li>Automated Certificate Management & Rotation</li>
|
||||
</ul>
|
||||
),
|
||||
},
|
||||
],
|
||||
cta: {
|
||||
text: 'Start tutorial',
|
||||
url:
|
||||
'https://learn.hashicorp.com/tutorials/consul/kubernetes-secure-agents?in=consul/kubernetes',
|
||||
},
|
||||
image: require('./images/features/secure.svg'),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</section>
|
||||
<section className={s.getStartedWrapper}>
|
||||
<h1 className={s.getStartedTitle}>Ways to get started</h1>
|
||||
<div className={s.getStartedContent}>
|
||||
<CardList
|
||||
title="Tutorials"
|
||||
className={s.getStartedCards}
|
||||
cards={[
|
||||
{
|
||||
eyebrow: '15 min',
|
||||
heading: 'Get started on Kubernetes',
|
||||
description:
|
||||
'Setup Consul service mesh to get experience deploying service sidecar proxies and securing service with mTLS.',
|
||||
url:
|
||||
'https://learn.hashicorp.com/tutorials/consul/service-mesh-deploy?in=consul/gs-consul-service-mesh',
|
||||
},
|
||||
{
|
||||
eyebrow: '22 min',
|
||||
heading: 'Secure Consul and registered services on Kubernetes',
|
||||
description:
|
||||
'Secure Consul on Kubernetes using gossip encryption, TLS certificates, Access Control Lists, and Consul intentions.',
|
||||
url:
|
||||
'https://learn.hashicorp.com/tutorials/consul/kubernetes-secure-agents?in=consul/kubernetes',
|
||||
},
|
||||
{
|
||||
eyebrow: '21 min',
|
||||
heading:
|
||||
'Layer 7 observability with Prometheus, Grafana, and Kubernetes',
|
||||
description:
|
||||
'Collect and visualize layer 7 metrics from services in your Kubernetes cluster using Consul service mesh, Prometheus, and Grafana.',
|
||||
url:
|
||||
'https://learn.hashicorp.com/tutorials/consul/kubernetes-layer7-observability?in=consul/kubernetes',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<DocsList
|
||||
title="Documentation"
|
||||
className={s.getStartedDocs}
|
||||
docs={[
|
||||
{
|
||||
icon: {
|
||||
src: require('./images/docs/helm-icon.svg'),
|
||||
alt: 'helm',
|
||||
},
|
||||
description:
|
||||
'Consul offers an official Helm chart for quickly deploying and upgrading Consul on Kubernetes.',
|
||||
cta: {
|
||||
text: 'Helm documentation',
|
||||
url: '/docs/k8s/installation/install',
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: {
|
||||
src: require('@hashicorp/mktg-logos/product/terraform/logomark/color.svg'),
|
||||
alt: 'terraform',
|
||||
},
|
||||
description:
|
||||
'Use Consul’s Terraform provider for deploying and maintaining Consul agents across both Kubernetes and non-Kubernetes environments.',
|
||||
cta: {
|
||||
text: 'Terraform provider',
|
||||
url:
|
||||
'https://registry.terraform.io/providers/hashicorp/consul/latest/docs',
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
.sideBySideTitle {
|
||||
composes: g-type-display-2 from global;
|
||||
margin-top: 0;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.leftSideText {
|
||||
composes: g-type-body from global;
|
||||
margin-bottom: 46px;
|
||||
}
|
||||
|
||||
.getStartedWrapper {
|
||||
composes: g-grid-container from global;
|
||||
padding-top: 131px;
|
||||
padding-bottom: 227px;
|
||||
|
||||
& .getStartedContent {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@media (--large) {
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
& .getStartedCards {
|
||||
width: 100%;
|
||||
margin-bottom: 120px;
|
||||
|
||||
@media (--large) {
|
||||
margin-bottom: 0;
|
||||
width: 584px;
|
||||
}
|
||||
}
|
||||
|
||||
& .getStartedDocs {
|
||||
width: 100%;
|
||||
|
||||
@media (--large) {
|
||||
max-width: 488px;
|
||||
margin-left: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.getStartedTitle {
|
||||
composes: g-type-display-1 from global;
|
||||
margin-top: 0;
|
||||
margin-bottom: 72px;
|
||||
}
|