Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/odd-snails-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@doc-kit/generator-react': patch
---

Redesign the index page
4 changes: 4 additions & 0 deletions packages/react/src/html/constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export const JSX_IMPORTS = {
name: 'FunctionSignature',
source: '@node-core/ui-components/Containers/FunctionSignature',
},
IndexPage: {
name: 'IndexPage',
source: resolve(ROOT, './ui/components/Layout/IndexPage'),
},
ArrowUpRightIcon: {
name: 'ArrowUpRightIcon',
source: '@heroicons/react/24/solid/ArrowUpRightIcon',
Expand Down
25 changes: 25 additions & 0 deletions packages/react/src/html/ui/components/Layout/IndexPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styles from './IndexPage.module.css';
import StabilityBadge from '../StabilityBadge';

import { project, version } from '#theme/config';

/**
* Body of the synthetic `index.html` page
*/
export default ({ modules }) => (
<>
<p>
The API reference documentation for {project} v{version.version}.
</p>

<ul className={styles.moduleIndex}>
{modules.map(({ name, href, stability }) => (
<li key={href}>
<a href={href}>{name}</a>

<StabilityBadge className={styles.badge} stability={stability} />
</li>
))}
</ul>
</>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.moduleIndex {
list-style: none;
padding: 0;

li {
padding: 0.5rem 0;
}

/* Draw a rule between items */
li + li {
border-top: 1px solid var(--color-brand-200);
}
}

:where([data-theme='dark'], [data-theme='dark'] *) .moduleIndex li + li {
border-color: var(--color-brand-800);
}

.badge {
display: inline-block;
margin-left: 0.25rem;
}
37 changes: 7 additions & 30 deletions packages/react/src/html/ui/components/MetaBar/index.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { CodeBracketIcon, DocumentIcon } from '@heroicons/react/24/outline';
import Badge from '@node-core/ui-components/Common/Badge';
import MetaBar from '@node-core/ui-components/Containers/MetaBar';
import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';

import styles from './index.module.css';
import StabilityBadge from '../StabilityBadge';

import { editURL } from '#theme/config';

Expand All @@ -12,40 +12,17 @@ const iconMap = {
MD: DocumentIcon,
};

const STABILITY_KINDS = ['error', 'warning', null, 'info'];
const STABILITY_LABELS = ['D', 'E', null, 'L'];
const STABILITY_TOOLTIPS = ['Deprecated', 'Experimental', null, 'Legacy'];

/**
* Renders a heading value with an optional stability badge
* @param {{ value: string, stability: number }} props
*/
const HeadingValue = ({ value, stability }) => {
if (stability === 2) {
return value;
}

const ariaLabel = STABILITY_TOOLTIPS[stability]
? `Stability: ${STABILITY_TOOLTIPS[stability]}`
: undefined;

return (
<>
{value}
const HeadingValue = ({ value, stability }) => (
<>
{value}

<Badge
size="small"
className={styles.badge}
kind={STABILITY_KINDS[stability]}
data-tooltip={STABILITY_TOOLTIPS[stability]}
aria-label={ariaLabel}
tabIndex={0}
>
{STABILITY_LABELS[stability]}
</Badge>
</>
);
};
<StabilityBadge className={styles.badge} stability={stability} />
</>
);

/**
* MetaBar component that displays table of contents and page metadata
Expand Down
29 changes: 29 additions & 0 deletions packages/react/src/html/ui/components/StabilityBadge.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Badge from '@node-core/ui-components/Common/Badge';

const STABILITY_KINDS = ['error', 'warning', null, 'info'];
const STABILITY_LABELS = ['D', 'E', null, 'L'];
const STABILITY_TOOLTIPS = ['Deprecated', 'Experimental', null, 'Legacy'];

/**
* Compact stability badge used next to API names
*
* @param {{ stability: number, className?: string }} props
*/
export default ({ stability, className }) => {
if (!STABILITY_LABELS[stability]) {
return null;
}

return (
<Badge
size="small"
className={className}
kind={STABILITY_KINDS[stability]}
data-tooltip={STABILITY_TOOLTIPS[stability]}
aria-label={`Stability: ${STABILITY_TOOLTIPS[stability]}`}
tabIndex={0}
>
{STABILITY_LABELS[stability]}
</Badge>
);
};
114 changes: 0 additions & 114 deletions packages/react/src/jsx-ast/utils/synthetic/__tests__/index.test.mjs

This file was deleted.

72 changes: 19 additions & 53 deletions packages/react/src/jsx-ast/utils/synthetic/index.mjs
Original file line number Diff line number Diff line change
@@ -1,80 +1,46 @@
'use strict';

import { h as createElement } from 'hastscript';
import getConfig from '@doc-kit/core/utils/configuration/index.mjs';

import { createSyntheticHead, wrapAsEntry } from './synthetic.mjs';
import { JSX_IMPORTS } from '../../../html/constants.mjs';
import { createJSXElement } from '../ast.mjs';
import { getSortedHeadNodes } from '../getSortedHeadNodes.mjs';

const STABILITY_BADGE_KINDS = [
'error',
'warning',
'default',
'info',
'neutral',
'neutral',
];

/**
* Maps a Node.js stability index to a UI badge kind.
*
* @param {string} index
*/
const getStabilityBadgeKind = index =>
STABILITY_BADGE_KINDS[parseInt(index, 10)] ?? 'neutral';

/**
* Builds the Stability Overview table from module heads that declare a
* top-level stability index, mirroring the `legacy-html-all` overview.
* Maps the sorted module heads to the plain props consumed by the `IndexPage`
* component: display name, page href, and numeric stability index (defaulting
* to stable, mirroring the ToC).
*
* @param {Array<import('@doc-kit/core/generators/metadata/types').MetadataEntry>} headEntries
*/
export const buildStabilityOverview = headEntries =>
createElement('table', [
createElement('thead', [
createElement('tr', [
createElement('th', 'API'),
createElement('th', 'Stability'),
]),
]),
createElement(
'tbody',
headEntries.map(({ heading, api, stability }) =>
createElement('tr', [
createElement(
'td',
createElement('a', { href: `${api}.html` }, heading.data.name)
),
createElement(
'td',
createJSXElement(JSX_IMPORTS.Badge.name, {
size: 'small',
kind: getStabilityBadgeKind(stability.data.index),
'aria-label': `Stability: ${stability.data.index}`,
children: stability.data.index,
}),
` ${stability.data.description.split('. ')[0]}`
),
])
)
),
]);
export const buildModuleProps = headEntries =>
headEntries.map(({ heading, api, stability }) => ({
name: heading.data.name,
href: `${api}.html`,
stability: parseInt(stability?.data.index ?? '2', 10),
}));

/**
* Builds the page descriptor for `index.html`
*
* @param {Array<import('@doc-kit/core/generators/metadata/types').MetadataEntry>} entries
*/
export const buildIndexPage = entries => {
const head = createSyntheticHead('index', 'Index');
const moduleEntries = getSortedHeadNodes(entries);
const config = getConfig('jsx-ast');
const head = createSyntheticHead(
'index',
`${config.project} Documentation Index`
);

return {
head,
entries: [
wrapAsEntry(head, [
buildStabilityOverview(moduleEntries.filter(entry => entry.stability)),
createJSXElement(JSX_IMPORTS.IndexPage.name, {
inline: false,
modules: buildModuleProps(getSortedHeadNodes(entries)),
}),
]),
],
};
Expand Down
Loading