From 36538591ce9a869a935c07e227355e8cd86c8140 Mon Sep 17 00:00:00 2001 From: marcelines Date: Tue, 6 Jun 2023 12:46:54 +0100 Subject: [PATCH] [website] Custom tags (#409) * feat: change tags component and add util to get color with opacity * feat: change some tags for the example purpose * fix: some issues and code organization * feat: removes complexity from the code and uses css color-mix function --- .../chart/components/chart-component.tsx | 3 +- apps/website/src/components/epic-overview.tsx | 45 ++----------- apps/website/src/components/table-issues.tsx | 8 +-- .../components/src/tag/get-custom-styles.ts | 64 +++++++++++++++++++ packages/components/src/tag/tag.stories.tsx | 15 +++++ packages/components/src/tag/tag.tsx | 36 ++++++++++- packages/components/src/text/text.tsx | 2 +- .../utils/get-color-with-opacity.ts | 18 ++++++ 8 files changed, 142 insertions(+), 49 deletions(-) create mode 100644 packages/components/src/tag/get-custom-styles.ts create mode 100644 packages/components/utils/get-color-with-opacity.ts diff --git a/apps/website/src/components/chart/components/chart-component.tsx b/apps/website/src/components/chart/components/chart-component.tsx index 49cc2fbb..81ed8b80 100644 --- a/apps/website/src/components/chart/components/chart-component.tsx +++ b/apps/website/src/components/chart/components/chart-component.tsx @@ -133,7 +133,7 @@ const ChartComponent = (props: Props): JSX.Element => { return { dy: '.33em', fill: '#A1ABBD', - fontFamily: 'Inter, sans-serif', + fontFamily: 'Menlo', fontSize: 11, textAnchor, } @@ -161,6 +161,7 @@ const ChartComponent = (props: Props): JSX.Element => { {...tickProps} fill="#A1ABBD" fontSize={11} + fontFamily="Menlo" textAnchor="middle" dx="-1em" > diff --git a/apps/website/src/components/epic-overview.tsx b/apps/website/src/components/epic-overview.tsx index fdf686e5..270d09da 100644 --- a/apps/website/src/components/epic-overview.tsx +++ b/apps/website/src/components/epic-overview.tsx @@ -56,41 +56,6 @@ const DATA = [ open_issues: 10, closed_issues: 130, }, - { - date: '2022-02-04', - open_issues: 10, - closed_issues: 140, - }, - { - date: '2022-02-05', - open_issues: 10, - closed_issues: 150, - }, - { - date: '2022-02-06', - open_issues: 10, - closed_issues: 160, - }, - { - date: '2022-02-07', - open_issues: 10, - closed_issues: 180, - }, - { - date: '2022-02-08', - open_issues: 10, - closed_issues: 190, - }, - { - date: '2022-02-09', - open_issues: 10, - closed_issues: 200, - }, - { - date: '2022-02-10', - open_issues: 0, - closed_issues: 220, - }, ] type Props = { @@ -126,20 +91,20 @@ export const EpicOverview = (props: Props) => { {description}
- +
- - + +
- - + +
diff --git a/apps/website/src/components/table-issues.tsx b/apps/website/src/components/table-issues.tsx index 1bfde8e7..8064bf23 100644 --- a/apps/website/src/components/table-issues.tsx +++ b/apps/website/src/components/table-issues.tsx @@ -56,10 +56,10 @@ export const TableIssues = () => {
- - - - + + + +
diff --git a/packages/components/src/tag/get-custom-styles.ts b/packages/components/src/tag/get-custom-styles.ts new file mode 100644 index 00000000..1e2c31a1 --- /dev/null +++ b/packages/components/src/tag/get-custom-styles.ts @@ -0,0 +1,64 @@ +import { getColorWithOpacity } from '../../utils/get-color-with-opacity' +import { tokens } from '../tokens' + +import type { TagProps } from './tag' +import type { ColorTokens, StackStyleProps } from '@tamagui/core' + +// TypeGuard for ColorTokens +function isColorTokens( + value: `#${string}` | ColorTokens +): value is ColorTokens { + return typeof value === 'string' && value.startsWith('$') +} + +/** + * Gets the styles for the custom tag + * @param props - the props of the tag + * @returns the styles for the custom tag or null if no color is provided + **/ +const getCustomStyles = (props: TagProps): StackStyleProps | null => { + const { color: colorFromProps, icon } = props + + if (!colorFromProps) { + return null + } + + let color: ColorTokens | string = colorFromProps + + if (isColorTokens(colorFromProps)) { + const colorToken = colorFromProps.replace( + '$', + '' + ) as keyof typeof tokens.color + color = tokens.color[colorToken]?.val || colorFromProps + } + + if (icon) { + return { + borderColor: getColorWithOpacity(color!, 0.2), + backgroundColor: getColorWithOpacity(color!, 0.1), + pressStyle: { + backgroundColor: getColorWithOpacity(color, 0.2), + borderColor: getColorWithOpacity(color, 0.3), + }, + hoverStyle: { + backgroundColor: getColorWithOpacity(color, 0.2), + borderColor: getColorWithOpacity(color, 0.3), + }, + } + } + + return { + borderColor: getColorWithOpacity(color, 0.2), + pressStyle: { + borderColor: getColorWithOpacity(color, 0.3), + backgroundColor: getColorWithOpacity(color, 0.1), + }, + hoverStyle: { + borderColor: getColorWithOpacity(color, 0.3), + backgroundColor: getColorWithOpacity(color, 0.1), + }, + } +} + +export { getCustomStyles } diff --git a/packages/components/src/tag/tag.stories.tsx b/packages/components/src/tag/tag.stories.tsx index ad81d7a4..1bd16fcd 100644 --- a/packages/components/src/tag/tag.stories.tsx +++ b/packages/components/src/tag/tag.stories.tsx @@ -1,3 +1,4 @@ +import { NftIcon } from '@status-im/icons' import { Stack } from '@tamagui/core' import { Tag } from './tag' @@ -26,6 +27,7 @@ export const Default: Story = { + @@ -37,6 +39,19 @@ export const Default: Story = { + + + + + + + + ) diff --git a/packages/components/src/tag/tag.tsx b/packages/components/src/tag/tag.tsx index f429c437..dbca591e 100644 --- a/packages/components/src/tag/tag.tsx +++ b/packages/components/src/tag/tag.tsx @@ -3,9 +3,11 @@ import { createElement } from 'react' import { Stack, styled } from '@tamagui/core' import { Text } from '../text' +import { getCustomStyles } from './get-custom-styles' import type { TextProps } from '../text' import type { IconProps } from '@status-im/icons' +import type { ColorTokens } from '@tamagui/core' import type { ComponentType } from 'react' type Props = { @@ -14,6 +16,8 @@ type Props = { label?: string selected?: boolean disabled?: boolean + onPress?: () => void + color?: ColorTokens | `#${string}` } const textSizes: Record, TextProps['size']> = { @@ -27,7 +31,7 @@ const iconSizes: Record, IconProps['size']> = { } const Tag = (props: Props) => { - const { size, icon, label, selected, disabled } = props + const { size, icon, label, selected, disabled, onPress, color } = props const renderIcon = () => { if (!icon) { @@ -47,10 +51,12 @@ const Tag = (props: Props) => { selected={selected} disabled={disabled} iconOnly={Boolean(icon && !label)} + onPress={() => onPress?.()} + {...getCustomStyles(props)} > {renderIcon()} {label && ( - + {label} )} @@ -62,6 +68,10 @@ export { Tag } export type { Props as TagProps } const Base = styled(Stack, { + tag: 'tag', + name: 'Tag', + accessibilityRole: 'button', + display: 'flex', flexDirection: 'row', alignItems: 'center', @@ -71,6 +81,18 @@ const Base = styled(Stack, { borderRadius: '$full', backgroundColor: '$white-100', + animation: 'fast', + cursor: 'pointer', + + hoverStyle: { + borderColor: '$neutral-30', + backgroundColor: '$neutral-5', + }, + pressStyle: { + borderColor: '$neutral-30', + backgroundColor: '$neutral-5', + }, + variants: { size: { 32: { @@ -86,11 +108,19 @@ const Base = styled(Stack, { gap: 5, }, }, - selected: { true: { backgroundColor: '$primary-50-opa-10', borderColor: '$primary-50', + + hoverStyle: { + backgroundColor: '$primary-50-opa-20', + borderColor: '$primary-60', + }, + pressStyle: { + backgroundColor: '$primary-50-opa-20', + borderColor: '$primary-60', + }, }, }, diff --git a/packages/components/src/text/text.tsx b/packages/components/src/text/text.tsx index f57c347e..ffe889bc 100644 --- a/packages/components/src/text/text.tsx +++ b/packages/components/src/text/text.tsx @@ -12,7 +12,7 @@ type Weight = NonNullable type Props = { children: React.ReactNode - color?: ColorTokens + color?: ColorTokens | string truncate?: boolean wrap?: false } & ( diff --git a/packages/components/utils/get-color-with-opacity.ts b/packages/components/utils/get-color-with-opacity.ts new file mode 100644 index 00000000..54c1688c --- /dev/null +++ b/packages/components/utils/get-color-with-opacity.ts @@ -0,0 +1,18 @@ +/** + * Gets the color with opacity based on the original color and opacity value + * @param color - the original color + * @param opacity - the opacity value + * @returns the color with opacity + **/ + +function getColorWithOpacity(color: string, opacity: number): string { + // Ensure the opacity value is within the valid range of 0 to 1 + const clampedOpacity = Math.max(0, Math.min(1, opacity)) * 100 + + // Construct the color string with opacity using CSS color-mix function + const newColor = `color-mix(in srgb, ${color} ${clampedOpacity}%, transparent);` + + return newColor +} + +export { getColorWithOpacity }