diff --git a/src/components/tag/Tag.tsx b/src/components/tag/Tag.tsx index c7080d0d..aafad4ef 100644 --- a/src/components/tag/Tag.tsx +++ b/src/components/tag/Tag.tsx @@ -1,16 +1,16 @@ import React, { forwardRef } from "react"; -import { PressableProps, TextStyle, ViewStyle } from "react-native"; +import { PressableProps, TextStyle } from "react-native"; +import { Close } from "../../icons"; import { Box, Text, Touchable } from "../../primitives"; import { useTheme } from "../../theme"; -import { createComponent, RenderPropType } from "../../utils"; +import { createComponent, RenderPropType, styleAdapter } from "../../utils"; import { createIcon } from "../create-icon"; import { Icon } from "../icon"; -import { useTagProps } from "./TagProps"; - export type TagSizes = "sm" | "md" | "lg" | "xl"; export type TagVariant = "solid" | "subtle" | "outline"; +export type TagTheme = "base" | "primary"; export interface TagProps extends PressableProps { /** @@ -23,6 +23,11 @@ export interface TagProps extends PressableProps { * @default solid */ variant: TagVariant; + /** + * The Theme of the Tag component. + * @default base + */ + themeColor: TagTheme; /** * A Prefix Element. * If added, the Tag will show a prefix Element before the Tag's text. @@ -38,11 +43,6 @@ export interface TagProps extends PressableProps { * If yes, the Tag will show a Close Icon after the Tag's text or Suffix. */ closable: boolean; - /** - * The Container style of the Tag component. - * @default {} - */ - touchableContainerStyle: ViewStyle; /** * The Text style of the Tag component. * @default {} @@ -56,78 +56,100 @@ const RNTag: React.FC> = forwardRef< >((props, ref) => { const tailwind = useTheme(); const tagTheme = useTheme("tag"); - const { - _tagLibProps: { size, variant }, - _tagOptions: { suffix, prefix }, - } = useTagProps(props); + size = "md", + variant = "solid", + themeColor = "base", + closable = false, + prefix, + suffix = closable ? } /> : null, + style, + ...otherProps + } = props; + + /* Prefix Slot */ + const _prefix = + prefix && + // @ts-ignore + (prefix?.type === Icon ? ( + createIcon({ + icon: prefix, + iconFill: tailwind.getColor( + props.disabled + ? tagTheme.themeColor[themeColor]?.[variant]?.icon?.disabled + : tagTheme.themeColor[themeColor]?.[variant]?.icon?.default, + ), + iconStyle: tailwind.style(tagTheme.size[size]?.prefix), + }) + ) : ( + {prefix} + )); + + /* Suffix Slot */ + const _suffix = + suffix && + // @ts-ignore + (suffix?.type === Icon ? ( + createIcon({ + icon: suffix, + iconFill: tailwind.getColor( + props.disabled + ? tagTheme.themeColor[themeColor]?.[variant]?.icon?.disabled + : tagTheme.themeColor[themeColor]?.[variant]?.icon?.default, + ), + iconStyle: tailwind.style(tagTheme.size[size]?.suffix), + }) + ) : ( + {suffix} + )); + + /** + * Tag Children + */ + const children = + typeof otherProps.children === "string" ? ( + + {props.children} + + ) : ( + props.children + ); + return ( [ + style={touchState => [ tailwind.style( tagTheme.base, - tagTheme.size.default[size], - tagTheme.variant.default[variant], - pressed && tagTheme.variant.pressed[variant], - props.disabled && tagTheme.variant.disabled[variant], + tagTheme.size[size]?.default, + tagTheme.themeColor[themeColor]?.[variant]?.container?.wrapper, + touchState.pressed + ? tagTheme.themeColor[themeColor]?.[variant]?.container?.pressed + : "", + props.disabled + ? tagTheme.themeColor[themeColor]?.[variant]?.container?.disabled + : "", ), - { ...props.touchableContainerStyle }, + styleAdapter(style, touchState, true), ]} - {...props} + {...otherProps} > - {prefix && - // @ts-ignore - (prefix?.type === Icon ? ( - createIcon({ - icon: prefix, - iconFill: tailwind.getColor( - props.disabled - ? tagTheme.variant.icon.disabled[variant] - : tagTheme.variant.icon.default[variant], - ), - iconStyle: tailwind.style(tagTheme.size.prefix[size]), - }) - ) : ( - - {prefix} - - ))} - {typeof props.children === "string" ? ( - - {props.children} - - ) : ( - props.children - )} - {suffix && - // @ts-ignore - (suffix?.type === Icon ? ( - createIcon({ - icon: suffix, - iconFill: tailwind.getColor( - props.disabled - ? tagTheme.variant.icon.disabled[variant] - : tagTheme.variant.icon.default[variant], - ), - iconStyle: tailwind.style(tagTheme.size.suffix[size]), - }) - ) : ( - - {suffix} - - ))} + {_prefix} + {children} + {closable && _suffix} ); }); diff --git a/src/components/tag/TagProps.tsx b/src/components/tag/TagProps.tsx deleted file mode 100644 index ec58850e..00000000 --- a/src/components/tag/TagProps.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { pick } from "lodash"; - -import { TAG_LIB_KEYS, TAG_OPTION_KEYS } from "./__keys"; -import { TagProps } from "./Tag"; - -type TagOptions = Pick; -interface TagPropsReturnType { - _tagLibProps: TagProps; - _tagOptions: TagOptions; -} - -export const useTagProps = ( - props: React.PropsWithChildren>, -): TagPropsReturnType => { - props = { - size: "lg", - variant: "solid", - closable: false, - ...props, - }; - const _tagLibProps = pick(props, TAG_LIB_KEYS) as TagProps; - const _tagOptions = pick(props, TAG_OPTION_KEYS) as TagOptions; - return { _tagLibProps, _tagOptions }; -}; diff --git a/src/components/tag/__keys.ts b/src/components/tag/__keys.ts deleted file mode 100644 index 635e3f2c..00000000 --- a/src/components/tag/__keys.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const TAG_LIB_KEYS = ["size", "variant"]; -export const TAG_OPTION_KEYS = ["prefix", "suffix", "closable"]; diff --git a/src/components/tag/index.ts b/src/components/tag/index.ts index 57b8437d..5b4c58bc 100644 --- a/src/components/tag/index.ts +++ b/src/components/tag/index.ts @@ -1,3 +1 @@ -export * from "./__keys"; export * from "./Tag"; -export * from "./TagProps"; diff --git a/src/theme/defaultTheme/tag.ts b/src/theme/defaultTheme/tag.ts index 17fc4b02..7485c296 100644 --- a/src/theme/defaultTheme/tag.ts +++ b/src/theme/defaultTheme/tag.ts @@ -1,76 +1,165 @@ export const tag = { base: "flex flex-row items-center justify-center relative", - variant: { - default: { - solid: "bg-gray-800 border border-transparent", - subtle: "bg-gray-100 border border-transparent", - outline: "bg-white border border-gray-200", - }, - disabled: { - solid: "bg-gray-200 border border-transparent", - subtle: "bg-gray-100 border border-transparent", - outline: "bg-white border border-gray-200", - }, - icon: { - default: { - solid: "text-gray-400", - subtle: "text-gray-500", - outline: "text-gray-400", + themeColor: { + base: { + solid: { + container: { + wrapper: "bg-gray-900 border border-transparent", + pressed: "bg-gray-700", + disabled: "bg-gray-200", + }, + text: { + default: "text-white-900", + disabled: "bg-gray-200 text-gray-500", + }, + icon: { + default: "text-white-900", + disabled: "text-gray-500", + }, + spinner: { + disabled: "border-gray-500", + }, }, - disabled: { - solid: "text-gray-400", - subtle: "text-gray-400", - outline: "text-gray-400", + subtle: { + container: { + wrapper: "bg-gray-100 border border-transparent", + pressed: "bg-gray-300", + disabled: "bg-gray-100", + }, + text: { + default: "text-gray-800", + disabled: "bg-gray-100 text-gray-500", + }, + icon: { + default: "text-gray-800", + disabled: "text-gray-500", + }, + spinner: { + disabled: "border-gray-500", + }, + }, + outline: { + container: { + wrapper: "bg-white-900 border border-gray-400", + pressed: "border-gray-500 bg-gray-300", + disabled: "bg-gray-100 border-gray-400", + }, + text: { + default: "text-gray-800", + disabled: "bg-gray-100 text-gray-500", + }, + icon: { + default: "text-gray-800", + disabled: "text-gray-500", + }, + spinner: { + disabled: "border-gray-500", + }, }, }, - text: { - default: { - solid: "text-white", - subtle: "text-gray-600", - outline: "text-gray-600", + primary: { + solid: { + container: { + wrapper: "bg-blue-600 border border-transparent", + pressed: "bg-blue-800", + disabled: "bg-blue-100", + }, + text: { + default: "text-white-900", + disabled: "text-blue-500", + }, + icon: { + default: "text-white-900", + disabled: "text-blue-500", + }, + spinner: { + disabled: "border-blue-500", + }, }, - disabled: { - solid: "text-gray-500", - subtle: "text-gray-400", - outline: "text-gray-400", + subtle: { + container: { + wrapper: "bg-blue-100 border border-transparent", + pressed: "bg-blue-300", + disabled: "bg-blue-100", + }, + text: { + default: "text-blue-800", + disabled: "text-blue-500", + }, + icon: { + default: "text-blue-800", + disabled: "text-blue-500", + }, + spinner: { + disabled: "border-blue-500", + }, + }, + outline: { + container: { + wrapper: "bg-white-900 border border-blue-400", + pressed: "border-blue-500 bg-blue-300", + disabled: "bg-blue-100 border-blue-400", + }, + text: { + default: "text-blue-800", + disabled: "text-blue-500", + }, + icon: { + default: "text-blue-800", + disabled: "text-blue-500", + }, + spinner: { + disabled: "border-blue-500", + }, + }, + ghost: { + container: { + wrapper: "bg-white-900 border border-transparent", + pressed: "bg-blue-300", + disabled: "", + }, + text: { + default: "text-blue-800", + disabled: "text-blue-500", + }, + icon: { + default: "text-blue-800", + disabled: "text-blue-500", + }, + spinner: { + disabled: "border-blue-500", + }, }, - }, - pressed: { - solid: "bg-gray-900", - subtle: "bg-gray-200", - outline: "bg-gray-100 border-gray-300 shadow-sm", }, }, size: { - default: { - sm: "min-h-5 w-auto min-w-5 px-1.5 rounded-[5px]", - md: "min-h-6 w-auto min-w-6 px-2 rounded-md", - lg: "min-h-7 w-auto min-w-7 px-2 rounded-md", - xl: "min-h-9 w-auto min-w-9 px-3 rounded-lg", - }, - prefix: { - sm: "w-3 mr-1.5 items-center justify-center", - md: "w-3 mr-1.5 items-center justify-center", - lg: "w-3 mr-1.5 items-center justify-center", - xl: "w-4 mr-1.5 items-center justify-center", + sm: { + default: "min-h-5 w-auto min-w-5 px-1.5 rounded-[5px]", + prefix: "w-3 mr-1.5 items-center justify-center", + suffix: "w-3 ml-1.5 items-center justify-center", + closable: "w-3 ml-1", + text: "text-cxs font-medium", }, - suffix: { - sm: "w-3 ml-1.5 items-center justify-center", - md: "w-3 ml-1.5 items-center justify-center", - lg: "w-3 ml-1.5 items-center justify-center", - xl: "w-4 ml-1.5 items-center justify-center", + md: { + default: "min-h-6 w-auto min-w-6 px-2 rounded-md", + prefix: "w-3 mr-1.5 items-center justify-center", + suffix: "w-3 ml-1.5 items-center justify-center", + closable: "w-3 ml-1", + text: "text-cxs font-medium", }, - closable: { - sm: "w-3 ml-1", - md: "w-3 ml-1", - lg: "w-3 ml-1", - xl: "w-4 ml-1.5", + lg: { + default: "min-h-7 w-auto min-w-7 px-2 rounded-md", + prefix: "w-3 mr-1.5 items-center justify-center", + suffix: "w-3 ml-1.5 items-center justify-center", + closable: "w-3 ml-1", + text: "text-sm font-medium", }, - text: { - sm: "text-cxs font-medium", - md: "text-cxs font-medium", - lg: "text-sm font-medium", - xl: "text-base font-medium", + xl: { + default: "min-h-9 w-auto min-w-9 px-3 rounded-lg", + prefix: "w-4 mr-1.5 items-center justify-center", + suffix: "w-4 ml-1.5 items-center justify-center", + closable: "w-4 ml-1.5", + text: "text-base font-medium", }, }, };