From ac4f0b0be80f151cbe33475012e91c5c055b0c6a Mon Sep 17 00:00:00 2001 From: Sergey Elpashev Date: Wed, 22 Jan 2025 10:56:19 +0300 Subject: [PATCH] Feat: added chakra ui --- bun.lockb | Bin 157114 -> 209636 bytes package.json | 6 ++- src/app/blog/[slug]/page.tsx | 8 +++ src/app/blog/page.tsx | 3 ++ src/components/ui/avatar.tsx | 74 ++++++++++++++++++++++++++ src/components/ui/button.tsx | 40 ++++++++++++++ src/components/ui/checkbox.tsx | 25 +++++++++ src/components/ui/close-button.tsx | 17 ++++++ src/components/ui/color-mode.tsx | 75 ++++++++++++++++++++++++++ src/components/ui/dialog.tsx | 62 ++++++++++++++++++++++ src/components/ui/drawer.tsx | 52 ++++++++++++++++++ src/components/ui/field.tsx | 33 ++++++++++++ src/components/ui/input-group.tsx | 53 +++++++++++++++++++ src/components/ui/popover.tsx | 59 +++++++++++++++++++++ src/components/ui/provider.tsx | 15 ++++++ src/components/ui/radio.tsx | 24 +++++++++ src/components/ui/slider.tsx | 82 +++++++++++++++++++++++++++++ src/components/ui/tooltip.tsx | 46 ++++++++++++++++ 18 files changed, 673 insertions(+), 1 deletion(-) create mode 100644 src/app/blog/[slug]/page.tsx create mode 100644 src/app/blog/page.tsx create mode 100644 src/components/ui/avatar.tsx create mode 100644 src/components/ui/button.tsx create mode 100644 src/components/ui/checkbox.tsx create mode 100644 src/components/ui/close-button.tsx create mode 100644 src/components/ui/color-mode.tsx create mode 100644 src/components/ui/dialog.tsx create mode 100644 src/components/ui/drawer.tsx create mode 100644 src/components/ui/field.tsx create mode 100644 src/components/ui/input-group.tsx create mode 100644 src/components/ui/popover.tsx create mode 100644 src/components/ui/provider.tsx create mode 100644 src/components/ui/radio.tsx create mode 100644 src/components/ui/slider.tsx create mode 100644 src/components/ui/tooltip.tsx diff --git a/bun.lockb b/bun.lockb index d446646fbafe55e6aa139856ae54a63453ce85ed..baf41ca1973558f3612ed3c53f7664cd7cb2941e 100755 GIT binary patch delta 66332 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 plg;lU=S;)%7iSeH_t&Q@ zy|%}*sCnb=BTwyI@N2Veh2;ki?6>mi9*Z`7^xnxOOAn};ca2Tzku<1Dj;_g7x;QvuTfTv;jlKpMf}Cs1 zF-U1hDpD$LgOmyzA*DipTmI?Rv})+z*zzN!G~`WWi3FauiRH)u^iO>?tuk^#aem$~ zTKXV-MfBpFv6FI&G;Mf6egQ%YBvB>!(MUh!Hl(D>LRLVQM^aSjLV7OgCfRbdEwfx& ziJ5Q)wMxcxBEn zM@l)z=#^Na8{L+MQC3dza826@PnOa?NU3LPcFEX$@@QKi{2?|VC4on?rwP`Xrj0V(Novx^HRkJGe{ID+)}2|KW_gr`lx9Q|k1YAO z8NZ3JD!wUW>3lja4V;L?IZAU|SgS}cBx7EB04aO|QYP={ya{Y0y)ydEwu+3m%9~ES^gSJk z*-CpNrSEy8#uXIhXxhlUaU&uo7M5to6Re1Xwk(XuFBpy+AoIrNP0$Xuvf|rNfHZJe zYpa5h`PmaDEvI<=#GIn3nx~DGFQ>S$D2E0F zlddXDNa-9Rq-WW~3yP%cend#ipJ{9Hm!mE39Fa3@qL^(gGe@rBx!L(+ko Tf<2 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 NTxHzqo5(U({tsV|ykP(U diff --git a/package.json b/package.json index 67b98ef..b9946ba 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,13 @@ "lint": "next lint" }, "dependencies": { + "@chakra-ui/react": "^3.4.0", + "@emotion/react": "^11.14.0", + "next": "15.1.5", + "next-themes": "^0.4.4", "react": "^19.0.0", "react-dom": "^19.0.0", - "next": "15.1.5" + "react-icons": "^5.4.0" }, "devDependencies": { "typescript": "^5", diff --git a/src/app/blog/[slug]/page.tsx b/src/app/blog/[slug]/page.tsx new file mode 100644 index 0000000..9d03ad4 --- /dev/null +++ b/src/app/blog/[slug]/page.tsx @@ -0,0 +1,8 @@ +export default async function Post({ params }: { params: { slug: string } }) { + const { slug } = params; + return ( +
+

