Skip to content

Commit 2cff44f

Browse files
author
Eric Olkowski
committed
feat: Created PropsTable component structure
1 parent 14320b8 commit 2cff44f

File tree

4 files changed

+225
-29
lines changed

4 files changed

+225
-29
lines changed

package-lock.json

Lines changed: 40 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@nanostores/react": "^0.8.0",
4545
"@patternfly/patternfly": "^6.0.0",
4646
"@patternfly/react-core": "^6.0.0",
47+
"@patternfly/react-table": "^6.0.0",
4748
"@types/react": "^18.3.12",
4849
"@types/react-dom": "^18.3.1",
4950
"astro": "^5.4.1",

src/components/PropsTable.tsx

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import { Label, Stack } from '@patternfly/react-core'
2+
import {
3+
Table,
4+
Thead,
5+
Th,
6+
Tr,
7+
Tbody,
8+
Td,
9+
TableText,
10+
} from '@patternfly/react-table'
11+
import { css } from '@patternfly/react-styles'
12+
import accessibleStyles from '@patternfly/react-styles/css/utilities/Accessibility/accessibility'
13+
import textStyles from '@patternfly/react-styles/css/utilities/Text/text'
14+
15+
type ComponentProp = {
16+
name: string
17+
isRequired?: boolean
18+
isBeta?: boolean
19+
isDeprecated?: boolean
20+
type?: string
21+
defaultValue?: string
22+
description: string
23+
}
24+
25+
type PropsTableProps = {
26+
componentName: string
27+
componentDescription?: string
28+
componentProps?: ComponentProp[]
29+
}
30+
31+
export const PropsTable: React.FunctionComponent<PropsTableProps> = ({
32+
componentName,
33+
componentDescription,
34+
componentProps,
35+
}) => {
36+
const hasPropsToRender = !!componentProps?.length
37+
const betaDeprecatedProps = hasPropsToRender
38+
? componentProps.filter((prop) => prop.isBeta && prop.isDeprecated)
39+
: []
40+
41+
if (betaDeprecatedProps.length) {
42+
throw new Error(
43+
`The following ${componentName} props have both the isBeta and isDeprecated tag: ${betaDeprecatedProps.map((prop) => prop.name).join(', ')}`,
44+
)
45+
}
46+
47+
const renderTagLabel = (componentProp: ComponentProp) => {
48+
const { isBeta, isDeprecated } = componentProp
49+
if (!isBeta && !isDeprecated) {
50+
return null
51+
}
52+
53+
return (
54+
<Label
55+
// Would need design eyes on outline vs filled
56+
variant="outline"
57+
color={`${isBeta ? 'blue' : 'orange'}`}
58+
isCompact
59+
>
60+
{isBeta ? 'Beta' : 'Deprecated'}
61+
</Label>
62+
)
63+
}
64+
65+
return (
66+
<>
67+
<h3>{componentName}</h3>
68+
<Stack hasGutter>
69+
{componentDescription && (
70+
<div className={css(textStyles.textColorSubtle)}>
71+
{componentDescription}
72+
</div>
73+
)}
74+
{hasPropsToRender && (
75+
<>
76+
<div id={`${componentName}-required`}>
77+
<span className={css(textStyles.textColorRequired)}>*</span>{' '}
78+
<span className={css(textStyles.textColorSubtle)}>
79+
indicates a required prop
80+
</span>
81+
</div>
82+
<Table
83+
variant="compact"
84+
aria-label={`Props for ${componentName}`}
85+
aria-describedby={`${componentName}-required`}
86+
gridBreakPoint="grid-lg"
87+
>
88+
<Thead>
89+
<Tr>
90+
<Th width={20}>Name</Th>
91+
<Th width={20}>Type</Th>
92+
<Th>Default</Th>
93+
<Th>Description</Th>
94+
</Tr>
95+
</Thead>
96+
<Tbody>
97+
{componentProps?.map((prop: ComponentProp) => (
98+
<Tr key={prop.name}>
99+
<Td>
100+
<TableText wrapModifier="breakWord">
101+
{prop.name}
102+
{prop.isRequired ? (
103+
<>
104+
<span
105+
aria-hidden="true"
106+
className={css(textStyles.textColorRequired)}
107+
>
108+
*
109+
</span>
110+
<span
111+
className={css(accessibleStyles.screenReader)}
112+
>
113+
required
114+
</span>
115+
</>
116+
) : (
117+
''
118+
)}{' '}
119+
{renderTagLabel(prop)}
120+
</TableText>
121+
</Td>
122+
<Td>
123+
<TableText wrapModifier="breakWord">
124+
{prop.type || 'No type info'}
125+
</TableText>
126+
</Td>
127+
<Td>
128+
<TableText wrapModifier="breakWord">
129+
{prop.defaultValue}
130+
</TableText>
131+
</Td>
132+
<Td>
133+
<TableText wrapModifier="breakWord">
134+
{prop.description}
135+
</TableText>
136+
</Td>
137+
</Tr>
138+
))}
139+
</Tbody>
140+
</Table>
141+
</>
142+
)}
143+
</Stack>
144+
</>
145+
)
146+
}

src/pages/index.astro

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
11
---
22
import '../styles/global.scss'
33
import MainLayout from '../layouts/Main.astro'
4+
import { PropsTable } from '../components/PropsTable'
5+
6+
const propsData = [
7+
{
8+
name: 'variant',
9+
type: "'success' | 'danger' | 'warning' | 'info' | 'custom'",
10+
defaultValue: '',
11+
description: 'Adds alert variant styles.',
12+
isBeta: true,
13+
},
14+
{
15+
name: 'children',
16+
isRequired: true,
17+
type: 'ReactNode',
18+
defaultValue: '',
19+
description: 'Content rendered inside the alert.',
20+
},
21+
{
22+
name: 'timeoutAnimation',
23+
isRequired: false,
24+
type: undefined,
25+
defaultValue: '3000',
26+
description:
27+
'If the user hovers over the alert and `timeout` expires, this is how long to wait before finally dismissing the alert.',
28+
isDeprecated: true,
29+
},
30+
]
431
---
532

633
<html lang="en">
@@ -12,6 +39,16 @@ import MainLayout from '../layouts/Main.astro'
1239
<title>PatternFly</title>
1340
</head>
1441
<body>
15-
<MainLayout title="PatternFly X Astro"> Page content </MainLayout>
42+
<MainLayout title="PatternFly X Astro">
43+
<PropsTable
44+
componentName="Alert"
45+
componentDescription="The main alert component."
46+
componentProps={propsData}
47+
/>
48+
<PropsTable
49+
componentName="AlertGroup"
50+
componentDescription="The container to render a list of alerts."
51+
/>
52+
</MainLayout>
1653
</body>
1754
</html>

0 commit comments

Comments
 (0)