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

docs: Implement interactive component documentation #128

Merged
merged 10 commits into from
Mar 4, 2025
43 changes: 6 additions & 37 deletions apps/starlight/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,56 +1,25 @@
// @ts-check
import { defineConfig } from 'astro/config';
import solidJs from '@astrojs/solid-js';
import starlight from '@astrojs/starlight';
import { sidebar } from './src/assets/sidebar.ts';

// https://astro.build/config
export default defineConfig({
base: '/jslibs/',
site: 'https://spuxx-dev.github.io',

integrations: [
solidJs(),
starlight({
title: '@spuxx/jslibs',
favicon: '/favicon.png',
social: {
github: 'https://github.com/spuxx-dev/jslibs',
blueSky: 'https://bsky.app/profile/spuxx.bsky.social',
},
sidebar: [
{
label: 'js-utils',
items: [
{ label: 'Introduction', slug: 'js-utils' },
{
label: 'Types',
slug: 'js-utils/types',
},
{
label: 'Services',
autogenerate: { directory: 'js-utils/services' },
},
{
label: 'Utilities',
autogenerate: { directory: 'js-utils/utils' },
},
],
},
{
label: 'browser-utils',
items: [
{
label: 'Introduction',
slug: 'browser-utils',
},
{
label: 'Styles and Themes',
slug: 'browser-utils/styles-and-themes',
},
{
label: 'Services',
autogenerate: { directory: 'browser-utils/services' },
},
],
},
],
customCss: ['./src/styles/global.css'],
sidebar,
}),
],
});
3 changes: 3 additions & 0 deletions apps/starlight/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
"@astrojs/mdx": "4.0.8",
"@astrojs/solid-js": "5.0.5",
"@astrojs/starlight": "0.32.1",
"@spuxx/browser-utils": "workspace:@spuxx/browser-utils@*",
"@spuxx/js-utils": "workspace:@spuxx/js-utils@*",
"@spuxx/solid": "workspace:@spuxx/solid@*",
"astro": "5.4.1",
"sharp": "0.33.5",
"solid-js": "1.9.4",
Expand Down
Binary file removed apps/starlight/src/assets/houston.webp
Binary file not shown.
57 changes: 57 additions & 0 deletions apps/starlight/src/assets/sidebar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { StarlightUserConfigWithPlugins } from 'node_modules/@astrojs/starlight/utils/plugins';

export const sidebar: StarlightUserConfigWithPlugins['sidebar'] = [
{
label: 'js-utils',
items: [
{ label: 'Introduction', slug: 'js-utils' },
{
label: 'Types',
slug: 'js-utils/types',
},
{
label: 'Services',
autogenerate: { directory: 'js-utils/services' },
},
{
label: 'Utilities',
autogenerate: { directory: 'js-utils/utils' },
},
],
},
{
label: 'browser-utils',
items: [
{
label: 'Introduction',
slug: 'browser-utils',
},
{
label: 'Styles and Themes',
slug: 'browser-utils/styles-and-themes',
},
{
label: 'Services',
autogenerate: { directory: 'browser-utils/services' },
},
],
},
{
label: 'solid',
items: [
{
label: 'Introduction',
slug: 'solid',
},
{
label: 'Components',
items: [
{
label: 'Layout',
autogenerate: { directory: 'solid/components/layout' },
},
],
},
],
},
];
12 changes: 12 additions & 0 deletions apps/starlight/src/components/interactive/Interactive.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
import { InteractiveSolid } from './InteractiveSolid';
import { type Argument } from './types';

interface Props {
componentName: string;
argDefinitions: Record<string, Argument<any>>;
title?: string;
}
---

<InteractiveSolid client:only="solid-js" {...Astro.props} />
51 changes: 51 additions & 0 deletions apps/starlight/src/components/interactive/InteractiveControls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Container } from '@packages/solid';
import { createSignal, For, type Component } from 'solid-js';
import { isEmptyOrWhitespace } from '@spuxx/js-utils';
import type { Argument } from './types';

interface Props {
argDefinitions: Record<string, Argument<unknown>>;
onArgsChange: (args: Record<string, unknown>) => void;
}

