[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/site.webmanifest
|
||||
|
||||
# react docs
|
||||
packages/react/docs
|
||||
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
|
|
|
@ -1,32 +1,45 @@
|
|||
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
|
||||
* @param {string} title - The button title
|
||||
* @param {string} className - Any EXTRA classes to add
|
||||
* @param {string} color - The main button color
|
||||
* @param {string} href - Set this to make it a link
|
||||
* @component
|
||||
* @param {object} props - All component props
|
||||
* @param {string} [props.btnProps={}] - Any props to pass to the button
|
||||
* @param {string} [props.children=[]] - The button children (content)
|
||||
* @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 = ({
|
||||
title = '',
|
||||
className = '',
|
||||
onClick = false,
|
||||
href = false,
|
||||
color = 'primary',
|
||||
children = [],
|
||||
btnProps = {},
|
||||
children = [],
|
||||
className = '',
|
||||
color = 'primary',
|
||||
href = false,
|
||||
onClick = false,
|
||||
title = '',
|
||||
}) => {
|
||||
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,
|
||||
...btnProps,
|
||||
}
|
||||
if (onClick) allProps.onClick = onClick
|
||||
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 =
|
||||
|
|
|
@ -31,10 +31,10 @@ export const Tabs = ({ tabs = '', active = 0, children, withModal = false }) =>
|
|||
)
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="tw:daisy-tabs tw:daisy-tabs-bordered" role="tablist">
|
||||
<div className="tw:border tw:border-base-300 tw:rounded-lg tw:pt-2">
|
||||
<div role="tablist" className="tw:daisy-tabs tw:daisy-tabs-border" role="tablist">
|
||||
{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' : ''
|
||||
} 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>{childrenWithTabSetter}</div>
|
||||
<div className="tw:p-4 tw:pb-2">{childrenWithTabSetter}</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
|
||||
---
|
||||
|
||||
:::note
|
||||
This page is yet to be created
|
||||
:::
|
||||
import { DocusaurusDoc } from '@freesewing/react/components/Docusaurus'
|
||||
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",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"prebuild": "./scripts/prebuild.sh",
|
||||
"predev": "npm run prebuild",
|
||||
"prestart": "npm run prebuild",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"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