From e70bb34190ea1c7f7a0c1d111c8d9646d9b5fd9f Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 15:42:35 +0700 Subject: [PATCH 01/13] =?UTF-8?q?=E2=9A=92=EF=B8=8F=20build:=20reorder=20p?= =?UTF-8?q?ackages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/package.json | 3 +- yarn.lock | 62 +++++----------------------------- 2 files changed, 11 insertions(+), 54 deletions(-) diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 7e369024..1c917e9f 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -5,8 +5,8 @@ "dependencies": { "@fontsource/inter": "^5.0.16", "@material-tailwind/react": "^2.1.7", - "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.0.4", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -15,6 +15,7 @@ "@types/react": "^18.2.42", "@types/react-dom": "^18.2.17", "assert": "^2.1.0", + "clsx": "^2.1.0", "date-fns": "^3.3.1", "downshift": "^8.2.3", "eslint-config-react-app": "^7.0.1", diff --git a/yarn.lock b/yarn.lock index 87b34483..d451b22d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1280,7 +1280,7 @@ resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.10.4", "@babel/runtime@^7.13.10", "@babel/runtime@^7.23.7", "@babel/runtime@^7.13.10", "@babel/runtime@^7.23.7", "@babel/runtime@^7.3.1": +"@babel/runtime@^7.10.4", "@babel/runtime@^7.13.10", "@babel/runtime@^7.23.7", "@babel/runtime@^7.3.1": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== @@ -3277,6 +3277,13 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== +"@radix-ui/primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" + integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-avatar@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.0.4.tgz#de9a5349d9e3de7bbe990334c4d2011acbbb9623" @@ -3288,57 +3295,6 @@ "@radix-ui/react-use-callback-ref" "1.0.1" "@radix-ui/react-use-layout-effect" "1.0.1" -"@radix-ui/react-compose-refs@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" - integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-context@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" - integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-primitive@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" - integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-slot" "1.0.2" - -"@radix-ui/react-slot@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" - integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - -"@radix-ui/react-use-callback-ref@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" - integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-use-layout-effect@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" - integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/primitive@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" - integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-checkbox@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz#98f22c38d5010dd6df4c5744cac74087e3275f4b" @@ -6314,7 +6270,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -clsx@^2.0.0: +clsx@^2.0.0, clsx@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb" integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg== From 237e9e5cb9120d22899c0b9a2611d888d0e0e565 Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 15:43:09 +0700 Subject: [PATCH 02/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=20implement=20class?= =?UTF-8?q?names=20utils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/utils/classnames.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 packages/frontend/src/utils/classnames.ts diff --git a/packages/frontend/src/utils/classnames.ts b/packages/frontend/src/utils/classnames.ts new file mode 100644 index 00000000..7c5139f9 --- /dev/null +++ b/packages/frontend/src/utils/classnames.ts @@ -0,0 +1,13 @@ +import { clsx } from 'clsx'; +import type { ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +/** + * Returns a merged class name string by merging and processing multiple class names and Tailwind CSS styles. + * + * @param {...string[]} args - One or more class names and/or Tailwind CSS styles to be merged. + * @returns {string} - The merged class name string. + */ +export function cn(...args: ClassValue[]): string { + return twMerge(clsx(args)); +} From 636f68d7a47b4527231f41457a597f744470bb36 Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 15:43:32 +0700 Subject: [PATCH 03/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=20add=20more=20icon?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shared/CustomIcon/CrossIcon.tsx | 21 +++++++++++++++++++ .../shared/CustomIcon/SearchIcon.tsx | 21 +++++++++++++++++++ .../shared/CustomIcon/WarningIcon.tsx | 21 +++++++++++++++++++ .../src/components/shared/CustomIcon/index.ts | 3 +++ 4 files changed, 66 insertions(+) create mode 100644 packages/frontend/src/components/shared/CustomIcon/CrossIcon.tsx create mode 100644 packages/frontend/src/components/shared/CustomIcon/SearchIcon.tsx create mode 100644 packages/frontend/src/components/shared/CustomIcon/WarningIcon.tsx diff --git a/packages/frontend/src/components/shared/CustomIcon/CrossIcon.tsx b/packages/frontend/src/components/shared/CustomIcon/CrossIcon.tsx new file mode 100644 index 00000000..8d649f0c --- /dev/null +++ b/packages/frontend/src/components/shared/CustomIcon/CrossIcon.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { CustomIcon, CustomIconProps } from './CustomIcon'; + +export const CrossIcon = (props: CustomIconProps) => { + return ( + + + + ); +}; diff --git a/packages/frontend/src/components/shared/CustomIcon/SearchIcon.tsx b/packages/frontend/src/components/shared/CustomIcon/SearchIcon.tsx new file mode 100644 index 00000000..7688adcd --- /dev/null +++ b/packages/frontend/src/components/shared/CustomIcon/SearchIcon.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { CustomIcon, CustomIconProps } from './CustomIcon'; + +export const SearchIcon = (props: CustomIconProps) => { + return ( + + + + ); +}; diff --git a/packages/frontend/src/components/shared/CustomIcon/WarningIcon.tsx b/packages/frontend/src/components/shared/CustomIcon/WarningIcon.tsx new file mode 100644 index 00000000..1fd27fb4 --- /dev/null +++ b/packages/frontend/src/components/shared/CustomIcon/WarningIcon.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { CustomIcon, CustomIconProps } from './CustomIcon'; + +export const WarningIcon = (props: CustomIconProps) => { + return ( + + + + ); +}; diff --git a/packages/frontend/src/components/shared/CustomIcon/index.ts b/packages/frontend/src/components/shared/CustomIcon/index.ts index 34b7f485..aeb7c87e 100644 --- a/packages/frontend/src/components/shared/CustomIcon/index.ts +++ b/packages/frontend/src/components/shared/CustomIcon/index.ts @@ -4,3 +4,6 @@ export * from './CheckIcon'; export * from './ChevronGrabberHorizontal'; export * from './ChevronLeft'; export * from './ChevronRight'; +export * from './WarningIcon'; +export * from './SearchIcon'; +export * from './CrossIcon'; From 33b61915399d8c7572136bedb50cd155d370b135 Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 15:43:53 +0700 Subject: [PATCH 04/13] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20feat:=20implement=20?= =?UTF-8?q?Input=20Field=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/shared/Input/Input.theme.ts | 68 ++++++++++++ .../src/components/shared/Input/Input.tsx | 100 ++++++++++++++++++ .../src/components/shared/Input/index.ts | 2 + 3 files changed, 170 insertions(+) create mode 100644 packages/frontend/src/components/shared/Input/Input.theme.ts create mode 100644 packages/frontend/src/components/shared/Input/Input.tsx create mode 100644 packages/frontend/src/components/shared/Input/index.ts diff --git a/packages/frontend/src/components/shared/Input/Input.theme.ts b/packages/frontend/src/components/shared/Input/Input.theme.ts new file mode 100644 index 00000000..e0ea2c5f --- /dev/null +++ b/packages/frontend/src/components/shared/Input/Input.theme.ts @@ -0,0 +1,68 @@ +import { VariantProps, tv } from 'tailwind-variants'; + +export const inputTheme = tv( + { + slots: { + container: [ + 'flex items-center rounded-lg relative', + 'placeholder:text-elements-disabled', + 'disabled:cursor-not-allowed disabled:bg-controls-disabled', + ], + label: ['text-sm', 'text-elements-high-em'], + description: ['text-xs', 'text-elements-low-em'], + input: [ + 'focus-ring', + 'block w-full h-full rounded-lg text-elements-mid-em', + 'shadow-sm', + 'border border-border-interactive', + 'disabled:shadow-none', + 'disabled:border-none', + ], + icon: ['text-elements-mid-em'], + iconContainer: [ + 'absolute inset-y-0 flex items-center z-10 cursor-pointer', + ], + helperIcon: [], + helperText: ['flex gap-2 items-center text-elements-danger'], + }, + variants: { + state: { + default: { + input: '', + }, + error: { + input: [ + 'outline outline-offset-0 outline-border-danger', + 'shadow-none', + ], + helperText: ['text-elements-danger'], + }, + }, + size: { + md: { + container: 'h-11', + input: 'text-sm pl-4 pr-4', + icon: 'h-[18px] w-[18px]', + helperText: 'text-sm', + helperIcon: 'h-5 w-5', + }, + sm: { + container: 'h-8', + input: 'text-xs pl-3 pr-3', + icon: 'h-4 w-4', + helperText: 'text-xs', + helperIcon: 'h-4 w-4', + }, + }, + }, + defaultVariants: { + size: 'md', + state: 'default', + }, + }, + { + responsiveVariants: true, + }, +); + +export type InputTheme = VariantProps; diff --git a/packages/frontend/src/components/shared/Input/Input.tsx b/packages/frontend/src/components/shared/Input/Input.tsx new file mode 100644 index 00000000..52b398e1 --- /dev/null +++ b/packages/frontend/src/components/shared/Input/Input.tsx @@ -0,0 +1,100 @@ +import React, { ReactNode, useMemo } from 'react'; +import { ComponentPropsWithoutRef } from 'react'; +import { InputTheme, inputTheme } from './Input.theme'; +import { cloneIcon } from 'utils/cloneIcon'; +import { cn } from 'utils/classnames'; +import { WarningIcon } from '../CustomIcon'; + +export interface InputProps + extends InputTheme, + Omit, 'size'> { + label?: string; + description?: string; + leftIcon?: ReactNode; + rightIcon?: ReactNode; + helperText?: string; +} + +export const Input = ({ + className, + label, + description, + leftIcon, + rightIcon, + helperText, + size, + state, + ...props +}: InputProps) => { + const styleProps = (({ size = 'md', state }) => ({ + size, + state, + }))({ size, state }); + + const { + container: containerCls, + label: labelCls, + description: descriptionCls, + input: inputCls, + icon: iconCls, + iconContainer: iconContainerCls, + helperText: helperTextCls, + helperIcon: helperIconCls, + } = inputTheme({ ...styleProps }); + + const renderLabels = useMemo( + () => ( +
+

{label}

+

{description}

+
+ ), + [labelCls, descriptionCls, label, description], + ); + + const renderLeftIcon = useMemo(() => { + return ( +
+ {cloneIcon(leftIcon, { className: iconCls(), ariaHidden: true })} +
+ ); + }, [iconCls, leftIcon]); + + const renderRightIcon = useMemo(() => { + return ( +
+ {cloneIcon(rightIcon, { className: iconCls(), ariaHidden: true })} +
+ ); + }, [rightIcon, iconCls]); + + const renderHelperText = useMemo( + () => ( +
+ {state && + cloneIcon(, { + ariaHidden: true, + })} +

{helperText}

+
+ ), + [state, helperText, helperTextCls], + ); + + return ( +
+ {renderLabels} +
+ {leftIcon && renderLeftIcon} + + {rightIcon && renderRightIcon} +
+ {renderHelperText} +
+ ); +}; diff --git a/packages/frontend/src/components/shared/Input/index.ts b/packages/frontend/src/components/shared/Input/index.ts new file mode 100644 index 00000000..9ffcc229 --- /dev/null +++ b/packages/frontend/src/components/shared/Input/index.ts @@ -0,0 +1,2 @@ +export * from './Input'; +export * from './Input.theme'; From 7d5963d77658e17a8f366d7035acbc1b08bab47d Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 15:44:21 +0700 Subject: [PATCH 05/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=20add=20input=20to?= =?UTF-8?q?=20page/components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/pages/components/index.tsx | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/components/index.tsx b/packages/frontend/src/pages/components/index.tsx index 456f433e..8cf092d5 100644 --- a/packages/frontend/src/pages/components/index.tsx +++ b/packages/frontend/src/pages/components/index.tsx @@ -3,7 +3,8 @@ import { Badge, BadgeProps } from 'components/shared/Badge'; import { Button, ButtonOrLinkProps } from 'components/shared/Button'; import { Calendar } from 'components/shared/Calendar'; import { Checkbox } from 'components/shared/Checkbox'; -import { PlusIcon } from 'components/shared/CustomIcon'; +import { SearchIcon, CrossIcon, PlusIcon } from 'components/shared/CustomIcon'; +import { Input } from 'components/shared/Input'; import React, { useState } from 'react'; import { Value } from 'react-calendar/dist/cjs/shared/types'; @@ -53,6 +54,59 @@ const Page = () => { {/* Insert Components here */}
+

Input

+
+
+ } + rightIcon={} + placeholder="Placeholder text" + /> + + +
+
+ } + rightIcon={} + description="Additional information or context" + placeholder="Placeholder text" + size="sm" + /> + + +
+
+ +
+

