Add icons and color to hint

This commit is contained in:
Samy Pessé
2023-10-30 18:48:17 -04:00
parent 80e4d7186c
commit d9b8ae95bd
7 changed files with 156 additions and 27 deletions
BIN
View File
Binary file not shown.
+1
View File
@@ -14,6 +14,7 @@
"@geist-ui/icons": "^1.0.2",
"@gitbook/api": "^0.11.1",
"@readme/openapi-parser": "^2.5.0",
"assert-never": "^1.2.1",
"bun-types": "^1.0.7",
"next": "13.5.6",
"react": "^18",
+3
View File
@@ -13,6 +13,7 @@ import { Tabs } from './Tabs';
import { Expandable } from './Expandable';
import { Table } from './Table';
import { Swagger } from './Swagger';
import { Embed } from './Embed';
export interface BlockProps<T> extends DocumentContextProps {
block: T;
@@ -49,6 +50,8 @@ export function Block<T>(props: BlockProps<T>) {
return <Table {...props} {...contextProps} />;
case 'swagger':
return <Swagger {...props} {...contextProps} />;
case 'embed':
return <Embed {...props} {...contextProps} />;
default:
return <div className={tcls(style)}>Unsupported block {block.type}</div>;
}
+30
View File
@@ -0,0 +1,30 @@
import { tcls } from '@/lib/tailwind';
import { BlockProps } from './Block';
import { Blocks } from './Blocks';
import { DocumentBlockEmbed } from '@gitbook/api';
import { api } from '@/lib/api';
export async function Embed(props: BlockProps<DocumentBlockEmbed>) {
const { block, style, ...contextProps } = props;
const { data: embed } = await api().urls.getEmbedByUrl({ url: block.data.url });
// TODO caption
if (embed.type === 'rich') {
return (
<div
className={tcls(style)}
dangerouslySetInnerHTML={{
__html: embed.html,
}}
/>
);
} else {
return (
<div className={tcls(style)}>
<div>{embed.title}</div>
</div>
);
}
}
+11 -23
View File
@@ -3,19 +3,18 @@ import IconHash from '@geist-ui/icons/hash';
import { BlockProps } from './Block';
import { Inlines } from './Inlines';
import { DocumentBlockHeading } from '@gitbook/api';
import { getBlockTextStyle } from './spacing';
export function Heading(props: BlockProps<DocumentBlockHeading>) {
const { block, style, ...contextProps } = props;
const headingStyle = STYLES[block.type];
const textStyle = getBlockTextStyle(block);
const Tag = TAGS[block.type];
const id = block.meta?.id ?? '';
return (
<headingStyle.tag
id={id}
className={tcls(headingStyle.className, 'group', 'relative', style)}
>
<Tag id={id} className={tcls(textStyle.textSize, 'group', 'relative', style)}>
<div
className={tcls(
'absolute',
@@ -27,7 +26,7 @@ export function Heading(props: BlockProps<DocumentBlockHeading>) {
'group-hover:opacity-100',
'group-focus:opacity-100',
'lg:flex',
headingStyle.lineHeight,
textStyle.lineHeight,
)}
>
<a
@@ -58,24 +57,13 @@ export function Heading(props: BlockProps<DocumentBlockHeading>) {
</div>
<Inlines {...contextProps} nodes={block.nodes} />
</headingStyle.tag>
</Tag>
);
}
const STYLES = {
'heading-1': {
tag: 'h2',
lineHeight: 'h-9',
className: ['text-3xl', 'font-semibold'],
},
'heading-2': {
tag: 'h3',
lineHeight: 'h-8',
className: ['text-2xl', 'font-semibold'],
},
'heading-3': {
tag: 'h4',
lineHeight: 'h-6',
className: ['text-base', 'font-semibold'],
},
const TAGS: { [type in DocumentBlockHeading['type']]: string } = {
// The h1 is reserved for the page title
'heading-1': 'h2',
'heading-2': 'h3',
'heading-3': 'h4',
};
+62 -4
View File
@@ -1,17 +1,75 @@
import { tcls } from '@/lib/tailwind';
import { ClassValue, tcls } from '@/lib/tailwind';
import { BlockProps } from './Block';
import { Blocks } from './Blocks';
import { DocumentBlockHint } from '@gitbook/api';
import IconInfo from '@geist-ui/icons/info';
import IconAlertTriangle from '@geist-ui/icons/alertTriangle';
import IconAlertCircle from '@geist-ui/icons/alertCircle';
import IconCheckInCircle from '@geist-ui/icons/checkInCircle';
import { getBlockTextStyle } from './spacing';
export function Hint(props: BlockProps<DocumentBlockHint>) {
const { block, style, ...contextProps } = props;
const hintStyle = HINT_STYLES[block.data.style];
const firstLine = getBlockTextStyle(block.nodes[0]);
return (
<div className={tcls('flex', 'flex-row', 'px-4', 'py-4', 'bg-slate-100', 'rounded', style)}>
<div className={tcls('w-7')}>
<div /> {/* TODO icon */}
<div
className={tcls(
'flex',
'flex-row',
'px-4',
'py-4',
'bg-slate-50',
'dark:bg-slate-900',
'rounded',
'border-l-4',
hintStyle.style,
style,
)}
>
<div
className={tcls(
'flex',
'items-center',
'justify-center',
'pr-3',
firstLine.lineHeight,
hintStyle.iconStyle,
)}
>
<hintStyle.icon className={tcls('w-5', 'h-5')} />
</div>
<Blocks {...contextProps} nodes={block.nodes} style={['flex-1']} />
</div>
);
}
const HINT_STYLES: {
[style in DocumentBlockHint['data']['style']]: {
icon: React.ComponentType<{ className?: string }>;
iconStyle: ClassValue;
style: ClassValue;
};
} = {
info: {
icon: IconInfo,
iconStyle: ['text-blue-500'],
style: ['border-blue-500'],
},
warning: {
icon: IconAlertCircle,
iconStyle: ['text-orange-500'],
style: ['border-orange-500'],
},
danger: {
icon: IconAlertTriangle,
iconStyle: ['text-red-500'],
style: ['border-red-500'],
},
success: {
icon: IconCheckInCircle,
iconStyle: ['text-green-500'],
style: ['border-green-500'],
},
};
+49
View File
@@ -0,0 +1,49 @@
import { ClassValue } from '@/lib/tailwind';
import { DocumentBlockListItem, DocumentBlocksEssentials } from '@gitbook/api';
import { assertNever } from 'assert-never';
/**
* Get the line height of a block
*/
export function getBlockTextStyle(block: DocumentBlocksEssentials | DocumentBlockListItem): {
/** Tailwind class for the text size */
textSize: ClassValue;
/** Tailwind class for the height (h-*) */
lineHeight: ClassValue;
} {
switch (block.type) {
case 'paragraph':
return {
textSize: ['text-base'],
lineHeight: 'h-6',
};
case 'heading-1':
return {
textSize: ['text-3xl', 'font-semibold'],
lineHeight: 'h-9',
};
case 'heading-2':
return {
textSize: ['text-2xl', 'font-semibold'],
lineHeight: 'h-8',
};
case 'heading-3':
return {
textSize: ['text-base', 'font-semibold'],
lineHeight: 'h-6',
};
case 'divider':
return {
textSize: [],
lineHeight: 'h-6',
};
case 'list-ordered':
case 'list-tasks':
case 'list-unordered':
return getBlockTextStyle(block.nodes[0]);
case 'list-item':
return getBlockTextStyle(block.nodes[0]);
default:
assertNever(block);
}
}