From ffaa806db5896a2d4d4661cd5169bce0d6089cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0ime=C4=8Dek?= Date: Sun, 7 Apr 2024 23:52:18 +0200 Subject: [PATCH 1/3] Added new Pagination component --- .changeset/smooth-flies-thank.md | 5 ++ .../ui/src/components/badge/Badge.stories.tsx | 13 +++++ .../ui/src/components/badge/Badge.styles.ts | 10 ++-- .../src/components/button/Button.stories.tsx | 13 +++++ .../ui/src/components/button/Button.styles.ts | 16 +++--- .../pagination/Pagination.stories.tsx | 44 ++++++++++++++++ .../pagination/Pagination.styles.ts | 10 ++++ .../pagination/PaginationContent.tsx | 12 +++++ .../pagination/PaginationEllipsis.tsx | 21 ++++++++ .../components/pagination/PaginationItem.tsx | 12 +++++ .../components/pagination/PaginationLink.tsx | 52 +++++++++++++++++++ .../components/pagination/PaginationNext.tsx | 17 ++++++ .../components/pagination/PaginationPrev.tsx | 17 ++++++ .../components/pagination/PaginationRoot.tsx | 31 +++++++++++ .../ui/src/components/pagination/index.ts | 7 +++ .../pagination/usePaginationContext.tsx | 24 +++++++++ 16 files changed, 291 insertions(+), 13 deletions(-) create mode 100644 .changeset/smooth-flies-thank.md create mode 100644 packages/ui/src/components/pagination/Pagination.stories.tsx create mode 100644 packages/ui/src/components/pagination/Pagination.styles.ts create mode 100644 packages/ui/src/components/pagination/PaginationContent.tsx create mode 100644 packages/ui/src/components/pagination/PaginationEllipsis.tsx create mode 100644 packages/ui/src/components/pagination/PaginationItem.tsx create mode 100644 packages/ui/src/components/pagination/PaginationLink.tsx create mode 100644 packages/ui/src/components/pagination/PaginationNext.tsx create mode 100644 packages/ui/src/components/pagination/PaginationPrev.tsx create mode 100644 packages/ui/src/components/pagination/PaginationRoot.tsx create mode 100644 packages/ui/src/components/pagination/index.ts create mode 100644 packages/ui/src/components/pagination/usePaginationContext.tsx diff --git a/.changeset/smooth-flies-thank.md b/.changeset/smooth-flies-thank.md new file mode 100644 index 0000000..c9a9db2 --- /dev/null +++ b/.changeset/smooth-flies-thank.md @@ -0,0 +1,5 @@ +--- +"@utima/ui": minor +--- + +Added new `Pagination` component diff --git a/packages/ui/src/components/badge/Badge.stories.tsx b/packages/ui/src/components/badge/Badge.stories.tsx index 5cf6104..2c68342 100644 --- a/packages/ui/src/components/badge/Badge.stories.tsx +++ b/packages/ui/src/components/badge/Badge.stories.tsx @@ -35,3 +35,16 @@ export const TextWrap: Story = { 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint, voluptate?', }, }; + +export const Multiline: Story = { + args: { + children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', + }, + decorators: [ + Story => ( +
+ +
+ ), + ], +}; diff --git a/packages/ui/src/components/badge/Badge.styles.ts b/packages/ui/src/components/badge/Badge.styles.ts index 7a05223..913260b 100644 --- a/packages/ui/src/components/badge/Badge.styles.ts +++ b/packages/ui/src/components/badge/Badge.styles.ts @@ -19,11 +19,11 @@ export const badgeDef = twOverrides( link: 'text-foreground border-transparent underline underline-offset-4', }, size: { - xs: 'py-0.5 px-1 gap-1 text-[10px]', - sm: 'py-[2px] px-1.5 gap-1 text-xs', - md: 'py-1 px-2 gap-1 text-xs', - lg: 'py-1.5 px-3 gap-1.5 text-sm', - xl: 'py-2 px-3 gap-2 text-base', + xs: 'min-h-5 px-1 gap-1 text-[10px]', + sm: 'min-h-6 py-[2px] px-1.5 gap-1 text-xs', + md: 'min-h-7 py-[2px] px-2 gap-1 text-xs', + lg: 'min-h-9 py-1 px-3 gap-1.5 text-sm', + xl: 'min-h-10 py-1 px-3 gap-2 text-base', }, outline: { primary: `bg-background text-primary`, diff --git a/packages/ui/src/components/button/Button.stories.tsx b/packages/ui/src/components/button/Button.stories.tsx index ba27dc1..c1df61b 100644 --- a/packages/ui/src/components/button/Button.stories.tsx +++ b/packages/ui/src/components/button/Button.stories.tsx @@ -33,3 +33,16 @@ export const Icon: Story = { children: null, }, }; + +export const Multiline: Story = { + args: { + children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', + }, + decorators: [ + Story => ( +
+ +
+ ), + ], +}; diff --git a/packages/ui/src/components/button/Button.styles.ts b/packages/ui/src/components/button/Button.styles.ts index 7591a8a..4ec30c5 100644 --- a/packages/ui/src/components/button/Button.styles.ts +++ b/packages/ui/src/components/button/Button.styles.ts @@ -30,15 +30,15 @@ export const buttonDef = twOverrides( link: 'text-foreground hover:text-foreground/70 active:text-foreground/90 underline-offset-4 hover:underline ring-foreground', }, size: { - xs: 'py-1 px-2 text-xs gap-x-1', - sm: 'py-1.5 px-3 text-sm gap-x-1', - md: 'py-2 px-4 text-sm gap-x-1', - lg: 'py-2.5 px-5 text-base gap-x-1.5', - xl: 'py-2.5 px-6 text-lg gap-x-2', + xs: 'min-h-7 py-1 px-2 text-xs gap-x-1', + sm: 'min-h-9 py-1 px-3 text-sm gap-x-1', + md: 'min-h-10 py-1.5 px-4 text-sm gap-x-1', + lg: 'min-h-11 py-1.5 px-5 text-base gap-x-1.5', + xl: 'min-h-12 py-2 px-6 text-lg gap-x-2', 'icon-xs': 'size-7', - 'icon-sm': 'size-8', - 'icon-md': 'size-9', - 'icon-lg': 'size-10', + 'icon-sm': 'size-9', + 'icon-md': 'size-10', + 'icon-lg': 'size-11', 'icon-xl': 'size-12', }, outline: { diff --git a/packages/ui/src/components/pagination/Pagination.stories.tsx b/packages/ui/src/components/pagination/Pagination.stories.tsx new file mode 100644 index 0000000..7668581 --- /dev/null +++ b/packages/ui/src/components/pagination/Pagination.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import * as Pagination from './index'; +import { PaginationEllipsis } from './PaginationEllipsis'; +import { PaginationLink } from './PaginationLink'; + +const meta: Meta = { + component: Pagination.Root, + tags: ['autodocs'], + title: 'Components/Pagination', + args: { + children: ( + + + Previous + + + 1 + + + 3 + + + + + + 10 + + + 12 + + + Next + + + ), + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Basic: Story = {}; diff --git a/packages/ui/src/components/pagination/Pagination.styles.ts b/packages/ui/src/components/pagination/Pagination.styles.ts new file mode 100644 index 0000000..8e157c7 --- /dev/null +++ b/packages/ui/src/components/pagination/Pagination.styles.ts @@ -0,0 +1,10 @@ +export const paginationDef = { + root: 'mx-auto flex w-full justify-center', + content: 'flex flex-row items-center gap-1', + icon: 'size-4', + ellipsis: { + content: 'flex h-9 w-9 items-center text-primary justify-center', + }, + item: '', + link: 'cursor-pointer', +}; diff --git a/packages/ui/src/components/pagination/PaginationContent.tsx b/packages/ui/src/components/pagination/PaginationContent.tsx new file mode 100644 index 0000000..caa1c6d --- /dev/null +++ b/packages/ui/src/components/pagination/PaginationContent.tsx @@ -0,0 +1,12 @@ +import { memo, type ComponentPropsWithoutRef } from 'react'; + +import { cn } from '@/utils'; + +import { paginationDef } from './Pagination.styles'; + +export const PaginationContent = memo(function PaginationContent({ + className, + ...restProps +}: ComponentPropsWithoutRef<'nav'>) { + return
    ; +}); diff --git a/packages/ui/src/components/pagination/PaginationEllipsis.tsx b/packages/ui/src/components/pagination/PaginationEllipsis.tsx new file mode 100644 index 0000000..416798e --- /dev/null +++ b/packages/ui/src/components/pagination/PaginationEllipsis.tsx @@ -0,0 +1,21 @@ +import { MoreHorizontal } from 'lucide-react'; +import { memo, type ComponentPropsWithoutRef } from 'react'; + +import { cn } from '@/utils'; + +import { paginationDef } from './Pagination.styles'; + +export const PaginationEllipsis = memo(function PaginationEllipsis({ + className, + ...restProps +}: ComponentPropsWithoutRef<'span'>) { + return ( + + + + ); +}); diff --git a/packages/ui/src/components/pagination/PaginationItem.tsx b/packages/ui/src/components/pagination/PaginationItem.tsx new file mode 100644 index 0000000..6dbdb66 --- /dev/null +++ b/packages/ui/src/components/pagination/PaginationItem.tsx @@ -0,0 +1,12 @@ +import { memo, type ComponentPropsWithoutRef } from 'react'; + +import { cn } from '@/utils'; + +import { paginationDef } from './Pagination.styles'; + +export const PaginationItem = memo(function PaginationItem({ + className, + ...props +}: ComponentPropsWithoutRef<'li'>) { + return
  • ; +}); diff --git a/packages/ui/src/components/pagination/PaginationLink.tsx b/packages/ui/src/components/pagination/PaginationLink.tsx new file mode 100644 index 0000000..64c6b1c --- /dev/null +++ b/packages/ui/src/components/pagination/PaginationLink.tsx @@ -0,0 +1,52 @@ +import { Slot } from '@radix-ui/react-slot'; +import type { VariantProps } from 'class-variance-authority'; +import { forwardRef, type ComponentPropsWithoutRef } from 'react'; + +import { cn } from '@/utils'; + +import { paginationDef } from './Pagination.styles'; +import { usePaginationContext } from './usePaginationContext'; +import { buttonStyles } from '../button/Button.styles'; + +export interface PaginationLinkProps + extends ComponentPropsWithoutRef<'a'>, + Pick, 'size'> { + asChild?: boolean; + active?: boolean; +} + +export const PaginationLink = forwardRef< + HTMLAnchorElement, + PaginationLinkProps +>(function PaginationLink( + { + className, + children, + size = 'md', + active = false, + asChild = false, + ...restProps + }, + ref, +) { + const { size: contextSize } = usePaginationContext(); + const Comp = asChild ? Slot : 'a'; + console.log(contextSize); + + return ( + + {children} + + ); +}); diff --git a/packages/ui/src/components/pagination/PaginationNext.tsx b/packages/ui/src/components/pagination/PaginationNext.tsx new file mode 100644 index 0000000..087bc4d --- /dev/null +++ b/packages/ui/src/components/pagination/PaginationNext.tsx @@ -0,0 +1,17 @@ +import { ChevronRight } from 'lucide-react'; +import { memo } from 'react'; + +import { paginationDef } from './Pagination.styles'; +import { PaginationLink, type PaginationLinkProps } from './PaginationLink'; + +export const PaginationNext = memo(function PaginationNext({ + children, + ...restProps +}: PaginationLinkProps) { + return ( + + {children} + + + ); +}); diff --git a/packages/ui/src/components/pagination/PaginationPrev.tsx b/packages/ui/src/components/pagination/PaginationPrev.tsx new file mode 100644 index 0000000..8c6a2e5 --- /dev/null +++ b/packages/ui/src/components/pagination/PaginationPrev.tsx @@ -0,0 +1,17 @@ +import { ChevronLeft } from 'lucide-react'; +import { memo } from 'react'; + +import { paginationDef } from './Pagination.styles'; +import { PaginationLink, type PaginationLinkProps } from './PaginationLink'; + +export const PaginationPrev = memo(function PaginationPrev({ + children, + ...restProps +}: PaginationLinkProps) { + return ( + + + {children} + + ); +}); diff --git a/packages/ui/src/components/pagination/PaginationRoot.tsx b/packages/ui/src/components/pagination/PaginationRoot.tsx new file mode 100644 index 0000000..696df57 --- /dev/null +++ b/packages/ui/src/components/pagination/PaginationRoot.tsx @@ -0,0 +1,31 @@ +import type { VariantProps } from 'class-variance-authority'; +import { memo, useMemo, type ComponentPropsWithoutRef } from 'react'; + +import { cn } from '@/utils'; + +import { paginationDef } from './Pagination.styles'; +import { PaginationContext } from './usePaginationContext'; +import type { buttonStyles } from '../button/Button.styles'; + +export interface PaginationRootProps extends ComponentPropsWithoutRef<'nav'> { + size?: VariantProps['size']; +} + +export const PaginationRoot = memo(function PaginationRoot({ + className, + size, + ...props +}: PaginationRootProps) { + const contextValue = useMemo(() => ({ size }), [size]); + + return ( + +