Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2025-06-23 17:46:31 +01:00
parent 27943fa058
commit b5a700b32f
14 changed files with 416 additions and 325 deletions
@@ -22,6 +22,7 @@ import {
import clsx from 'clsx';
import { FieldLabel } from '../FieldLabel';
import { FieldError } from '../FieldError';
import { useStyles } from '../../hooks/useStyles';
import type { RadioGroupProps, RadioProps } from './types';
@@ -40,6 +41,8 @@ export const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(
...rest
} = props;
const { classNames } = useStyles('RadioGroup');
useEffect(() => {
if (!label && !ariaLabel && !ariaLabelledBy) {
console.warn(
@@ -54,7 +57,7 @@ export const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(
return (
<AriaRadioGroup
className={clsx('canon-RadioGroup', className)}
className={clsx(classNames.root, className)}
aria-label={ariaLabel}
aria-labelledby={ariaLabelledBy}
{...rest}
@@ -65,7 +68,7 @@ export const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(
secondaryLabel={secondaryLabelText}
description={description}
/>
<div className="canon-RadioGroupContent">{children}</div>
<div className={classNames.content}>{children}</div>
<FieldError />
</AriaRadioGroup>
);
@@ -78,8 +81,14 @@ RadioGroup.displayName = 'RadioGroup';
export const Radio = forwardRef<HTMLLabelElement, RadioProps>((props, ref) => {
const { className, ...rest } = props;
const { classNames } = useStyles('RadioGroup');
return (
<AriaRadio className={clsx('canon-Radio', className)} {...rest} ref={ref} />
<AriaRadio
className={clsx(classNames.radio, className)}
{...rest}
ref={ref}
/>
);
});
@@ -17,53 +17,70 @@
import { forwardRef } from 'react';
import { ScrollArea as ScrollAreaPrimitive } from '@base-ui-components/react/scroll-area';
import clsx from 'clsx';
import { useStyles } from '../../hooks/useStyles';
const ScrollAreaRoot = forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={clsx('canon-ScrollAreaRoot', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('ScrollArea');
return (
<ScrollAreaPrimitive.Root
ref={ref}
className={clsx(classNames.root, className)}
{...props}
/>
);
});
ScrollAreaRoot.displayName = ScrollAreaPrimitive.Root.displayName;
const ScrollAreaViewport = forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Viewport
ref={ref}
className={clsx('canon-ScrollAreaViewport', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('ScrollArea');
return (
<ScrollAreaPrimitive.Viewport
ref={ref}
className={clsx(classNames.viewport, className)}
{...props}
/>
);
});
ScrollAreaViewport.displayName = ScrollAreaPrimitive.Viewport.displayName;
const ScrollAreaScrollbar = forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Scrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Scrollbar>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Scrollbar
ref={ref}
className={clsx('canon-ScrollAreaScrollbar', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('ScrollArea');
return (
<ScrollAreaPrimitive.Scrollbar
ref={ref}
className={clsx(classNames.scrollbar, className)}
{...props}
/>
);
});
ScrollAreaScrollbar.displayName = ScrollAreaPrimitive.Scrollbar.displayName;
const ScrollAreaThumb = forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Thumb>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Thumb>
>(({ className, ...props }, ref) => (
<ScrollAreaPrimitive.Thumb
ref={ref}
className={clsx('canon-ScrollAreaThumb', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('ScrollArea');
return (
<ScrollAreaPrimitive.Thumb
ref={ref}
className={clsx(classNames.thumb, className)}
{...props}
/>
);
});
ScrollAreaThumb.displayName = ScrollAreaPrimitive.Thumb.displayName;
/** @public */
+16 -14
View File
@@ -21,6 +21,7 @@ import clsx from 'clsx';
import './Select.styles.css';
import { SelectProps } from './types';
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
import { useStyles } from '../../hooks/useStyles';
/** @public */
export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
@@ -37,8 +38,7 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
...rest
} = props;
// Get the responsive value for the variant
const responsiveSize = useResponsiveValue(size);
const { classNames, dataAttributes } = useStyles('Select');
// Generate unique IDs for accessibility
const selectId = useId();
@@ -58,7 +58,7 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
);
return (
<div className={clsx('canon-Select', className)} style={style} ref={ref}>
<div className={clsx(classNames.root, className)} style={style} ref={ref}>
{label && (
<label
className="canon-SelectLabel"
@@ -68,7 +68,7 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
>
{label}
{required && (
<span aria-hidden="true" className="canon-SelectRequired">
<span aria-hidden="true" className={classNames.required}>
(Required)
</span>
)}
@@ -78,33 +78,35 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
<SelectPrimitive.Trigger
ref={triggerRef}
id={selectId}
className="canon-SelectTrigger"
data-size={responsiveSize}
className={classNames.trigger}
data-size={dataAttributes.size}
data-invalid={error}
>
<SelectPrimitive.Value
className="canon-SelectValue"
className={classNames.value}
placeholder={placeholder}
/>
<SelectPrimitive.Icon className="canon-SelectIcon">
<SelectPrimitive.Icon className={classNames.icon}>
<Icon name="chevron-down" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
<SelectPrimitive.Portal>
<SelectPrimitive.Backdrop />
<SelectPrimitive.Positioner>
<SelectPrimitive.Popup className="canon-SelectPopup">
<SelectPrimitive.Popup className={classNames.popup}>
{options?.map(option => (
<SelectPrimitive.Item
key={option.value}
value={option.value}
disabled={option.disabled}
className="canon-SelectItem"
className={classNames.item}
>
<SelectPrimitive.ItemIndicator className="canon-SelectItemIndicator">
<SelectPrimitive.ItemIndicator
className={classNames.itemIndicator}
>
<Icon name="check" />
</SelectPrimitive.ItemIndicator>
<SelectPrimitive.ItemText className="canon-SelectItemText">
<SelectPrimitive.ItemText className={classNames.itemText}>
{option.label}
</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
@@ -114,12 +116,12 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
</SelectPrimitive.Portal>
</SelectPrimitive.Root>
{description && (
<p className="canon-SelectDescription" id={descriptionId}>
<p className={classNames.description} id={descriptionId}>
{description}
</p>
)}
{error && (
<p className="canon-SelectError" id={errorId} role="alert">
<p className={classNames.error} id={errorId} role="alert">
{error}
</p>
)}
@@ -17,13 +17,16 @@
import { forwardRef } from 'react';
import { Switch as AriaSwitch } from 'react-aria-components';
import type { SwitchProps } from './types';
import { useStyles } from '../../hooks/useStyles';
/** @public */
export const Switch = forwardRef<HTMLLabelElement, SwitchProps>(
({ label, ...props }, ref) => {
const { classNames } = useStyles('Switch');
return (
<AriaSwitch className="canon-Switch" ref={ref} {...props}>
<div className="canon-SwitchIndicator" />
<AriaSwitch className={classNames.root} ref={ref} {...props}>
<div className={classNames.indicator} />
{label}
</AriaSwitch>
);
+53 -28
View File
@@ -20,63 +20,88 @@ import { TableCell } from './TableCell/TableCell';
import { TableCellText } from './TableCellText/TableCellText';
import { TableCellLink } from './TableCellLink/TableCellLink';
import { TableCellProfile } from './TableCellProfile/TableCellProfile';
import { useStyles } from '../../hooks/useStyles';
const TableRoot = forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<table ref={ref} className={clsx('canon-TableRoot', className)} {...props} />
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<table ref={ref} className={clsx(classNames.root, className)} {...props} />
);
});
TableRoot.displayName = 'TableRoot';
const TableHeader = forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead
ref={ref}
className={clsx('canon-TableHeader', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<thead
ref={ref}
className={clsx(classNames.header, className)}
{...props}
/>
);
});
TableHeader.displayName = 'TableHeader';
const TableBody = forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody ref={ref} className={clsx('canon-TableBody', className)} {...props} />
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<tbody ref={ref} className={clsx(classNames.body, className)} {...props} />
);
});
TableBody.displayName = 'TableBody';
const TableRow = forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr ref={ref} className={clsx('canon-TableRow', className)} {...props}>
{props.children}
</tr>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<tr ref={ref} className={clsx(classNames.row, className)} {...props}>
{props.children}
</tr>
);
});
TableRow.displayName = 'TableRow';
const TableHead = forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th ref={ref} className={clsx('canon-TableHead', className)} {...props} />
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<th ref={ref} className={clsx(classNames.head, className)} {...props} />
);
});
TableHead.displayName = 'TableHead';
const TableCaption = forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={clsx('canon-TableCaption', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<caption
ref={ref}
className={clsx(classNames.caption, className)}
{...props}
/>
);
});
TableCaption.displayName = 'TableCaption';
/**
@@ -16,14 +16,19 @@
import { forwardRef } from 'react';
import clsx from 'clsx';
import { useStyles } from '../../../hooks/useStyles';
/** @public */
const TableCell = forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td ref={ref} className={clsx('canon-TableCell', className)} {...props} />
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<td ref={ref} className={clsx(classNames.cell, className)} {...props} />
);
});
TableCell.displayName = 'TableCell';
export { TableCell };
@@ -19,27 +19,32 @@ import clsx from 'clsx';
import { TableCellLinkProps } from './types';
import { Text } from '../../Text/Text';
import { Link } from '../../Link/Link';
import { useStyles } from '../../../hooks/useStyles';
/** @public */
const TableCellLink = forwardRef<HTMLDivElement, TableCellLinkProps>(
({ className, title, description, href, render, ...props }, ref) => (
<div
ref={ref}
className={clsx('canon-TableCellLink', className)}
{...props}
>
{title && (
<Link href={href} render={render}>
{title}
</Link>
)}
{description && (
<Text variant="body" color="secondary">
{description}
</Text>
)}
</div>
),
({ className, title, description, href, render, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<div
ref={ref}
className={clsx(classNames.cellLink, className)}
{...props}
>
{title && (
<Link href={href} render={render}>
{title}
</Link>
)}
{description && (
<Text variant="body" color="secondary">
{description}
</Text>
)}
</div>
);
},
);
TableCellLink.displayName = 'TableCellLink';
@@ -20,40 +20,45 @@ import { TableCellProfileProps } from './types';
import { Text } from '../../Text/Text';
import { Link } from '../../Link/Link';
import { Avatar } from '@base-ui-components/react/avatar';
import { useStyles } from '../../../hooks/useStyles';
/** @public */
const TableCellProfile = forwardRef<HTMLDivElement, TableCellProfileProps>(
({ className, src, name, to, withImage = true, ...rest }, ref) => (
<div
ref={ref}
className={clsx('canon-TableCellProfile', className)}
{...rest}
>
{withImage && (
<Avatar.Root className="canon-TableCellProfileAvatar">
<Avatar.Image
src={src}
width="20"
height="20"
className="canon-TableCellProfileAvatarImage"
/>
<Avatar.Fallback className="canon-TableCellProfileAvatarFallback">
{(name || '')
.split(' ')
.map(word => word[0])
.join('')
.toLocaleUpperCase('en-US')
.slice(0, 1)}
</Avatar.Fallback>
</Avatar.Root>
)}
{name && to ? (
<Link to={to}>{name}</Link>
) : (
<Text variant="body">{name}</Text>
)}
</div>
),
({ className, src, name, to, withImage = true, ...rest }, ref) => {
const { classNames } = useStyles('Table');
return (
<div
ref={ref}
className={clsx(classNames.cellProfile, className)}
{...rest}
>
{withImage && (
<Avatar.Root className={classNames.cellProfileAvatar}>
<Avatar.Image
src={src}
width="20"
height="20"
className={classNames.cellProfileAvatarImage}
/>
<Avatar.Fallback className={classNames.cellProfileAvatarFallback}>
{(name || '')
.split(' ')
.map(word => word[0])
.join('')
.toLocaleUpperCase('en-US')
.slice(0, 1)}
</Avatar.Fallback>
</Avatar.Root>
)}
{name && to ? (
<Link to={to}>{name}</Link>
) : (
<Text variant="body">{name}</Text>
)}
</div>
);
},
);
TableCellProfile.displayName = 'TableCellProfile';
@@ -18,23 +18,28 @@ import { forwardRef } from 'react';
import clsx from 'clsx';
import { TableCellTextProps } from './types';
import { Text } from '../../Text/Text';
import { useStyles } from '../../../hooks/useStyles';
/** @public */
const TableCellText = forwardRef<HTMLDivElement, TableCellTextProps>(
({ className, title, description, ...props }, ref) => (
<div
ref={ref}
className={clsx('canon-TableCellText', className)}
{...props}
>
{title && <Text variant="body">{title}</Text>}
{description && (
<Text variant="body" color="secondary">
{description}
</Text>
)}
</div>
),
({ className, title, description, ...props }, ref) => {
const { classNames } = useStyles('Table');
return (
<div
ref={ref}
className={clsx(classNames.cellText, className)}
{...props}
>
{title && <Text variant="body">{title}</Text>}
{description && (
<Text variant="body" color="secondary">
{description}
</Text>
)}
</div>
);
},
);
TableCellText.displayName = 'TableCellText';
+48 -31
View File
@@ -18,56 +18,73 @@ import { forwardRef } from 'react';
import { Tabs as TabsPrimitive } from '@base-ui-components/react/tabs';
import type { TabsRootWithoutOrientation } from './types';
import clsx from 'clsx';
import { useStyles } from '../../hooks/useStyles';
const TabsRoot = forwardRef<
React.ElementRef<typeof TabsPrimitive.Root>,
TabsRootWithoutOrientation
>(({ className, ...props }, ref) => (
<TabsPrimitive.Root
ref={ref}
className={clsx('canon-TabsRoot', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Tabs');
return (
<TabsPrimitive.Root
ref={ref}
className={clsx(classNames.root, className)}
{...props}
/>
);
});
TabsRoot.displayName = TabsPrimitive.Root.displayName;
const TabsList = forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, children, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={clsx('canon-TabsList', className)}
{...props}
>
{children}
<TabsPrimitive.Indicator className="canon-TabsIndicator" />
</TabsPrimitive.List>
));
>(({ className, children, ...props }, ref) => {
const { classNames } = useStyles('Tabs');
return (
<TabsPrimitive.List
ref={ref}
className={clsx(classNames.list, className)}
{...props}
>
{children}
<TabsPrimitive.Indicator className={classNames.indicator} />
</TabsPrimitive.List>
);
});
TabsList.displayName = TabsPrimitive.List.displayName;
const TabsTab = forwardRef<
React.ElementRef<typeof TabsPrimitive.Tab>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Tab>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Tab
ref={ref}
className={clsx('canon-TabsTab', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Tabs');
return (
<TabsPrimitive.Tab
ref={ref}
className={clsx(classNames.tab, className)}
{...props}
/>
);
});
TabsTab.displayName = TabsPrimitive.Tab.displayName;
const TabsPanel = forwardRef<
React.ElementRef<typeof TabsPrimitive.Panel>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Panel>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Panel
ref={ref}
className={clsx('canon-TabsPanel', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Tabs');
return (
<TabsPrimitive.Panel
ref={ref}
className={clsx(classNames.panel, className)}
{...props}
/>
);
});
TabsPanel.displayName = TabsPrimitive.Panel.displayName;
/** @public */
+9 -10
View File
@@ -15,10 +15,10 @@
*/
import { forwardRef } from 'react';
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
import clsx from 'clsx';
import type { ElementType } from 'react';
import type { TextProps } from './types';
import { useStyles } from '../../hooks/useStyles';
function TextComponent<T extends ElementType = 'p'>(
{
@@ -35,19 +35,18 @@ function TextComponent<T extends ElementType = 'p'>(
) {
const Component = as || 'p';
// Get the responsive values for the variant and weight
const responsiveVariant = useResponsiveValue(variant);
const responsiveWeight = useResponsiveValue(weight);
const responsiveColor = useResponsiveValue(color);
const { classNames, dataAttributes } = useStyles('Text', {
variant,
weight,
color,
truncate,
});
return (
<Component
ref={ref}
className={clsx('canon-Text', className)}
data-variant={responsiveVariant}
data-weight={responsiveWeight}
data-color={responsiveColor}
data-truncate={truncate}
className={clsx(classNames.root, className)}
{...dataAttributes}
style={style}
{...restProps}
/>
@@ -16,12 +16,12 @@
import { forwardRef, useEffect } from 'react';
import { Input, TextField as AriaTextField } from 'react-aria-components';
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
import clsx from 'clsx';
import { FieldLabel } from '../FieldLabel';
import { FieldError } from '../FieldError';
import type { TextFieldProps } from './types';
import { useStyles } from '../../hooks/useStyles';
/** @public */
export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
@@ -49,7 +49,9 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
}, [label, ariaLabel, ariaLabelledBy]);
// Get the responsive value for the variant
const responsiveSize = useResponsiveValue(size);
const { classNames, dataAttributes } = useStyles('TextField', {
size,
});
// If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required.
const secondaryLabelText =
@@ -57,8 +59,8 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
return (
<AriaTextField
className={clsx('canon-TextField', className)}
data-size={responsiveSize}
className={clsx(classNames.root, className)}
{...dataAttributes}
aria-label={ariaLabel}
aria-labelledby={ariaLabelledBy}
{...rest}
@@ -69,18 +71,21 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
secondaryLabel={secondaryLabelText}
description={description}
/>
<div className="canon-TextFieldInputWrapper" data-size={responsiveSize}>
<div
className={classNames.inputWrapper}
data-size={dataAttributes.size}
>
{icon && (
<div
className="canon-TextFieldIcon"
data-size={responsiveSize}
className={classNames.icon}
data-size={dataAttributes.size}
aria-hidden="true"
>
{icon}
</div>
)}
<Input
className="canon-TextFieldInput"
className={classNames.input}
{...(icon && { 'data-icon': true })}
placeholder={placeholder}
/>
@@ -17,68 +17,85 @@
import { forwardRef } from 'react';
import { Tooltip as TooltipPrimitive } from '@base-ui-components/react/tooltip';
import clsx from 'clsx';
import { useStyles } from '../../hooks/useStyles';
const TooltipTrigger = forwardRef<
React.ElementRef<typeof TooltipPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TooltipPrimitive.Trigger
ref={ref}
className={clsx('canon-TooltipTrigger', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Tooltip');
return (
<TooltipPrimitive.Trigger
ref={ref}
className={clsx(classNames.trigger, className)}
{...props}
/>
);
});
TooltipTrigger.displayName = TooltipPrimitive.Trigger.displayName;
const TooltipPositioner = forwardRef<
React.ElementRef<typeof TooltipPrimitive.Positioner>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Positioner>
>(({ className, ...props }, ref) => (
<TooltipPrimitive.Positioner
ref={ref}
className={clsx('canon-TooltipPositioner', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Tooltip');
return (
<TooltipPrimitive.Positioner
ref={ref}
className={clsx(classNames.positioner, className)}
{...props}
/>
);
});
TooltipPositioner.displayName = TooltipPrimitive.Positioner.displayName;
const TooltipPopup = forwardRef<
React.ElementRef<typeof TooltipPrimitive.Popup>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Popup>
>(({ className, ...props }, ref) => (
<TooltipPrimitive.Popup
ref={ref}
className={clsx('canon-TooltipPopup', className)}
{...props}
/>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Tooltip');
return (
<TooltipPrimitive.Popup
ref={ref}
className={clsx(classNames.popup, className)}
{...props}
/>
);
});
TooltipPopup.displayName = TooltipPrimitive.Popup.displayName;
const TooltipArrow = forwardRef<
React.ElementRef<typeof TooltipPrimitive.Arrow>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Arrow>
>(({ className, ...props }, ref) => (
<TooltipPrimitive.Arrow
ref={ref}
className={clsx('canon-TooltipArrow', className)}
{...props}
>
<svg width="20" height="10" viewBox="0 0 20 10" fill="none">
<path
d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
className="canon-TooltipArrow-fill"
/>
<path
d="M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z"
className="canon-TooltipArrow-outer-stroke"
/>
<path
d="M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z"
className="canon-TooltipArrow-inner-stroke"
/>
</svg>
</TooltipPrimitive.Arrow>
));
>(({ className, ...props }, ref) => {
const { classNames } = useStyles('Tooltip');
return (
<TooltipPrimitive.Arrow
ref={ref}
className={clsx(classNames.arrow, className)}
{...props}
>
<svg width="20" height="10" viewBox="0 0 20 10" fill="none">
<path
d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
className="canon-TooltipArrow-fill"
/>
<path
d="M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z"
className="canon-TooltipArrow-outer-stroke"
/>
<path
d="M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z"
className="canon-TooltipArrow-inner-stroke"
/>
</svg>
</TooltipPrimitive.Arrow>
);
});
TooltipArrow.displayName = TooltipPrimitive.Arrow.displayName;
/** @public */
@@ -139,6 +139,13 @@ export const componentDefinitions = {
separator: 'canon-MenuSeparator',
},
},
RadioGroup: {
classNames: {
root: 'canon-RadioGroup',
content: 'canon-RadioGroupContent',
radio: 'canon-Radio',
},
},
ScrollArea: {
classNames: {
root: 'canon-ScrollAreaRoot',
@@ -147,117 +154,87 @@ export const componentDefinitions = {
thumb: 'canon-ScrollAreaThumb',
},
},
// Typography Components
Select: {
classNames: {
root: 'canon-Select',
required: 'canon-SelectRequired',
trigger: 'canon-SelectTrigger',
value: 'canon-SelectValue',
icon: 'canon-SelectIcon',
popup: 'canon-SelectPopup',
item: 'canon-SelectItem',
itemIndicator: 'canon-SelectItemIndicator',
itemText: 'canon-SelectItemText',
description: 'canon-SelectDescription',
error: 'canon-SelectError',
},
dataAttributes: {
size: ['small', 'medium'] as const,
},
},
Switch: {
classNames: {
root: 'canon-Switch',
indicator: 'canon-SwitchIndicator',
},
},
Table: {
classNames: {
root: 'canon-TableRoot',
header: 'canon-TableHeader',
body: 'canon-TableBody',
row: 'canon-TableRow',
head: 'canon-TableHead',
caption: 'canon-TableCaption',
cell: 'canon-TableCell',
cellText: 'canon-TableCellText',
cellLink: 'canon-TableCellLink',
cellProfile: 'canon-TableCellProfile',
cellProfileAvatar: 'canon-TableCellProfileAvatar',
cellProfileAvatarImage: 'canon-TableCellProfileAvatarImage',
cellProfileAvatarFallback: 'canon-TableCellProfileAvatarFallback',
cellProfileName: 'canon-TableCellProfileName',
cellProfileLink: 'canon-TableCellProfileLink',
},
},
Tabs: {
classNames: {
root: 'canon-TabsRoot',
list: 'canon-TabsList',
indicator: 'canon-TabsIndicator',
tab: 'canon-TabsTab',
panel: 'canon-TabsPanel',
},
},
Text: {
classNames: {
root: 'canon-Text',
},
dataAttributes: {
variant: ['body', 'caption', 'label'] as const,
weight: ['regular', 'medium', 'bold'] as const,
color: ['primary', 'secondary', 'muted'] as const,
variant: ['subtitle', 'body', 'caption', 'label'] as const,
weight: ['regular', 'bold'] as const,
color: ['primary', 'secondary', 'danger', 'warning', 'success'] as const,
truncate: [true, false] as const,
},
},
TextField: {
classNames: {
root: 'canon-TextField',
input: 'canon-TextField-input',
label: 'canon-TextField-label',
error: 'canon-TextField-error',
helper: 'canon-TextField-helper',
container: 'canon-TextField-container',
inputWrapper: 'canon-TextFieldInputWrapper',
icon: 'canon-TextFieldIcon',
input: 'canon-TextFieldInput',
},
dataAttributes: {
invalid: [true, false] as const,
disabled: [true, false] as const,
},
},
Select: {
classNames: {
root: 'canon-Select',
trigger: 'canon-Select-trigger',
content: 'canon-Select-content',
item: 'canon-Select-item',
value: 'canon-Select-value',
icon: 'canon-Select-icon',
separator: 'canon-Select-separator',
},
dataAttributes: {
invalid: [true, false] as const,
disabled: [true, false] as const,
open: [true, false] as const,
},
},
Switch: {
classNames: {
root: 'canon-Switch',
thumb: 'canon-Switch-thumb',
track: 'canon-Switch-track',
},
dataAttributes: {
checked: [true, false] as const,
disabled: [true, false] as const,
},
},
// Navigation Components
Tabs: {
classNames: {
root: 'canon-Tabs',
list: 'canon-Tabs-list',
tab: 'canon-Tabs-tab',
panel: 'canon-Tabs-panel',
trigger: 'canon-Tabs-trigger',
},
},
// Data Display Components
Table: {
classNames: {
root: 'canon-Table',
header: 'canon-Table-header',
body: 'canon-Table-body',
footer: 'canon-Table-footer',
row: 'canon-Table-row',
cell: 'canon-Table-cell',
headerCell: 'canon-Table-headerCell',
caption: 'canon-Table-caption',
},
},
DataTable: {
classNames: {
root: 'canon-DataTable',
container: 'canon-DataTable-container',
header: 'canon-DataTable-header',
body: 'canon-DataTable-body',
row: 'canon-DataTable-row',
cell: 'canon-DataTable-cell',
headerCell: 'canon-DataTable-headerCell',
toolbar: 'canon-DataTable-toolbar',
pagination: 'canon-DataTable-pagination',
search: 'canon-DataTable-search',
filters: 'canon-DataTable-filters',
},
},
// Feedback Components
Tooltip: {
classNames: {
root: 'canon-Tooltip',
trigger: 'canon-Tooltip-trigger',
content: 'canon-Tooltip-content',
arrow: 'canon-Tooltip-arrow',
trigger: 'canon-TooltipTrigger',
positioner: 'canon-TooltipPositioner',
popup: 'canon-TooltipPopup',
arrow: 'canon-TooltipArrow',
},
},
// Disclosure Components
// Utility Components
} as const satisfies Record<string, ComponentDefinition>;