@workday/canvas-kit-preview-react
Version:
Canvas Kit Preview is made up of components that have the full design and a11y review, are part of the DS ecosystem and are approved for use in product. The API's could be subject to change, but not without strong communication and migration strategies.
283 lines (282 loc) • 13 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Pill = void 0;
const react_1 = __importDefault(require("react"));
const button_1 = require("@workday/canvas-kit-react/button");
const common_1 = require("@workday/canvas-kit-react/common");
const layout_1 = require("@workday/canvas-kit-react/layout");
const tokens_1 = require("@workday/canvas-kit-react/tokens");
const canvas_kit_styling_1 = require("@workday/canvas-kit-styling");
const usePillModel_1 = require("./usePillModel");
const PillIcon_1 = require("./PillIcon");
const PillIconButton_1 = require("./PillIconButton");
const PillCount_1 = require("./PillCount");
const PillAvatar_1 = require("./PillAvatar");
const PillLabel_1 = require("./PillLabel");
const icon_1 = require("@workday/canvas-kit-react/icon");
const StyledBasePill = (0, common_1.styled)(button_1.BaseButton)({
display: 'inline-flex',
alignItems: 'center',
borderRadius: tokens_1.borderRadius.m,
flexShrink: 0,
...tokens_1.type.levels.subtext.large,
color: tokens_1.colors.blackPepper400,
boxShadow: 'none',
outline: 'none',
fontWeight: tokens_1.type.properties.fontWeights.medium,
WebkitFontSmoothing: 'antialiased',
MozOsxFontSmoothing: 'grayscale',
width: 'fit-content',
padding: `2px ${tokens_1.space.xxs}`,
height: tokens_1.space.m,
position: 'relative',
'span[data-count="ck-pill-count"]': {
borderTop: `${(0, canvas_kit_styling_1.px2rem)(1)} solid transparent`,
borderBottom: `${(0, canvas_kit_styling_1.px2rem)(1)} solid transparent`,
borderRight: `${(0, canvas_kit_styling_1.px2rem)(1)} solid transparent`,
},
[ ]: tokens_1.colors.soap300,
[ ]: tokens_1.colors.licorice200,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.licorice200,
// This style ensures the removable button icon changes when you hover over the pill and not just the removable PillButton
button: {
[ ]: tokens_1.colors.licorice200,
},
'&:focus-visible, &.focus': {
[ ]: tokens_1.colors.soap300,
[ ]: tokens_1.colors.blueberry400,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.licorice500,
button: {
[ ]: tokens_1.colors.licorice500,
},
'span[data-count="ck-pill-count"]': {
borderColor: tokens_1.colors.blueberry400,
},
},
'&:hover, &.hover': {
[ ]: tokens_1.colors.soap400,
[ ]: tokens_1.colors.licorice400,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.licorice500,
button: {
[ ]: tokens_1.colors.licorice500,
},
},
'&:active, &.active': {
[ ]: tokens_1.colors.soap500,
[ ]: tokens_1.colors.licorice500,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.licorice500,
button: {
[ ]: tokens_1.colors.soap500,
[ ]: tokens_1.colors.licorice500,
},
'span[data-count="ck-pill-count"]': {
backgroundColor: tokens_1.colors.soap600,
borderColor: 'transparent',
},
},
'&:disabled, &.disabled': {
[ ]: tokens_1.colors.soap100,
[ ]: tokens_1.colors.licorice100,
[ ]: tokens_1.colors.licorice100,
[ ]: '1',
[ ]: tokens_1.colors.licorice100,
button: {
[ ]: tokens_1.colors.licorice100,
},
},
}, ({ variant }) => ({
'&:focus-visible, &.focus': {
borderColor: variant === 'removable' ? undefined : tokens_1.colors.blueberry400,
...(0, common_1.focusRing)({
width: 0,
inset: 'inner',
innerColor: tokens_1.colors.blueberry400,
outerColor: tokens_1.colors.blueberry400,
separation: 1,
}),
},
}), layout_1.boxStyleFn);
const StyledRemoveablePill = (0, common_1.styled)(StyledBasePill)({
[ ]: tokens_1.colors.soap300,
[ ]: tokens_1.colors.licorice200,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.soap100,
'&:focus-visible, &.focus': {
[ ]: tokens_1.colors.soap300,
[ ]: tokens_1.colors.licorice200,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.soap300,
boxShadow: 'none',
},
'&:hover, &.hover': {
[ ]: tokens_1.colors.soap300,
[ ]: tokens_1.colors.licorice200,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.soap300,
},
'&:active, &.active': {
[ ]: tokens_1.colors.soap500,
[ ]: tokens_1.colors.licorice500,
[ ]: tokens_1.colors.blackPepper400,
[ ]: tokens_1.colors.soap500,
},
'&:disabled, &.disabled': {
[ ]: tokens_1.colors.soap100,
[ ]: tokens_1.colors.licorice100,
[ ]: tokens_1.colors.licorice100,
[ ]: tokens_1.colors.soap100,
},
cursor: 'default',
overflow: 'revert',
position: 'relative',
});
const StyledReadOnlyPill = (0, common_1.styled)(StyledRemoveablePill)({
[ ]: 'transparent',
'&:hover, &.hover': {
[ ]: 'transparent',
},
'&:focus-visible, &.focus': {
[ ]: 'transparent',
},
'&:active, &.active': {
[ ]: 'transparent',
},
'&:disabled, &.disabled': {
[ ]: 'transparent',
},
border: `${(0, canvas_kit_styling_1.px2rem)(1)} solid ${tokens_1.colors.licorice200}`,
});
/**
* By default, a `Pill` renders an interactive element that accepts subcomponents. By "interactive"
* we mean that the Pill container is a focusable element (a `<button>`). All leading elements
* (icons or avatars) are intended to be descriptive, helping support the label. They should not
* receive focus.
*
* `Pill` is the container component. It also provides a React context model for its subcomponents.
* Based on the `variant` prop this component will render different styled `Pill`s.
*
* Example of read only:
*
* ```tsx
* <Pill variant="readOnly">This is a read only</Pill>
* ```
*
* Example of interactive:
*
* ```tsx
* <Pill onClick={() => console.log('clicked')}>
* <Pill.Avatar /> Regina Skeltor
* </Pill>
* ```
*
* Example of removable:
*
* ```tsx
* <Pill variant="removable">
* <Pill.Avatar /> Regina Skeltor
* <Pill.IconButton onClick={() => console.log('clicked')} />
* </Pill>
* ```
*
* If you set the `Pill` `variant` to `removable`, it will render a `<span>` element. You can then
* provide a `Pill.IconButton` that acts as the focus target. This creates a smaller, more
* intentional click target that prevents users from accidentally deleting an item.
*
* ```tsx
* <Pill variant="removable">
* Shoes
* <Pill.IconButton onClick={() => console.log('handle remove')} />
* </Pill>
* ```
*/
exports.Pill = (0, common_1.createContainer)('button')({
displayName: 'Pill',
modelHook: usePillModel_1.usePillModel,
subComponents: {
/**
* This component renders an avatar. It supports all props of the `Avatar` component.
*
* ```tsx
* <Pill variant="removable">
* <Pill.Avatar url={avatarUrl} />
* Regina Skeltor
* <Pill.IconButton onClick={() => console.log('handle remove')} />
* </Pill>
* ```
*/
Avatar: PillAvatar_1.PillAvatar,
/**
* This component renders its `children` as the count.
*
* ```tsx
* <Pill onClick={() => console.warn('clicked')}>
* Shoes
* <Pill.Count>30</Pill.Count>
* </Pill>
* ```
*/
Count: PillCount_1.PillCount,
/**
* This component renders an `icon`. It not be used with the `default` styling – not `readOnly`
* or `removable` variants. By default it renders a `plusIcon` but it can be overridden by
* providing an icon to the `icon` prop.
*
* ```tsx
* <Pill onClick={() => console.warn('clicked')}>
* <Pill.Icon />
* <Pill.Label>Regina Skeltor</Pill.Label>
* </Pill>
* ```
*/
Icon: PillIcon_1.PillIcon,
/**
* This component renders a custom icon button. It is only intended to be used with the
* `removable` variant. By default, it renders a `xSmallIcon` but can be overridden by providing
* an icon to the `icon` prop.
*
* ```tsx
* <Pill variant="removable">
* Pink Shirts
* <Pill.IconButton onClick={() => console.warn('clicked')} />
* </Pill>
* ```
*/
IconButton: PillIconButton_1.PillIconButton,
/**
* This component renders a `<span>` that automatically handles overflow by rendering a tooltip.
* There's no need to use this component directly since the overflow is handled for you automatically.
*
* ```tsx
* <Pill variant="readOnly">
* <Pill.Label>Read-only</Pill.Label>
* </Pill>
* ```
*/
Label: PillLabel_1.PillLabel,
},
})(({ variant = 'default', maxWidth, ...elemProps }, Element, model) => {
return (react_1.default.createElement(react_1.default.Fragment, null,
variant === 'readOnly' && (react_1.default.createElement(StyledReadOnlyPill, { as: Element !== 'button' ? Element : 'span', id: model.state.id, maxWidth: model.state.maxWidth, ...elemProps },
react_1.default.createElement(PillLabel_1.PillLabel, null, elemProps.children))),
variant === 'default' && (react_1.default.createElement(StyledBasePill, { as: Element, ...elemProps, disabled: model.state.disabled },
react_1.default.createElement(layout_1.Flex, { gap: "xxxs", display: "inline-flex", alignItems: "center" }, react_1.default.Children.map(elemProps.children, (child, index) => {
if (typeof child === 'string') {
return react_1.default.createElement(PillLabel_1.PillLabel, { key: index }, child);
}
return (react_1.default.createElement(layout_1.Flex.Item, { key: index, display: "inline-flex" }, child));
})))),
variant === 'removable' && (react_1.default.createElement(StyledRemoveablePill, { as: Element !== 'button' ? Element : 'span', variant: variant, type: undefined, ...(0, canvas_kit_styling_1.handleCsProp)(elemProps, [model.state.disabled ? 'disabled' : undefined]) },
react_1.default.createElement(layout_1.Flex, { gap: "xxxs", display: "inline-flex", alignItems: "center", justifyContent: "center" }, react_1.default.Children.map(elemProps.children, (child, index) => {
if (typeof child === 'string') {
return react_1.default.createElement(PillLabel_1.PillLabel, { key: index }, child);
}
return react_1.default.createElement(layout_1.Flex.Item, { key: index }, child);
}))))));
});