diff --git a/.changeset/witty-planets-sing.md b/.changeset/witty-planets-sing.md new file mode 100644 index 0000000000..4c58393d0e --- /dev/null +++ b/.changeset/witty-planets-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Fix the Icon component when the name is not found to return null instead of an empty SVG. diff --git a/canon-docs/src/app/(docs)/components/box/page.mdx b/canon-docs/src/app/(docs)/components/box/page.mdx index 2e1d00a274..c1413dbe19 100644 --- a/canon-docs/src/app/(docs)/components/box/page.mdx +++ b/canon-docs/src/app/(docs)/components/box/page.mdx @@ -1,9 +1,10 @@ import { CodeBlock } from '@/components/CodeBlock'; import { PropsTable } from '@/components/PropsTable'; -import { spacePropsList } from '@/utils/spaceProps'; import { Tabs } from '@/components/Tabs'; import { Snippet } from '@/components/Snippet'; import { BoxPreview } from '@/snippets/box'; +import { boxPropDefs } from './props'; +import { spacingPropDefs } from '../../../../utils/propDefs'; # Box @@ -36,60 +37,13 @@ Box is the lowest-level component in Canon. It provides a consistent API for sty This is the Box component, our lowest-level component. Here are all the available properties. - + Padding and margin are used to create space around your component using our predefined spacing tokens. We would recommend to use padding over margin to avoid collapsing margins but both are available. - + ## Examples diff --git a/canon-docs/src/app/(docs)/components/box/props.ts b/canon-docs/src/app/(docs)/components/box/props.ts new file mode 100644 index 0000000000..f3e38984dd --- /dev/null +++ b/canon-docs/src/app/(docs)/components/box/props.ts @@ -0,0 +1,24 @@ +import { + classNamePropDefs, + displayPropDefs, + heightPropDefs, + positionPropDefs, + stylePropDefs, + widthPropDefs, +} from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const boxPropDefs: Record = { + as: { + type: 'enum', + values: ['div', 'span'], + default: 'div', + responsive: true, + }, + ...widthPropDefs, + ...heightPropDefs, + ...positionPropDefs, + ...displayPropDefs, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/button/page.mdx b/canon-docs/src/app/(docs)/components/button/page.mdx index c92b5b9921..a92a6675d1 100644 --- a/canon-docs/src/app/(docs)/components/button/page.mdx +++ b/canon-docs/src/app/(docs)/components/button/page.mdx @@ -11,7 +11,7 @@ import { ButtonResponsive, } from '@/snippets/button'; import { buttonVariants } from '@/snippets/_snippets'; -import { buttonPropDefs } from '../../../../../../packages/canon/src/components/Button/Button.props'; +import { buttonPropDefs } from './props'; # Button diff --git a/canon-docs/src/app/(docs)/components/button/props.ts b/canon-docs/src/app/(docs)/components/button/props.ts new file mode 100644 index 0000000000..813dcaa6f0 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/button/props.ts @@ -0,0 +1,19 @@ +import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const buttonPropDefs: Record = { + variant: { + type: 'enum', + values: ['primary', 'secondary'], + default: 'primary', + responsive: true, + }, + size: { + type: 'enum', + values: ['small', 'medium'], + default: 'medium', + responsive: true, + }, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/checkbox/page.mdx b/canon-docs/src/app/(docs)/components/checkbox/page.mdx index 26a5d0f955..fd2ec42e1b 100644 --- a/canon-docs/src/app/(docs)/components/checkbox/page.mdx +++ b/canon-docs/src/app/(docs)/components/checkbox/page.mdx @@ -4,6 +4,7 @@ import { Snippet } from '@/components/Snippet'; import { Tabs } from '@/components/Tabs'; import { CodeBlock } from '@/components/CodeBlock'; import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; +import { checkboxPropDefs } from './props'; # Checkbox @@ -42,50 +43,7 @@ A checkbox component that can be used to trigger actions. - void", - responsive: false, - }, - disabled: { - type: 'boolean', - responsive: false, - }, - required: { - type: 'boolean', - responsive: false, - }, - name: { - type: 'string', - responsive: false, - }, - value: { - type: 'string', - responsive: false, - }, - className: { - type: 'string', - responsive: false, - }, - style: { - type: 'CSSProperties', - responsive: false, - }, - }} -/> + ## Examples diff --git a/canon-docs/src/app/(docs)/components/checkbox/props.ts b/canon-docs/src/app/(docs)/components/checkbox/props.ts new file mode 100644 index 0000000000..8abbac1ec9 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/checkbox/props.ts @@ -0,0 +1,44 @@ +import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const checkboxPropDefs: Record = { + label: { + type: 'string', + responsive: false, + }, + defaultChecked: { + type: 'enum', + values: ['boolean', "'indeterminate'"], + responsive: false, + }, + checked: { + type: 'enum', + values: ['boolean', "'indeterminate'"], + responsive: false, + }, + onChange: { + type: 'enum', + values: ["(checked: boolean | 'indeterminate') => void"], + responsive: false, + }, + disabled: { + type: 'enum', + values: ['boolean'], + responsive: false, + }, + required: { + type: 'enum', + values: ['boolean'], + responsive: false, + }, + name: { + type: 'string', + responsive: false, + }, + value: { + type: 'string', + responsive: false, + }, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/container/page.mdx b/canon-docs/src/app/(docs)/components/container/page.mdx index ace3bdcaeb..0dbe0223e5 100644 --- a/canon-docs/src/app/(docs)/components/container/page.mdx +++ b/canon-docs/src/app/(docs)/components/container/page.mdx @@ -1,9 +1,9 @@ import { CodeBlock } from '@/components/CodeBlock'; import { PropsTable } from '@/components/PropsTable'; -import { spacePropsList } from '@/utils/spaceProps'; import { Tabs } from '@/components/Tabs'; import { Snippet } from '@/components/Snippet'; import { ContainerPreview } from '@/snippets/container'; +import { containerPropDefs } from './props'; # Container @@ -32,46 +32,7 @@ content on the page. ## API reference - + ## Examples diff --git a/canon-docs/src/app/(docs)/components/container/props.ts b/canon-docs/src/app/(docs)/components/container/props.ts new file mode 100644 index 0000000000..4a3410ec12 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/container/props.ts @@ -0,0 +1,12 @@ +import { + classNamePropDefs, + stylePropDefs, + gapPropDefs, +} from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const containerPropDefs: Record = { + ...gapPropDefs, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/field/page.mdx b/canon-docs/src/app/(docs)/components/field/page.mdx index 83029be506..54c091faeb 100644 --- a/canon-docs/src/app/(docs)/components/field/page.mdx +++ b/canon-docs/src/app/(docs)/components/field/page.mdx @@ -4,6 +4,12 @@ import { Tabs } from '@/components/Tabs'; import { CodeBlock } from '@/components/CodeBlock'; import { FieldPreview } from '@/snippets/field'; import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; +import { + fieldRootPropDefs, + fieldLabelPropDefs, + fieldDescriptionPropDefs, + fieldErrorPropDefs, +} from './props'; # Field @@ -49,113 +55,25 @@ A wrapper around `Input` or `Select` component to add label, description and err Groups all parts of the field. Renders a `
` element. - string | string[] | null | Promise', - responsive: false, - }, - validationMode: { - type: ['onBlur', 'onChange'], - responsive: false, - }, - validationDebounceTime: { - type: 'number', - responsive: false, - }, - className: { - type: 'string', - responsive: false, - }, - style: { - type: 'CSSProperties', - responsive: false, - }, - }} -/> + ### Field.Label An accessible label that is automatically associated with the field control. Renders a `
diff --git a/canon-docs/src/components/HeadlessBanners/BaseUI.tsx b/canon-docs/src/components/HeadlessBanners/BaseUI.tsx index 8401cafd78..86a0e1ecbd 100644 --- a/canon-docs/src/components/HeadlessBanners/BaseUI.tsx +++ b/canon-docs/src/components/HeadlessBanners/BaseUI.tsx @@ -35,7 +35,7 @@ export const BaseUI = ({ href }: BaseUIProps) => { {href && ( Discover more - + )} diff --git a/canon-docs/src/components/PropsTable/PropsTable.tsx b/canon-docs/src/components/PropsTable/PropsTable.tsx index 62917eaeed..c10daf5082 100644 --- a/canon-docs/src/components/PropsTable/PropsTable.tsx +++ b/canon-docs/src/components/PropsTable/PropsTable.tsx @@ -9,6 +9,7 @@ type PropData = { values?: string | string[]; responsive?: boolean; default?: string; + type?: string; }; // Modify the PropsTable component to use the new type @@ -17,57 +18,58 @@ export const PropsTable = >({ }: { data: T; }) => { - const completeData = { - ...data, - className: { - values: 'string', - responsive: false, - }, - style: { - values: 'CSSProperties', - responsive: false, - }, - }; + if (!data) return null; return ( - Prop - Type - Default - Responsive + Prop + Type + Default + + Responsive + - {Object.keys(completeData).map(n => ( - - - {n} - - -
- {completeData[n].values === 'icon' ? ( - Object.keys(icons).map(icon => {icon}) - ) : Array.isArray(completeData[n].values) ? ( - completeData[n].values.map(t => {t}) - ) : ( - {completeData[n].values} - )} -
-
- - - {completeData[n].default ? completeData[n].default : '-'} - - - - {completeData[n].responsive ? 'Yes' : 'No'} - -
- ))} + {Object.keys(data).map(n => { + const enumValues = + data[n].values === 'icon' + ? Object.keys(icons).map(icon => {icon}) + : Array.isArray(data[n].values) && + data[n].values.map(t => {t}); + + return ( + + + {n} + + +
+ {data[n].type === 'string' && string} + {data[n].type === 'number' && number} + {data[n].type === 'boolean' && boolean} + {data[n].type === 'enum' && enumValues} + {data[n].type === 'enum | string' && ( + <> + {enumValues} + string + + )} +
+
+ + {data[n].default ? data[n].default : '-'} + + + {data[n].responsive ? 'Yes' : 'No'} + +
+ ); + })}
); diff --git a/canon-docs/src/components/Table/Table.tsx b/canon-docs/src/components/Table/Table.tsx index 19ae69822e..d817ce3b1b 100644 --- a/canon-docs/src/components/Table/Table.tsx +++ b/canon-docs/src/components/Table/Table.tsx @@ -1,19 +1,3 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - import React from 'react'; import styles from './styles.module.css'; @@ -37,9 +21,18 @@ export const HeaderRow = ({ children }: { children: React.ReactNode }) => { return {children}; }; -export const HeaderCell = ({ children }: { children: React.ReactNode }) => { +export const HeaderCell = ({ + children, + style, +}: { + children: React.ReactNode; + style?: React.CSSProperties; +}) => { return ( - + {children} ); @@ -49,6 +42,16 @@ export const Row = ({ children }: { children: React.ReactNode }) => { return {children}; }; -export const Cell = ({ children }: { children: React.ReactNode }) => { - return {children}; +export const Cell = ({ + children, + style, +}: { + children: React.ReactNode; + style?: React.CSSProperties; +}) => { + return ( + + {children} + + ); }; diff --git a/canon-docs/src/components/Table/styles.module.css b/canon-docs/src/components/Table/styles.module.css index b05ee2c039..3381f39e58 100644 --- a/canon-docs/src/components/Table/styles.module.css +++ b/canon-docs/src/components/Table/styles.module.css @@ -1,19 +1,3 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - .wrapper { border: 1px solid var(--border); border-radius: 4px; diff --git a/canon-docs/src/components/Toolbar/theme-name.tsx b/canon-docs/src/components/Toolbar/theme-name.tsx index 6b35d0efcc..277ecad9df 100644 --- a/canon-docs/src/components/Toolbar/theme-name.tsx +++ b/canon-docs/src/components/Toolbar/theme-name.tsx @@ -24,7 +24,7 @@ export const ThemeNameSelector = () => { placeholder="Select a theme" /> - + diff --git a/canon-docs/src/snippets/button.tsx b/canon-docs/src/snippets/button.tsx index a7df4315f9..aa20b3e46a 100644 --- a/canon-docs/src/snippets/button.tsx +++ b/canon-docs/src/snippets/button.tsx @@ -28,8 +28,8 @@ export const ButtonWithIcons = () => { return ( - - + @@ -40,8 +40,8 @@ export const ButtonFullWidth = () => { return ( - - + @@ -78,7 +78,7 @@ export const ButtonPlayground = () => { Button