Skip to content

Commit

Permalink
refactor(dashboard-for-dapps): remove ui-kit dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
ditoglez committed Dec 19, 2024
1 parent 6010b70 commit 420b570
Show file tree
Hide file tree
Showing 20 changed files with 650 additions and 24 deletions.
5 changes: 2 additions & 3 deletions apps/dashboard-for-dapps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"dependencies": {
"@chakra-ui/react": "^3.0.2",
"@idos-network/idos-sdk": "workspace:*",
"@idos-network/ui-kit": "workspace:*",
"@stablelib/base64": "^1.0.1",
"@stablelib/utf8": "^1.0.1",
"@tanstack/query-sync-storage-persister": "^5.59.20",
Expand All @@ -25,10 +24,10 @@
"ascii85": "^1.0.2",
"ethers": "^6.13.4",
"match-sorter": "^7.0.0",
"next-themes": "^0.4.3",
"next-themes": "^0.4.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-icons": "^5.4.0",
"tweetnacl": "^1.0.3",
"viem": "2.x",
"wagmi": "^2.12.25"
Expand Down
33 changes: 33 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { ButtonProps as ChakraButtonProps } from "@chakra-ui/react";
import { AbsoluteCenter, Button as ChakraButton, Span, Spinner } from "@chakra-ui/react";
import { forwardRef } from "react";

interface ButtonLoadingProps {
loading?: boolean;
loadingText?: React.ReactNode;
}

export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {}

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(props, ref) {
const { loading, disabled, loadingText, children, ...rest } = props;
return (
<ChakraButton ref={ref} disabled={loading || disabled} {...rest}>
{loading && !loadingText ? (
<>
<AbsoluteCenter display="inline-flex">
<Spinner size="inherit" color="inherit" />
</AbsoluteCenter>
<Span opacity={0}>{children}</Span>
</>
) : loading && loadingText ? (
<>
<Spinner size="inherit" color="inherit" />
{loadingText}
</>
) : (
children
)}
</ChakraButton>
);
});
16 changes: 16 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/close-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { ButtonProps as ChakraCloseButtonProps } from "@chakra-ui/react";
import { IconButton as ChakraIconButton } from "@chakra-ui/react";
import { forwardRef } from "react";
import { LuX } from "react-icons/lu";

export interface CloseButtonProps extends ChakraCloseButtonProps {}

export const CloseButton = forwardRef<HTMLButtonElement, CloseButtonProps>(
function CloseButton(props, ref) {
return (
<ChakraIconButton variant="ghost" aria-label="Close" ref={ref} {...props}>
{props.children ?? <LuX />}
</ChakraIconButton>
);
},
);
62 changes: 62 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/color-mode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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 { forwardRef } from "react";
import { LuMoon, LuSun } from "react-icons/lu";

export interface ColorModeProviderProps extends ThemeProviderProps {}

export function ColorModeProvider(props: ColorModeProviderProps) {
return <ThemeProvider attribute="class" disableTransitionOnChange {...props} />;
}

export function useColorMode() {
const { resolvedTheme, setTheme } = useTheme();
const toggleColorMode = () => {
setTheme(resolvedTheme === "light" ? "dark" : "light");
};
return {
colorMode: resolvedTheme,
setColorMode: setTheme,
toggleColorMode,
};
}

export function useColorModeValue<T>(light: T, dark: T) {
const { colorMode } = useColorMode();
return colorMode === "light" ? light : dark;
}

export function ColorModeIcon() {
const { colorMode } = useColorMode();
return colorMode === "light" ? <LuSun /> : <LuMoon />;
}

interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}

export const ColorModeButton = forwardRef<HTMLButtonElement, ColorModeButtonProps>(
function ColorModeButton(props, ref) {
const { toggleColorMode } = useColorMode();
return (
<ClientOnly fallback={<Skeleton boxSize="8" />}>
<IconButton
onClick={toggleColorMode}
variant="ghost"
aria-label="Toggle color mode"
size="sm"
ref={ref}
{...props}
css={{
_icon: {
width: "5",
height: "5",
},
}}
>
<ColorModeIcon />
</IconButton>
</ClientOnly>
);
},
);
35 changes: 35 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/data-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { DataList as ChakraDataList, IconButton } from "@chakra-ui/react";
import { forwardRef } from "react";
import { HiOutlineInformationCircle } from "react-icons/hi2";
import { ToggleTip } from "./toggle-tip";

export const DataListRoot = ChakraDataList.Root;

interface ItemProps extends ChakraDataList.ItemProps {
label: React.ReactNode;
value: React.ReactNode;
info?: React.ReactNode;
grow?: boolean;
}

export const DataListItem = forwardRef<HTMLDivElement, ItemProps>(
function DataListItem(props, ref) {
const { label, info, value, children, grow, ...rest } = props;
return (
<ChakraDataList.Item ref={ref} {...rest}>
<ChakraDataList.ItemLabel flex={grow ? "1" : undefined}>
{label}
{info && (
<ToggleTip content={info}>
<IconButton variant="ghost" aria-label="info" size="2xs">
<HiOutlineInformationCircle />
</IconButton>
</ToggleTip>
)}
</ChakraDataList.ItemLabel>
<ChakraDataList.ItemValue flex={grow ? "1" : undefined}>{value}</ChakraDataList.ItemValue>
{children}
</ChakraDataList.Item>
);
},
);
48 changes: 48 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react";
import { forwardRef } from "react";
import { CloseButton } from "./close-button";

interface DialogContentProps extends ChakraDialog.ContentProps {
portalled?: boolean;
portalRef?: React.RefObject<HTMLElement>;
backdrop?: boolean;
}

