From b97a12beed8678ae649add0059c8a8faddd0d344 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 9 Dec 2024 19:09:13 +0000 Subject: [PATCH 1/2] Add new Checkbox component Signed-off-by: Charles de Dreuille --- .../components/Checkbox/Checkbox.stories.tsx | 35 +++++++++++++++++ .../src/components/Checkbox/Checkbox.tsx | 32 +++++++++++++++ .../canon/src/components/Checkbox/index.ts | 16 ++++++++ .../canon/src/components/Checkbox/styles.css | 39 +++++++++++++++++++ packages/canon/src/components/Icon/Icon.tsx | 11 +++--- packages/canon/src/components/Icon/icons.ts | 2 + packages/canon/src/components/Icon/styles.css | 30 ++++++++++++++ packages/canon/src/components/Icon/types.ts | 1 + packages/canon/src/theme/styles.css | 2 + 9 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 packages/canon/src/components/Checkbox/Checkbox.stories.tsx create mode 100644 packages/canon/src/components/Checkbox/Checkbox.tsx create mode 100644 packages/canon/src/components/Checkbox/index.ts create mode 100644 packages/canon/src/components/Checkbox/styles.css create mode 100644 packages/canon/src/components/Icon/styles.css diff --git a/packages/canon/src/components/Checkbox/Checkbox.stories.tsx b/packages/canon/src/components/Checkbox/Checkbox.stories.tsx new file mode 100644 index 0000000000..7ebe4d3df4 --- /dev/null +++ b/packages/canon/src/components/Checkbox/Checkbox.stories.tsx @@ -0,0 +1,35 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; +import { Checkbox } from './Checkbox'; + +const meta = { + title: 'Components/Checkbox', + component: Checkbox, + parameters: { + layout: 'centered', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + children: 'Primary button', + }, +}; diff --git a/packages/canon/src/components/Checkbox/Checkbox.tsx b/packages/canon/src/components/Checkbox/Checkbox.tsx new file mode 100644 index 0000000000..178c3b67ec --- /dev/null +++ b/packages/canon/src/components/Checkbox/Checkbox.tsx @@ -0,0 +1,32 @@ +/* + * 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 { CheckboxRoot, CheckboxIndicator } from '@base_ui/react'; +import { Icon } from '@backstage/canon'; + +export const Checkbox = () => { + return ( + + ); +}; diff --git a/packages/canon/src/components/Checkbox/index.ts b/packages/canon/src/components/Checkbox/index.ts new file mode 100644 index 0000000000..094502442d --- /dev/null +++ b/packages/canon/src/components/Checkbox/index.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ +export { Checkbox } from './Checkbox'; diff --git a/packages/canon/src/components/Checkbox/styles.css b/packages/canon/src/components/Checkbox/styles.css new file mode 100644 index 0000000000..fb7e0d0ab7 --- /dev/null +++ b/packages/canon/src/components/Checkbox/styles.css @@ -0,0 +1,39 @@ +.checkbox-label { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: var(--canon-spacing-xs); + font-size: var(--canon-font-sizes-xs); + font-family: var(--canon-font-regular); + color: var(--canon-text-primary); + + & .checkbox { + all: unset; + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + box-shadow: inset 0 0 0 1px var(--canon-outline); + cursor: pointer; + border-radius: 2px; + + &[data-state='unchecked'] { + & .checkbox-indicator { + display: none; + } + } + + &[data-state='checked'] { + background: var(--canon-accent); + } + } + + & .checkbox-indicator { + display: flex; + align-items: center; + justify-content: center; + color: var(--canon-text-primary-on-accent); + } +} diff --git a/packages/canon/src/components/Icon/Icon.tsx b/packages/canon/src/components/Icon/Icon.tsx index d7891c23cf..587e3c0a23 100644 --- a/packages/canon/src/components/Icon/Icon.tsx +++ b/packages/canon/src/components/Icon/Icon.tsx @@ -19,15 +19,16 @@ import { useTheme } from '../../theme/context'; import type { IconNames } from './types'; /** @public */ -export const Icon = ({ name }: { name: IconNames }) => { +export const Icon = (props: { name: IconNames; size?: number }) => { + const { name, size = 16 } = props; const { icons } = useTheme(); - const RemixIcon = icons[name]; + const RemixIcon = icons[name] as React.ComponentType<{ className?: string }>; if (!RemixIcon) { - console.error(`Icon "${name}" not found.`); - return ; // Return default icon perhaps? + console.error(`Icon "${name}" not found or is not a valid component.`); + return ; // Return a default icon or handle the error appropriately } - return ; + return ; }; diff --git a/packages/canon/src/components/Icon/icons.ts b/packages/canon/src/components/Icon/icons.ts index 7fe2bf0056..ff5cd9a507 100644 --- a/packages/canon/src/components/Icon/icons.ts +++ b/packages/canon/src/components/Icon/icons.ts @@ -34,6 +34,7 @@ import { RiArrowLeftCircleLine, RiArrowRightCircleLine, RiArrowUpCircleLine, + RiCheckLine, } from '@remixicon/react'; // List of default icons @@ -46,6 +47,7 @@ export const defaultIcons: IconMap = { arrowLeftCircle: RiArrowLeftCircleLine, arrowRightCircle: RiArrowRightCircleLine, arrowUpCircle: RiArrowUpCircleLine, + check: RiCheckLine, chevronDown: RiArrowDownSLine, chevronUp: RiArrowUpSLine, chevronLeft: RiArrowLeftSLine, diff --git a/packages/canon/src/components/Icon/styles.css b/packages/canon/src/components/Icon/styles.css new file mode 100644 index 0000000000..234105ed4e --- /dev/null +++ b/packages/canon/src/components/Icon/styles.css @@ -0,0 +1,30 @@ +/* + * 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. + */ + +.icon-12 { + width: 12px; + height: 12px; +} + +.icon-16 { + width: 16px; + height: 16px; +} + +.icon-24 { + width: 24px; + height: 24px; +} diff --git a/packages/canon/src/components/Icon/types.ts b/packages/canon/src/components/Icon/types.ts index d60eaca020..bac853257b 100644 --- a/packages/canon/src/components/Icon/types.ts +++ b/packages/canon/src/components/Icon/types.ts @@ -24,6 +24,7 @@ export type IconNames = | 'arrowLeftCircle' | 'arrowRightCircle' | 'arrowUpCircle' + | 'check' | 'chevronDown' | 'chevronLeft' | 'chevronRight' diff --git a/packages/canon/src/theme/styles.css b/packages/canon/src/theme/styles.css index ad2433ef74..8cb74374c6 100644 --- a/packages/canon/src/theme/styles.css +++ b/packages/canon/src/theme/styles.css @@ -27,3 +27,5 @@ @import '../components/Inline/styles.css'; @import '../components/Grid/styles.css'; @import '../components/Container/styles.css'; +@import '../components/Icon/styles.css'; +@import '../components/Checkbox/styles.css'; From 6b2d46b046f683a2a4dab277b1baac9d3e05cd67 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 10 Dec 2024 08:46:24 +0000 Subject: [PATCH 2/2] Improve API Signed-off-by: Charles de Dreuille --- packages/canon/report.api.md | 35 +++++++++- .../components/Checkbox/Checkbox.stories.tsx | 2 +- .../src/components/Checkbox/Checkbox.tsx | 48 +++++++++++--- .../canon/src/components/Checkbox/Docs.mdx | 66 +++++++++++++++++++ .../canon/src/components/Checkbox/index.ts | 1 + .../canon/src/components/Checkbox/types.ts | 29 ++++++++ packages/canon/src/index.ts | 1 + 7 files changed, 172 insertions(+), 10 deletions(-) create mode 100644 packages/canon/src/components/Checkbox/Docs.mdx create mode 100644 packages/canon/src/components/Checkbox/types.ts diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index c27b8da09b..b314020d81 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -129,6 +129,35 @@ export interface ButtonProps { variant?: 'primary' | 'secondary' | 'tertiary'; } +// @public (undocumented) +export const Checkbox: React_2.ForwardRefExoticComponent< + CheckboxProps & React_2.RefAttributes +>; + +// @public (undocumented) +export interface CheckboxProps { + // (undocumented) + checked?: boolean; + // (undocumented) + className?: string; + // (undocumented) + defaultChecked?: boolean; + // (undocumented) + disabled?: boolean; + // (undocumented) + label?: string; + // (undocumented) + name?: string; + // (undocumented) + onChange?: (checked: boolean) => void; + // (undocumented) + required?: boolean; + // (undocumented) + style?: React.CSSProperties; + // (undocumented) + value?: string; +} + // @public (undocumented) export type Color = | 'primary' @@ -237,7 +266,10 @@ export interface GridProps extends SpaceProps, ColorProps { } // @public (undocumented) -export const Icon: ({ name }: { name: IconNames }) => React_2.JSX.Element; +export const Icon: (props: { + name: IconNames; + size?: number; +}) => React_2.JSX.Element; // @public (undocumented) export type IconMap = Partial>; @@ -252,6 +284,7 @@ export type IconNames = | 'arrowLeftCircle' | 'arrowRightCircle' | 'arrowUpCircle' + | 'check' | 'chevronDown' | 'chevronLeft' | 'chevronRight' diff --git a/packages/canon/src/components/Checkbox/Checkbox.stories.tsx b/packages/canon/src/components/Checkbox/Checkbox.stories.tsx index 7ebe4d3df4..ffd874ffe7 100644 --- a/packages/canon/src/components/Checkbox/Checkbox.stories.tsx +++ b/packages/canon/src/components/Checkbox/Checkbox.stories.tsx @@ -30,6 +30,6 @@ type Story = StoryObj; export const Primary: Story = { args: { - children: 'Primary button', + label: 'Accept terms and conditions', }, }; diff --git a/packages/canon/src/components/Checkbox/Checkbox.tsx b/packages/canon/src/components/Checkbox/Checkbox.tsx index 178c3b67ec..3021032421 100644 --- a/packages/canon/src/components/Checkbox/Checkbox.tsx +++ b/packages/canon/src/components/Checkbox/Checkbox.tsx @@ -17,16 +17,48 @@ import React from 'react'; import { CheckboxRoot, CheckboxIndicator } from '@base_ui/react'; import { Icon } from '@backstage/canon'; +import type { CheckboxProps } from './types'; -export const Checkbox = () => { - return ( - - ); -}; + ); + + return label ? ( + + ) : ( + checkboxElement + ); + }, +); diff --git a/packages/canon/src/components/Checkbox/Docs.mdx b/packages/canon/src/components/Checkbox/Docs.mdx new file mode 100644 index 0000000000..9d9b4e4915 --- /dev/null +++ b/packages/canon/src/components/Checkbox/Docs.mdx @@ -0,0 +1,66 @@ +import { Canvas, Meta, Unstyled, Source } from '@storybook/blocks'; +import * as CheckboxStories from './Checkbox.stories'; +import { Title, Text } from '../../../docs/components'; +import { PropsTable } from '../../../docs/components/PropsTable'; + + + + + +Checkbox +A checkbox component that can be used to trigger actions. + + + + + + + API reference + + + 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, + }, + }} +/> + + diff --git a/packages/canon/src/components/Checkbox/index.ts b/packages/canon/src/components/Checkbox/index.ts index 094502442d..f6dfbf6beb 100644 --- a/packages/canon/src/components/Checkbox/index.ts +++ b/packages/canon/src/components/Checkbox/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { Checkbox } from './Checkbox'; +export type { CheckboxProps } from './types'; diff --git a/packages/canon/src/components/Checkbox/types.ts b/packages/canon/src/components/Checkbox/types.ts new file mode 100644 index 0000000000..0240954afa --- /dev/null +++ b/packages/canon/src/components/Checkbox/types.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +/** @public */ +export interface CheckboxProps { + label?: string; + defaultChecked?: boolean; + checked?: boolean; + onChange?: (checked: boolean) => void; + disabled?: boolean; + required?: boolean; + className?: string; + name?: string; + value?: string; + style?: React.CSSProperties; +} diff --git a/packages/canon/src/index.ts b/packages/canon/src/index.ts index 6497be2945..5d0ebb5a2e 100644 --- a/packages/canon/src/index.ts +++ b/packages/canon/src/index.ts @@ -33,3 +33,4 @@ export * from './components/Container'; // UI components export * from './components/Button'; export * from './components/Icon'; +export * from './components/Checkbox';