From 58f0032c7b26e185eef8a75ad02a3371001c7da4 Mon Sep 17 00:00:00 2001 From: Saheb Giri Date: Fri, 29 Dec 2023 13:23:15 +0530 Subject: [PATCH 1/7] feat: add divider component --- .../src/components/atoms/Divider/Divider.tsx | 12 ++++++++++++ .../src/components/atoms/Divider/divider.css | 5 +++++ .../src/components/atoms/Divider/index.ts | 1 + packages/ui-toolkit/src/components/atoms/index.ts | 1 + packages/ui-toolkit/stories/Divider.stories.tsx | 15 +++++++++++++++ 5 files changed, 34 insertions(+) create mode 100644 packages/ui-toolkit/src/components/atoms/Divider/Divider.tsx create mode 100644 packages/ui-toolkit/src/components/atoms/Divider/divider.css create mode 100644 packages/ui-toolkit/src/components/atoms/Divider/index.ts create mode 100644 packages/ui-toolkit/stories/Divider.stories.tsx diff --git a/packages/ui-toolkit/src/components/atoms/Divider/Divider.tsx b/packages/ui-toolkit/src/components/atoms/Divider/Divider.tsx new file mode 100644 index 00000000..ec4aa0c0 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/Divider/Divider.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +import './divider.css'; + + +const Divider = () => { + return
; +}; + +export default Divider; diff --git a/packages/ui-toolkit/src/components/atoms/Divider/divider.css b/packages/ui-toolkit/src/components/atoms/Divider/divider.css new file mode 100644 index 00000000..ca83422c --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/Divider/divider.css @@ -0,0 +1,5 @@ +.divider23divider { + border-top: 1px; + width: 100%; + margin: 0; +} \ No newline at end of file diff --git a/packages/ui-toolkit/src/components/atoms/Divider/index.ts b/packages/ui-toolkit/src/components/atoms/Divider/index.ts new file mode 100644 index 00000000..d84c86b0 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/Divider/index.ts @@ -0,0 +1 @@ +export { default as Divider } from './Divider'; diff --git a/packages/ui-toolkit/src/components/atoms/index.ts b/packages/ui-toolkit/src/components/atoms/index.ts index ca84f359..19971673 100644 --- a/packages/ui-toolkit/src/components/atoms/index.ts +++ b/packages/ui-toolkit/src/components/atoms/index.ts @@ -31,3 +31,4 @@ export * from './NumberInput'; export * from './InputField'; export * from './NumberPicker'; export * from './IconButton'; +export * from './Divider'; diff --git a/packages/ui-toolkit/stories/Divider.stories.tsx b/packages/ui-toolkit/stories/Divider.stories.tsx new file mode 100644 index 00000000..de9c994f --- /dev/null +++ b/packages/ui-toolkit/stories/Divider.stories.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import { Story } from '@storybook/react'; + +import { Divider } from '../src/components/atoms'; + +export default { + title: 'Divider', + component: Divider +}; + + +const Template: Story = () => ; + +export const Default = Template.bind({}); From a319363ff53fb2a5a6799261698acf57885c1cc5 Mon Sep 17 00:00:00 2001 From: Saheb Giri Date: Tue, 2 Jan 2024 12:13:51 +0530 Subject: [PATCH 2/7] feat: add icon view component --- .../components/atoms/IconView/IconView.tsx | 62 +++++++++++++++++++ .../atoms/IconView/iconView.constants.ts | 6 ++ .../components/atoms/IconView/iconView.css | 20 ++++++ .../src/components/atoms/IconView/index.tsx | 1 + .../ui-toolkit/src/components/atoms/index.ts | 1 + .../ui-toolkit/stories/IconView.stories.tsx | 39 ++++++++++++ 6 files changed, 129 insertions(+) create mode 100644 packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx create mode 100644 packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts create mode 100644 packages/ui-toolkit/src/components/atoms/IconView/iconView.css create mode 100644 packages/ui-toolkit/src/components/atoms/IconView/index.tsx create mode 100644 packages/ui-toolkit/stories/IconView.stories.tsx diff --git a/packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx b/packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx new file mode 100644 index 00000000..7245d8f1 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import cn from 'classnames'; + +import { ReactIconProps } from '@groww-tech/icon-store'; + +import { SIZES } from '../../../utils/constants'; +import { ICON_VIEW_SIZE } from './iconView.constants'; + +import './iconView.css'; + +export default function IconView(props: Props) { + const { iconComponent, size, isContained } = props; + + + const getIconSize = () => { + switch (size) { + case SIZES.SMALL: + return 16; + + case SIZES.BASE: + return 20; + + case SIZES.LARGE: + return 24; + + case SIZES.XLARGE: + return 28; + + default: + return 20; + } + }; + + const iconProps = { + className: 'absolute-center', + size: getIconSize() + }; + + const iconViewClasses = cn(`iv98IconContainer iv98${size} circle`, { + backgroundTertiary: isContained + }); + + return
{iconComponent(iconProps as ReactIconProps)}
; +} + + +type RequiredProps = { + iconComponent: (props: ReactIconProps) => JSX.Element; +}; + + +type DefaultProps = { + size?: ValueOf; + isContained?: boolean; +}; + +IconView.defaultProps = { + size: SIZES.BASE, + isContained: false +}; + +export type Props = RequiredProps & DefaultProps; diff --git a/packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts b/packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts new file mode 100644 index 00000000..39e06034 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts @@ -0,0 +1,6 @@ +export const ICON_VIEW_SIZE = { + SMALL: 'Small', + BASE: 'Base', + LARGE: 'Large', + XLARGE: 'XLarge' +} as const; diff --git a/packages/ui-toolkit/src/components/atoms/IconView/iconView.css b/packages/ui-toolkit/src/components/atoms/IconView/iconView.css new file mode 100644 index 00000000..67ca3b0c --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/IconView/iconView.css @@ -0,0 +1,20 @@ +.iv98IconContainer { + width: fit-content; + height: fit-content; +} + +.iv98Small { + padding: 8px; +} + +.iv98Base { + padding: 10px; +} + +.iv98Large { + padding: 12px; +} + +.iv98XLarge { + padding: 14px; +} diff --git a/packages/ui-toolkit/src/components/atoms/IconView/index.tsx b/packages/ui-toolkit/src/components/atoms/IconView/index.tsx new file mode 100644 index 00000000..017104e8 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/IconView/index.tsx @@ -0,0 +1 @@ +export { default as IconView } from './IconView'; diff --git a/packages/ui-toolkit/src/components/atoms/index.ts b/packages/ui-toolkit/src/components/atoms/index.ts index ca84f359..8c35d846 100644 --- a/packages/ui-toolkit/src/components/atoms/index.ts +++ b/packages/ui-toolkit/src/components/atoms/index.ts @@ -31,3 +31,4 @@ export * from './NumberInput'; export * from './InputField'; export * from './NumberPicker'; export * from './IconButton'; +export * from './IconView'; diff --git a/packages/ui-toolkit/stories/IconView.stories.tsx b/packages/ui-toolkit/stories/IconView.stories.tsx new file mode 100644 index 00000000..5ec89797 --- /dev/null +++ b/packages/ui-toolkit/stories/IconView.stories.tsx @@ -0,0 +1,39 @@ +import React, { useState } from 'react'; +import { Story } from '@storybook/react'; + +import { IconView } from '../src/components/atoms/IconView'; +import { Props as IconViewProps } from '../src/components/atoms/IconView/IconView'; +import { Edit } from '@groww-tech/icon-store/mi'; + +export default { + title: 'IconView', + component: IconView, + argTypes: { + size: { + control: { + type: 'select', + options: [ 'Small', 'Base', 'Large', 'XLarge' ] + } + } + } +}; + + +const Template: Story = (args) => ( +
+ +
+); + +export const Default = Template.bind({}); +Default.args = { + iconComponent: (iconProps: any) => , + size: 'Base' +}; + +export const Contained = Template.bind({}); +Contained.args = { + iconComponent: (iconProps: any) => , + size: 'Base', + isContained: true +}; From ca4aa48c65ca88f5530496d2261d27c4b7eb33bd Mon Sep 17 00:00:00 2001 From: Saheb Giri Date: Thu, 4 Jan 2024 12:58:55 +0530 Subject: [PATCH 3/7] feat: add avatar component --- .../src/components/atoms/Avatar/Avatar.tsx | 184 ++++++++++++++++++ .../atoms/Avatar/avatar.constants.ts | 4 + .../src/components/atoms/Avatar/avatar.css | 37 ++++ .../src/components/atoms/Avatar/index.ts | 1 + .../ui-toolkit/src/components/atoms/index.ts | 1 + .../ui-toolkit/stories/Avatar.stories.tsx | 63 ++++++ 6 files changed, 290 insertions(+) create mode 100644 packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx create mode 100644 packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts create mode 100644 packages/ui-toolkit/src/components/atoms/Avatar/avatar.css create mode 100644 packages/ui-toolkit/src/components/atoms/Avatar/index.ts create mode 100644 packages/ui-toolkit/stories/Avatar.stories.tsx diff --git a/packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx b/packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx new file mode 100644 index 00000000..937ce372 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx @@ -0,0 +1,184 @@ +import React, { useState, useEffect } from 'react'; +import cn from 'classnames'; +import { AccountBalance } from '@groww-tech/icon-store/mi'; + +import { SIZES } from '../../../utils/constants'; +import { AVATAR_SHAPE } from './avatar.constants'; + +import './avatar.css'; + + +function getInitials(name: string) { + const names = name.trim().split(' '); + const firstName = names[0] ?? ''; + const lastName = names.length > 1 ? names[names.length - 1] : ''; + + const initial = firstName && lastName ? `${firstName.charAt(0)}${lastName.charAt(0)}` : firstName.charAt(0); + + return initial.toUpperCase(); +} + + +type Status = 'loading' | 'failed' | 'pending' | 'loaded'; + + +const useImage = (src: string): Status => { + const [ status, setStatus ] = useState('pending'); + + useEffect(() => { + const image = new Image(); + + image.src = src; + + image.onload = () => { + setStatus('loaded'); + }; + + image.onerror = () => { + setStatus('failed'); + }; + + setStatus('loading'); + + return () => { + // Cleanup on unmount or if src changes + image.onload = null; + image.onerror = null; + }; + }, [ src ]); + + return status; +}; + + +const Avatar = (props: Props) => { + const { src, name, size, isDisabled, shape } = props; + + const status = useImage(src); + + const initials = getInitials(name); + + + const getAvatarSize = () => { + switch (size) { + case SIZES.XSMALL: + return 24; + + case SIZES.SMALL: + return 32; + + case SIZES.BASE: + return 40; + + case SIZES.LARGE: + return 48; + + case SIZES.XLARGE: + return 56; + + default: + return 40; + } + }; + + const avatarSize = getAvatarSize(); + + const avatarDimensionClasses = cn(`av91Avatar${size}`); + + const avatarInitialClasses = cn('av91AvatarInitialContainer absolute-center circle'); + + const avatarImgClasses = cn({ + circle: shape === AVATAR_SHAPE.CIRCULAR, + av91AvatarRectangular: shape === AVATAR_SHAPE.RECTANGULAR, + av91AvatarImageDisabled: isDisabled + }); + + const avatarIconContainerClasses = cn('av91AvatarInitialContainer absolute-center', { + av91AvatarRectangular: shape === AVATAR_SHAPE.RECTANGULAR, + backgroundTertiary: !isDisabled, + backgroundSecondary: isDisabled + }); + + const avatarIconClasses = cn({ + contentDisabled: isDisabled, + contentSecondary: !isDisabled + }); + + const backgroundClasses = cn({ + backgroundAccentSubtle: !isDisabled, + backgroundTertiary: isDisabled + }); + + const fontClasses = cn({ + bodySmallHeavy: size === SIZES.XSMALL || size === SIZES.SMALL, + bodyBaseHeavy: size === SIZES.BASE, + bodyLargeHeavy: size === SIZES.LARGE, + bodyXLargeHeavy: size === SIZES.XLARGE, + contentPositive: !isDisabled, + contentDisabled: isDisabled + }); + + const avatarInitial = ( +
+ {initials} +
+ ); + + const avatarIcon = ( +
+ +
+ ); + + const avatarImage = {name}; + const avatarDisabled = shape === AVATAR_SHAPE.RECTANGULAR ? avatarIcon : avatarInitial; + + switch (status) { + case 'loading': + return avatarDisabled; + + case 'failed': + return avatarDisabled; + + case 'loaded': + return avatarImage; + + case 'pending': + return avatarDisabled; + + default: + return avatarDisabled; + } +}; + + +type RequiredProps = { + name: string; + src: string; +}; + + +type DefaultProps = { + size: ValueOf; + shape: ValueOf; + isDisabled: boolean; +}; + +export type Props = RequiredProps & DefaultProps & Partial; + +Avatar.defaultProps = { + isDisabled: false, + size: 'Base', + shape: 'Circular' +} as DefaultProps; + +export default Avatar; diff --git a/packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts b/packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts new file mode 100644 index 00000000..1df903c9 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts @@ -0,0 +1,4 @@ +export const AVATAR_SHAPE = { + CIRCULAR: 'Circular', + RECTANGULAR: 'Rectangular' +} as const; diff --git a/packages/ui-toolkit/src/components/atoms/Avatar/avatar.css b/packages/ui-toolkit/src/components/atoms/Avatar/avatar.css new file mode 100644 index 00000000..f0334a38 --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/Avatar/avatar.css @@ -0,0 +1,37 @@ +.av91AvatarInitialContainer { + width: fit-content; + height: fit-content; +} + +.av91AvatarRectangular { + border-radius: 8px; +} + +.av91AvatarImageDisabled { + filter: grayscale(100%) opacity(50%); +} + +.av91AvatarXSmall { + height: 24px; + width: 24px; +} + +.av91AvatarSmall { + height: 32px; + width: 32px; +} + +.av91AvatarBase { + height: 40px; + width: 40px; +} + +.av91AvatarLarge { + height: 48px; + width: 48px; +} + +.av91AvatarXLarge { + height: 56px; + width: 56px; +} diff --git a/packages/ui-toolkit/src/components/atoms/Avatar/index.ts b/packages/ui-toolkit/src/components/atoms/Avatar/index.ts new file mode 100644 index 00000000..fdf35d3a --- /dev/null +++ b/packages/ui-toolkit/src/components/atoms/Avatar/index.ts @@ -0,0 +1 @@ +export { default as Avatar } from './Avatar'; diff --git a/packages/ui-toolkit/src/components/atoms/index.ts b/packages/ui-toolkit/src/components/atoms/index.ts index ca84f359..688f8c4a 100644 --- a/packages/ui-toolkit/src/components/atoms/index.ts +++ b/packages/ui-toolkit/src/components/atoms/index.ts @@ -31,3 +31,4 @@ export * from './NumberInput'; export * from './InputField'; export * from './NumberPicker'; export * from './IconButton'; +export * from './Avatar'; diff --git a/packages/ui-toolkit/stories/Avatar.stories.tsx b/packages/ui-toolkit/stories/Avatar.stories.tsx new file mode 100644 index 00000000..3819a7bd --- /dev/null +++ b/packages/ui-toolkit/stories/Avatar.stories.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { Story } from '@storybook/react'; + +import { Avatar } from '../src/components/atoms'; +import { Props as AvatarProps } from '../src/components/atoms/Avatar/Avatar'; + +export default { + title: 'Avatar', + component: Avatar, + argTypes: { + size: { + control: { + type: 'select', + options: [ 'XSmall', 'Small', 'Base', 'Large', 'XLarge' ] + } + }, + shape: { + control: { + type: 'select', + options: [ 'Circular', 'Rectangular' ] + } + } + } +}; + + +const Template: Story = (args) => ; + +export const Circular = Template.bind({}); +Circular.args = { + name: 'Dan Abramov', + src: 'https://bit.ly/dan-abramov', + size: 'Base', + isDisabled: false, + shape: 'Circular' +}; + +export const CircularPlaceholder = Template.bind({}); +CircularPlaceholder.args = { + name: 'Dan Abramov', + src: 'https://bit.ly/broken-image', + size: 'Base', + isDisabled: false, + shape: 'Circular' +}; + +export const Rectangular = Template.bind({}); +Rectangular.args = { + name: 'Navi Nifty 50 Index Fund Direct Growth', + src: 'https://assets-netstorage.groww.in/mf-assets/logos/peerless_groww.png', + size: 'Base', + isDisabled: false, + shape: 'Rectangular' +}; + +export const RectangularPlaceholder = Template.bind({}); +RectangularPlaceholder.args = { + name: 'Navi Nifty 50 Index Fund Direct Growth', + src: 'https://bit.ly/broken-image', + size: 'Base', + isDisabled: false, + shape: 'Rectangular' +}; From 6e92a51fd3b3285dd2d0fce1f8c8cf0e22d552f0 Mon Sep 17 00:00:00 2001 From: Saheb Giri Date: Mon, 8 Jan 2024 17:19:33 +0530 Subject: [PATCH 4/7] feat: update tabs component --- .../src/components/atoms/Tabs/Tabs.tsx | 162 ++++++++---------- .../src/components/atoms/Tabs/tabs.css | 93 +++++----- packages/ui-toolkit/stories/Tabs.stories.tsx | 54 +++--- 3 files changed, 139 insertions(+), 170 deletions(-) diff --git a/packages/ui-toolkit/src/components/atoms/Tabs/Tabs.tsx b/packages/ui-toolkit/src/components/atoms/Tabs/Tabs.tsx index 05749405..f9cbca85 100644 --- a/packages/ui-toolkit/src/components/atoms/Tabs/Tabs.tsx +++ b/packages/ui-toolkit/src/components/atoms/Tabs/Tabs.tsx @@ -1,27 +1,52 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import cn from 'classnames'; import './tabs.css'; +type TabMeta = { + left: number; + width: number; +}; + + const Tabs = (props: Props) => { - const { - onTabSelect, - activeTabIndexOnMount, - data, - showBottomBorder, - customStyleTab, - isHorizScrollable - } = props; + const { onTabSelect, defaultIndex, data, showBottomBorder, isFitted } = props; - const [ activeIndex, setActiveIndex ] = useState(activeTabIndexOnMount); + const [ activeIndex, setActiveIndex ] = useState(defaultIndex); + const tabsRef = useRef(null); + const [ tabsMeta, setTabsMeta ] = useState([]); - const { width, left } = getActiveTabDimensions(data, activeIndex); + useEffect(() => { + setActiveIndex(props.defaultIndex); + }, [ props.defaultIndex ]); useEffect(() => { - setActiveIndex(props.activeTabIndexOnMount); - }, [ props.activeTabIndexOnMount ]); + const computeDimensions = () => { + if (!tabsRef.current) return; + + const tabsMetadata: TabMeta[] = []; + + for (let i = 0; i < tabsRef.current.childElementCount; i++) { + const element = tabsRef.current.children[i] as HTMLElement; + + tabsMetadata.push({ + width: element.offsetWidth, + left: element.offsetLeft + }); + } + + setTabsMeta(tabsMetadata); + }; + + computeDimensions(); + + window.addEventListener('load', computeDimensions); + return () => { + window.removeEventListener('load', computeDimensions); + }; + }, [ isFitted ]); const onTabClick = (index: number) => { @@ -32,113 +57,78 @@ const Tabs = (props: Props) => { onTabSelect(index); }; + const tabClasses = cn('tabs8Tab', { + borderPrimary: showBottomBorder + }); - return ( -
- { - ((typeof width === 'number' ? width : parseInt(width)) > 0) && -
- } + const tabItemClasses = cn('tabs8TabItem cur-po headingXSmall'); + + const tabParentClasses = cn('valign-wrapper tabs8Parent', { + flex: isFitted + }); -
+ return ( +
+
{ data.map((item, key) => { return ( -
{item.name} -
+ ); }) }
+ { + tabsMeta[activeIndex] && + }
); }; - -const getActiveTabDimensions = (data: Tab[], activeIndex: number) => { - let left = 0; - let width:number|string = 0; - - const activeTab = data[activeIndex]; - - if (activeTab && activeTab.hasOwnProperty('width') && activeTab.hasOwnProperty('left')) { - width = activeTab.width || 0; - left = activeTab.left || 0; - - return { - 'width': width, - 'left': left - }; - - } else { - if (typeof document !== 'undefined') { - const prevActiveElement = document?.getElementsByClassName('tabs8TextActive') as HTMLCollectionOf; - - if (prevActiveElement && prevActiveElement.length) { - const currentActiveElement = prevActiveElement[0]?.parentElement?.children[activeIndex] as HTMLElement; - - return { - 'width': currentActiveElement?.offsetWidth, - 'left': currentActiveElement?.offsetLeft - }; - - } else { - return { - 'width': width, - 'left': left - }; - } - - } else { - return { - 'width': 0, - 'left': 0 - }; - } - } - -}; - - const defaultProps: DefaultProps = { showBottomBorder: true, - activeTabIndexOnMount: 0, - customStyleTab: 'tabs8Text', - isHorizScrollable: false + defaultIndex: 0, + isFitted: false }; type DefaultProps = { showBottomBorder: boolean; - activeTabIndexOnMount: number; - customStyleTab: string; - isHorizScrollable: boolean; -} + defaultIndex: number; + isFitted: boolean; +}; type RequiredProps = { data: Tab[]; onTabSelect: (index: number) => void; -} +}; type Tab = { description?: string; - name: React.ReactNode; - style?: React.CSSProperties; - width?: number | string; - left?: number; -} - + name: string; +}; Tabs.defaultProps = defaultProps; diff --git a/packages/ui-toolkit/src/components/atoms/Tabs/tabs.css b/packages/ui-toolkit/src/components/atoms/Tabs/tabs.css index ed14a154..946c30e0 100644 --- a/packages/ui-toolkit/src/components/atoms/Tabs/tabs.css +++ b/packages/ui-toolkit/src/components/atoms/Tabs/tabs.css @@ -1,75 +1,60 @@ -.tabs8Container { +.tabs8Tab { position: relative; - max-height: 55px; -} + border-width: 0 0 1px 0; + + overflow-x: auto; -.bottomBorderOnly { - border-width: 0 0 1px 0 !important; + /* IE and Edge */ + -ms-overflow-style: none; + + /* Firefox */ + scrollbar-width: none; } -.tabs8Text { - line-height: 15px; - padding-right: 45px; - height: 30px; - cursor: pointer; - color: var(--gray900); +.tabs8Tab::-webkit-scrollbar { + display: none; } -.tabs8TextActive { - color: var(--green500); +.tabs8Parent { + min-width: max-content; } .tabs8Line { position: absolute; bottom: 0; height: 3px; + width: 0; background: var(--green500); will-change: left, width; - transition: left 0.2s linear, width 0.2s linear; + transition: left 0.2s, width 0.2s; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); } +.tabs8TabItem { + border: 0; + margin: 0; + padding: 0; + width: auto; + overflow: visible; + background: transparent; + line-height: normal; + padding: 14px 35px; +} +.tabs8TabItem::-moz-focus-inner { + border: 0; + padding: 0; +} -@media (max-width: 1025px) { - .tabs8Container { - max-height: 25px; - overflow-x: auto; - - /* IE and Edge */ - -ms-overflow-style: none; - - /* Firefox */ - scrollbar-width: none; - } - - .tabs8Container::-webkit-scrollbar { - display: none; - } - - .tabs8PageWidth20Mgn { - width: calc(100vw - 40px); - overflow-y: auto; - } - - .tabs8Text { - font-size: 15px; - font-weight: 500; - border-radius: 25px; - padding-right: 24px; - height: 25px; - -webkit-font-smoothing: auto; - } - - .tabs8TextActive { - color: var(--green500); - } +.tabs8TabItem:hover { + background-color: var(--gray50); +} - .tabs8Line { - will-change: left, width; - transition: left 0.2s linear, width 0.2s linear; - } +.tabs8TabItem:active { + background-color: var(--gray100); +} - .tabs8Parent { - min-width: max-content; - } +.tabs8TabItemFlex1 { + flex: 1; + flex-wrap: nowrap; } diff --git a/packages/ui-toolkit/stories/Tabs.stories.tsx b/packages/ui-toolkit/stories/Tabs.stories.tsx index f6475648..8e23eaa0 100644 --- a/packages/ui-toolkit/stories/Tabs.stories.tsx +++ b/packages/ui-toolkit/stories/Tabs.stories.tsx @@ -1,5 +1,5 @@ -import React, { useState } from 'react'; -import { Story } from "@storybook/react"; +import React from 'react'; +import { Story } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { Props as TabsProps } from '../src/components/atoms/Tabs/Tabs'; @@ -8,44 +8,38 @@ import { Tabs } from '../src/components/atoms'; export default { title: 'Tabs', component: Tabs, - argTypes: { - } + argTypes: {} }; -const Template: Story = (args) => + +const Template: Story = (args) => ; export const Default = Template.bind({}); -const WALLETS_TABS = [ +const data = [ + { + name: 'Option 1' + }, { - width: 168, - left: 10, - name: ( -
- DEPOSIT -
- ) + name: 'Option 2' }, { - width: 208, - left: 180, - name: ( -
- WITHDRAW -
- ) + name: 'Option 3' + }, + { + name: 'Option 4' } -] +]; Default.args = { - data: WALLETS_TABS, + data, showBottomBorder: true, - customStyleTab: "", - onTabSelect: action('onSelect') -} + onTabSelect: (index) => console.log(data.at(index)), + isFitted: false +}; +export const Fitted = Template.bind({}); +Fitted.args = { + ...Default.args, + isFitted: true +}; From 16c5216958fe8c39739ff821db421cf12fb379e8 Mon Sep 17 00:00:00 2001 From: Saheb Giri Date: Tue, 9 Jan 2024 17:40:29 +0530 Subject: [PATCH 5/7] chore: replace sizes constant with avatar sizes --- .../src/components/atoms/Avatar/Avatar.tsx | 37 +++++++++---------- .../atoms/Avatar/avatar.constants.ts | 10 ++++- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx b/packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx index 937ce372..6dacce10 100644 --- a/packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx +++ b/packages/ui-toolkit/src/components/atoms/Avatar/Avatar.tsx @@ -2,8 +2,7 @@ import React, { useState, useEffect } from 'react'; import cn from 'classnames'; import { AccountBalance } from '@groww-tech/icon-store/mi'; -import { SIZES } from '../../../utils/constants'; -import { AVATAR_SHAPE } from './avatar.constants'; +import { AVATAR_SHAPES, AVATAR_SIZES } from './avatar.constants'; import './avatar.css'; @@ -61,19 +60,19 @@ const Avatar = (props: Props) => { const getAvatarSize = () => { switch (size) { - case SIZES.XSMALL: + case AVATAR_SIZES.XSMALL: return 24; - case SIZES.SMALL: + case AVATAR_SIZES.SMALL: return 32; - case SIZES.BASE: + case AVATAR_SIZES.BASE: return 40; - case SIZES.LARGE: + case AVATAR_SIZES.LARGE: return 48; - case SIZES.XLARGE: + case AVATAR_SIZES.XLARGE: return 56; default: @@ -88,13 +87,13 @@ const Avatar = (props: Props) => { const avatarInitialClasses = cn('av91AvatarInitialContainer absolute-center circle'); const avatarImgClasses = cn({ - circle: shape === AVATAR_SHAPE.CIRCULAR, - av91AvatarRectangular: shape === AVATAR_SHAPE.RECTANGULAR, + circle: shape === AVATAR_SHAPES.CIRCULAR, + av91AvatarRectangular: shape === AVATAR_SHAPES.RECTANGULAR, av91AvatarImageDisabled: isDisabled }); const avatarIconContainerClasses = cn('av91AvatarInitialContainer absolute-center', { - av91AvatarRectangular: shape === AVATAR_SHAPE.RECTANGULAR, + av91AvatarRectangular: shape === AVATAR_SHAPES.RECTANGULAR, backgroundTertiary: !isDisabled, backgroundSecondary: isDisabled }); @@ -110,10 +109,10 @@ const Avatar = (props: Props) => { }); const fontClasses = cn({ - bodySmallHeavy: size === SIZES.XSMALL || size === SIZES.SMALL, - bodyBaseHeavy: size === SIZES.BASE, - bodyLargeHeavy: size === SIZES.LARGE, - bodyXLargeHeavy: size === SIZES.XLARGE, + bodySmallHeavy: size === AVATAR_SIZES.XSMALL || size === AVATAR_SIZES.SMALL, + bodyBaseHeavy: size === AVATAR_SIZES.BASE, + bodyLargeHeavy: size === AVATAR_SIZES.LARGE, + bodyXLargeHeavy: size === AVATAR_SIZES.XLARGE, contentPositive: !isDisabled, contentDisabled: isDisabled }); @@ -140,7 +139,7 @@ const Avatar = (props: Props) => { height={avatarSize} width={avatarSize} />; - const avatarDisabled = shape === AVATAR_SHAPE.RECTANGULAR ? avatarIcon : avatarInitial; + const avatarDisabled = shape === AVATAR_SHAPES.RECTANGULAR ? avatarIcon : avatarInitial; switch (status) { case 'loading': @@ -168,8 +167,8 @@ type RequiredProps = { type DefaultProps = { - size: ValueOf; - shape: ValueOf; + size: ValueOf; + shape: ValueOf; isDisabled: boolean; }; @@ -177,8 +176,8 @@ export type Props = RequiredProps & DefaultProps & Partial; Avatar.defaultProps = { isDisabled: false, - size: 'Base', - shape: 'Circular' + size: AVATAR_SIZES.BASE, + shape: AVATAR_SHAPES.CIRCULAR } as DefaultProps; export default Avatar; diff --git a/packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts b/packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts index 1df903c9..fc7d7ed2 100644 --- a/packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts +++ b/packages/ui-toolkit/src/components/atoms/Avatar/avatar.constants.ts @@ -1,4 +1,12 @@ -export const AVATAR_SHAPE = { +export const AVATAR_SHAPES = { CIRCULAR: 'Circular', RECTANGULAR: 'Rectangular' } as const; + +export const AVATAR_SIZES = { + XSMALL: 'XSmall', + SMALL: 'Small', + BASE: 'Base', + LARGE: 'Large', + XLARGE: 'XLarge' +} as const; From 5bb531ee51235e3a5c376a3440b49a2d83f815bf Mon Sep 17 00:00:00 2001 From: Saheb Giri Date: Tue, 9 Jan 2024 17:45:11 +0530 Subject: [PATCH 6/7] chore: replace sizes constant with icon view sizes --- .../src/components/atoms/IconView/IconView.tsx | 15 +++++++-------- .../atoms/IconView/iconView.constants.ts | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx b/packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx index 7245d8f1..277fb01a 100644 --- a/packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx +++ b/packages/ui-toolkit/src/components/atoms/IconView/IconView.tsx @@ -3,8 +3,7 @@ import cn from 'classnames'; import { ReactIconProps } from '@groww-tech/icon-store'; -import { SIZES } from '../../../utils/constants'; -import { ICON_VIEW_SIZE } from './iconView.constants'; +import { ICON_VIEW_SIZES } from './iconView.constants'; import './iconView.css'; @@ -14,16 +13,16 @@ export default function IconView(props: Props) { const getIconSize = () => { switch (size) { - case SIZES.SMALL: + case ICON_VIEW_SIZES.SMALL: return 16; - case SIZES.BASE: + case ICON_VIEW_SIZES.BASE: return 20; - case SIZES.LARGE: + case ICON_VIEW_SIZES.LARGE: return 24; - case SIZES.XLARGE: + case ICON_VIEW_SIZES.XLARGE: return 28; default: @@ -50,12 +49,12 @@ type RequiredProps = { type DefaultProps = { - size?: ValueOf; + size?: ValueOf; isContained?: boolean; }; IconView.defaultProps = { - size: SIZES.BASE, + size: ICON_VIEW_SIZES.BASE, isContained: false }; diff --git a/packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts b/packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts index 39e06034..5a1ef02b 100644 --- a/packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts +++ b/packages/ui-toolkit/src/components/atoms/IconView/iconView.constants.ts @@ -1,4 +1,4 @@ -export const ICON_VIEW_SIZE = { +export const ICON_VIEW_SIZES = { SMALL: 'Small', BASE: 'Base', LARGE: 'Large', From a53fcaafd0f8a6e56bb0d5c9acd93142915b712f Mon Sep 17 00:00:00 2001 From: Saheb Giri Date: Wed, 10 Jan 2024 12:35:18 +0530 Subject: [PATCH 7/7] chore: bump up ui toolkit to v0.5.5 --- packages/ui-toolkit/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-toolkit/package.json b/packages/ui-toolkit/package.json index d5c912f7..4a0cdd0c 100644 --- a/packages/ui-toolkit/package.json +++ b/packages/ui-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@groww-tech/ui-toolkit", - "version": "0.5.4", + "version": "0.5.5", "description": "A lightning nature UI", "main": "dist/cjs/index.js", "module": "dist/esm/index.js",