Skip to content

Commit

Permalink
feat(#80): component table
Browse files Browse the repository at this point in the history
  • Loading branch information
kenjishiromajp committed Oct 23, 2023
1 parent 587da6f commit a57393b
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 91 deletions.
12 changes: 6 additions & 6 deletions apps/site/content/design-system/components/alert/code.mdoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Looks
### Looks

```jsx
<div>
Expand All @@ -23,7 +23,7 @@

---

## Text
### Text

```jsx
<div>
Expand All @@ -48,7 +48,7 @@

---

## Heading
### Heading

```jsx
<Alert look="info" heading="I am an alert heading">
Expand All @@ -61,7 +61,7 @@

---

## Custom
### Custom

```jsx
<Alert look="info" icon={TelephoneIcon}>
Expand All @@ -71,7 +71,7 @@

---

## Dismissible
### Dismissible

```jsx
<Alert look="info" dismissible>
Expand All @@ -81,7 +81,7 @@

---

## Controlled
### Controlled

```jsx
() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use client';

import { DocumentElement } from '@keystatic/core';
import { DocumentRenderer } from '@keystatic/core/renderer';
import { Button, Container, Grid, Item } from '@westpac/ui';
import { NewWindowIcon } from '@westpac/ui/icon';
import { useMemo } from 'react';

import { ComponentPropsTable } from '@/components/component-props-table';
import { Code } from '@/components/content-blocks/typography';
Expand All @@ -14,6 +16,15 @@ import { TableOfContents } from '../intro/components';
import { type CodeContentProps } from '.';

export function CodeContent({ content, westpacUIInfo, componentProps, subComponentProps }: CodeContentProps) {
const tableOfContents = useMemo(() => {
return content.reduce((acc, item: DocumentElement & { level?: number }) => {
if (item.type === 'heading' && item?.level && item.level <= 3) {
return [...acc, { title: item.children[0].text as string }];
}
return acc;
}, [] as { title: string }[]);
}, [content]);

return (
<>
<section className="py-7 sm:pb-10 sm:pt-15">
Expand Down Expand Up @@ -58,14 +69,17 @@ export function CodeContent({ content, westpacUIInfo, componentProps, subCompone
</table>
</Item>
<Item span={{ initial: 12, sm: 4 }} start={{ initial: 1, sm: 9 }}>
<TableOfContents contents={[{ title: 'test' }]} />
<TableOfContents contents={tableOfContents} />
</Item>
</Grid>
</Container>
</section>
<Container className="py-15">
<DocumentRenderer document={content} renderers={DOCUMENT_RENDERERS} componentBlocks={{}} />
</Container>
<section className="border-t border-t-border">
<Container className="py-15">
<h2 className="typography-body-6 mb-4 font-bold sm:mb-8">Development examples</h2>
<DocumentRenderer document={content} renderers={DOCUMENT_RENDERERS} componentBlocks={{}} />
</Container>
</section>
<section className="bg-white py-7 sm:pb-10 sm:pt-15">
<Container>
<Heading level={2}>Props</Heading>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,18 @@ function Group({ label, level, crumbs, children, ...props }: GroupProps) {
<AnimatePresence initial={false}>
{open && (
<m.div
className="overflow-hidden"
initial={{
height: 0,
opacity: 0,
opacity: 1,
}}
animate={{
height: 'auto',
opacity: 1,
}}
exit={{
height: 0,
opacity: 0,
opacity: 1,
}}
transition={{ duration: 0.3, ease: 'easeInOut' }}
>
Expand Down
2 changes: 2 additions & 0 deletions apps/site/src/components/code/code.component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';
import React, { Fragment, useCallback, useMemo, useState } from 'react';
import { LiveProvider } from 'react-live';
import { useOverlayTriggerState } from 'react-stately';

import { StaticCode } from '../static-code';

Expand All @@ -13,6 +14,7 @@ const LIVE_SCOPE = {
useState,
useCallback,
useMemo,
useOverlayTriggerState,
Fragment,
React,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,64 @@
import { Badge, Table } from '@westpac/ui';
import { clsx } from 'clsx';
import React from 'react';

import { type ComponentPropsTableProps } from './component-props-table.types';

export function ComponentPropsTable({ className, componentProps, ...props }: ComponentPropsTableProps) {
console.dir(componentProps, { depth: null });
return (
<Table bordered striped {...props}>
<Table.Caption className="text-left">{componentProps.displayName} props</Table.Caption>
<Table.Header>
<Table.Row>
{[
{ label: 'Property', className: 'w-1/12' },
{ label: 'Type', className: 'w-1/12' },
{ label: 'Default', className: 'w-1/12' },
{ label: 'Required', className: 'w-1/12' },
{ label: 'Description', className: 'w-3/12' },
].map(({ label, className }) => (
<Table.HeaderCell key={label} className={`text-left ${className}`}>
{label}
</Table.HeaderCell>
))}
</Table.Row>
</Table.Header>
<Table.Body>
{Object.entries(componentProps.props || {}).map(([key, value]) => {
const type = value.type.name;
const defaultValue = value.defaultValue?.value;
const required = value.required ? 'true' : 'false';
<div className="-mx-2 overflow-x-auto px-2 xsl:-mx-5 xsl:px-5 sm:-mx-6 sm:px-6 md:-mx-8 md:px-8 lg:-mx-10 lg:px-10">
<Table bordered striped {...props} className={clsx('min-w-[800px]', className)}>
<Table.Caption className="text-left">{componentProps.displayName} props</Table.Caption>
<Table.Header>
<Table.Row>
{[
{ label: 'Property', className: 'w-1/12' },
{ label: 'Type', className: 'w-1/12' },
{ label: 'Default', className: 'w-1/12' },
{ label: 'Required', className: 'w-1/12' },
{ label: 'Description', className: 'w-3/12' },
].map(({ label, className }) => (
<Table.HeaderCell key={label} className={`text-left ${className}`}>
{label}
</Table.HeaderCell>
))}
</Table.Row>
</Table.Header>
<Table.Body>
{Object.entries(componentProps.props || {}).map(([key, value]) => {
const type = value.type.name;
const defaultValue = value.defaultValue?.value;
const required = value.required ? 'true' : 'false';

return (
<Table.Row key={key}>
<Table.Cell className="w-1/12">{key}</Table.Cell>
<Table.Cell className="w-1/12">
{type && (
<Badge color="faint" className="whitespace-normal bg-background text-left">
{type}
</Badge>
)}
</Table.Cell>
<Table.Cell className="w-1/12">
{defaultValue && (
return (
<Table.Row key={key}>
<Table.Cell className="w-1/12">{key}</Table.Cell>
<Table.Cell className="w-1/12">
{type && (
<Badge color="faint" className="whitespace-normal bg-background text-left">
{type}
</Badge>
)}
</Table.Cell>
<Table.Cell className="w-1/12">
{defaultValue && (
<Badge color="faint" className="bg-background">
{defaultValue}
</Badge>
)}
</Table.Cell>
<Table.Cell className="w-1/12">
<Badge color="faint" className="bg-background">
{defaultValue}
{required}
</Badge>
)}
</Table.Cell>
<Table.Cell className="w-1/12">
<Badge color="faint" className="bg-background">
{required}
</Badge>
</Table.Cell>
<Table.Cell className="w-3/12">{value.description}</Table.Cell>
</Table.Row>
);
})}
</Table.Body>
</Table>
</Table.Cell>
<Table.Cell className="w-3/12">{value.description}</Table.Cell>
</Table.Row>
);
})}
</Table.Body>
</Table>
</div>
);
}
66 changes: 36 additions & 30 deletions packages/ui/generate-component-types.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,44 @@ const TYPES_TO_BE_IGNORED = [
const results = await glob(components);

const data = Object.fromEntries(
tsConfigParser.parse(results).map(({ displayName, description, props, filePath, ...rest }) => {
tsConfigParser.parse(results).reduce((acc, { displayName, description, props, filePath, tags }) => {
if (tags.private !== undefined) {
return acc;
}
return [
filePath.replace(process.cwd(), '').replace('/src/components/', '').replace('src/components/', ''),
{
displayName,
description,
// Sort the required props before the non-required props, then sort alphabetically
props: Object.fromEntries(
Object.values(props)
.sort((a, b) => {
if (a.required !== b.required) {
if (a.required) return -1;
return 1;
}
return a.name.localeCompare(b.name);
})
.filter(a => {
if (TYPES_TO_BE_IGNORED.includes(a.parent ? a.parent.name : '')) {
return false;
}
return true;
})
.map(a => {
if (a.name === 'tag' && a.type.name.indexOf('more ...') !== -1) {
return [a.name, { ...a, type: { ...a.type, name: 'keyof IntrinsicElements' } }];
}
return [a.name, a];
}),
),
},
...acc,
[
filePath.replace(process.cwd(), '').replace('/src/components/', '').replace('src/components/', ''),
{
displayName,
description,
// Sort the required props before the non-required props, then sort alphabetically
props: Object.fromEntries(
Object.values(props)
.sort((a, b) => {
if (a.required !== b.required) {
if (a.required) return -1;
return 1;
}
return a.name.localeCompare(b.name);
})
.filter(a => {
if (TYPES_TO_BE_IGNORED.includes(a.parent ? a.parent.name : '')) {
return false;
}
return true;
})
.map(a => {
if (a.name === 'tag' && a.type.name.indexOf('more ...') !== -1) {
return [a.name, { ...a, type: { ...a.type, name: 'keyof IntrinsicElements' } }];
}
return [a.name, a];
}),
),
},
],
];
}),
}, []),
);

// Create the output folder if it doesn't exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ interface OptionProps<T = any> {
state: ListState<T>;
}

/**
* @private
*/
export function Option({ item, state }: OptionProps) {
const ref = React.useRef<HTMLLIElement>(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { Option } from '../list-box-option/index.js';

import { type ListBoxSectionProps } from './list-box-section.types.js';

/**
* @private
*/
export function ListBoxSection({ section, state }: ListBoxSectionProps) {
const { itemProps, headingProps, groupProps } = useListBoxSection({
heading: section.rendered,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { useListBox } from 'react-aria';
import { ListBoxSection, Option } from './components/index.js';
import { ListBoxProps } from './list-box.types.js';

/**
* @private
*/
export function ListBox(props: ListBoxProps) {
const ref = React.useRef<HTMLUListElement>(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import * as React from 'react';
import { DismissButton, Overlay, usePopover } from 'react-aria';

import { PopoverProps } from './popover.types.js';

/**
* @private
*/
export function Popover(props: PopoverProps) {
const ref = React.useRef<HTMLDivElement>(null);
const { popoverRef = ref, state, children, className, isNonModal, portalContainer } = props;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { HTMLAttributes, ReactNode } from 'react';
import { type AriaPopoverProps } from 'react-aria';
import { type OverlayTriggerState } from 'react-stately';

// @private
export type PopoverProps = Omit<AriaPopoverProps, 'popoverRef'> & {
/**
* Popover content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { styles } from './add-ons.styles.js';
import { InputAddOnProps } from './add-ons.types.js';
import { DefaultAddOn, IconAddOn, TextAddOn } from './components/index.js';

/**
* @private
*/
export const InputAddOn = ({
position,
icon: Icon,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import React from 'react';
import { styles } from './default-add-on.styles.js';
import { type DefaultAddOnProps } from './default-add-on.types.js';

/**
* @private
*/
export const DefaultAddOn = ({ position, className, children, ...props }: DefaultAddOnProps) => {
return (
<div className={styles({ className })} {...props}>
Expand Down
Loading

0 comments on commit a57393b

Please sign in to comment.