Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add markdown tabs #113

Merged
merged 6 commits into from
Sep 30, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions content/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,48 @@ projects. Use it to automate parts of your development workflow, including model
training and evaluation, comparing ML experiments across your project history,
and monitoring changing datasets.

<toggle>
<tab title="Tab 1">

Suspendisse vulputate quis tellus vitae dapibus. Vestibulum sit amet gravida
dolor. Curabitur erat lectus, aliquet vitae orci convallis, varius iaculis
mauris. Suspendisse sed tellus dolor. `Cras` in fringilla dui, vel malesuada
libero. Aliquam erat volutpat. Aliquam a felis eros. Sed sagittis felis eu massa
condimentum molestie. Etiam non pellentesque arcu. Donec sit amet elit justo.
Curabitur maximus, ipsum ac pulvinar varius, tortor neque tempus arcu, ac
tincidunt ipsum leo a mauris. Quisque sagittis augue non augue tincidunt semper.
Sed tortor lorem, pellentesque ac pretium eu, facilisis at neque.

</tab>
<tab title="Tab 2">

Curabitur bibendum massa et leo mattis cursus. Phasellus eu feugiat velit, sit
amet commodo metus. Duis ante tortor, rhoncus vel risus eu, ultrices dignissim
sapien. Maecenas at nisl vitae risus tincidunt varius id sit amet urna. Aenean
blandit augue tellus, vel mattis sapien accumsan vitae. Mauris mollis enim ut
justo dictum auctor. Integer sed nisl sit amet **metus varius fringilla**. Morbi
sit amet sollicitudin dui, nec egestas erat. Donec ullamcorper nulla mauris, non
volutpat nisi consectetur sit amet. Duis quis feugiat lacus, vitae venenatis
eros. Aliquam enim odio, vulputate a egestas sed, malesuada vel mauris. Fusce
efficitur feugiat purus eget convallis. Nam vulputate pretium nisi vel
porttitor. Duis pretium bibendum congue.

</tab>
<tab title="Tab 3">

Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
curae; In pellentesque dolor dui, nec viverra augue interdum quis. Vestibulum
mattis dui at sapien egestas, non ornare _lacus convallis_. Pellentesque et
gravida elit. Integer volutpat ligula eu lorem commodo blandit. Maecenas eu
lobortis felis, eu cursus mi. Maecenas nisi enim, vehicula sit amet tellus
efficitur, vehicula bibendum nunc. Donec sed sollicitudin dolor. Curabitur
aliquam metus sed arcu fringilla, ac lobortis odio varius. Suspendisse at elit
justo. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet.

</tab>
</toggle>

<cards>

<card href="/doc/start" heading="Get Started">
Expand All @@ -26,6 +68,30 @@ and monitoring changing datasets.

</cards>

<toggle>
<tab title="Tab 1">

```
cat results.txt >> report.md
```

</tab>
<tab title="Tab 2">

```
cml-publish graph.png --md >> report.md
```

</tab>
<tab title="Tab 3">

```
cd example_cml
```

</tab>
</toggle>