export const DialogContent = forwardRef<HTMLDivElement, DialogContentProps>(
function DialogContent(props, ref) {
const { children, portalled = true, portalRef, backdrop = true, ...rest } = props;

return (
<Portal disabled={!portalled} container={portalRef}>
{backdrop && <ChakraDialog.Backdrop />}
<ChakraDialog.Positioner>
<ChakraDialog.Content ref={ref} {...rest} asChild={false}>
{children}
</ChakraDialog.Content>
</ChakraDialog.Positioner>
</Portal>
);
},
);

export const DialogCloseTrigger = forwardRef<HTMLButtonElement, ChakraDialog.CloseTriggerProps>(
function DialogCloseTrigger(props, ref) {
return (
<ChakraDialog.CloseTrigger position="absolute" top="2" insetEnd="2" {...props} asChild>
<CloseButton size="sm" ref={ref}>
{props.children}
</CloseButton>
</ChakraDialog.CloseTrigger>
);
},
);

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;
44 changes: 44 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/drawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react";
import { forwardRef } from "react";
import { CloseButton } from "./close-button";

interface DrawerContentProps extends ChakraDrawer.ContentProps {
portalled?: boolean;
portalRef?: React.RefObject<HTMLElement>;
offset?: ChakraDrawer.ContentProps["padding"];
}

export const DrawerContent = forwardRef<HTMLDivElement, DrawerContentProps>(
function DrawerContent(props, ref) {
const { children, portalled = true, portalRef, offset, ...rest } = props;
return (
<Portal disabled={!portalled} container={portalRef}>
<ChakraDrawer.Positioner padding={offset}>
<ChakraDrawer.Content ref={ref} {...rest} asChild={false}>
{children}
</ChakraDrawer.Content>
</ChakraDrawer.Positioner>
</Portal>
);
},
);

export const DrawerCloseTrigger = forwardRef<HTMLButtonElement, ChakraDrawer.CloseTriggerProps>(
function DrawerCloseTrigger(props, ref) {
return (
<ChakraDrawer.CloseTrigger position="absolute" top="2" insetEnd="2" {...props} asChild>
<CloseButton size="sm" ref={ref} />
</ChakraDrawer.CloseTrigger>
);
},
);

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;
38 changes: 38 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/empty-state.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { EmptyState as ChakraEmptyState, VStack } from "@chakra-ui/react";
import { forwardRef } from "react";
import { LuSearchSlash } from "react-icons/lu";

export interface EmptyStateProps extends ChakraEmptyState.RootProps {
title: string;
description?: string;
icon?: React.ReactNode;
}

export const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(
function EmptyState(props, ref) {
const { title, description, icon, children, ...rest } = props;

return (
<ChakraEmptyState.Root ref={ref} {...rest}>
<ChakraEmptyState.Content>
{icon ? (
<ChakraEmptyState.Indicator>{icon}</ChakraEmptyState.Indicator>
) : (
<ChakraEmptyState.Indicator>
<LuSearchSlash />
</ChakraEmptyState.Indicator>
)}
{description ? (
<VStack textAlign="center">
<ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
<ChakraEmptyState.Description>{description}</ChakraEmptyState.Description>
</VStack>
) : (
<ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
)}
{children}
</ChakraEmptyState.Content>
</ChakraEmptyState.Root>
);
},
);
26 changes: 26 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Field as ChakraField } from "@chakra-ui/react";
import { forwardRef } from "react";

export interface FieldProps extends Omit<ChakraField.RootProps, "label"> {
label?: React.ReactNode;
helperText?: React.ReactNode;
errorText?: React.ReactNode;
optionalText?: React.ReactNode;
}

export const Field = forwardRef<HTMLDivElement, FieldProps>(function Field(props, ref) {
const { label, children, helperText, errorText, optionalText, ...rest } = props;
return (
<ChakraField.Root ref={ref} {...rest}>
{label && (
<ChakraField.Label>
{label}
<ChakraField.RequiredIndicator fallback={optionalText} />
</ChakraField.Label>
)}
{children}
{helperText && <ChakraField.HelperText>{helperText}</ChakraField.HelperText>}
{errorText && <ChakraField.ErrorText>{errorText}</ChakraField.ErrorText>}
</ChakraField.Root>
);
});
12 changes: 12 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export * from "./button";
export * from "./color-mode";
export * from "./close-button";
export * from "./data-list";
export * from "./dialog";
export * from "./drawer";
export * from "./empty-state";
export * from "./field";
export * from "./password-input";
export * from "./provider";
export * from "./refresh-button";
export * from "./search-field";
38 changes: 38 additions & 0 deletions apps/dashboard-for-dapps/src/components/ui/input-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { BoxProps, InputElementProps } from "@chakra-ui/react";
import { Group, InputElement } from "@chakra-ui/react";
import { cloneElement, forwardRef } from "react";

export interface InputGroupProps extends BoxProps {
startElementProps?: InputElementProps;
endElementProps?: InputElementProps;
startElement?: React.ReactNode;
endElement?: React.ReactNode;
children: React.ReactElement;
}

export const InputGroup = forwardRef<HTMLDivElement, InputGroupProps>(
function InputGroup(props, ref) {
const { startElement, startElementProps, endElement, endElementProps, children, ...rest } =
props;

return (
<Group ref={ref} {...rest}>
{startElement && (
<InputElement pointerEvents="none" {...startElementProps}>
{startElement}
</InputElement>
)}
{cloneElement(children, {
...(startElement && { ps: "calc(var(--input-height) - 6px)" }),
...(endElement && { pe: "calc(var(--input-height) - 6px)" }),
...children.props,
})}
{endElement && (
<InputElement placement="end" {...endElementProps}>
{endElement}
</InputElement>
)}
</Group>
);
},
);
Loading

0 comments on commit 420b570

Please sign in to comment.