export const InteractiveControls: Component<Props> = (props) => {
const { argDefinitions, onArgsChange } = props;
const [args, setArgs] = createSignal<Record<string, unknown>>({});

const handleArgsChange = (event: Event) => {
const target = event.target as HTMLInputElement;
const newArgs = { ...args(), [target.name]: target.checked ?? target.value };
for (const key in newArgs) {
if (isEmptyOrWhitespace(newArgs[key])) delete newArgs[key];
}
setArgs(newArgs);
onArgsChange(newArgs);
};

const controls = Object.entries(argDefinitions).map(([key, def]) => (
<label>
{key}
{': '}
{def.type === 'boolean' && (
<input
type="checkbox"
name={key}
checked={args()[key] as boolean}
on:change={handleArgsChange}
/>
)}
{def.options && (
<select name={key} on:change={handleArgsChange}>
<option label="Use default value"></option>
<For each={def.options}>{(option) => <option>{String(option)}</option>}</For>
</select>
)}
</label>
));

return (
<Container noPadding style={{ display: 'flex', 'flex-direction': 'column' }}>
<For each={controls}>{(control) => control}</For>
</Container>
);
};
71 changes: 71 additions & 0 deletions apps/starlight/src/components/interactive/InteractiveSolid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { createEffect, createSignal, Show, type Component } from 'solid-js';
import { render } from 'solid-js/web';
import { Container, Divider, Heading } from '@spuxx/solid';
import { InteractiveControls } from './InteractiveControls';
import type { Argument } from './types';

interface Props {
componentName: string;
argDefinitions: Record<string, Argument<unknown>>;
title?: string;
}

export const InteractiveSolid: Component<Props> = (props) => {
const { title, componentName, argDefinitions } = props;

let dispose: (() => void) | undefined;
// eslint-disable-next-line prefer-const
let containerRef: HTMLDivElement | null = null;

const [state, setState] = createSignal<{
component: Component | null;
args: Record<string, unknown>;
}>({ component: null, args: {} });

const importComponent = async () => {
const module = await import(`@spuxx/solid`);
const importedComponent = module[componentName as keyof typeof module] as Component;
setState({ component: importedComponent, args: {} });
};
importComponent();

const handleArgsChange = (args: Record<string, unknown>) => {
setState({ component: state().component!, args });
};

createEffect(() => {
const { component, args } = state();
if (dispose) {
dispose();
}

if (containerRef && component) {
dispose = render(() => component(args), containerRef);
}
});

return (
<div>
<Container variant="contained" color="gradient">
<Heading level={4}>Interactive Example: {title ?? componentName}</Heading>
<Divider />

<Show when={state().component}>
<InteractiveControls argDefinitions={argDefinitions} onArgsChange={handleArgsChange} />
<Container
variant="contained"
color="background"
style={{
padding: '2rem',
}}
>
<div ref={containerRef!} />
</Container>
</Show>
<Show when={!state().component}>
<p>No component specified.</p>
</Show>
</Container>
</div>
);
};
3 changes: 3 additions & 0 deletions apps/starlight/src/components/interactive/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Interactive from './Interactive.astro';
export * from './types';
export { Interactive };
4 changes: 4 additions & 0 deletions apps/starlight/src/components/interactive/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Argument<T> {
type: 'string' | 'number' | 'boolean';
options?: T[];
}
4 changes: 4 additions & 0 deletions apps/starlight/src/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ import { CardGrid, Card, LinkCard } from '@astrojs/starlight/components';
`@spuxx/browser-utils` contains a selection of common utilities for use in browser applications.
<LinkCard title="View Documentation" href="browser-utils" link />
</Card>
<Card title="@spuxx/solid" icon="seti:html">
`@spuxx/solid` contains a selection of components for use in SolidJS applications.
<LinkCard title="View Documentation" href="solid" link />
</Card>
</CardGrid>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: 'Divider'
description: 'A library containing various production-ready components for SolidJS applications.'
---

import TypeDoc from '@docs/solid/components/layout/divider.md';
import { BaseColor, ContentColor } from '@packages/browser-utils/dist/main';
import { Interactive } from '@src/components/interactive';

<Interactive
componentName="Divider"
argDefinitions={{
color: {
type: 'string',
options: Object.values({ ...BaseColor, ...ContentColor }),
},
variant: {
type: 'string',
options: ['straight', 'sleek'],
},
vertical: {
type: 'boolean',
},
}}
/>

<TypeDoc />
8 changes: 8 additions & 0 deletions apps/starlight/src/content/docs/solid/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: 'Solid'
description: 'A library containing various production-ready components for SolidJS applications.'
---

import README from '@packages/solid/README.md';

<README />
2 changes: 2 additions & 0 deletions apps/starlight/src/styles/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import '@spuxx/browser-utils/styles';
@import '@spuxx/browser-utils/themes';
8 changes: 5 additions & 3 deletions packages/browser-utils/src/styles.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
@import './styles/variables.css';
@import './styles/variants.css';
@import './styles/colors.css';
@import './styles/animations.css';

@import './styles/layout.css';
@import './styles/application.css';

@import './styles/components.css';
@import './styles/modal.css';
@import './styles/variants.css';
@import './styles/colors.css';
@import './styles/animations.css';
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
}

.spx-container[spx-variant='outlined'] {
color: inherit;
color: inherit !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

.spx-divider[spx-vertical] {
display: flex;
min-height: 1em;
height: 100%;
align-self: stretch;
width: 1px;
Expand Down
Loading