✅ Please join our [community](https://dvc.org/community) or use the
[support](https://dvc.org/support) channels if you have any questions or need
specific help. We are very responsive ⚡.
Expand All @@ -35,3 +101,39 @@ us a ⭐ if you like the project!

✅ Contribute to CML [on GitHub](https://github.com/iterative/cml) or help us
improve this [documentation](https://github.com/iterative/cml.dev) 🙏.

<toggle>
<tab title="Tab 4">

- m metus sed arcu fringilla, ac lobortis odio varius. Suspendisse at elit
justo. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet.
- m metus sed arcu fringilla, ac lobortis odio varius. Suspendisse at elit
justo. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet
- m metus sed arcu fringilla, ac lobortis odio varius. Suspendisse at elit
justo. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet

</tab>
<tab title="Tab 5">

- Vestibulum nec sapien at
- Praesent in dictum
- Vestibulum nec sapien at
- Praesent in dictum

</tab>
<tab title="Tab 6">

- Maecenas at nisl vitae risus tincidunt variu
- Maecenas at nisl vitae risus tincidunt variu
- m metus sed arcu fringilla, ac lobortis odio varius. Suspendisse at elit
justo. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet. Praesent in dictum leo. Vestibulum nec sapien at tortor molestie
imperdiet

</tab>
</toggle>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { createContext, useState } from 'react'

interface ITogglesData {
[key: string]: { texts: string[]; checkedInd: number }
}

interface ITogglesContext {
addNewToggle?: (id: string, texts: string[]) => void
updateToggleInd?: (id: string, newInd: number) => void
togglesData?: ITogglesData
}

export const TogglesContext = createContext<ITogglesContext>({})

export const TogglesProvider: React.FC = ({ children }) => {
const [togglesData, setTogglesData] = useState({})

const addNewToggle = (id: string, texts: string[]): void => {
const togglesDataCopy: ITogglesData = { ...togglesData }
togglesDataCopy[id] = { texts, checkedInd: 0 }
setTogglesData(togglesDataCopy)
}

const updateToggleInd = (id: string, newInd: number): void => {
const togglesDataCopy: ITogglesData = { ...togglesData }
const selectedTabText = togglesDataCopy[id].texts[newInd]
togglesDataCopy[id] = { ...togglesDataCopy[id], checkedInd: newInd }

for (const [toggleId, { texts }] of Object.entries(togglesDataCopy)) {
if (texts.includes(selectedTabText)) {
togglesDataCopy[toggleId] = {
...togglesDataCopy[toggleId],
checkedInd: togglesDataCopy[id].texts.indexOf(selectedTabText)
}
}
}

setTogglesData(togglesDataCopy)
}

return (
<TogglesContext.Provider
value={{ addNewToggle, updateToggleInd, togglesData }}
>
{children}
</TogglesContext.Provider>
)
}
92 changes: 89 additions & 3 deletions src/components/pages/Documentation/Markdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import React, {
useCallback,
useEffect,
useRef,
useState,
ReactNode,
ReactElement
ReactElement,
useContext
} from 'react'
import cn from 'classnames'
import { nanoid } from 'nanoid'
import { navigate } from '@reach/router'
import rehypeReact from 'rehype-react'
import Collapsible from 'react-collapsible'
Expand All @@ -17,6 +20,7 @@ import { getPathWithSource } from '../../../../utils/shared/sidebar'
import sharedStyles from '../styles.module.css'
import 'github-markdown-css/github-markdown.css'
import styles from './styles.module.css'
import { TogglesContext, TogglesProvider } from './ToggleProvider'

const isInsideCodeBlock = (node: Element): boolean => {
while (node?.parentNode) {
Expand Down Expand Up @@ -117,6 +121,84 @@ const Card: React.FC<{
)
}

const ToggleTab: React.FC<{
id: string
title: string
ind: number
onChange: () => void
checked: boolean
}> = ({ children, id, checked, ind, onChange, title }) => {
const inputId = `tab-${id}-${ind}`

return (
<>
<input
id={inputId}
type="radio"
name={`toggle-${id}`}
onChange={onChange}
checked={checked}
/>
<label className={styles.tabHeading} htmlFor={inputId}>
{title}
</label>
{children}
</>
)
}

const Toggle: React.FC<{
children: Array<{ props: { title: string } } | string>
}> = ({ children }) => {
const [toggleId, setToggleId] = useState('')
const {
addNewToggle = (): null => null,
updateToggleInd = (): null => null,
togglesData = {}
} = useContext(TogglesContext)
const tabs: Array<{ props: { title: string } } | string> = children.filter(
child => child !== '\n'
)
const tabsTitles = tabs.map(tab =>
typeof tab === 'object' ? tab.props.title : ''
)

useEffect(() => {
if (toggleId === '') {
const newId = nanoid()
addNewToggle(newId, tabsTitles)
setToggleId(newId)
}

if (toggleId && !togglesData[toggleId]) {
addNewToggle(toggleId, tabsTitles)
}
}, [togglesData])

return (
<div className={styles.toggle}>
{tabs.map((tab, i) => (
<ToggleTab
ind={i}
key={i}
title={tabsTitles[i]}
id={toggleId}
checked={
i === (togglesData[toggleId] ? togglesData[toggleId].checkedInd : 0)
}
onChange={(): void => updateToggleInd(toggleId, i)}
>
{tab}
</ToggleTab>
))}
</div>
)
}

const Tab: React.FC = ({ children }) => (
<div className={styles.tab}>{children}</div>
)

const renderAst = new rehypeReact({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createElement: React.createElement as any,
Expand All @@ -125,7 +207,9 @@ const renderAst = new rehypeReact({
details: Details,
a: Link,
card: Card,
cards: Cards
cards: Cards,
toggle: Toggle,
tab: Tab
}
}).Compiler

Expand Down Expand Up @@ -192,7 +276,9 @@ const Markdown: React.FC<IMarkdownProps> = ({
<i className={cn(sharedStyles.buttonIcon, styles.githubIcon)} /> Edit on
GitHub
</Link>
<div className="markdown-body">{renderAst(htmlAst)}</div>
<TogglesProvider>
<div className="markdown-body">{renderAst(htmlAst)}</div>
</TogglesProvider>
<div className={styles.navButtons}>
<Link className={styles.navButton} href={prev || '#'}>
<i className={cn(styles.navButtonIcon, styles.prev)} />
Expand Down
50 changes: 50 additions & 0 deletions src/components/pages/Documentation/Markdown/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,53 @@ a.card {
background-color: var(--color-light-blue);
}
}

.toggle {
display: flex;
flex-wrap: wrap;

input {
height: 0;
opacity: 0;
position: absolute;
width: 0;
overflow: hidden;
}

input:checked + label {
color: var(--color-azure);
border-color: var(--color-azure);
}

input:checked + label + .tab {
height: initial;
opacity: initial;
position: static;
width: 100%;
overflow: visible;
}

.tabHeading {
padding: 12px 16px 10px;
background-color: transparent;
border: none;
border-bottom: 2px solid transparent;
font-weight: bold;
font-size: 16px;
font-family: var(--font-brandon);
order: -1;

&:hover {
cursor: pointer;
}
}
}

.tab {
margin: 10px 0 0;
height: 0;
opacity: 0;
position: absolute;
overflow: hidden;
width: 0;
}