[dev] feat: Started working on component reference docs
This commit is contained in:
parent
965e32b9d5
commit
cb68284d54
10 changed files with 256 additions and 21 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -94,6 +94,10 @@ sites/dev/public/mstile-150x150.png
|
||||||
sites/dev/public/safari-pinned-tab.svg
|
sites/dev/public/safari-pinned-tab.svg
|
||||||
sites/dev/public/site.webmanifest
|
sites/dev/public/site.webmanifest
|
||||||
|
|
||||||
|
# react docs
|
||||||
|
packages/react/docs
|
||||||
|
|
||||||
|
|
||||||
# Node dependencies
|
# Node dependencies
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,45 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A button with an icon and a label. Common across our UI
|
* A button with an icon and a label, something which we commonly use across our UI.
|
||||||
*
|
*
|
||||||
* @param {object} props - All React props
|
* @component
|
||||||
* @param {string} title - The button title
|
* @param {object} props - All component props
|
||||||
* @param {string} className - Any EXTRA classes to add
|
* @param {string} [props.btnProps={}] - Any props to pass to the button
|
||||||
* @param {string} color - The main button color
|
* @param {string} [props.children=[]] - The button children (content)
|
||||||
* @param {string} href - Set this to make it a link
|
* @param {string} [props.className=''] - Any extra classes to add to the button
|
||||||
|
* @param {string} [props.title=''] - The button title
|
||||||
|
* @param {string} [props.color='primary'] - The main button color, one of DaisyUI's named colors
|
||||||
|
* @param {string} [props.href=false] - Set this to render a link instead of a button
|
||||||
|
* @param {function} [props.onClick=false] - Set this to render a button instead of a link
|
||||||
|
* @returns {JSX.Element}
|
||||||
*/
|
*/
|
||||||
export const IconButton = ({
|
export const IconButton = ({
|
||||||
title = '',
|
|
||||||
className = '',
|
|
||||||
onClick = false,
|
|
||||||
href = false,
|
|
||||||
color = 'primary',
|
|
||||||
children = [],
|
|
||||||
btnProps = {},
|
btnProps = {},
|
||||||
|
children = [],
|
||||||
|
className = '',
|
||||||
|
color = 'primary',
|
||||||
|
href = false,
|
||||||
|
onClick = false,
|
||||||
|
title = '',
|
||||||
}) => {
|
}) => {
|
||||||
const allProps = {
|
const allProps = {
|
||||||
className: `${staticLinkClasses} tw:daisy-btn-${color} hover:tw:text-${color}-content ${className}`,
|
className: `tw:daisy-btn-${color} hover:tw:text-${color}-content ${className}`,
|
||||||
title: title,
|
title: title,
|
||||||
...btnProps,
|
...btnProps,
|
||||||
}
|
}
|
||||||
if (onClick) allProps.onClick = onClick
|
if (onClick) allProps.onClick = onClick
|
||||||
else if (href) allProps.href = href
|
else if (href) allProps.href = href
|
||||||
|
|
||||||
return onClick ? <button {...allProps}>{children}</button> : <a {...allProps}>{children}</a>
|
return onClick ? (
|
||||||
|
<button {...allProps}>
|
||||||
|
<div className={`tw:text-${color}-content ${staticLinkClasses}`}>{children}</div>
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<a {...allProps}>
|
||||||
|
<div className={`tw:text-${color}-content ${staticLinkClasses}`}>{children}</div>
|
||||||
|
</a>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const staticLinkClasses =
|
const staticLinkClasses =
|
||||||
|
|
|
@ -31,10 +31,10 @@ export const Tabs = ({ tabs = '', active = 0, children, withModal = false }) =>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="tw:border tw:border-base-300 tw:rounded-lg tw:pt-2">
|
||||||
<div className="tw:daisy-tabs tw:daisy-tabs-bordered" role="tablist">
|
<div role="tablist" className="tw:daisy-tabs tw:daisy-tabs-border" role="tablist">
|
||||||
{tablist.map((title, tabId) => {
|
{tablist.map((title, tabId) => {
|
||||||
const btnClasses = `tw:text-lg tw:font-bold tw:capitalize tw:daisy-tab tw:h-auto tw:daisy-tabs-bordered tw:grow tw:py-1 ${
|
const btnClasses = `tw:text-lg tw:font-bold tw:capitalize tw:daisy-tab tw:h-auto tw:grow tw:py-1 ${
|
||||||
activeTab === tabId ? 'tw:daisy-tab-active' : ''
|
activeTab === tabId ? 'tw:daisy-tab-active' : ''
|
||||||
} tw:border-b-2 tw:border-solid tw:border-x-0 tw:border-t-0 tw:bg-transparent`
|
} tw:border-b-2 tw:border-solid tw:border-x-0 tw:border-t-0 tw:bg-transparent`
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ export const Tabs = ({ tabs = '', active = 0, children, withModal = false }) =>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div>{childrenWithTabSetter}</div>
|
<div className="tw:p-4 tw:pb-2">{childrenWithTabSetter}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
30
packages/react/jsdoc.json
Normal file
30
packages/react/jsdoc.json
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"plugins": [ ],
|
||||||
|
"recurseDepth": 10,
|
||||||
|
"source":{
|
||||||
|
"includePattern": ".+\\.mjs$",
|
||||||
|
"excludePattern": "(^|\\/|\\\\)_"
|
||||||
|
},
|
||||||
|
"sourceType": "module",
|
||||||
|
"tags":{
|
||||||
|
"allowUnknownTags": true,
|
||||||
|
"dictionaries":[
|
||||||
|
"jsdoc",
|
||||||
|
"closure"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"templates":{
|
||||||
|
"monospaceLinks": false,
|
||||||
|
"cleverLinks": false,
|
||||||
|
"default":{
|
||||||
|
"outputSourceFiles": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"opts":{
|
||||||
|
"_":[ ],
|
||||||
|
"debug": false,
|
||||||
|
"encoding": "utf8",
|
||||||
|
"explain": true,
|
||||||
|
"recurse": true
|
||||||
|
}
|
||||||
|
}
|
5
packages/react/mkdocs.sh
Executable file
5
packages/react/mkdocs.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
mkdir -p ./docs/components
|
||||||
|
|
||||||
|
jsdoc -c jsdoc.json components/Account/ > ../../sites/dev/prebuild/jsdoc/react/components/account.json
|
||||||
|
jsdoc -c jsdoc.json components/Button/ > ../../sites/dev/prebuild/jsdoc/react/components/button.json
|
|
@ -2,6 +2,18 @@
|
||||||
title: Button
|
title: Button
|
||||||
---
|
---
|
||||||
|
|
||||||
:::note
|
import { DocusaurusDoc } from '@freesewing/react/components/Docusaurus'
|
||||||
This page is yet to be created
|
import { jsdocIconButton } from '@site/prebuild/jsdoc/components.button.mjs'
|
||||||
:::
|
import { ComponentDocs } from '@site/src/components/component-docs.js'
|
||||||
|
|
||||||
|
<DocusaurusDoc>
|
||||||
|
|
||||||
|
The **Button** component family provides the following components:
|
||||||
|
|
||||||
|
- [IconButton](#iconbutton)
|
||||||
|
|
||||||
|
## IconButton
|
||||||
|
|
||||||
|
<ComponentDocs docs={jsdocIconButton} />
|
||||||
|
|
||||||
|
</DocusaurusDoc>
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
"deploy": "docusaurus deploy",
|
"deploy": "docusaurus deploy",
|
||||||
"clear": "docusaurus clear",
|
"clear": "docusaurus clear",
|
||||||
"serve": "docusaurus serve",
|
"serve": "docusaurus serve",
|
||||||
|
"prebuild": "./scripts/prebuild.sh",
|
||||||
|
"predev": "npm run prebuild",
|
||||||
|
"prestart": "npm run prebuild",
|
||||||
"write-translations": "docusaurus write-translations",
|
"write-translations": "docusaurus write-translations",
|
||||||
"write-heading-ids": "docusaurus write-heading-ids"
|
"write-heading-ids": "docusaurus write-heading-ids"
|
||||||
},
|
},
|
||||||
|
|
60
sites/dev/scripts/prebuild.mjs
Normal file
60
sites/dev/scripts/prebuild.mjs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import { root, globDir, readJsonFile, writeFile } from '../../../scripts/fs.mjs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
const prefix = 'packages/react'
|
||||||
|
const cdir = ['prebuild', 'jsdoc', 'react', 'components']
|
||||||
|
const components = await globDir(cdir, '**/*.json')
|
||||||
|
|
||||||
|
for (const file of components) {
|
||||||
|
const data = await processJsdocFile(file)
|
||||||
|
await writeJsdocFiles(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processJsdocFile(file) {
|
||||||
|
const all = {
|
||||||
|
components: {},
|
||||||
|
}
|
||||||
|
const data = await readJsonFile([...cdir, path.basename(file)])
|
||||||
|
const family = path.basename(file.slice(0, -5))
|
||||||
|
all.components[family] = []
|
||||||
|
for (const entry of data) {
|
||||||
|
// Is it a component?
|
||||||
|
const yes = entry.tags
|
||||||
|
? entry.tags.filter((tag) => tag.title === 'component').length > 0
|
||||||
|
: false
|
||||||
|
if (yes)
|
||||||
|
all.components[family].push({
|
||||||
|
family,
|
||||||
|
name: entry.name,
|
||||||
|
file: relativePath(entry.meta.filename, entry.meta.path),
|
||||||
|
line: entry.meta.lineno,
|
||||||
|
importAs: `import { ${entry.name} } from "${importPath(entry.meta.path)}"`,
|
||||||
|
desc: entry.description,
|
||||||
|
params: entry.params,
|
||||||
|
return: entry.returns,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeJsdocFiles(data) {
|
||||||
|
for (const [family, d] of Object.entries(data.components)) {
|
||||||
|
const code = d.map(
|
||||||
|
(entry) => `export const jsdoc${entry.name} = ${JSON.stringify(entry)}` + '\n'
|
||||||
|
)
|
||||||
|
await writeFile(['prebuild', 'jsdoc', `components.${family}.mjs`], code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function importPath(folder) {
|
||||||
|
return `@freesewing/react` + folder.split(prefix).pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
function relativePath(filename, folder) {
|
||||||
|
return prefix + folder.split(prefix).pop() + '/' + filename
|
||||||
|
}
|
||||||
|
|
||||||
|
function componentFamily(folder) {
|
||||||
|
return folder.split(`${prefix}/components/`).pop()
|
||||||
|
}
|
6
sites/dev/scripts/prebuild.sh
Executable file
6
sites/dev/scripts/prebuild.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd ../../packages/react
|
||||||
|
./mkdocs.sh
|
||||||
|
cd -
|
||||||
|
node scripts/prebuild.mjs
|
102
sites/dev/src/components/component-docs.js
Normal file
102
sites/dev/src/components/component-docs.js
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Highlight } from '@freesewing/react/components/Highlight'
|
||||||
|
import { Tabs, Tab } from '@freesewing/react/components/Tab'
|
||||||
|
import { FingerprintIcon, WarningIcon } from '@freesewing/react/components/Icon'
|
||||||
|
import { IconButton } from '@freesewing/react/components/Button'
|
||||||
|
import { MiniNote } from '@freesewing/react/components/Mini'
|
||||||
|
|
||||||
|
export const ComponentDocs = ({ docs }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>{docs.desc}</p>
|
||||||
|
<Tabs tabs="Import, Props, Example, Source">
|
||||||
|
<Tab>
|
||||||
|
<p>
|
||||||
|
You can import the <code>{docs.name}</code> component from the <b>{docs.family}</b>{' '}
|
||||||
|
component family in the <code>@freesewing/react</code> package:
|
||||||
|
</p>
|
||||||
|
<Highlight language="js">{docs.importAs}</Highlight>
|
||||||
|
</Tab>
|
||||||
|
<Tab>
|
||||||
|
<p>
|
||||||
|
The <code>{docs.name}</code> component takes the following props:
|
||||||
|
</p>
|
||||||
|
<PropsTable docs={docs} />
|
||||||
|
</Tab>
|
||||||
|
<Tab>
|
||||||
|
<MiniNote>
|
||||||
|
Note that this component will take up the full width made available to it.
|
||||||
|
</MiniNote>
|
||||||
|
<Highlight language="js">
|
||||||
|
{[
|
||||||
|
`import { FingerprintIcon, WarningIcon } from '@freesewing/react/components/Icon'`,
|
||||||
|
`import { IconButton } from '@freesewing/react/components/Button'`,
|
||||||
|
``,
|
||||||
|
`<IconButton>`,
|
||||||
|
` <FingerprintIcon />`,
|
||||||
|
` Primary (default)`,
|
||||||
|
`</IconButton>`,
|
||||||
|
`<br />`,
|
||||||
|
`<IconButton color="warning">`,
|
||||||
|
` <WarningIcon />`,
|
||||||
|
` Warning`,
|
||||||
|
`</IconButton>`,
|
||||||
|
].join('\n')}
|
||||||
|
</Highlight>
|
||||||
|
<IconButton>
|
||||||
|
<FingerprintIcon />
|
||||||
|
Primary (default)
|
||||||
|
</IconButton>
|
||||||
|
<br />
|
||||||
|
<IconButton color="warning">
|
||||||
|
<WarningIcon />
|
||||||
|
Warning
|
||||||
|
</IconButton>
|
||||||
|
</Tab>
|
||||||
|
<Tab>
|
||||||
|
<p>
|
||||||
|
The <code>{docs.name}</code> component is defined{' '}
|
||||||
|
<a
|
||||||
|
href={`https://codeberg.org/freesewing/freesewing/src/branch/develop/${docs.file}#L${docs.line}`}
|
||||||
|
>
|
||||||
|
on{' '}
|
||||||
|
<b>
|
||||||
|
line
|
||||||
|
{docs.line}
|
||||||
|
</b>{' '}
|
||||||
|
in <b>{docs.file}</b>
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PropsTable = ({ docs }) => (
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Optional</th>
|
||||||
|
<th>Default Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{docs.params.map((prop, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td>{prop.name}</td>
|
||||||
|
<td>{prop.type.names}</td>
|
||||||
|
<td>{prop.description}</td>
|
||||||
|
<td>{prop.optional ? 'yes' : 'no'}</td>
|
||||||
|
<td>
|
||||||
|
<code>{prop.defaultvalue}</code>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue