Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
30 changes: 10 additions & 20 deletions src/components/Layout/MDXWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, {
PropsWithChildren,
useState,
createContext,
isValidElement,
Expand All @@ -15,18 +14,17 @@ import type { CodeSnippetProps, SDKType } from '@ably/ui/core/CodeSnippet';
import cn from '@ably/ui/core/utils/cn';

import { getRandomChannelName } from '../blocks/software/Code/get-random-channel-name';
import Aside from '../blocks/dividers/Aside';

import If from './mdx/If';
import { useCopyableHeaders } from './mdx/headers';
import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from './mdx/tables';
import Table from './mdx/Table';
import { Tiles } from './mdx/tiles';
import { PageHeader } from './mdx/PageHeader';
import Admonition from './mdx/Admonition';

import { Frontmatter, PageContextType } from './Layout';
import { ActivePage } from './utils/nav';

import { HtmlComponentPropsData } from '../html-component-props';
import { MarkdownProvider } from '../Markdown';

import Article from '../Article';
Expand Down Expand Up @@ -158,15 +156,6 @@ const WrappedCodeSnippet: React.FC<{ activePage: ActivePage } & CodeSnippetProps
);
};

const WrappedAside = (props: PropsWithChildren<{ 'data-type': string }>) => {
return (
<Aside
attribs={{ 'data-type': props['data-type'] }}
data={(<>{props.children}</>) as unknown as HtmlComponentPropsData}
/>
);
};

const META_DESCRIPTION_FALLBACK = `Ably provides a suite of APIs to build, extend, and deliver powerful digital experiences in realtime. Organizations like Toyota, Bloomberg, HubSpot, and Hopin depend on Ably’s platform to offload the growing complexity of business-critical realtime data synchronization at global scale.`;
const META_PRODUCT_FALLBACK = 'pub_sub';

Expand Down Expand Up @@ -221,13 +210,14 @@ const MDXWrapper: React.FC<MDXWrapperProps> = ({ children, pageContext, location
components={{
If,
Code: (props) => <WrappedCodeSnippet activePage={activePage} apiKeys={apiKeys} {...props} />,
Aside: WrappedAside,
table: Table,
thead: TableHead,
tbody: TableBody,
tr: TableRow,
th: TableHeader,
td: TableCell,
Aside: Admonition,
Table,
table: Table.Root,
thead: Table.Header,
tbody: Table.Body,
tr: Table.Row,
th: Table.Head,
td: Table.Cell,
Tiles,
}}
>
Expand Down
90 changes: 90 additions & 0 deletions src/components/Layout/mdx/Admonition.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from 'react';
import cn from '@ably/ui/core/utils/cn';

type AdmonitionVariant =
| 'neutral'
| 'note'
| 'further-reading'
| 'important'
| 'new'
| 'warning'
| 'experimental'
| 'updated';

interface AdmonitionProps extends React.HTMLAttributes<HTMLElement> {
'data-type'?: AdmonitionVariant;
}

const admonitionConfig: Record<
AdmonitionVariant,
{
borderColor: string;
backgroundColor: string;
title: string;
}
> = {
neutral: {
borderColor: 'border-l-neutral-500 dark:border-l-neutral-800',
backgroundColor: 'bg-neutral-100 dark:bg-neutral-1200',
title: 'Category',
},
note: {
borderColor: 'border-l-blue-500 dark:border-l-blue-400',
backgroundColor: 'bg-blue-100 dark:bg-blue-800',
title: 'Note',
},
'further-reading': {
borderColor: 'border-l-green-500 dark:border-l-green-400',
backgroundColor: 'bg-green-100 dark:bg-green-800',
title: 'Further reading',
},
important: {
borderColor: 'border-l-orange-500 dark:border-l-orange-600',
backgroundColor: 'bg-orange-100 dark:bg-orange-1000',
title: 'Important',
},
new: {
borderColor: 'border-l-yellow-500 dark:border-l-yellow-400',
backgroundColor: 'bg-yellow-100 dark:bg-yellow-800',
title: 'New',
},
warning: {
borderColor: 'border-l-yellow-500 dark:border-l-yellow-400',
backgroundColor: 'bg-yellow-100 dark:bg-yellow-800',
title: 'Warning',
},
experimental: {
borderColor: 'border-l-purple-500 dark:border-l-purple-400',
backgroundColor: 'bg-purple-100 dark:bg-purple-800',
title: 'Experimental',
},
updated: {
borderColor: 'border-l-pink-500 dark:border-l-pink-400',
backgroundColor: 'bg-pink-100 dark:bg-pink-800',
title: 'Updated',
},
};

const Admonition: React.FC<AdmonitionProps> = ({ 'data-type': dataType = 'note', children, className, ...rest }) => {
const { borderColor, backgroundColor, title } = admonitionConfig[dataType] ?? admonitionConfig.note;

return (
<aside
{...rest}
data-type={dataType}
className={cn(
'border-l px-6 py-4 my-4 rounded-r-lg text-neutral-1000 dark:text-neutral-300',
borderColor,
backgroundColor,
className,
)}
>
<div className="text-sm leading-relaxed [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&>*:nth-child(2)]:inline [&>*:nth-child(3)]:mt-5">
<strong className="font-bold ui-text-p2">{title}: </strong>
{children}
</div>
</aside>
);
};

export default Admonition;
124 changes: 124 additions & 0 deletions src/components/Layout/mdx/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React from 'react';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Predominantly generated by Claude but with Radix as a very close guide.

import cn from '@ably/ui/core/utils/cn';

// Table Root Component
interface TableRootProps extends React.HTMLAttributes<HTMLDivElement> {
children: React.ReactNode;
}

const TableRoot: React.FC<TableRootProps> = ({ children, className, ...props }) => {
return (
<div className={cn('overflow-x-auto my-4 rounded-lg overflow-hidden', className)} {...props}>
<table className="w-full border-separate border-spacing-0 text-left text-sm">{children}</table>
</div>
);
};

// Table Header Component
interface TableHeaderProps extends React.HTMLAttributes<HTMLTableSectionElement> {
children: React.ReactNode;
}

const TableHeader: React.FC<TableHeaderProps> = ({ children, className, ...props }) => {
return (
<thead className={cn('bg-neutral-100 dark:bg-neutral-1200', className)} {...props}>
{children}
</thead>
);
};

// Table Body Component
interface TableBodyProps extends React.HTMLAttributes<HTMLTableSectionElement> {
children: React.ReactNode;
}

const TableBody: React.FC<TableBodyProps> = ({ children, className, ...props }) => {
return (
<tbody className={className} {...props}>
{children}
</tbody>
);
};

// Table Row Component
interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
children: React.ReactNode;
}

const TableRow: React.FC<TableRowProps> = ({ children, className, ...props }) => {
return (
<tr className={cn('first:border-t', className)} {...props}>
{children}
</tr>
);
};

// Table Head Cell Component
interface TableHeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
children: React.ReactNode;
}

