feat(nx-dev): add deepdive callout component
This commit is contained in:
parent
61ecd4b4f8
commit
daf5837a21
@ -94,14 +94,14 @@ Your content goes here.
|
|||||||
{% /callout %}
|
{% /callout %}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Disclosure
|
#### Deep Dives
|
||||||
|
|
||||||
A disclosure can be used for less important information that is initially collapsed.
|
These are special callouts that are collapsed with the intention of containing more deep-dive information about the topic which isn't required to understand right away.
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
{% disclosure title="string" %}
|
{% callout type="deepdive" title="string" %}
|
||||||
Your content goes here.
|
Your deep-dive content goes here.
|
||||||
{% /disclosure %}
|
{% /callout %}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Cards
|
#### Cards
|
||||||
|
|||||||
@ -251,7 +251,7 @@ If we don't use the `nx affected` command in CI, no matter how our repo is struc
|
|||||||
|
|
||||||
Note that the 50% chance of any project being modified is an arbitrary number. If we had picked a lower chance of being modified all the expected values would decrease as well. Every repository is different, but this illustrates that a flatter structure will help speed up your CI pipeline.
|
Note that the 50% chance of any project being modified is an arbitrary number. If we had picked a lower chance of being modified all the expected values would decrease as well. Every repository is different, but this illustrates that a flatter structure will help speed up your CI pipeline.
|
||||||
|
|
||||||
{% disclosure title="The Math Behind the Expected Number of Affected Projects" %}
|
{% callout title="The Math Behind the Expected Number of Affected Projects" type="deepdive" %}
|
||||||
|
|
||||||
**Definitions:**
|
**Definitions:**
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ Note that the 50% chance of any project being modified is an arbitrary number. I
|
|||||||
**Expected Number of Affected Projects:**
|
**Expected Number of Affected Projects:**
|
||||||
ℙa(1) + ℙa(2) + ℙa(3) = 0.5 + 0.5 + 0.5 = 1.5
|
ℙa(1) + ℙa(2) + ℙa(3) = 0.5 + 0.5 + 0.5 = 1.5
|
||||||
|
|
||||||
{% /disclosure %}
|
{% /callout %}
|
||||||
|
|
||||||
## Reduce Wasted Time with Remote Caching
|
## Reduce Wasted Time with Remote Caching
|
||||||
|
|
||||||
|
|||||||
@ -33,8 +33,8 @@ distribute-on:
|
|||||||
large-changeset: 10 linux-medium-js
|
large-changeset: 10 linux-medium-js
|
||||||
```
|
```
|
||||||
|
|
||||||
{% callout type="note" title="How is the size of the PR determined?" %}
|
{% callout type="deepdive" title="How is the size of the PR determined?" %}
|
||||||
To determine the size of the PR, Nx Cloud calculates the ratio between the number of [affected projects](/ci/features/affected) and the total number of projects in the workspace. It then categorizes it as small, medium, or large.
|
To determine the size of the PR, Nx Cloud calculates the relationship between the number of [affected projects](/ci/features/affected) and the total number of projects in the workspace. It then assigns it to one of the three categories: small, medium, or large.
|
||||||
{% /callout %}
|
{% /callout %}
|
||||||
|
|
||||||
You can then reference it in your CI pipeline configuration:
|
You can then reference it in your CI pipeline configuration:
|
||||||
|
|||||||
@ -19,8 +19,6 @@ import { CallToAction } from './lib/tags/call-to-action.component';
|
|||||||
import { callToAction } from './lib/tags/call-to-action.schema';
|
import { callToAction } from './lib/tags/call-to-action.schema';
|
||||||
import { Card, Cards, LinkCard } from './lib/tags/cards.component';
|
import { Card, Cards, LinkCard } from './lib/tags/cards.component';
|
||||||
import { card, cards, linkCard } from './lib/tags/cards.schema';
|
import { card, cards, linkCard } from './lib/tags/cards.schema';
|
||||||
import { Disclosure } from './lib/tags/disclosure.component';
|
|
||||||
import { disclosure } from './lib/tags/disclosure.schema';
|
|
||||||
import { GithubRepository } from './lib/tags/github-repository.component';
|
import { GithubRepository } from './lib/tags/github-repository.component';
|
||||||
import { githubRepository } from './lib/tags/github-repository.schema';
|
import { githubRepository } from './lib/tags/github-repository.schema';
|
||||||
import { StackblitzButton } from './lib/tags/stackblitz-button.component';
|
import { StackblitzButton } from './lib/tags/stackblitz-button.component';
|
||||||
@ -78,7 +76,6 @@ export const getMarkdocCustomConfig = (
|
|||||||
'call-to-action': callToAction,
|
'call-to-action': callToAction,
|
||||||
card,
|
card,
|
||||||
cards,
|
cards,
|
||||||
disclosure,
|
|
||||||
'link-card': linkCard,
|
'link-card': linkCard,
|
||||||
'github-repository': githubRepository,
|
'github-repository': githubRepository,
|
||||||
'stackblitz-button': stackblitzButton,
|
'stackblitz-button': stackblitzButton,
|
||||||
@ -107,7 +104,6 @@ export const getMarkdocCustomConfig = (
|
|||||||
CallToAction,
|
CallToAction,
|
||||||
Card,
|
Card,
|
||||||
Cards,
|
Cards,
|
||||||
Disclosure,
|
|
||||||
LinkCard,
|
LinkCard,
|
||||||
CustomLink,
|
CustomLink,
|
||||||
FenceWrapper,
|
FenceWrapper,
|
||||||
|
|||||||
@ -1,13 +1,19 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import cx from 'classnames';
|
||||||
import {
|
import {
|
||||||
|
ChevronRightIcon,
|
||||||
|
ChevronDownIcon,
|
||||||
CheckCircleIcon,
|
CheckCircleIcon,
|
||||||
ExclamationCircleIcon,
|
ExclamationCircleIcon,
|
||||||
HandRaisedIcon,
|
HandRaisedIcon,
|
||||||
InformationCircleIcon,
|
InformationCircleIcon,
|
||||||
|
AcademicCapIcon,
|
||||||
} from '@heroicons/react/24/outline';
|
} from '@heroicons/react/24/outline';
|
||||||
import cx from 'classnames';
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
type CalloutType = 'note' | 'warning' | 'check' | 'caution';
|
type CalloutType = 'note' | 'warning' | 'check' | 'caution' | 'deepdive';
|
||||||
|
|
||||||
const typeMap: Record<
|
const typeMap: Record<
|
||||||
CalloutType,
|
CalloutType,
|
||||||
{
|
{
|
||||||
@ -26,7 +32,7 @@ const typeMap: Record<
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
backgroundColor: 'bg-slate-50 dark:bg-slate-800/40',
|
backgroundColor: 'bg-slate-50 dark:bg-slate-800/40',
|
||||||
borderColor: 'ring-slate-100 dark:ring-slate-700',
|
borderColor: 'border-slate-200 dark:border-slate-700',
|
||||||
titleColor: 'text-slate-600 dark:text-slate-300',
|
titleColor: 'text-slate-600 dark:text-slate-300',
|
||||||
textColor: 'text-slate-700 dark:text-slate-400',
|
textColor: 'text-slate-700 dark:text-slate-400',
|
||||||
},
|
},
|
||||||
@ -38,7 +44,7 @@ const typeMap: Record<
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
backgroundColor: 'bg-yellow-50 dark:bg-yellow-900/30',
|
backgroundColor: 'bg-yellow-50 dark:bg-yellow-900/30',
|
||||||
borderColor: 'ring-yellow-100 dark:ring-yellow-900',
|
borderColor: 'border-yellow-200 dark:border-yellow-800',
|
||||||
titleColor: 'text-yellow-600 dark:text-yellow-400',
|
titleColor: 'text-yellow-600 dark:text-yellow-400',
|
||||||
textColor: 'text-yellow-700 dark:text-yellow-600',
|
textColor: 'text-yellow-700 dark:text-yellow-600',
|
||||||
},
|
},
|
||||||
@ -50,7 +56,7 @@ const typeMap: Record<
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
backgroundColor: 'bg-green-50 dark:bg-green-900/30',
|
backgroundColor: 'bg-green-50 dark:bg-green-900/30',
|
||||||
borderColor: 'ring-green-100 dark:ring-green-900',
|
borderColor: 'border-green-200 dark:border-green-800',
|
||||||
titleColor: 'text-green-600 dark:text-green-400',
|
titleColor: 'text-green-600 dark:text-green-400',
|
||||||
textColor: 'text-green-700 dark:text-green-600',
|
textColor: 'text-green-700 dark:text-green-600',
|
||||||
},
|
},
|
||||||
@ -59,43 +65,82 @@ const typeMap: Record<
|
|||||||
<HandRaisedIcon className="h-5 w-5 text-red-500" aria-hidden="true" />
|
<HandRaisedIcon className="h-5 w-5 text-red-500" aria-hidden="true" />
|
||||||
),
|
),
|
||||||
backgroundColor: 'bg-red-50 dark:bg-red-900/30',
|
backgroundColor: 'bg-red-50 dark:bg-red-900/30',
|
||||||
borderColor: 'ring-red-100 dark:ring-red-900',
|
borderColor: 'border-red-200 dark:border-red-800',
|
||||||
titleColor: 'text-red-600 dark:text-red-400',
|
titleColor: 'text-red-600 dark:text-red-400',
|
||||||
textColor: 'text-red-700 dark:text-red-600',
|
textColor: 'text-red-700 dark:text-red-600',
|
||||||
},
|
},
|
||||||
|
deepdive: {
|
||||||
|
icon: (
|
||||||
|
<AcademicCapIcon className="h-5 w-5 text-blue-500" aria-hidden="true" />
|
||||||
|
),
|
||||||
|
backgroundColor: 'bg-blue-50 dark:bg-blue-900/30',
|
||||||
|
borderColor: 'border-blue-200 dark:border-blue-800',
|
||||||
|
titleColor: 'text-white-600 dark:text-white-400',
|
||||||
|
textColor: 'text-white-700 dark:text-white-600',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Callout({
|
export function Callout({
|
||||||
title,
|
title,
|
||||||
type,
|
type,
|
||||||
children,
|
children,
|
||||||
|
defaultExpanded = false,
|
||||||
}: {
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
type: CalloutType;
|
type: CalloutType;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
defaultExpanded?: boolean;
|
||||||
}) {
|
}) {
|
||||||
|
const [isOpen, setIsOpen] = useState(type !== 'deepdive');
|
||||||
const ui = typeMap[type] || typeMap.note;
|
const ui = typeMap[type] || typeMap.note;
|
||||||
|
const isCollapsible = type === 'deepdive';
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isCollapsible) {
|
||||||
|
setIsOpen(defaultExpanded);
|
||||||
|
}
|
||||||
|
}, [defaultExpanded, isCollapsible]);
|
||||||
|
|
||||||
|
const toggleOpen = () => {
|
||||||
|
if (isCollapsible) {
|
||||||
|
setIsOpen(!isOpen);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// We use `<span>`s because we are inside `<p>`s
|
|
||||||
return (
|
return (
|
||||||
<span
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
'my-6 block rounded-md p-4 ring-1',
|
'my-6 overflow-hidden rounded-md border',
|
||||||
ui.backgroundColor,
|
ui.borderColor,
|
||||||
ui.borderColor
|
ui.backgroundColor
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className="flex">
|
<div
|
||||||
|
onClick={toggleOpen}
|
||||||
|
className={cx(
|
||||||
|
'flex w-full items-center justify-between p-4',
|
||||||
|
'transition-colors duration-200 hover:bg-opacity-80',
|
||||||
|
{ 'cursor-pointer': isCollapsible }
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<span className="flex items-center">
|
||||||
<span className="flex-shrink-0">{ui.icon}</span>
|
<span className="flex-shrink-0">{ui.icon}</span>
|
||||||
<span className="ml-3">
|
<span className={cx('ml-3 text-sm font-medium', ui.titleColor)}>
|
||||||
<span className={cx('mt-0 block text-sm font-medium', ui.titleColor)}>
|
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
<span className={cx('prose-sm mt-2 block', ui.textColor)}>
|
|
||||||
{children}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
|
{isCollapsible &&
|
||||||
|
(isOpen ? (
|
||||||
|
<ChevronDownIcon className="h-5 w-5" />
|
||||||
|
) : (
|
||||||
|
<ChevronRightIcon className="h-5 w-5" />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{isOpen && (
|
||||||
|
<div className="px-4 pb-4 pt-0">
|
||||||
|
<span className={cx('prose-sm block', ui.textColor)}>{children}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ChevronDoubleUpIcon,
|
|
||||||
ChevronDoubleDownIcon,
|
|
||||||
} from '@heroicons/react/24/outline';
|
|
||||||
import cx from 'classnames';
|
|
||||||
import { ReactNode, useState } from 'react';
|
|
||||||
|
|
||||||
const ui = {
|
|
||||||
upIcon: (
|
|
||||||
<ChevronDoubleUpIcon
|
|
||||||
className="h-5 w-5 text-slate-500 dark:text-slate-300"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
downIcon: (
|
|
||||||
<ChevronDoubleDownIcon
|
|
||||||
className="h-5 w-5 text-slate-500 dark:text-slate-300"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
backgroundColor: 'bg-slate-50 dark:bg-slate-800/40',
|
|
||||||
borderColor: 'ring-slate-100 dark:ring-slate-700',
|
|
||||||
titleColor: 'text-slate-600 dark:text-slate-300',
|
|
||||||
textColor: 'text-slate-700 dark:text-slate-400',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Disclosure({
|
|
||||||
title,
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
title: string;
|
|
||||||
children: ReactNode;
|
|
||||||
}) {
|
|
||||||
const [collapsed, setCollapsed] = useState(true);
|
|
||||||
|
|
||||||
// We use `<span>`s because we are inside `<p>`s
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className={cx(
|
|
||||||
'my-6 block flex-col rounded-md bg-slate-50 ring-1 ring-slate-100 dark:bg-slate-800/40 dark:ring-slate-700',
|
|
||||||
ui.backgroundColor,
|
|
||||||
ui.borderColor
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
onClick={() => setCollapsed(!collapsed)}
|
|
||||||
className="flex flex-shrink-0 cursor-pointer p-4"
|
|
||||||
>
|
|
||||||
{collapsed ? ui.downIcon : ui.upIcon}
|
|
||||||
<span className={cx('ml-3 block text-sm font-medium', ui.titleColor)}>
|
|
||||||
{title}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span className={cx('block p-4 pl-12 pt-0', collapsed ? 'hidden' : '')}>
|
|
||||||
<span className={cx('prose-sm block', ui.textColor)}>{children}</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import { Schema } from '@markdoc/markdoc';
|
|
||||||
|
|
||||||
export const disclosure: Schema = {
|
|
||||||
render: 'Disclosure',
|
|
||||||
description: 'Display the enclosed content in a collapsible box',
|
|
||||||
children: ['paragraph', 'tag', 'list'],
|
|
||||||
attributes: {
|
|
||||||
title: {
|
|
||||||
type: 'String',
|
|
||||||
required: true,
|
|
||||||
description: 'The title displayed at the top of the collapsible box',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Loading…
x
Reference in New Issue
Block a user