mirror of
https://github.com/wavetermdev/docusaurus-og.git
synced 2026-08-05 13:46:35 -07:00
feat: implement the Roadmap mdx component; refs #90
This commit is contained in:
+11
-4
@@ -17,14 +17,21 @@
|
||||
line-height: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
.lsd-button--large {
|
||||
padding: 9px 39px;
|
||||
}
|
||||
|
||||
.lsd-button--small {
|
||||
padding: 5px 11px;
|
||||
}
|
||||
}
|
||||
|
||||
@include utils.responsive('lg', 'down') {
|
||||
.mdx-cta-button {
|
||||
@include lsd.typography('label2');
|
||||
|
||||
button {
|
||||
padding: 6px 12px;
|
||||
.lsd-button--large {
|
||||
@include lsd.typography('label2');
|
||||
padding: 5px 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ export const CallToActionButton: React.FC<CallToActionButtonProps> = ({
|
||||
return (
|
||||
<LinkElement
|
||||
className={clsx('mdx-cta-button', className)}
|
||||
variant="body1"
|
||||
variant={size === 'large' ? 'label1' : 'label2'}
|
||||
component="a"
|
||||
href={href}
|
||||
target={'_blank'}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
@use '../../../css/utils';
|
||||
@use '../../../css/lsd';
|
||||
|
||||
.mdx-roadmap {
|
||||
width: 100%;
|
||||
border-top: 1px solid rgb(var(--lsd-border-primary));
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
.mdx-roadmap__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
gap: 1rem;
|
||||
|
||||
> * {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.mdx-roadmap__actions {
|
||||
margin-top: 7.25rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 0 1rem;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
gap: 0 1rem;
|
||||
overflow-y: scroll;
|
||||
scroll-snap-type: x mandatory;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-item {
|
||||
width: 236px;
|
||||
min-height: 308px;
|
||||
gap: 1rem;
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 23px;
|
||||
border-bottom: 1px solid rgb(var(--lsd-border-primary));
|
||||
scroll-snap-align: start !important;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-period-container {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-border {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: calc(100% + 1rem);
|
||||
height: 50%;
|
||||
position: absolute;
|
||||
border-bottom: 1px solid rgb(var(--lsd-border-primary));
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-border--dashed {
|
||||
border-bottom-style: dashed;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-period {
|
||||
padding: 3px 12px;
|
||||
display: inline-block;
|
||||
border-radius: 10rem;
|
||||
color: rgb(var(--lsd-text-secondary)) !important;
|
||||
background-color: rgb(var(--lsd-surface-secondary));
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-item:last-child {
|
||||
.mdx-roadmap__timeline-border {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include utils.responsive('lg', 'down') {
|
||||
.mdx-roadmap__header {
|
||||
flex-direction: column;
|
||||
|
||||
h2 {
|
||||
@include lsd.typography('body1');
|
||||
}
|
||||
}
|
||||
|
||||
.mdx-roadmap__actions {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
.mdx-roadmap__timeline-item {
|
||||
width: 204px;
|
||||
min-height: 306px;
|
||||
}
|
||||
}
|
||||
|
||||
@include utils.responsive('sm', 'down') {
|
||||
.mdx-roadmap__scroll {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import {
|
||||
IconButton,
|
||||
IconButtonGroup,
|
||||
NavigateBeforeIcon,
|
||||
NavigateNextIcon,
|
||||
Typography,
|
||||
} from '@acid-info/lsd-react'
|
||||
import clsx from 'clsx'
|
||||
import React, { useRef } from 'react'
|
||||
import './Roadmap.scss'
|
||||
|
||||
export type TimelineItem = {
|
||||
period: string
|
||||
description: string
|
||||
borderStyle?: 'solid' | 'dashed'
|
||||
}
|
||||
|
||||
export type RoadmapProps = Omit<
|
||||
React.HTMLAttributes<HTMLDivElement>,
|
||||
'title'
|
||||
> & {
|
||||
title: React.ReactNode
|
||||
description?: React.ReactNode
|
||||
timeline?: TimelineItem[]
|
||||
}
|
||||
|
||||
export const Roadmap: React.FC<RoadmapProps> = ({
|
||||
title,
|
||||
description,
|
||||
timeline = [],
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
const timelineRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const scroll = (direction: -1 | 1) => {
|
||||
const el = timelineRef.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 (
|
||||
<div className={clsx(className, 'mdx-roadmap')} {...props}>
|
||||
<div className="mdx-roadmap__header">
|
||||
<Typography component="h2" variant="h6">
|
||||
{title}
|
||||
</Typography>
|
||||
|
||||
{description && (
|
||||
<Typography component="p" variant="h4">
|
||||
{description}
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
<div className="mdx-roadmap__actions">
|
||||
{children && <div className="mdx-roadmap__cta">{children}</div>}
|
||||
<div className="mdx-roadmap__scroll">
|
||||
<IconButtonGroup size="small" color="primary">
|
||||
<IconButton size="small" onClick={scroll.bind(null, -1)}>
|
||||
<NavigateBeforeIcon />
|
||||
</IconButton>
|
||||
<IconButton size="small" onClick={scroll.bind(null, 1)}>
|
||||
<NavigateNextIcon />
|
||||
</IconButton>
|
||||
</IconButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
{timeline.length > 0 && (
|
||||
<div
|
||||
ref={timelineRef}
|
||||
className="mdx-roadmap__timeline hidden-scrollbar"
|
||||
>
|
||||
{timeline.map((item, index) => (
|
||||
<div key={index} className="mdx-roadmap__timeline-item">
|
||||
<div className="mdx-roadmap__timeline-header">
|
||||
<div className="mdx-roadmap__timeline-period-container">
|
||||
<div
|
||||
className={clsx(
|
||||
'mdx-roadmap__timeline-border',
|
||||
item.borderStyle === 'dashed' &&
|
||||
'mdx-roadmap__timeline-border--dashed',
|
||||
)}
|
||||
/>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
component="span"
|
||||
className="mdx-roadmap__timeline-period"
|
||||
>
|
||||
{item.period}
|
||||
</Typography>
|
||||
</div>
|
||||
<Typography
|
||||
variant="h3"
|
||||
component="span"
|
||||
className="mdx-roadmap__timeline-index"
|
||||
>
|
||||
{`${index < 9 ? '0' : ''}${index + 1}`}
|
||||
</Typography>
|
||||
</div>
|
||||
<Typography
|
||||
variant="h6"
|
||||
component="p"
|
||||
className="mdx-roadmap__timeline-description"
|
||||
dangerouslySetInnerHTML={{ __html: item.description }}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './Roadmap'
|
||||
@@ -13,4 +13,5 @@ export * from './HeroTitle'
|
||||
export * from './PoweredBy'
|
||||
export * from './ScrollToBottom'
|
||||
export * from './Showcase'
|
||||
export * from './Roadmap'
|
||||
export * from './HeroVideo'
|
||||
|
||||
@@ -1216,4 +1216,16 @@ code {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hidden-scrollbar {
|
||||
/* Chrome, Safari and Opera */
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Firefox, Edge and IE */
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
@import './blog.scss';
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ export const SearchResults: React.FC<SearchResultsProps> = ({
|
||||
return (
|
||||
<div className={clsx(styles.root, total === 0 && styles.noResults)}>
|
||||
{total === 0 && <SearchResultMessage>No result.</SearchResultMessage>}
|
||||
<div className={clsx(styles.groups, 'hidden-scrollbar')}>
|
||||
<div className={clsx(styles.groups)}>
|
||||
{grouped.map(([category, items], index) => (
|
||||
<React.Fragment key={index}>
|
||||
<SearchResultGroup className={styles.group} title={category}>
|
||||
|
||||
Reference in New Issue
Block a user