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 new file mode 100644 index 0000000000..ffd874ffe7 --- /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: { + label: 'Accept terms and conditions', + }, +}; diff --git a/packages/canon/src/components/Checkbox/Checkbox.tsx b/packages/canon/src/components/Checkbox/Checkbox.tsx new file mode 100644 index 0000000000..3021032421 --- /dev/null +++ b/packages/canon/src/components/Checkbox/Checkbox.tsx @@ -0,0 +1,64 @@ +/* + * 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'; +import type { CheckboxProps } from './types'; + +/** @public */ +export const Checkbox = React.forwardRef( + (props, ref) => { + const { + label, + checked, + onChange, + disabled, + required, + className, + name, + value, + style, + } = props; + + const checkboxElement = ( + + + + + + ); + + 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 new file mode 100644 index 0000000000..f6dfbf6beb --- /dev/null +++ b/packages/canon/src/components/Checkbox/index.ts @@ -0,0 +1,17 @@ +/* + * 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'; +export type { CheckboxProps } from './types'; 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/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/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/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'; 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';