Button

{['primary', 'secondary', 'tertiary', 'danger'].map( From b6630670356afb699f242454bd7161c5a5ad5e99 Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 17:07:30 +0700 Subject: [PATCH 06/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=20use=20absolute=20?= =?UTF-8?q?import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/shared/Input/Input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/shared/Input/Input.tsx b/packages/frontend/src/components/shared/Input/Input.tsx index 52b398e1..0905f556 100644 --- a/packages/frontend/src/components/shared/Input/Input.tsx +++ b/packages/frontend/src/components/shared/Input/Input.tsx @@ -1,9 +1,9 @@ import React, { ReactNode, useMemo } from 'react'; import { ComponentPropsWithoutRef } from 'react'; import { InputTheme, inputTheme } from './Input.theme'; +import { WarningIcon } from 'components/shared/CustomIcon'; import { cloneIcon } from 'utils/cloneIcon'; import { cn } from 'utils/classnames'; -import { WarningIcon } from '../CustomIcon'; export interface InputProps extends InputTheme, From 5f6723fad634cb8fe15209004c9bd2603fb250bb Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 17:07:59 +0700 Subject: [PATCH 07/13] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20create?= =?UTF-8?q?=20new=20renderInput=20for=20component=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/components/renders/input.tsx | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 packages/frontend/src/pages/components/renders/input.tsx diff --git a/packages/frontend/src/pages/components/renders/input.tsx b/packages/frontend/src/pages/components/renders/input.tsx new file mode 100644 index 00000000..bc0b79ff --- /dev/null +++ b/packages/frontend/src/pages/components/renders/input.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { Input } from 'components/shared/Input'; +import { SearchIcon, CrossIcon } from 'components/shared/CustomIcon'; + +export const renderInputs = () => { + return ( + <> +
+ } + rightIcon={} + placeholder="Placeholder text" + /> + + +
+
+ } + rightIcon={} + description="Additional information or context" + placeholder="Placeholder text" + size="sm" + /> + + +
+ + ); +}; From 807a4b11974c4795a725f14c454ec4045ac23d7c Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 17:08:14 +0700 Subject: [PATCH 08/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/pages/components/index.tsx | 57 +------------------ 1 file changed, 2 insertions(+), 55 deletions(-) diff --git a/packages/frontend/src/pages/components/index.tsx b/packages/frontend/src/pages/components/index.tsx index 1a76f3af..dcd8941a 100644 --- a/packages/frontend/src/pages/components/index.tsx +++ b/packages/frontend/src/pages/components/index.tsx @@ -1,11 +1,5 @@ import React, { useState } from 'react'; -import { Avatar, AvatarVariants } from 'components/shared/Avatar'; -import { Badge, BadgeProps } from 'components/shared/Badge'; -import { Button, ButtonOrLinkProps } from 'components/shared/Button'; import { Calendar } from 'components/shared/Calendar'; -import { Checkbox } from 'components/shared/Checkbox'; -import { SearchIcon, CrossIcon, PlusIcon } from 'components/shared/CustomIcon'; -import { Input } from 'components/shared/Input'; import { Value } from 'react-calendar/dist/cjs/shared/types'; import { renderCheckbox, @@ -19,6 +13,7 @@ import { renderTabs, renderVerticalTabs, } from './renders/tabs'; +import { renderInputs } from './renders/input'; const Page = () => { const [singleDate, setSingleDate] = useState(); @@ -40,55 +35,7 @@ const Page = () => { {/* Button */}

Input

-
-
- } - rightIcon={} - placeholder="Placeholder text" - /> - - -
-
- } - rightIcon={} - description="Additional information or context" - placeholder="Placeholder text" - size="sm" - /> - - -
-
+
{renderInputs()}
From 195d957251b48a8da64ada7568f99af2e5dc39be Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 17:08:33 +0700 Subject: [PATCH 09/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=20restructure=20tai?= =?UTF-8?q?lwind=20classnames?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/shared/Input/Input.theme.ts | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/components/shared/Input/Input.theme.ts b/packages/frontend/src/components/shared/Input/Input.theme.ts index e0ea2c5f..65dbdfb6 100644 --- a/packages/frontend/src/components/shared/Input/Input.theme.ts +++ b/packages/frontend/src/components/shared/Input/Input.theme.ts @@ -4,26 +4,40 @@ export const inputTheme = tv( { slots: { container: [ - 'flex items-center rounded-lg relative', + 'flex', + 'items-center', + 'rounded-lg', + 'relative', 'placeholder:text-elements-disabled', - 'disabled:cursor-not-allowed disabled:bg-controls-disabled', + 'disabled:cursor-not-allowed', + 'disabled:bg-controls-disabled', ], label: ['text-sm', 'text-elements-high-em'], description: ['text-xs', 'text-elements-low-em'], input: [ 'focus-ring', - 'block w-full h-full rounded-lg text-elements-mid-em', + 'block', + 'w-full', + 'h-full', + 'rounded-lg', + 'text-elements-mid-em', 'shadow-sm', - 'border border-border-interactive', + 'border', + 'border-border-interactive', 'disabled:shadow-none', 'disabled:border-none', ], icon: ['text-elements-mid-em'], iconContainer: [ - 'absolute inset-y-0 flex items-center z-10 cursor-pointer', + 'absolute', + 'inset-y-0', + 'flex', + 'items-center', + 'z-10', + 'cursor-pointer', ], helperIcon: [], - helperText: ['flex gap-2 items-center text-elements-danger'], + helperText: ['flex', 'gap-2', 'items-center', 'text-elements-danger'], }, variants: { state: { @@ -32,10 +46,12 @@ export const inputTheme = tv( }, error: { input: [ - 'outline outline-offset-0 outline-border-danger', + 'outline', + 'outline-offset-0', + 'outline-border-danger', 'shadow-none', ], - helperText: ['text-elements-danger'], + helperText: 'text-elements-danger', }, }, size: { From 448d0ceb7c75ec3ce4034bc9def6d6d66b45c6b6 Mon Sep 17 00:00:00 2001 From: Andre H Date: Wed, 21 Feb 2024 17:10:45 +0700 Subject: [PATCH 10/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=201=20classname=20p?= =?UTF-8?q?er=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/shared/Input/Input.theme.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/shared/Input/Input.theme.ts b/packages/frontend/src/components/shared/Input/Input.theme.ts index 65dbdfb6..8def6a0d 100644 --- a/packages/frontend/src/components/shared/Input/Input.theme.ts +++ b/packages/frontend/src/components/shared/Input/Input.theme.ts @@ -57,17 +57,17 @@ export const inputTheme = tv( size: { md: { container: 'h-11', - input: 'text-sm pl-4 pr-4', - icon: 'h-[18px] w-[18px]', + input: ['text-sm pl-4 pr-4'], + icon: ['h-[18px] w-[18px]'], helperText: 'text-sm', - helperIcon: 'h-5 w-5', + helperIcon: ['h-5 w-5'], }, sm: { container: 'h-8', - input: 'text-xs pl-3 pr-3', - icon: 'h-4 w-4', + input: ['text-xs pl-3 pr-3'], + icon: ['h-4 w-4'], helperText: 'text-xs', - helperIcon: 'h-4 w-4', + helperIcon: ['h-4 w-4'], }, }, }, From da2f7ede426025e9657cad31b62c3df524c937db Mon Sep 17 00:00:00 2001 From: Andre H Date: Thu, 22 Feb 2024 09:15:17 +0700 Subject: [PATCH 11/13] =?UTF-8?q?=F0=9F=94=A7=20chore:=20add=20dependency?= =?UTF-8?q?=20to=20usememo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/shared/Input/Input.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/shared/Input/Input.tsx b/packages/frontend/src/components/shared/Input/Input.tsx index 0905f556..f5bbdca5 100644 --- a/packages/frontend/src/components/shared/Input/Input.tsx +++ b/packages/frontend/src/components/shared/Input/Input.tsx @@ -58,7 +58,7 @@ export const Input = ({ {cloneIcon(leftIcon, { className: iconCls(), ariaHidden: true })}
); - }, [iconCls, leftIcon]); + }, [cloneIcon, iconCls, iconContainerCls, leftIcon]); const renderRightIcon = useMemo(() => { return ( @@ -66,7 +66,7 @@ export const Input = ({ {cloneIcon(rightIcon, { className: iconCls(), ariaHidden: true })}
); - }, [rightIcon, iconCls]); + }, [cloneIcon, iconCls, iconContainerCls, rightIcon]); const renderHelperText = useMemo( () => ( @@ -78,7 +78,7 @@ export const Input = ({

{helperText}

), - [state, helperText, helperTextCls], + [cloneIcon, state, helperIconCls, helperText, helperTextCls], ); return ( From eb6a72742565d36ef71f9dfe207a08873e7bb127 Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Thu, 22 Feb 2024 09:17:22 +0700 Subject: [PATCH 12/13] [T-4862: feat] Link component (#88) --- .../components/shared/Button/Button.theme.ts | 23 +++++++++++++++++++ .../frontend/src/pages/components/index.tsx | 16 ++++++++++++- .../src/pages/components/renders/button.tsx | 16 +++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/shared/Button/Button.theme.ts b/packages/frontend/src/components/shared/Button/Button.theme.ts index 897fdfbc..6c9614c6 100644 --- a/packages/frontend/src/components/shared/Button/Button.theme.ts +++ b/packages/frontend/src/components/shared/Button/Button.theme.ts @@ -118,6 +118,29 @@ export const buttonTheme = tv( 'disabled:border-transparent', 'disabled:shadow-none', ], + link: [ + 'p-0', + 'gap-1.5', + 'text-elements-link', + 'rounded', + 'focus-ring', + 'hover:underline', + 'hover:text-elements-link-hovered', + 'disabled:text-controls-disabled', + 'disabled:hover:no-underline', + ], + 'link-emphasized': [ + 'p-0', + 'gap-1.5', + 'text-elements-high-em', + 'rounded', + 'underline', + 'focus-ring', + 'hover:text-elements-link-hovered', + 'disabled:text-controls-disabled', + 'disabled:hover:no-underline', + 'dark:text-elements-on-high-contrast', + ], unstyled: [], }, }, diff --git a/packages/frontend/src/pages/components/index.tsx b/packages/frontend/src/pages/components/index.tsx index c1c46f6c..507563a0 100644 --- a/packages/frontend/src/pages/components/index.tsx +++ b/packages/frontend/src/pages/components/index.tsx @@ -7,7 +7,11 @@ import { } from './renders/checkbox'; import { avatars, avatarsFallback } from './renders/avatar'; import { renderBadges } from './renders/badge'; -import { renderButtonIcons, renderButtons } from './renders/button'; +import { + renderButtonIcons, + renderButtons, + renderLinks, +} from './renders/button'; import { renderTabWithBadges, renderTabs, @@ -112,6 +116,16 @@ const Page = () => {

Vertical Tabs

{renderVerticalTabs()}
+ +
+ + {/* Link */} +
+

Link

+
+ {renderLinks()} +
+
diff --git a/packages/frontend/src/pages/components/renders/button.tsx b/packages/frontend/src/pages/components/renders/button.tsx index c1c69c48..f5272d3e 100644 --- a/packages/frontend/src/pages/components/renders/button.tsx +++ b/packages/frontend/src/pages/components/renders/button.tsx @@ -47,3 +47,19 @@ export const renderButtonIcons = () => { )); }; + +export const renderLinks = () => { + return ['link', 'link-emphasized', 'disabled'].map((variant) => ( + + )); +}; From 6df094bf2e3d18719816d32e3dbc7e423064c803 Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Thu, 22 Feb 2024 10:45:19 +0700 Subject: [PATCH 13/13] [T-4861: feat] Inline notification component (#86) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ⚡️ feat: create info square icon component * ⚡️ feat: create inline notification component * 📝 docs: add js doc comment and add inline notification component to the example page * 🐛 fix: use the right method of `useCallback --- .../shared/CustomIcon/InfoSquareIcon.tsx | 21 +++++ .../src/components/shared/CustomIcon/index.ts | 1 + .../InlineNotification.theme.ts | 78 +++++++++++++++++++ .../InlineNotification/InlineNotification.tsx | 68 ++++++++++++++++ .../shared/InlineNotification/index.ts | 1 + .../frontend/src/pages/components/index.tsx | 19 ++++- .../renders/inlineNotifications.tsx | 43 ++++++++++ 7 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 packages/frontend/src/components/shared/CustomIcon/InfoSquareIcon.tsx create mode 100644 packages/frontend/src/components/shared/InlineNotification/InlineNotification.theme.ts create mode 100644 packages/frontend/src/components/shared/InlineNotification/InlineNotification.tsx create mode 100644 packages/frontend/src/components/shared/InlineNotification/index.ts create mode 100644 packages/frontend/src/pages/components/renders/inlineNotifications.tsx diff --git a/packages/frontend/src/components/shared/CustomIcon/InfoSquareIcon.tsx b/packages/frontend/src/components/shared/CustomIcon/InfoSquareIcon.tsx new file mode 100644 index 00000000..273131d6 --- /dev/null +++ b/packages/frontend/src/components/shared/CustomIcon/InfoSquareIcon.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { CustomIcon, CustomIconProps } from './CustomIcon'; + +export const InfoSquareIcon = (props: CustomIconProps) => { + return ( + + + + ); +}; diff --git a/packages/frontend/src/components/shared/CustomIcon/index.ts b/packages/frontend/src/components/shared/CustomIcon/index.ts index 6479a1dd..18dbf249 100644 --- a/packages/frontend/src/components/shared/CustomIcon/index.ts +++ b/packages/frontend/src/components/shared/CustomIcon/index.ts @@ -4,6 +4,7 @@ export * from './CheckIcon'; export * from './ChevronGrabberHorizontal'; export * from './ChevronLeft'; export * from './ChevronRight'; +export * from './InfoSquareIcon'; export * from './WarningIcon'; export * from './SearchIcon'; export * from './CrossIcon'; diff --git a/packages/frontend/src/components/shared/InlineNotification/InlineNotification.theme.ts b/packages/frontend/src/components/shared/InlineNotification/InlineNotification.theme.ts new file mode 100644 index 00000000..43536b55 --- /dev/null +++ b/packages/frontend/src/components/shared/InlineNotification/InlineNotification.theme.ts @@ -0,0 +1,78 @@ +import { VariantProps, tv } from 'tailwind-variants'; + +export const inlineNotificationTheme = tv({ + slots: { + wrapper: ['rounded-xl', 'flex', 'gap-2', 'items-start', 'w-full', 'border'], + content: ['flex', 'flex-col', 'gap-1'], + title: [], + description: [], + icon: ['flex', 'items-start'], + }, + variants: { + variant: { + info: { + wrapper: ['border-border-info-light', 'bg-base-bg-emphasized-info'], + title: ['text-elements-on-emphasized-info'], + description: ['text-elements-on-emphasized-info'], + icon: ['text-elements-info'], + }, + danger: { + wrapper: ['border-border-danger-light', 'bg-base-bg-emphasized-danger'], + title: ['text-elements-on-emphasized-danger'], + description: ['text-elements-on-emphasized-danger'], + icon: ['text-elements-danger'], + }, + warning: { + wrapper: [ + 'border-border-warning-light', + 'bg-base-bg-emphasized-warning', + ], + title: ['text-elements-on-emphasized-warning'], + description: ['text-elements-on-emphasized-warning'], + icon: ['text-elements-warning'], + }, + success: { + wrapper: [ + 'border-border-success-light', + 'bg-base-bg-emphasized-success', + ], + title: ['text-elements-on-emphasized-success'], + description: ['text-elements-on-emphasized-success'], + icon: ['text-elements-success'], + }, + generic: { + wrapper: ['border-border-separator', 'bg-base-bg-emphasized'], + title: ['text-elements-high-em'], + description: ['text-elements-on-emphasized-info'], + icon: ['text-elements-high-em'], + }, + }, + size: { + sm: { + wrapper: ['px-2', 'py-2'], + title: ['leading-4', 'text-xs'], + description: ['leading-4', 'text-xs'], + icon: ['h-4', 'w-4'], + }, + md: { + wrapper: ['px-3', 'py-3'], + title: ['leading-5', 'tracking-[-0.006em]', 'text-sm'], + description: ['leading-5', 'tracking-[-0.006em]', 'text-sm'], + icon: ['h-5', 'w-5'], + }, + }, + hasDescription: { + true: { + title: ['font-medium'], + }, + }, + }, + defaultVariants: { + variant: 'generic', + size: 'md', + }, +}); + +export type InlineNotificationTheme = VariantProps< + typeof inlineNotificationTheme +>; diff --git a/packages/frontend/src/components/shared/InlineNotification/InlineNotification.tsx b/packages/frontend/src/components/shared/InlineNotification/InlineNotification.tsx new file mode 100644 index 00000000..b3b2845c --- /dev/null +++ b/packages/frontend/src/components/shared/InlineNotification/InlineNotification.tsx @@ -0,0 +1,68 @@ +import React, { ReactNode, useCallback } from 'react'; +import { ComponentPropsWithoutRef } from 'react'; +import { + InlineNotificationTheme, + inlineNotificationTheme, +} from './InlineNotification.theme'; +import { InfoSquareIcon } from 'components/shared/CustomIcon'; +import { cloneIcon } from 'utils/cloneIcon'; + +export interface InlineNotificationProps + extends ComponentPropsWithoutRef<'div'>, + InlineNotificationTheme { + /** + * The title of the notification + */ + title: string; + /** + * The description of the notification + */ + description?: string; + /** + * The icon to display in the notification + * @default + */ + icon?: ReactNode; +} + +/** + * A notification that is displayed inline with the content + * + * @example + * ```tsx + * + * ``` + */ +export const InlineNotification = ({ + className, + title, + description, + size, + variant, + icon, + ...props +}: InlineNotificationProps) => { + const { + wrapper, + content, + title: titleClass, + description: descriptionClass, + icon: iconClass, + } = inlineNotificationTheme({ size, variant, hasDescription: !!description }); + + // Render custom icon or default icon + const renderIcon = useCallback(() => { + if (!icon) return ; + return cloneIcon(icon, { className: iconClass() }); + }, [icon]); + + return ( +
+ {renderIcon()} +
+

{title}

+ {description &&

{description}

} +
+
+ ); +}; diff --git a/packages/frontend/src/components/shared/InlineNotification/index.ts b/packages/frontend/src/components/shared/InlineNotification/index.ts new file mode 100644 index 00000000..fbe7bbd4 --- /dev/null +++ b/packages/frontend/src/components/shared/InlineNotification/index.ts @@ -0,0 +1 @@ +export * from './InlineNotification'; diff --git a/packages/frontend/src/pages/components/index.tsx b/packages/frontend/src/pages/components/index.tsx index ab6be949..b2c81d31 100644 --- a/packages/frontend/src/pages/components/index.tsx +++ b/packages/frontend/src/pages/components/index.tsx @@ -17,6 +17,10 @@ import { renderTabs, renderVerticalTabs, } from './renders/tabs'; +import { + renderInlineNotificationWithDescriptions, + renderInlineNotifications, +} from './renders/inlineNotifications'; import { renderInputs } from './renders/input'; const Page = () => { @@ -25,7 +29,7 @@ const Page = () => { return (
-
+

Manual Storybook

Get started by editing{' '} @@ -125,6 +129,19 @@ const Page = () => {

+ {/* Inline notification */} +
+

Inline Notification

+
+ {renderInlineNotifications()} +
+
+ {renderInlineNotificationWithDescriptions()} +
+
+ +
+ {/* Link */}

Link

diff --git a/packages/frontend/src/pages/components/renders/inlineNotifications.tsx b/packages/frontend/src/pages/components/renders/inlineNotifications.tsx new file mode 100644 index 00000000..fc36b914 --- /dev/null +++ b/packages/frontend/src/pages/components/renders/inlineNotifications.tsx @@ -0,0 +1,43 @@ +import { InlineNotification } from 'components/shared/InlineNotification'; +import { InlineNotificationTheme } from 'components/shared/InlineNotification/InlineNotification.theme'; +import React from 'react'; + +const inlineNotificationVariants = [ + 'info', + 'danger', + 'warning', + 'success', + 'generic', +]; +const inlineNotificationSizes = ['md', 'sm']; + +export const renderInlineNotifications = () => { + return inlineNotificationVariants.map((variant) => ( +
+ {inlineNotificationSizes.map((size) => ( + + ))} +
+ )); +}; + +export const renderInlineNotificationWithDescriptions = () => { + return inlineNotificationVariants.map((variant) => ( +
+ {inlineNotificationSizes.map((size) => ( + + ))} +
+ )); +};