const TableHead: React.FC<TableHeadProps> = ({ children, className, ...props }) => {
return (
<th
className={cn(
'px-4 py-3 text-left font-bold text-neutral-1000 dark:text-neutral-300',
'first:rounded-tl-lg last:rounded-tr-lg',
'border-t first:border-l last:border-r border-b border-neutral-300 dark:border-neutral-1000',
className,
)}
{...props}
>
{children}
</th>
);
};

// Table Cell Component
interface TableCellProps extends React.TdHTMLAttributes<HTMLTableCellElement> {
children: React.ReactNode;
}

const TableCell: React.FC<TableCellProps> = ({ children, className, ...props }) => {
return (
<td
className={cn(
'px-4 py-3 font-medium text-neutral-1000 dark:text-neutral-300',
'first:border-l last:border-r border-b border-neutral-300 dark:border-neutral-1000',
'[table>tbody:first-child_tr:first-child_&]:border-t',
'[table>tbody:first-child_tr:first-child_&]:first:rounded-tl-lg [table>tbody:first-child_tr:first-child_&]:last:rounded-tr-lg',
'[tr:last-child_&]:first:rounded-bl-lg [tr:last-child_&]:last:rounded-br-lg',
className,
)}
{...props}
>
{children}
</td>
);
};

// Table Caption Component (optional)
interface TableCaptionProps extends React.HTMLAttributes<HTMLTableCaptionElement> {
children: React.ReactNode;
}

const TableCaption: React.FC<TableCaptionProps> = ({ children, className, ...props }) => {
return (
<caption className={cn('mt-2 text-sm text-neutral-600 dark:text-neutral-700', className)} {...props}>
{children}
</caption>
);
};

// Compound component pattern
export const Table = Object.assign(TableRoot, {
Root: TableRoot,
Header: TableHeader,
Body: TableBody,
Row: TableRow,
Head: TableHead,
Cell: TableCell,
Caption: TableCaption,
});

export default Table;
33 changes: 0 additions & 33 deletions src/components/Layout/mdx/tables.tsx

This file was deleted.