Post: {slug}

+
+ ); +} diff --git a/src/app/blog/page.tsx b/src/app/blog/page.tsx new file mode 100644 index 0000000..e10b7e9 --- /dev/null +++ b/src/app/blog/page.tsx @@ -0,0 +1,3 @@ +export default function Blog() { + return

Blog

; +} diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..cd84664 --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,74 @@ +"use client" + +import type { GroupProps, SlotRecipeProps } from "@chakra-ui/react" +import { Avatar as ChakraAvatar, Group } from "@chakra-ui/react" +import * as React from "react" + +type ImageProps = React.ImgHTMLAttributes + +export interface AvatarProps extends ChakraAvatar.RootProps { + name?: string + src?: string + srcSet?: string + loading?: ImageProps["loading"] + icon?: React.ReactElement + fallback?: React.ReactNode +} + +export const Avatar = React.forwardRef( + function Avatar(props, ref) { + const { name, src, srcSet, loading, icon, fallback, children, ...rest } = + props + return ( + + + {fallback} + + + {children} + + ) + }, +) + +interface AvatarFallbackProps extends ChakraAvatar.FallbackProps { + name?: string + icon?: React.ReactElement +} + +const AvatarFallback = React.forwardRef( + function AvatarFallback(props, ref) { + const { name, icon, children, ...rest } = props + return ( + + {children} + {name != null && children == null && <>{getInitials(name)}} + {name == null && children == null && ( + {icon} + )} + + ) + }, +) + +function getInitials(name: string) { + const names = name.trim().split(" ") + const firstName = names[0] != null ? names[0] : "" + const lastName = names.length > 1 ? names[names.length - 1] : "" + return firstName && lastName + ? `${firstName.charAt(0)}${lastName.charAt(0)}` + : firstName.charAt(0) +} + +interface AvatarGroupProps extends GroupProps, SlotRecipeProps<"avatar"> {} + +export const AvatarGroup = React.forwardRef( + function AvatarGroup(props, ref) { + const { size, variant, borderless, ...rest } = props + return ( + + + + ) + }, +) diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..21d5f4b --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,40 @@ +import type { ButtonProps as ChakraButtonProps } from "@chakra-ui/react" +import { + AbsoluteCenter, + Button as ChakraButton, + Span, + Spinner, +} from "@chakra-ui/react" +import * as React from "react" + +interface ButtonLoadingProps { + loading?: boolean + loadingText?: React.ReactNode +} + +export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {} + +export const Button = React.forwardRef( + function Button(props, ref) { + const { loading, disabled, loadingText, children, ...rest } = props + return ( + + {loading && !loadingText ? ( + <> + + + + {children} + + ) : loading && loadingText ? ( + <> + + {loadingText} + + ) : ( + children + )} + + ) + }, +) diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx new file mode 100644 index 0000000..2a27c2f --- /dev/null +++ b/src/components/ui/checkbox.tsx @@ -0,0 +1,25 @@ +import { Checkbox as ChakraCheckbox } from "@chakra-ui/react" +import * as React from "react" + +export interface CheckboxProps extends ChakraCheckbox.RootProps { + icon?: React.ReactNode + inputProps?: React.InputHTMLAttributes + rootRef?: React.Ref +} + +export const Checkbox = React.forwardRef( + function Checkbox(props, ref) { + const { icon, children, inputProps, rootRef, ...rest } = props + return ( + + + + {icon || } + + {children != null && ( + {children} + )} + + ) + }, +) diff --git a/src/components/ui/close-button.tsx b/src/components/ui/close-button.tsx new file mode 100644 index 0000000..94af488 --- /dev/null +++ b/src/components/ui/close-button.tsx @@ -0,0 +1,17 @@ +import type { ButtonProps } from "@chakra-ui/react" +import { IconButton as ChakraIconButton } from "@chakra-ui/react" +import * as React from "react" +import { LuX } from "react-icons/lu" + +export type CloseButtonProps = ButtonProps + +export const CloseButton = React.forwardRef< + HTMLButtonElement, + CloseButtonProps +>(function CloseButton(props, ref) { + return ( + + {props.children ?? } + + ) +}) diff --git a/src/components/ui/color-mode.tsx b/src/components/ui/color-mode.tsx new file mode 100644 index 0000000..a87f63b --- /dev/null +++ b/src/components/ui/color-mode.tsx @@ -0,0 +1,75 @@ +"use client" + +import type { IconButtonProps } from "@chakra-ui/react" +import { ClientOnly, IconButton, Skeleton } from "@chakra-ui/react" +import { ThemeProvider, useTheme } from "next-themes" +import type { ThemeProviderProps } from "next-themes" +import * as React from "react" +import { LuMoon, LuSun } from "react-icons/lu" + +export interface ColorModeProviderProps extends ThemeProviderProps {} + +export function ColorModeProvider(props: ColorModeProviderProps) { + return ( + + ) +} + +export type ColorMode = "light" | "dark" + +export interface UseColorModeReturn { + colorMode: ColorMode + setColorMode: (colorMode: ColorMode) => void + toggleColorMode: () => void +} + +export function useColorMode(): UseColorModeReturn { + const { resolvedTheme, setTheme } = useTheme() + const toggleColorMode = () => { + setTheme(resolvedTheme === "light" ? "dark" : "light") + } + return { + colorMode: resolvedTheme as ColorMode, + setColorMode: setTheme, + toggleColorMode, + } +} + +export function useColorModeValue(light: T, dark: T) { + const { colorMode } = useColorMode() + return colorMode === "dark" ? dark : light +} + +export function ColorModeIcon() { + const { colorMode } = useColorMode() + return colorMode === "dark" ? : +} + +interface ColorModeButtonProps extends Omit {} + +export const ColorModeButton = React.forwardRef< + HTMLButtonElement, + ColorModeButtonProps +>(function ColorModeButton(props, ref) { + const { toggleColorMode } = useColorMode() + return ( + }> + + + + + ) +}) diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx new file mode 100644 index 0000000..89d68a5 --- /dev/null +++ b/src/components/ui/dialog.tsx @@ -0,0 +1,62 @@ +import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react" +import { CloseButton } from "./close-button" +import * as React from "react" + +interface DialogContentProps extends ChakraDialog.ContentProps { + portalled?: boolean + portalRef?: React.RefObject + backdrop?: boolean +} + +export const DialogContent = React.forwardRef< + HTMLDivElement, + DialogContentProps +>(function DialogContent(props, ref) { + const { + children, + portalled = true, + portalRef, + backdrop = true, + ...rest + } = props + + return ( + + {backdrop && } + + + {children} + + + + ) +}) + +export const DialogCloseTrigger = React.forwardRef< + HTMLButtonElement, + ChakraDialog.CloseTriggerProps +>(function DialogCloseTrigger(props, ref) { + return ( + + + {props.children} + + + ) +}) + +export const DialogRoot = ChakraDialog.Root +export const DialogFooter = ChakraDialog.Footer +export const DialogHeader = ChakraDialog.Header +export const DialogBody = ChakraDialog.Body +export const DialogBackdrop = ChakraDialog.Backdrop +export const DialogTitle = ChakraDialog.Title +export const DialogDescription = ChakraDialog.Description +export const DialogTrigger = ChakraDialog.Trigger +export const DialogActionTrigger = ChakraDialog.ActionTrigger diff --git a/src/components/ui/drawer.tsx b/src/components/ui/drawer.tsx new file mode 100644 index 0000000..ccb96c8 --- /dev/null +++ b/src/components/ui/drawer.tsx @@ -0,0 +1,52 @@ +import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react" +import { CloseButton } from "./close-button" +import * as React from "react" + +interface DrawerContentProps extends ChakraDrawer.ContentProps { + portalled?: boolean + portalRef?: React.RefObject + offset?: ChakraDrawer.ContentProps["padding"] +} + +export const DrawerContent = React.forwardRef< + HTMLDivElement, + DrawerContentProps +>(function DrawerContent(props, ref) { + const { children, portalled = true, portalRef, offset, ...rest } = props + return ( + + + + {children} + + + + ) +}) + +export const DrawerCloseTrigger = React.forwardRef< + HTMLButtonElement, + ChakraDrawer.CloseTriggerProps +>(function DrawerCloseTrigger(props, ref) { + return ( + + + + ) +}) + +export const DrawerTrigger = ChakraDrawer.Trigger +export const DrawerRoot = ChakraDrawer.Root +export const DrawerFooter = ChakraDrawer.Footer +export const DrawerHeader = ChakraDrawer.Header +export const DrawerBody = ChakraDrawer.Body +export const DrawerBackdrop = ChakraDrawer.Backdrop +export const DrawerDescription = ChakraDrawer.Description +export const DrawerTitle = ChakraDrawer.Title +export const DrawerActionTrigger = ChakraDrawer.ActionTrigger diff --git a/src/components/ui/field.tsx b/src/components/ui/field.tsx new file mode 100644 index 0000000..dd3b66f --- /dev/null +++ b/src/components/ui/field.tsx @@ -0,0 +1,33 @@ +import { Field as ChakraField } from "@chakra-ui/react" +import * as React from "react" + +export interface FieldProps extends Omit { + label?: React.ReactNode + helperText?: React.ReactNode + errorText?: React.ReactNode + optionalText?: React.ReactNode +} + +export const Field = React.forwardRef( + function Field(props, ref) { + const { label, children, helperText, errorText, optionalText, ...rest } = + props + return ( + + {label && ( + + {label} + + + )} + {children} + {helperText && ( + {helperText} + )} + {errorText && ( + {errorText} + )} + + ) + }, +) diff --git a/src/components/ui/input-group.tsx b/src/components/ui/input-group.tsx new file mode 100644 index 0000000..5d8fb32 --- /dev/null +++ b/src/components/ui/input-group.tsx @@ -0,0 +1,53 @@ +import type { BoxProps, InputElementProps } from "@chakra-ui/react" +import { Group, InputElement } from "@chakra-ui/react" +import * as React from "react" + +export interface InputGroupProps extends BoxProps { + startElementProps?: InputElementProps + endElementProps?: InputElementProps + startElement?: React.ReactNode + endElement?: React.ReactNode + children: React.ReactElement + startOffset?: InputElementProps["paddingStart"] + endOffset?: InputElementProps["paddingEnd"] +} + +export const InputGroup = React.forwardRef( + function InputGroup(props, ref) { + const { + startElement, + startElementProps, + endElement, + endElementProps, + children, + startOffset = "6px", + endOffset = "6px", + ...rest + } = props + + const child = + React.Children.only>(children) + + return ( + + {startElement && ( + + {startElement} + + )} + {React.cloneElement(child, { + ...(startElement && { + ps: `calc(var(--input-height) - ${startOffset})`, + }), + ...(endElement && { pe: `calc(var(--input-height) - ${endOffset})` }), + ...children.props, + })} + {endElement && ( + + {endElement} + + )} + + ) + }, +) diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx new file mode 100644 index 0000000..3320659 --- /dev/null +++ b/src/components/ui/popover.tsx @@ -0,0 +1,59 @@ +import { Popover as ChakraPopover, Portal } from "@chakra-ui/react" +import { CloseButton } from "./close-button" +import * as React from "react" + +interface PopoverContentProps extends ChakraPopover.ContentProps { + portalled?: boolean + portalRef?: React.RefObject +} + +export const PopoverContent = React.forwardRef< + HTMLDivElement, + PopoverContentProps +>(function PopoverContent(props, ref) { + const { portalled = true, portalRef, ...rest } = props + return ( + + + + + + ) +}) + +export const PopoverArrow = React.forwardRef< + HTMLDivElement, + ChakraPopover.ArrowProps +>(function PopoverArrow(props, ref) { + return ( + + + + ) +}) + +export const PopoverCloseTrigger = React.forwardRef< + HTMLButtonElement, + ChakraPopover.CloseTriggerProps +>(function PopoverCloseTrigger(props, ref) { + return ( + + + + ) +}) + +export const PopoverTitle = ChakraPopover.Title +export const PopoverDescription = ChakraPopover.Description +export const PopoverFooter = ChakraPopover.Footer +export const PopoverHeader = ChakraPopover.Header +export const PopoverRoot = ChakraPopover.Root +export const PopoverBody = ChakraPopover.Body +export const PopoverTrigger = ChakraPopover.Trigger diff --git a/src/components/ui/provider.tsx b/src/components/ui/provider.tsx new file mode 100644 index 0000000..fd0331b --- /dev/null +++ b/src/components/ui/provider.tsx @@ -0,0 +1,15 @@ +"use client" + +import { ChakraProvider, defaultSystem } from "@chakra-ui/react" +import { + ColorModeProvider, + type ColorModeProviderProps, +} from "./color-mode" + +export function Provider(props: ColorModeProviderProps) { + return ( + + + + ) +} diff --git a/src/components/ui/radio.tsx b/src/components/ui/radio.tsx new file mode 100644 index 0000000..b3919d0 --- /dev/null +++ b/src/components/ui/radio.tsx @@ -0,0 +1,24 @@ +import { RadioGroup as ChakraRadioGroup } from "@chakra-ui/react" +import * as React from "react" + +export interface RadioProps extends ChakraRadioGroup.ItemProps { + rootRef?: React.Ref + inputProps?: React.InputHTMLAttributes +} + +export const Radio = React.forwardRef( + function Radio(props, ref) { + const { children, inputProps, rootRef, ...rest } = props + return ( + + + + {children && ( + {children} + )} + + ) + }, +) + +export const RadioGroup = ChakraRadioGroup.Root diff --git a/src/components/ui/slider.tsx b/src/components/ui/slider.tsx new file mode 100644 index 0000000..55a7283 --- /dev/null +++ b/src/components/ui/slider.tsx @@ -0,0 +1,82 @@ +import { Slider as ChakraSlider, For, HStack } from "@chakra-ui/react" +import * as React from "react" + +export interface SliderProps extends ChakraSlider.RootProps { + marks?: Array + label?: React.ReactNode + showValue?: boolean +} + +export const Slider = React.forwardRef( + function Slider(props, ref) { + const { marks: marksProp, label, showValue, ...rest } = props + const value = props.defaultValue ?? props.value + + const marks = marksProp?.map((mark) => { + if (typeof mark === "number") return { value: mark, label: undefined } + return mark + }) + + const hasMarkLabel = !!marks?.some((mark) => mark.label) + + return ( + + {label && !showValue && ( + {label} + )} + {label && showValue && ( + + {label} + + + )} + + + + + + + + + ) + }, +) + +function SliderThumbs(props: { value?: number[] }) { + const { value } = props + return ( + + {(_, index) => ( + + + + )} + + ) +} + +interface SliderMarksProps { + marks?: Array +} + +const SliderMarks = React.forwardRef( + function SliderMarks(props, ref) { + const { marks } = props + if (!marks?.length) return null + + return ( + + {marks.map((mark, index) => { + const value = typeof mark === "number" ? mark : mark.value + const label = typeof mark === "number" ? undefined : mark.label + return ( + + + {label} + + ) + })} + + ) + }, +) diff --git a/src/components/ui/tooltip.tsx b/src/components/ui/tooltip.tsx new file mode 100644 index 0000000..43a8a6c --- /dev/null +++ b/src/components/ui/tooltip.tsx @@ -0,0 +1,46 @@ +import { Tooltip as ChakraTooltip, Portal } from "@chakra-ui/react" +import * as React from "react" + +export interface TooltipProps extends ChakraTooltip.RootProps { + showArrow?: boolean + portalled?: boolean + portalRef?: React.RefObject + content: React.ReactNode + contentProps?: ChakraTooltip.ContentProps + disabled?: boolean +} + +export const Tooltip = React.forwardRef( + function Tooltip(props, ref) { + const { + showArrow, + children, + disabled, + portalled = true, + content, + contentProps, + portalRef, + ...rest + } = props + + if (disabled) return children + + return ( + + {children} + + + + {showArrow && ( + + + + )} + {content} + + + + + ) + }, +)