Merge pull request #157 from acid-info/topic-upgrade-lsd

chore: upgrade @acid-info/lsd-react
This commit is contained in:
Hossein Mehrabi
2023-12-15 19:49:53 +03:30
committed by GitHub
41 changed files with 854 additions and 273 deletions
@@ -2,7 +2,6 @@ import {
Hero,
HeroTitle,
HeroDescription,
HeroVideo,
HeroActions,
HeroAction,
CallToActionSection,
@@ -20,77 +19,238 @@ import {
ShowcaseCard,
JobsPerDepartment,
GithubChallenges,
LogoCarousel,
} from '../components/mdx'
import * as jobData from '/generated/jobs.json'
import * as challengesData from '/generated/challenges.json'
<Hero size="large">
<HeroInfo>
<HeroTitle>{'Defend Against Data Censorship With Codex'}</HeroTitle>
<HeroDescription>
{
'Codex is a durable, decentralized data storage protocol, created so the world community can preserve its most important knowledge without risk of censorship.'
}
</HeroDescription>
<HeroActions>
<HeroAction href="https://twitter.com/Codex_storage" target="_blank">
Follow Codex
</HeroAction>
</HeroActions>
</HeroInfo>
<HeroVideo placeholderSrc="/hero/atlas02-1080x1080-placeholder.png">
<source
src="/hero/atlas02-2048x2048-24fps-1M.mov"
type='video/mp4; codecs="hvc1"'
/>
<source src="/hero/atlas02-2048x2048-24fps-1M.webm" type="video/webm" />
</HeroVideo>
</Hero>
<Box top={{ xs: 32 }} bottom={{ xs: 144, lg: 216 }}>
<HeroTitle size="large">
{'LIGHT AND PERFORMANT CLIENTS, FOR THE ETHEREUM NETWORK'}
</HeroTitle>
<HeroDescription size="large">
{
'Run Nimbus on lightweight devices or premium servers with equal ease and peace of mind. Trusted by solo stakers and enterprise node operators alike.'
}
</HeroDescription>
<HeroActions>
<HeroAction href="https://twitter.com/Codex_storage" target="_blank">
Learn more
</HeroAction>
</HeroActions>
</Box>
<FeatureList
id="features"
id="clients"
alignment="top"
ctaPosition="top"
title="Nimbus Clients"
features={[
{
title: 'Durable',
description: (
<>
<strong>Codex</strong> implements advanced erasure coding techniques
to ensure data stored is always retrievable without relying on
inefficient full replication methods.
</>
),
title: 'Consensus Client',
description:
'An ultra-light client that contributes to the network and does not require syncing.',
},
{
title: 'Accessible',
title: 'Verified Web3 Proxy',
description:
'Participating in the Codex network is highly accessible thanks to its permissionless nature, and bandwidth usage optimizations like its "lazy repair" system and lightweight ZK-based remote auditing system.',
'A lightweight execution layer client to complement the consensus layer - coming soon.',
},
{
title: 'Decentralized',
title: 'Portal Client',
description:
"The network's native marketplace incentivizes wide participation, ensuring robust resistance to censorship and external attack.",
'An ultra-light client that contributes to the network and does not require syncing.',
},
{
title: 'Low-cost',
title: 'Execution Client',
description:
"Codex's design slashes the costs associated with traditional cloud storage providers while democratizing opportunities to contribute excess system resources to the network.",
'A lightweight execution layer client to complement the consensus layer - coming soon.',
},
]}
>
<CallToActionButton variant="outlined" href="/about">
Read more
<CallToActionButton variant="outlined" size="small">
read more
</CallToActionButton>
</FeatureList>
<Box top={{ xs: 144, lg: 216 }}>
<SectionHeader title="Nimbus attributes">
<CallToActionButton variant="outlined" size="small" href="/">
Read mroe
</CallToActionButton>
</SectionHeader>
<Box top={{ xs: 100, lg: 100 }}>
<Grid
xs={{ cols: 2, wrap: true, gap: '1.5rem 1em' }}
lg={{ cols: 4, gap: '1rem' }}
>
<Grid.Item>
<ShowcaseCard
index={1}
name="Lightweight"
description="A low resource footprint makes Nimbus an attractive option for solo stakers and distributed validators. Institutional operators benefit from having more headroom in their setup, preventing failure when Ethereum is under stress."
/>
</Grid.Item>
<Grid.Item>
<ShowcaseCard
index={2}
name="Secure"
description="Nimbus has undergone extensive security testing from some of the leading security firms in blockchain technology, including ConsenSys Diligence, Trail Of Bits, and NCC Group."
/>
</Grid.Item>
<Grid.Item>
<ShowcaseCard
index={3}
name="Easy to use"
description="Nimbus offers a simple consensus layer setup combining beacon node and validator clients, or the flexibility to run the two independently. Get up and running quickly in one of three steps."
/>
</Grid.Item>
<Grid.Item>
<ShowcaseCard
index={4}
name="Downtime resilient"
description="Nimbus includes several features to improve redundancy and resilience. For example, distributed keystore support allows for pairing a single Nimbus instance with multiple Web3Signer servers. If one of the instances fails, another takes over. Plus Nimbus can support multiple Beacon Nodes, creating redundancy and resilience against downtime."
/>
</Grid.Item>
</Grid>
</Box>
</Box>
<Box top={{ xs: 144, lg: 216 }}>
<CallToActionSection
title="Used by"
columns={2}
description="Codex is still under development as part of the Logos Collective's tech stack. Logos builds shared public infrastructure to provide trust-minimized, corruption-resistant governing services and social institutions to underserved citizens."
title="Run the Nimbus Consensus client"
description={
<>
Follow the detailed
<br />
step-by-step guide here
</>
}
list={[
{
title: 'Simple setup',
description:
'Run integrated Nimbus Beacon Node and Validator Client together.',
},
{
title: 'Beacon setup',
description:
'Use Nimbus Beacon Node with an alternative validator client.',
},
{
title: 'Beacon setup',
description:
'Use Nimbus Validator Client with an alternative Beacon Node',
},
]}
label="Get Nimbus"
target="_blank"
href="https://nimbus.guide/quick-start.html"
/>
</Box>
<Box top={{ xs: 144, lg: 216 }}>
<CallToActionSection
columns={2}
title="User Endorsements"
description="Nimbus is trusted by Etherem validators diverse in both size and operating requirements. But don't just take our word for it."
href="https://nimbus.team"
label="Get Nimbus"
target="_blank"
/>
<Box top={{ xs: 100, lg: 100 }}>
<Grid
xs={{ cols: 2, wrap: true, gap: '1.5rem 1em' }}
lg={{ cols: 4, gap: '1rem' }}
>
<Grid.Item>
<ShowcaseCard
logoSrc="/showcase/status-mark-black.svg"
logoSrcDark="/showcase/status-mark-white.svg"
description="We're thankful that Nimbus is building infrastructure that extends Ethereum, and is additive to a crypto-first mobile OS like ethOS. We know first hand that Nimbus is incredibly easy to work with, and boasts great dev support from the team."
borderStyle="none"
/>
</Grid.Item>
<Grid.Item>
<ShowcaseCard
name="DSRV"
description="DSRV has been keen to improve client diversity, and we've been running Nimbus with close to 2000 validators over the last 16 months including Ethereum mainnet. We found Nimbus consensus client to be both reliable and easy to operate while requiring fewer resources, making it worth recommending to every validator not just solo stakers."
borderStyle="none"
/>
</Grid.Item>
<Grid.Item>
<ShowcaseCard
name="Protolamba"
description="Processing 60 billion attestation data points of the Ethereum Beacon Chain only took ~45 min. How? ( . . .) Thanks to the amazing work by Nimbus, this uses their era-format to read all beacon-chain data very quickly, in parallel slices, without much lookup cost."
borderStyle="none"
/>
</Grid.Item>
<Grid.Item>
<ShowcaseCard
name="Diva Staking"
description="Happy to collaborate with the great minds from Nimbus to push the boundaries of staking & DVT!"
borderStyle="none"
/>
</Grid.Item>
</Grid>
</Box>
</Box>
<Box top={{ xs: 144, lg: 216 }}>
<LogoCarousel title="Nimbus Users" items={[
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
},
{
logoSrc: "/showcase/status-mark-black.svg",
logoSrcDark: "/showcase/status-mark-white.svg",
}
]} />
</Box>
<Box top={{ xs: 144, lg: 100 }}>
<CallToActionSection
title="Team"
columns={1}
@@ -183,7 +343,6 @@ import * as challengesData from '/generated/challenges.json'
<Roadmap
title="Roadmap"
description="Nomos is currently in its first proof-of-concept iteration and aims to release its beta version, Katana, before the end of Q4 2023."
bottom={{ xs: '4rem', lg: '7.25rem' }}
timeline={[
{
period: [2013],
@@ -36,7 +36,7 @@ export const ColorCard: React.FC<ColorCardProps> = ({
<div className={styles.info}>
<Typography
className={styles.title}
variant="subtitle1"
variant="subtitle2"
component="div"
>
{title}
+1 -1
View File
@@ -21,7 +21,7 @@
},
"dependencies": {
"@acid-info/docusaurus-og": "^1.0.0-alpha.111",
"@acid-info/lsd-react": "^0.1.0-alpha.21",
"@acid-info/lsd-react": "^0.1.0-beta.1",
"@docusaurus/core": "^2.4.1",
"@docusaurus/mdx-loader": "^2.4.1",
"@docusaurus/module-type-aliases": "^2.4.1",
@@ -1,18 +1,22 @@
import { useColorMode } from '@docusaurus/theme-common'
import { clsx } from 'clsx'
import React, { CSSProperties } from 'react'
import React from 'react'
import styles from './style.module.scss'
import AddSvg from '../../static/icons/add.svg'
import ArrowLCircleSvg from '../../static/icons/arrow-left-circle.svg'
import ArrowL from '../../static/icons/arrow-left.svg'
import ArrowRCircleSvg from '../../static/icons/arrow-right-circle.svg'
import ArrowR from '../../static/icons/arrow-right.svg'
import Avatar from '../../static/icons/avatar.svg'
import CloseSvg from '../../static/icons/close.svg'
import CopySvg from '../../static/icons/copy.svg'
import DiscordWhiteSvg from '../../static/icons/discord-white.svg'
import DiscordSvg from '../../static/icons/discord.svg'
import DiscourseSvg from '../../static/icons/discourse.svg'
import DotSvg from '../../static/icons/dot.svg'
import DownloadSvg from '../../static/icons/download.svg'
import DropdownSvg from '../../static/icons/dropdown.svg'
import EditSvg from '../../static/icons/edit.svg'
import ExternalLinkSvg from '../../static/icons/external-link.svg'
@@ -23,15 +27,13 @@ import GithubWhiteSvg from '../../static/icons/github-white.svg'
import GScholarSvg from '../../static/icons/gscholar.svg'
import HistorySvg from '../../static/icons/history.svg'
import LinkedinSvg from '../../static/icons/linkedin.svg'
import RemoveSvg from '../../static/icons/remove.svg'
import SearchSvg from '../../static/icons/search.svg'
import StatusSvg from '../../static/icons/status.svg'
import TelegramWhiteSvg from '../../static/icons/telegram-white.svg'
import TelegramSvg from '../../static/icons/telegram.svg'
import TwitterSvg from '../../static/icons/twitter.svg'
import DiscordWhiteSvg from '../../static/icons/discord-white.svg'
import TelegramWhiteSvg from '../../static/icons/telegram-white.svg'
import XWhiteSvg from '../../static/icons/x-white.svg'
import Avatar from '../../static/icons/avatar.svg'
import DownloadSvg from '../../static/icons/download.svg'
type TIconProps = {
size?: 's' | 'm' | 'l'
@@ -40,19 +42,20 @@ type TIconProps = {
type TProps = {
children?: JSX.Element
fill?: string
fill?: boolean
stroke?: boolean
} & TIconProps
export const Icon = (props: TProps): JSX.Element => {
const { children, size = 'm' } = props
const { colorMode, setColorMode } = useColorMode()
return (
<div
className={clsx(
styles.icon,
colorMode === 'dark' ? styles.dark : styles.light,
styles[size],
props.stroke && styles.stroke,
props.fill && styles.fill,
props.className && props.className,
)}
>
@@ -234,3 +237,15 @@ export const IconDownload = (props: TIconProps): JSX.Element => (
<DownloadSvg />
</Icon>
)
export const IconAdd = (props: TIconProps): JSX.Element => (
<Icon {...props} stroke>
<AddSvg />
</Icon>
)
export const IconRemove = (props: TIconProps): JSX.Element => (
<Icon {...props} stroke>
<RemoveSvg />
</Icon>
)
@@ -15,15 +15,38 @@
width: 40px;
}
}
}
&.dark {
.fill {
fill: var(--ifm-color-black);
[data-theme='dark'] {
.icon {
&.fill {
&,
* {
fill: var(--ifm-color-white);
}
}
.stroke {
stroke: var(--ifm-color-white);
&.stroke {
svg,
svg * {
stroke: var(--ifm-color-white);
}
}
}
}
[data-theme='light'] {
.icon {
&.fill {
&,
* {
fill: var(--ifm-color-black);
}
}
&.stroke {
svg,
svg * {
stroke: var(--ifm-color-black);
}
}
}
&.light {
}
}
@@ -0,0 +1,45 @@
@use '../../../css/utils';
@use '../../../css/lsd';
.mdx-accordion-item {
border-bottom: 1px solid rgb(var(--lsd-border-primary));
> input {
display: none;
}
}
.mdx-accordion-item__header {
min-height: 88px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 16px 0;
gap: 0 16px;
&,
* {
cursor: pointer;
}
}
.mdx-accordion-item__content-wrapper {
overflow: hidden;
height: auto;
}
.mdx-accordion-item__content {
height: 0;
}
.mdx-accordion-item--open {
.mdx-accordion-item__content {
height: auto;
padding-top: 6px;
padding-bottom: 1.875rem;
}
}
@include utils.responsive('lg', 'down') {
}
@@ -0,0 +1,72 @@
import clsx from 'clsx'
import React, { useEffect, useState } from 'react'
import './AccordionItem.scss'
import { Typography } from '@acid-info/lsd-react'
import { IconAdd, IconRemove } from '../../Icon'
import uniqueId from 'lodash/uniqueId'
export type AccordionItemProps = Omit<
React.HTMLProps<HTMLDivElement>,
'title'
> & {
open?: boolean
title: React.ReactNode
onToggle?: (open: boolean) => void
}
export const AccordionItem: React.FC<AccordionItemProps> = ({
open: openProp,
onToggle,
title,
className,
children,
...props
}) => {
const id = uniqueId('accordion-item-')
const [open, setOpen] = useState(openProp ?? false)
if (typeof openProp !== 'undefined' && openProp !== open) {
setOpen(openProp)
}
const handleToggle = () => {
if (typeof openProp !== 'undefined') {
onToggle && onToggle(!open)
} else {
setOpen((val) => !val)
}
}
return (
<div
className={clsx(
className,
'mdx-accordion-item',
open && 'mdx-accordion-item--open',
)}
{...props}
>
<input type="checkbox" id={id} checked={open} />
<div
role="button"
className="mdx-accordion-item__header"
onClick={() => handleToggle()}
>
<Typography
className="mdx-accordion-item__title"
variant="h5"
component="label"
htmlFor={id}
>
{title}
</Typography>
<div className="mdx-accordion-item__icon">
{open ? <IconRemove /> : <IconAdd />}
</div>
</div>
<div className="mdx-accordion-item__content-wrapper">
<div className="mdx-accordion-item__content">{children}</div>
</div>
</div>
)
}
@@ -0,0 +1 @@
export * from './AccordionItem'
@@ -101,7 +101,7 @@ export const AssetCard: React.FC<AssetCardProps> = ({
{title && (
<Typography
component="div"
variant="subtitle1"
variant="subtitle2"
className="mdx-asset-card__title"
>
{title}
@@ -19,7 +19,16 @@
.mdx-cta-section--title-only {
.mdx-cta-section__title {
@include lsd.typography('h1', false);
@include lsd.typography('h5', false);
font-weight: 300;
max-width: 886px;
}
}
.mdx-cta-section--title-button {
.mdx-cta-section__title {
@include lsd.typography('display4', false);
font-weight: 300;
max-width: 886px;
@@ -27,8 +36,7 @@
@include utils.responsive('lg', 'down') {
.mdx-cta-section__title {
font-size: 1.5rem !important;
line-height: 2rem !important;
@include lsd.typography('h4', false);
}
}
}
@@ -41,11 +49,11 @@
}
.mdx-cta-section__title {
@include lsd.typography('h6', false);
@include lsd.typography('h5', false);
}
.mdx-cta-section__description {
@include lsd.typography('h4', false);
@include lsd.typography('h3', false);
}
.mdx-cta-section__link {
@@ -65,7 +73,7 @@
.mdx-cta-section--simple {
.mdx-cta-section__title {
@include lsd.typography('h6', false);
@include lsd.typography('h5', false);
}
.mdx-cta-section__description {
@@ -91,11 +99,11 @@
}
.mdx-cta-section__title {
@include lsd.typography('h6', false);
@include lsd.typography('h5', false);
}
.mdx-cta-section__description {
@include lsd.typography('h2', false);
@include lsd.typography('h1', false);
margin-top: 2rem;
}
@@ -145,8 +153,7 @@
}
& > p {
font-size: 1.5rem !important;
line-height: 2rem !important;
@include lsd.typography('h4', true);
}
}
}
@@ -155,12 +162,10 @@
@include utils.responsive('lg', 'down') {
.mdx-cta-section__title {
font-size: 1rem !important;
line-height: 100% !important;
@include lsd.typography('subtitle2', true);
}
.mdx-cta-section__description {
font-size: 1.5rem !important;
line-height: 2rem !important;
@include lsd.typography('h4', true);
}
}
@@ -117,10 +117,13 @@ export const CallToActionSection: React.FC<CallToActionSectionProps> = ({
}) => {
const withDescription = !!description
const withList = list.length > 0
const withButton = !!href
const display =
title && !withDescription && !withList
title && !withDescription && !withButton && !withList
? 'title-only'
: title && !description && !withList && withButton
? 'title-button'
: title && description && columns === 2
? `full-width`
: title && description && list.length > 0
@@ -158,10 +161,10 @@ export const CallToActionSection: React.FC<CallToActionSectionProps> = ({
<div className="mdx-cta-section__list">
{list.map((option, index) => (
<div key={index}>
<Typography variant="subtitle1" component="div">
<Typography variant="subtitle2" component="div">
{option.title}
</Typography>
<Typography variant="h3" component="p">
<Typography variant="h2" component="p">
{option.description}
</Typography>
</div>
@@ -69,9 +69,21 @@
.mdx-feature-list__feature-description {
}
.mdx-feature-list__extra {
margin-top: 3.5rem;
padding: 0 1rem;
.mdx-feature-list__header {
display: flex;
flex-direction: row;
align-items: center;
gap: 2rem;
}
.mdx-feature-list--cta-top {
}
.mdx-feature-list--cta-bottom {
.mdx-feature-list__extra {
margin-top: 3.5rem;
padding: 0 1rem;
}
}
@include utils.responsive('lg', 'up') {
@@ -110,14 +122,16 @@
@include utils.responsive('lg', 'down') {
.mdx-feature-list {
.mdx-feature-list__title {
@include lsd.typography('subtitle1', false);
@include lsd.typography('subtitle2', false);
padding: 1rem 0;
}
}
.mdx-feature-list__extra {
margin-top: 2rem;
padding: 0;
.mdx-feature-list--cta-bottom {
.mdx-feature-list__extra {
margin-top: 2rem;
padding: 0;
}
}
.mdx-feature-list__list {
@@ -136,12 +150,12 @@
}
.mdx-feature-list__feature-title {
@include lsd.typography('h5', false);
@include lsd.typography('h4', false);
margin-top: 1rem;
}
.mdx-feature-list__feature-description {
@include lsd.typography('subtitle1');
@include lsd.typography('body1', false);
margin-top: 3rem;
}
@@ -24,6 +24,11 @@ export type FeatureListProps = Omit<
* The vertical alignment of feature description.
*/
alignment?: 'bottom' | 'top'
/**
* The position of the call to action buttons.
*/
ctaPosition?: 'top' | 'bottom'
}
/**
@@ -53,6 +58,7 @@ export const FeatureList: React.FC<FeatureListProps> = ({
alignment = 'bottom',
features = [],
className,
ctaPosition = 'bottom',
children,
...props
}) => {
@@ -62,16 +68,22 @@ export const FeatureList: React.FC<FeatureListProps> = ({
className,
'mdx-feature-list',
`mdx-feature-list--${alignment}-aligned`,
`mdx-feature-list--cta-${ctaPosition}`,
)}
{...props}
>
<Typography
variant="h6"
component="h1"
className="mdx-feature-list__title"
>
{title}
</Typography>
<div className="mdx-feature-list__header">
<Typography
variant="h5"
component="h1"
className="mdx-feature-list__title"
>
{title}
</Typography>
{children && ctaPosition === 'top' && (
<div className="mdx-feature-list__extra">{children}</div>
)}
</div>
<div className="mdx-feature-list__list">
{features.map((feature, index) => (
<div key={index} className={clsx('mdx-feature-list__feature')}>
@@ -84,14 +96,14 @@ export const FeatureList: React.FC<FeatureListProps> = ({
{index + 1}
</Typography>
<Typography
variant="h3"
variant="h2"
component="h2"
className="mdx-feature-list__feature-title"
>
{feature.title}
</Typography>
<Typography
variant="h6"
variant="h5"
component="h3"
className="mdx-feature-list__feature-description"
>
@@ -102,7 +114,9 @@ export const FeatureList: React.FC<FeatureListProps> = ({
</div>
))}
</div>
{children && <div className="mdx-feature-list__extra">{children}</div>}
{children && ctaPosition === 'bottom' && (
<div className="mdx-feature-list__extra">{children}</div>
)}
</div>
)
}
@@ -104,7 +104,7 @@ export const SingleGithubChallenge: React.FC<SingleGithubChallengeProps> = ({
return (
<div className="mdx-ghc__container">
<Link href={issue.url} className="mdx-ghc__issue-title-link">
<Typography variant="h6" className="mdx-ghc__issue-title">
<Typography variant="h5" className="mdx-ghc__issue-title">
{issue.title}
</Typography>
</Link>
@@ -1,15 +1,10 @@
import {
ChevronLeftIcon,
ChevronRightIcon,
IconButton,
IconButtonGroup,
THEME_BREAKPOINTS,
} from '@acid-info/lsd-react'
import { THEME_BREAKPOINTS } from '@acid-info/lsd-react'
import { css } from '@emotion/react'
import styled from '@emotion/styled'
import clsx from 'clsx'
import React, { useRef } from 'react'
import { lsdUtils } from '../../../lib/lsd.utils'
import { ScrollButtons } from '../ScrollButtons'
import { GridItem } from './GridItem'
export type GridProps = React.ComponentProps<typeof GridRoot> & {
@@ -29,62 +24,17 @@ export const Grid: { Item: typeof GridItem } & React.FC<GridProps> = ({
}) => {
const ref = useRef<HTMLDivElement>(null)
const scroll = (direction: -1 | 1) => {
const el = ref.current
if (!el) return
const itemWidth = el.children[0]?.getBoundingClientRect?.()?.width ?? 236
el.scrollTo({
behavior: 'smooth',
left:
el.scrollLeft +
(el.getBoundingClientRect()?.width - itemWidth) * direction,
})
}
return (
<GridRoot {...props} className={clsx(props.className, 'mdx-grid')}>
<div className="mdx-grid__actions">
{actions}
<div
className={clsx(
'mdx-grid__scroll',
spacingButtons && 'mdx-grid__scroll--spacing-buttons',
)}
>
<IconButtonGroup size="small" color="primary">
<IconButton
className={clsx(
'mdx-grid__scroll-button',
leftLabel?.length && 'mdx-grid__scroll-button--with-label',
)}
size="small"
onClick={scroll.bind(null, -1)}
>
<ChevronLeftIcon />
{leftLabel.length ? (
<span className="mdx-grid__scroll-button-label">
{leftLabel}
</span>
) : null}
</IconButton>
<IconButton
className={clsx(
'mdx-grid__scroll-button',
rightLabel?.length && 'mdx-grid__scroll-button--with-label',
)}
size="small"
onClick={scroll.bind(null, +1)}
>
{rightLabel.length ? (
<span className="mdx-grid__scroll-button-label">
{rightLabel}
</span>
) : null}
<ChevronRightIcon />
</IconButton>
</IconButtonGroup>
</div>
<ScrollButtons
containerRef={ref}
className="mdx-grid__scroll"
leftLabel={leftLabel}
rightLabel={rightLabel}
spacing={spacingButtons ? 'spaced' : 'grouped'}
/>
</div>
<div ref={ref} className={clsx('mdx-grid__content', 'hidden-scrollbar')}>
{children}
@@ -113,26 +63,6 @@ const GridRoot = styled.div<{
.mdx-grid__scroll {
display: flex;
flex-direction: row;
gap: 0 1rem;
margin-left: auto;
}
.mdx-grid__scroll--spacing-buttons {
width: 100%;
> div {
justify-content: space-between;
width: 100%;
}
> div > button:not(:last-child) {
border-right: 1px solid rgb(var(--lsd-border-primary)) !important;
}
}
.mdx-grid__scroll-button {
display: flex;
}
.mdx-grid__content {
@@ -211,47 +141,4 @@ const GridRoot = styled.div<{
`}
`)
})}
${(props) =>
lsdUtils.responsive(
props.theme as any,
'md',
'up',
)(css`
.mdx-grid__scroll-button--with-label {
width: auto;
min-width: 83px;
padding: 5px 11px 5px 9px;
gap: 12px;
&:first-of-type {
justify-content: flex-start;
}
&:last-of-type {
justify-content: flex-start;
}
}
`)}
${(props) =>
lsdUtils.responsive(
props.theme as any,
'sm',
'down',
)(css`
.mdx-grid__scroll {
& > div {
justify-content: flex-end;
> button:not(:last-child) {
border-right: none !important;
}
}
}
.mdx-grid__scroll-button-label {
display: none;
}
`)}
`
@@ -21,7 +21,7 @@ export const HeroDescription: React.FC<HeroDescriptionProps> = ({
return (
<Typography
variant={'h5'}
variant={'h4'}
className={clsx(
className,
'mdx-hero-description',
@@ -30,7 +30,7 @@ export const SingleDepartmentJobs: React.FC<SingleDepartmentJobsProps> = ({
className="mdx-jpd__job-link"
>
<div className="mdx-jpd__job-title-container">
<Typography variant="h6" className="mdx-jpd__job-title">
<Typography variant="h5" className="mdx-jpd__job-title">
{job.title}
</Typography>
<IconExternalLink className="mdx-jpd__external-link-icon" />
@@ -0,0 +1,33 @@
@use '../../../css/utils';
@use '../../../css/lsd';
.mdx-logo-carousel {
.mdx-section-header__title {
flex-basis: 100%;
}
.mdx-section-header__extra {
margin-left: auto;
}
.mdx-logo-carousel__inner {
margin-top: 100px;
}
.mdx-logo-carousel__item {
flex-shrink: 0;
}
.mdx-logo-carousel__logo {
height: 56px;
width: auto;
}
}
@include utils.responsive('lg', 'down') {
.mdx-logo-carousel {
.mdx-logo-carousel__inner {
margin-top: 64px;
}
}
}
@@ -0,0 +1,64 @@
import { Typography } from '@acid-info/lsd-react'
import ThemedImage from '@theme/ThemedImage'
import clsx from 'clsx'
import React, { useRef } from 'react'
import './LogoCarousel.scss'
import { Grid, SectionHeader } from '..'
import { ScrollButtons } from '../ScrollButtons'
import { useHydrated } from '../../../lib/useHydrated'
export type LogoCarouselProps = Omit<
React.HTMLAttributes<HTMLDivElement>,
'title'
> & {
title?: React.ReactNode
items?: {
title?: string
logoSrc?: string
logoSrcDark?: string
}[]
}
export const LogoCarousel: React.FC<LogoCarouselProps> = ({
title,
className,
items = [],
children,
...props
}) => {
const hydrated = useHydrated()
const ref = useRef<HTMLDivElement>(null)
const containerRef = useRef<HTMLElement | null>(null)
if (typeof window !== 'undefined' && hydrated && !containerRef.current) {
containerRef.current =
ref.current?.querySelector('.mdx-grid__content') ?? null
console.log(containerRef.current, ref.current)
}
return (
<div ref={ref} className={clsx(className, 'mdx-logo-carousel')} {...props}>
<SectionHeader title={title}>
<ScrollButtons containerRef={containerRef} />
</SectionHeader>
<Grid
className="mdx-logo-carousel__inner"
xs={{ wrap: false, gap: '96px', scrollButtons: false }}
>
{items.map((item) => (
<Grid.Item className="mdx-logo-carousel__item">
<ThemedImage
className="mdx-logo-carousel__logo"
title={item.title}
sources={{
dark: item.logoSrcDark ?? item.logoSrc ?? '',
light: item.logoSrc ?? item.logoSrcDark ?? '',
}}
/>
</Grid.Item>
))}
</Grid>
</div>
)
}
@@ -0,0 +1 @@
export * from './LogoCarousel'

Some files were not shown because too many files have changed in this diff Show More