Add new Checkbox component

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2024-12-09 19:09:13 +00:00
parent e22c946a76
commit b97a12beed
9 changed files with 163 additions and 5 deletions
@@ -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<typeof Checkbox>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
children: 'Primary button',
},
};
@@ -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 (
<label className="checkbox-label">
<CheckboxRoot className="checkbox">
<CheckboxIndicator className="checkbox-indicator">
<Icon name="check" size={12} />
</CheckboxIndicator>
</CheckboxRoot>
Label
</label>
);
};
@@ -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';
@@ -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);
}
}
+6 -5
View File
@@ -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 <svg />; // Return default icon perhaps?
console.error(`Icon "${name}" not found or is not a valid component.`);
return <svg />; // Return a default icon or handle the error appropriately
}
return <RemixIcon />;
return <RemixIcon className={`icon-${size}`} />;
};
@@ -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,
@@ -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;
}
@@ -24,6 +24,7 @@ export type IconNames =
| 'arrowLeftCircle'
| 'arrowRightCircle'
| 'arrowUpCircle'
| 'check'
| 'chevronDown'
| 'chevronLeft'
| 'chevronRight'
+2
View File
@@ -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';