diff --git a/packages/admin-ui/src/Tag/Tag.stories.tsx b/packages/admin-ui/src/Tag/Tag.stories.tsx new file mode 100644 index 00000000000..1053fd4337e --- /dev/null +++ b/packages/admin-ui/src/Tag/Tag.stories.tsx @@ -0,0 +1,142 @@ +import React from "react"; +import { ReactComponent as XIcon } from "@material-design-icons/svg/round/close.svg"; +import type { Meta, StoryObj } from "@storybook/react"; +import { Tag } from "./Tag"; +import { Icon } from "~/Icon"; + +const meta: Meta = { + title: "Components/Tag", + component: Tag, + tags: ["autodocs"], + parameters: { + layout: "padded" + } +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + label: "Label" + } +}; + +export const WithIcon: Story = { + args: { + ...Default.args, + icon: } label={"Close"} size={"sm"} /> + } +}; + +export const NeutralBase: Story = { + args: { + ...WithIcon.args, + variant: "neutral-base" + } +}; + +export const NeutralBaseDisabled: Story = { + args: { + ...NeutralBase.args, + disabled: true + } +}; + +export const NeutralLight: Story = { + args: { + ...WithIcon.args, + variant: "neutral-light" + } +}; + +export const NeutralLightDisabled: Story = { + args: { + ...NeutralLight.args, + disabled: true + } +}; + +export const NeutralStrong: Story = { + args: { + ...WithIcon.args, + variant: "neutral-strong" + } +}; + +export const NeutralStrongDisabled: Story = { + args: { + ...NeutralStrong.args, + disabled: true + } +}; + +export const NeutralDark: Story = { + args: { + ...WithIcon.args, + variant: "neutral-dark" + } +}; + +export const NeutralDarkDisabled: Story = { + args: { + ...NeutralDark.args, + disabled: true + } +}; + +export const Accent: Story = { + args: { + ...WithIcon.args, + variant: "accent" + } +}; + +export const AccentDisabled: Story = { + args: { + ...Accent.args, + disabled: true + } +}; + +export const Success: Story = { + args: { + ...WithIcon.args, + variant: "success" + } +}; + +export const SuccessDisabled: Story = { + args: { + ...Success.args, + disabled: true + } +}; + +export const Warning: Story = { + args: { + ...WithIcon.args, + variant: "warning" + } +}; + +export const WarningDisabled: Story = { + args: { + ...Warning.args, + disabled: true + } +}; + +export const Destructive: Story = { + args: { + ...WithIcon.args, + variant: "destructive" + } +}; + +export const DestructiveDisabled: Story = { + args: { + ...Destructive.args, + disabled: true + } +}; diff --git a/packages/admin-ui/src/Tag/Tag.tsx b/packages/admin-ui/src/Tag/Tag.tsx new file mode 100644 index 00000000000..3374df97bf9 --- /dev/null +++ b/packages/admin-ui/src/Tag/Tag.tsx @@ -0,0 +1,91 @@ +import * as React from "react"; +import { cn, cva, makeDecoratable, type VariantProps } from "~/utils"; +import { Icon } from "~/Icon"; + +const tagVariants = cva( + [ + "inline-flex items-center gap-xxs rounded-sm text-sm text-regular transition-colors cursor-default overflow-hidden", + "focus:outline-none", + "aria-disabled:cursor-not-allowed" + ], + { + variants: { + hasIcon: { + true: "pl-xs-plus pt-xxs pb-xxs pr-xxs", + false: "pl-xs-plus pr-xs-plus pt-xxs pb-xxs" + }, + variant: { + "neutral-base": [ + "border-sm px-[calc(theme(padding.xs-plus)-theme(borderWidth.sm))] py-[calc(theme(padding.xxs)-theme(borderWidth.sm))]", + "bg-transparent border-neutral-muted text-neutral-primary fill-neutral-xstrong/50", + "hover:bg-neutral-light", + "aria-disabled:bg-transparent aria-disabled:border-neutral-dimmed aria-disabled:text-neutral-disabled aria-disabled:fill-neutral-xstrong/25" + ], + "neutral-light": [ + "bg-neutral-muted text-neutral-primary fill-neutral-xstrong/50", + "hover:bg-neutral-strong", + "aria-disabled:bg-neutral-muted aria-disabled:text-neutral-muted aria-disabled:fill-neutral-xstrong/25" + ], + "neutral-strong": [ + "bg-neutral-xstrong text-neutral-light fill-neutral-base/60", + "hover:bg-neutral-dark", + "aria-disabled:bg-neutral-strong aria-disabled:fill-neutral-base/50" + ], + "neutral-dark": [ + "bg-neutral-dark text-neutral-light fill-neutral-base/60", + "hover:bg-neutral-xstrong", + "aria-disabled:bg-neutral-strong aria-disabled:fill-neutral-base/50" + ], + accent: [ + "bg-primary-default text-neutral-light fill-neutral-base/60", + "hover:bg-primary-strong", + "aria-disabled:bg-primary-disabled aria-disabled:fill-neutral-base/50" + ], + success: [ + "bg-success-default text-neutral-light fill-neutral-base/60", + "hover:bg-success-strong", + "aria-disabled:bg-success-disabled aria-disabled:fill-neutral-base/50" + ], + warning: [ + "bg-warning-muted text-neutral-primary fill-neutral-xstrong/50", + "hover:bg-warning-default", + "aria-disabled:bg-warning-disabled aria-disabled:text-neutral-disabled aria-disabled:fill-neutral-xstrong/25" + ], + destructive: [ + "bg-destructive-default text-neutral-light fill-neutral-base fill-neutral-base/60", + "hover:bg-destructive-strong", + "aria-disabled:bg-destructive-disabled aria-disabled:fill-neutral-base/50" + ] + } + }, + defaultVariants: { + variant: "neutral-base" + } + } +); + +export interface TagProps + extends Omit, "children">, + VariantProps { + label: React.ReactNode; + icon: React.ReactElement | React.ReactNode; + disabled?: boolean; +} + +const DecoratableTag = ({ className, variant, label, icon, disabled, ...props }: TagProps) => { + const hasIcon = React.useMemo(() => Boolean(icon), [icon]); + + return ( + + {label} + {icon} + + ); +}; +const Tag = makeDecoratable("Tag", DecoratableTag); + +export { Tag }; diff --git a/packages/admin-ui/src/Tag/index.ts b/packages/admin-ui/src/Tag/index.ts new file mode 100644 index 00000000000..5b4c58bcebc --- /dev/null +++ b/packages/admin-ui/src/Tag/index.ts @@ -0,0 +1 @@ +export * from "./Tag"; diff --git a/packages/admin-ui/src/index.ts b/packages/admin-ui/src/index.ts index e21c0f5ce64..48e632c7fb2 100644 --- a/packages/admin-ui/src/index.ts +++ b/packages/admin-ui/src/index.ts @@ -17,6 +17,7 @@ export * from "./Separator"; export * from "./Slider"; export * from "./Switch"; export * from "./Tabs"; +export * from "./Tag"; export * from "./Text"; export * from "./Textarea"; export * from "./Toast"; diff --git a/packages/ui/package.json b/packages/ui/package.json index e2f3bb4c3e5..9856c188b1d 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -18,7 +18,6 @@ "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", "@material-design-icons/svg": "^0.14.3", - "@rmwc/chip": "^14.2.2", "@rmwc/data-table": "^14.2.2", "@rmwc/dialog": "^14.2.2", "@rmwc/drawer": "^14.2.2", diff --git a/packages/ui/src/Chips/Chip.tsx b/packages/ui/src/Chips/Chip.tsx index 69198138458..1865e770a7d 100644 --- a/packages/ui/src/Chips/Chip.tsx +++ b/packages/ui/src/Chips/Chip.tsx @@ -1,13 +1,44 @@ import React, { useCallback } from "react"; -import { Chip as RmwcChip, ChipProps as RmwcChipProps } from "@rmwc/chip"; +import { Tag as AdminTag } from "@webiny/admin-ui"; + +export interface RmwcChipProps { + /** Text for your Chip. */ + label?: React.ReactNode; + /** makes the Chip appear selected. */ + selected?: boolean; + /** Instance of an Icon Component. */ + icon?: any; + /** Instance of an Icon Component. */ + trailingIcon?: any; + /** Defaults to true. Set this to false if your trailing icon is something other than a remove button. */ + trailingIconRemovesChip?: boolean; + /** An optional chip ID that will be included in callback evt.detail. If this is not passed, RMWC will attempt to use the "key" prop if present. */ + id?: string; + /** Includes an optional checkmark for the chips selected state. */ + checkmark?: boolean; + /** Additional children will be rendered in the text area. */ + children?: React.ReactNode; + /** A callback for click or enter key. This should be used over onClick for accessibility reasons. evt.detail = { chipId: string } */ + onInteraction?: (evt: any) => void; + /** A callback for click or enter key for the trailing icon. material-components-web always treats this as an intent to remove the chip. evt.detail = { chipId: string } */ + onTrailingIconInteraction?: (evt: any) => void; + /** A callback that is fired once the chip is in an exited state from removing it. evt.detail = { chipId: string } */ + onRemove?: (evt: any) => void; + /** Advanced: A reference to the MDCFoundation. */ + foundationRef?: any; +} export interface ChipProps extends Omit { onRemove: (ev: React.MouseEvent) => void; trailingIcon?: React.ReactNode; } +/** + * @deprecated This component is deprecated and will be removed in future releases. + * Please use the `Tag` component from the `@webiny/admin-ui` package instead. + */ export const Chip = (props: ChipProps) => { - const { children, trailingIcon, onRemove, ...rest } = props; + const { children, label, trailingIcon, onRemove, ...rest } = props; const onRemoveCb = useCallback( (ev: React.MouseEvent) => { @@ -21,16 +52,8 @@ export const Chip = (props: ChipProps) => { let trailingIconElement = null; if (trailingIcon) { - trailingIconElement = ( - - {trailingIcon} - - ); + trailingIconElement = {trailingIcon}; } - return ( - - {children} {trailingIconElement} - - ); + return ; }; diff --git a/packages/ui/src/Chips/Chips.tsx b/packages/ui/src/Chips/Chips.tsx index 2069c250cd2..723c7ae84e3 100644 --- a/packages/ui/src/Chips/Chips.tsx +++ b/packages/ui/src/Chips/Chips.tsx @@ -1,8 +1,6 @@ import React from "react"; import classNames from "classnames"; -import { ChipSet } from "@rmwc/chip"; import { Chip } from "./Chip"; -import { chipIconWrapper, disabledChips } from "./styles"; export interface ChipsProps { /** @@ -26,17 +24,16 @@ export interface ChipsProps { style?: React.CSSProperties; } +/** + * @deprecated This component is deprecated and will be removed in future releases. + * Please use the `Tag` component from the `@webiny/admin-ui` package instead. + */ export const Chips = (props: ChipsProps) => { - const { children, className, disabled, ...rest } = props; + const { children, className, ...rest } = props; return ( - +
{children} - +
); }; diff --git a/packages/ui/src/Chips/README.md b/packages/ui/src/Chips/README.md deleted file mode 100644 index b8b18c48097..00000000000 --- a/packages/ui/src/Chips/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Chips - -### Design - -https://material.io/design/components/chips.html - -### Description - -`Chips` allow users to enter information, make selections, filter content, or trigger actions. - -### Import - -```js -import { Chips, Chip, ChipText, ChipIcon } from "@webiny/ui/Chips"; -``` diff --git a/packages/ui/src/Chips/icons/baseline-done-24px.svg b/packages/ui/src/Chips/icons/baseline-done-24px.svg deleted file mode 100644 index 0482857b7b8..00000000000 --- a/packages/ui/src/Chips/icons/baseline-done-24px.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/ui/src/Chips/icons/baseline-email-24px.svg b/packages/ui/src/Chips/icons/baseline-email-24px.svg deleted file mode 100644 index b7fb8349408..00000000000 --- a/packages/ui/src/Chips/icons/baseline-email-24px.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/ui/src/Chips/styles.ts b/packages/ui/src/Chips/styles.ts deleted file mode 100644 index 6306cba64c9..00000000000 --- a/packages/ui/src/Chips/styles.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { css } from "emotion"; - -export const chipIconWrapper = css({ - ".mdc-evolution-chip__text-label": { - display: "flex", - alignItems: "center", - ".mdc-chip__icon": { - svg: { - width: 18, - height: 18 - } - } - } -}); - -export const disabledChips = css({ - opacity: 0.75, - pointerEvents: "none" -}); diff --git a/yarn.lock b/yarn.lock index 2f2e41c2841..b75f505adec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18994,7 +18994,6 @@ __metadata: "@emotion/react": ^11.10.6 "@emotion/styled": ^11.10.6 "@material-design-icons/svg": ^0.14.3 - "@rmwc/chip": ^14.2.2 "@rmwc/data-table": ^14.2.2 "@rmwc/dialog": ^14.2.2 "@rmwc/drawer": ^14.2.2