diff --git a/libs/blocks/src/lib/fast-payment/base/base.spec.tsx b/libs/blocks/src/lib/fast-payment/base/base.spec.tsx index 9cce50385..490130ad3 100644 --- a/libs/blocks/src/lib/fast-payment/base/base.spec.tsx +++ b/libs/blocks/src/lib/fast-payment/base/base.spec.tsx @@ -1,45 +1,13 @@ -import { render } from '@testing-library/react'; - -import { - FlagAndorraIcon, - FlagAustraliaIcon, - FlagBurkinaFasoIcon, -} from '@deriv/quill-icons/Flags'; +import { render, screen } from '@testing-library/react'; import Base from './index'; -import { CardContent } from '@deriv-com/components'; +import { cards } from './data'; const title = 'Hassle-free deposits and withdrawals'; const desc = 'Make instant deposits from 10,000 HKD. Withdraw in minutes.'; - -const cards: CardContent[] = [ - { - header: '', - color: 'gray', - align: 'center', - size: 'lg', - icon: , - className: 'h-fit', - nonContentClassName: 'p-general-xl', - }, - { - header: '', - color: 'gray', - align: 'center', - size: 'lg', - icon: , - className: 'h-fit', - nonContentClassName: 'p-general-xl', - }, - { - header: '', - color: 'gray', - align: 'center', - size: 'lg', - icon: , - className: 'h-fit', - nonContentClassName: 'p-general-xl', - }, -]; +const link = { + content: 'testing', + href: '/', +}; describe('FastPayment', () => { it('should render successfully', () => { @@ -47,9 +15,10 @@ describe('FastPayment', () => { , ); @@ -58,7 +27,9 @@ describe('FastPayment', () => { expect(container.querySelector('h2')).toBeTruthy(); expect(queryByText(title)).toBeTruthy(); expect(queryByText(desc)).toBeTruthy(); - expect(document.getElementById('cards-container')).toBeTruthy(); + expect(screen.getByTestId('cards-container')).toBeTruthy(); + expect(screen.getByTestId('fast-payment-link')).toBeTruthy(); + expect(screen.getByTestId('fast-payment-description')).toBeTruthy(); }); //render without description @@ -69,14 +40,15 @@ describe('FastPayment', () => { content={{ className: 'h-fit', cols: 'infinite', - cards: cards, + cards: cards.slice(0, 3), }} />, ); expect(container.querySelector('h2')).toBeTruthy(); - expect(document.getElementById('fast-payment-description')).toBeNull(); - expect(document.getElementById('cards-container')).toBeTruthy(); - expect(document.getElementById('infinite-carousel')).toBeTruthy(); + expect(screen.queryByTestId('fast-payment-description')).toBeNull(); + expect(screen.queryByTestId('fast-payment-link')).toBeNull(); + expect(screen.getByTestId('cards-container')).toBeTruthy(); + expect(screen.queryAllByTestId('infinite-carousel')).toBeTruthy(); }); }); diff --git a/libs/blocks/src/lib/fast-payment/base/base.stories.tsx b/libs/blocks/src/lib/fast-payment/base/base.stories.tsx index 3b94b47b8..d9912217c 100644 --- a/libs/blocks/src/lib/fast-payment/base/base.stories.tsx +++ b/libs/blocks/src/lib/fast-payment/base/base.stories.tsx @@ -1,32 +1,32 @@ import type { Meta, StoryObj } from '@storybook/react'; import Base from '.'; -import { cards } from './data'; +import { cards, sliderCards } from './data'; const content: Record = { - two_col: { + twoCol: { cols: 'two', cards: cards.slice(0, 2), }, - three_col: { + threeCol: { cols: 'three', cards: cards.slice(0, 3), }, - four_col: { + fourCol: { cols: 'four', cards: cards.slice(0, 4), }, - five_col: { + fiveCol: { cols: 'five', cards: cards.slice(0, 5), }, carousel: { cols: 'infinite', - cards: cards, + cards: sliderCards, }, }; const links: Record = { - with_link: { + withLink: { content: 'Learn More', href: '#', }, @@ -34,7 +34,7 @@ const links: Record = { }; const meta = { - title: 'Blocks/FastPayment/Default', + title: 'Blocks/FastPayment', component: Base, tags: ['autodocs'], argTypes: { @@ -44,6 +44,7 @@ const meta = { title: { description: '`string`', }, + className: { table: { disable: true } }, link: { description: '`{content: ReactNode, href: string}`', options: Object.keys(links), @@ -74,11 +75,12 @@ type Story = StoryObj; export const Default: Story = { args: { description: 'Make instant deposits from 10,000 HKD. Withdraw in minutes.', - title: 'Hassle-free deposits and withdrawals', + title: 'Hassle-free deposits and withdrawals.', link: { content: 'Learn More', href: '#', }, + className: 'bg-background-primary-container', disclaimer: '*Disclaimer text goes here.', content: { cards: cards.slice(0, 3), @@ -151,7 +153,7 @@ export const Carousel: Story = { ...Default.args, content: { cols: 'infinite', - cards: cards, + cards: sliderCards, }, }, }; diff --git a/libs/blocks/src/lib/fast-payment/base/data.tsx b/libs/blocks/src/lib/fast-payment/base/data.tsx index eae573f75..42fe70123 100644 --- a/libs/blocks/src/lib/fast-payment/base/data.tsx +++ b/libs/blocks/src/lib/fast-payment/base/data.tsx @@ -4,7 +4,7 @@ import { PaymentMethodSkrillBrandIcon, } from '@deriv/quill-icons'; -export const cards: CardContent[] = [ +export const sliderCards: CardContent[] = [ { id: 1, icon: , @@ -76,3 +76,46 @@ export const cards: CardContent[] = [ align: 'center', }, ]; + +export const cards: CardContent[] = [ + { + id: 1, + color: 'gray', + size: 'xs', + align: 'center', + header: 'Header.', + description: 'Description.', + }, + { + id: 2, + color: 'gray', + size: 'xs', + align: 'center', + header: 'Header.', + description: 'Description.', + }, + { + id: 3, + color: 'gray', + size: 'xs', + align: 'center', + header: 'Header.', + description: 'Description.', + }, + { + id: 4, + color: 'gray', + size: 'xs', + align: 'center', + header: 'Header.', + description: 'Description.', + }, + { + id: 5, + color: 'gray', + size: 'xs', + align: 'center', + header: 'Header.', + description: 'Description.', + }, +]; diff --git a/libs/blocks/src/lib/fast-payment/base/index.tsx b/libs/blocks/src/lib/fast-payment/base/index.tsx index dcd6b3817..3245af08b 100644 --- a/libs/blocks/src/lib/fast-payment/base/index.tsx +++ b/libs/blocks/src/lib/fast-payment/base/index.tsx @@ -1,4 +1,4 @@ -import { FluidContainer, Heading, Text } from '@deriv/quill-design'; +import { FluidContainer, Heading, Text, qtJoin } from '@deriv/quill-design'; import { CardsContainer, CustomLink } from '@deriv-com/components'; import { FastPaymentProps } from '../types'; @@ -10,34 +10,46 @@ const Base: React.FC = ({ description, link, disclaimer, - content: { cards = [], cols = 'three', dense }, + content: { cards = [], cols = 'three', dense, sliderClass }, + className, }) => { return ( - -
- {title} - {description && {description}} - - {link && ( -
- - {link.content} - -
- )} - - {disclaimer && ( - - {disclaimer} - - )} -
+ + {title} + {description && ( + + {description} + + )} + {link && ( + + {link.content} + + )} + + {disclaimer && ( + + {disclaimer} + + )} ); }; diff --git a/libs/blocks/src/lib/fast-payment/types/index.ts b/libs/blocks/src/lib/fast-payment/types/index.ts index ba21c5961..8f7c0bcdd 100644 --- a/libs/blocks/src/lib/fast-payment/types/index.ts +++ b/libs/blocks/src/lib/fast-payment/types/index.ts @@ -12,4 +12,5 @@ export interface FastPaymentProps { link?: LinkProps; disclaimer?: ReactNode; content: Omit, 'variant'>; + className?: string; } diff --git a/libs/components/src/lib/cards-container/cards-container.classname.ts b/libs/components/src/lib/cards-container/cards-container.classname.ts new file mode 100644 index 000000000..d07bd617c --- /dev/null +++ b/libs/components/src/lib/cards-container/cards-container.classname.ts @@ -0,0 +1,45 @@ +import { cva } from 'class-variance-authority'; + +export const colsClass = cva('flex flex-wrap gap-gap-lg', { + variants: { + dense: { + true: 'lg:max-w-max', + false: '', + }, + justify: { + center: 'lg:justify-center', + start: 'justify-start', + }, + }, + compoundVariants: [ + { + dense: [true, false], + className: 'w-full', + }, + ], + defaultVariants: { + dense: false, + justify: 'start', + }, +}); + +export const cardContainer = cva('flex overflow-hidden', { + variants: { + cols: { + infinite: 'w-screen', + two: '', + three: '', + four: '', + five: '', + }, + }, + compoundVariants: [ + { + cols: ['two', 'three', 'four', 'five'], + className: 'w-full', + }, + ], + defaultVariants: { + cols: 'two', + }, +}); diff --git a/libs/components/src/lib/cards-container/index.tsx b/libs/components/src/lib/cards-container/index.tsx index c83f5204d..1caf1a30e 100644 --- a/libs/components/src/lib/cards-container/index.tsx +++ b/libs/components/src/lib/cards-container/index.tsx @@ -1,5 +1,7 @@ -import { qtJoin, qtMerge } from '@deriv/quill-design'; +import { qtMerge } from '@deriv/quill-design'; import Card, { CardVariants } from '../card'; +import { cva } from 'class-variance-authority'; +import { cardContainer, colsClass } from './cards-container.classname'; export type CardVariantType = keyof CardVariants; @@ -16,21 +18,13 @@ export interface CardsContainerProps { cols?: CardsContainerCols; dense?: boolean; className?: string; + sliderClass?: string; } /** * * Important: The gap is currently set at 16px. If additional gap variants are introduced, make sure to update this value accordingly. */ -const cardColsVariant: { [key in CardsContainerCols]: string } = { - two: 'basis-full sm:basis-[calc((100%-16px)/2)]', - three: - 'basis-full sm:basis-[calc((100%-16px)/2)] lg:basis-[calc((100%-16px*2)/3)]', - four: 'basis-full sm:basis-[calc((100%-16px)/2)] lg:basis-[calc((100%-16px*3)/4)]', - five: 'basis-full sm:basis-[calc((100%-16px)/2)] lg:basis-[calc((100%-16px*4)/5)]', - infinite: 'animate-slide flex', -}; - const columns = { two: 2, three: 3, @@ -44,53 +38,66 @@ export const CardsContainer = ({ dense = false, variant, className, + sliderClass = 'animate-slide', }: CardsContainerProps) => { const CardComponent = Card[variant]; + const div = cva('gap-gap-lg pr-general-md', { + variants: { + cols: { + two: '', + three: 'lg:basis-[calc((100%-16px*2)/3)]', + four: 'lg:basis-[calc((100%-16px*3)/4)]', + five: 'lg:basis-[calc((100%-16px*4)/5)]', + infinite: 'flex', + }, + }, + compoundVariants: [ + { + cols: ['two', 'three', 'four', 'five'], + className: 'basis-full sm:basis-[calc((100%-16px)/2)]', + }, + { + cols: ['infinite'], + className: sliderClass, + }, + ], + defaultVariants: { + cols: 'two', + }, + }); + return (
{cols === 'infinite' ? ( - <> - {Array.from(Array(3).keys()).map((index) => ( - - ))} - + Array.from({ length: 3 }, (_, index) => ( +
+ {cards.map((card) => ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + + ))} +
+ )) ) : (
{cards.map((card) => ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore diff --git a/package-lock.json b/package-lock.json index 77cd9dd36..22a9d4706 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "class-variance-authority": "^0.7.0", "closest-match": "^1.3.3", "clsx": "^2.0.0", + "cva": "npm:class-variance-authority@^0.7.0", "leaflet": "^1.9.4", "next": "13.4.19", "next-image-export-optimizer": "^1.8.5", @@ -17969,6 +17970,18 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "node_modules/cva": { + "name": "class-variance-authority", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", + "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", + "dependencies": { + "clsx": "2.0.0" + }, + "funding": { + "url": "https://joebell.co.uk" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", diff --git a/package.json b/package.json index 78edbcb48..403e30635 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "class-variance-authority": "^0.7.0", "closest-match": "^1.3.3", "clsx": "^2.0.0", + "cva": "npm:class-variance-authority@^0.7.0", "leaflet": "^1.9.4", "next": "13.4.19", "next-image-export-optimizer": "^1.8.5", diff --git a/tailwind.config.js b/tailwind.config.js index 2b0c0ed6c..699a75ce4 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -12,9 +12,14 @@ module.exports = { '0%': { transform: 'translateX(0)' }, '100%': { transform: 'translateX(-100%)' }, }, + slideRtl: { + '0%': { transform: 'translateX(0)' }, + '100%': { transform: 'translateX(100%)' }, + }, }, animation: { - slide: '20s slide infinite linear', + slide: '50s slide infinite linear', + slideRtl: '50s slideRtl infinite linear', }, }, },