diff --git a/.changeset/fair-queens-travel.md b/.changeset/fair-queens-travel.md new file mode 100644 index 00000000..caf3f897 --- /dev/null +++ b/.changeset/fair-queens-travel.md @@ -0,0 +1,7 @@ +--- +"@polkadex/ux": major +"docs": minor +"web": minor +--- + +Scaffolding of Basic Shared Components diff --git a/.github/workflows/pr-main.yml b/.github/workflows/pr-main.yml index 0a1c6e8f..f4b2f6b0 100644 --- a/.github/workflows/pr-main.yml +++ b/.github/workflows/pr-main.yml @@ -2,7 +2,7 @@ name: CI Build and Test on: pull_request: - types: [labeled] + types: [labeled, synchronize] push: branches: [main] diff --git a/apps/docs/app/page.tsx b/apps/docs/app/page.tsx index a265aa1c..d46fa508 100644 --- a/apps/docs/app/page.tsx +++ b/apps/docs/app/page.tsx @@ -1,5 +1,4 @@ import Image from "next/image"; -import { Card } from "ui"; import styles from "./page.module.css"; @@ -125,13 +124,7 @@ export default function Page(): JSX.Element { -
- {LINKS.map(({ title, href, description }) => ( - - {description} - - ))} -
+
); } diff --git a/apps/docs/next.config.js b/apps/docs/next.config.js index b19cd371..848b4e08 100644 --- a/apps/docs/next.config.js +++ b/apps/docs/next.config.js @@ -1,4 +1,4 @@ module.exports = { reactStrictMode: true, - transpilePackages: ["ui", "react-providers"], + transpilePackages: ["@polkadex/ux", "react-providers"], }; diff --git a/apps/docs/package.json b/apps/docs/package.json index 88d56d22..b3e04168 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -12,7 +12,7 @@ "next": "^13.4.19", "react": "^18.2.0", "react-dom": "^18.2.0", - "ui": "*" + "@polkadex/ux": "*" }, "devDependencies": { "@next/eslint-plugin-next": "^13.4.19", diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx index 7ce283eb..3e9df9d8 100644 --- a/apps/web/app/page.tsx +++ b/apps/web/app/page.tsx @@ -1,6 +1,5 @@ "use client"; import Image from "next/image"; -import { Card } from "ui"; import styles from "./page.module.css"; @@ -124,13 +123,7 @@ export default function Page(): JSX.Element { -
- {LINKS.map(({ title, href, description }) => ( - - {description} - - ))} -
+
); } diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 64d6eb3e..6a3ed026 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -1,7 +1,7 @@ module.exports = { reactStrictMode: false, transpilePackages: [ - "ui", + "@polkadex/ux", "@polkadex/react-providers", "@chainsafe/metamask-polkadot-adapter", ], diff --git a/apps/web/package.json b/apps/web/package.json index bb5d5abc..41c3026b 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,7 +14,7 @@ "react-dom": "^18.2.0", "@polkadex/react-providers": "*", "@polkadot-cloud/react": "^0.1.127", - "ui": "*" + "@polkadex/ux": "*" }, "devDependencies": { "@next/eslint-plugin-next": "^13.4.19", diff --git a/packages/ui/README.md b/packages/ui/README.md new file mode 100644 index 00000000..7033f249 --- /dev/null +++ b/packages/ui/README.md @@ -0,0 +1,7 @@ +# Polkadex UX + +## Getting Started +An open source design system for building modern websites and applications. + +## Documentation +Visit http://ux.polkadex.trade to view the documentation. diff --git a/packages/ui/card.tsx b/packages/ui/card.tsx deleted file mode 100644 index e6551f32..00000000 --- a/packages/ui/card.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from "react"; - -export function Card({ - className, - title, - children, - href, -}: { - className?: string; - title: string; - children: React.ReactNode; - href: string; -}): JSX.Element { - return ( - -

- {title} -> -

-

{children}

-
- ); -} diff --git a/packages/ui/index.ts b/packages/ui/index.ts new file mode 100644 index 00000000..d8b2730f --- /dev/null +++ b/packages/ui/index.ts @@ -0,0 +1,2 @@ +// component exports +export * from "./src/components"; diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx deleted file mode 100644 index 926b1511..00000000 --- a/packages/ui/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -// component exports -export { Card } from "./card"; diff --git a/packages/ui/package.json b/packages/ui/package.json index b7e4c127..f2470ee0 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,21 +1,47 @@ { - "name": "ui", - "version": "0.0.0", - "main": "./index.tsx", - "types": "./index.tsx", + "name": "@polkadex/ux", + "version": "0.0.1", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", "license": "MIT", + "files": [ + "dist/**" + ], "scripts": { - "lint": "eslint .", - "generate:component": "turbo gen react-component" + "dev": "tsup index.ts --format esm,cjs --watch --dts", + "build": "tsup index.ts --format esm,cjs --dts", + "typecheck": "tsc --noEmit", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", + "lint": "eslint ./src" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { "@turbo/gen": "^1.10.12", "@types/node": "^20.5.2", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", - "eslint-config-custom": "*", - "react": "^18.2.0", + "autoprefixer": "^10.4.16", + "classnames": "^2.3.2", + "@polkadex-ts/eslint-config": "*", + "postcss": "^8.4.31", + "tailwind-merge": "^2.0.0", "tsconfig": "*", - "typescript": "^4.5.2" + "typescript": "^4.5.2", + "tsup": "^7.2.0", + "tailwindcss-animate": "^1.0.7" + }, + "dependencies": { + "@heroicons/react": "^2.0.18", + "@radix-ui/react-alert-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tooltip": "^1.0.7", + "tailwindcss": "^3.3.5", + "react-use": "^17.4.0" } } diff --git a/packages/ui/postcss.config.js b/packages/ui/postcss.config.js new file mode 100644 index 00000000..12a703d9 --- /dev/null +++ b/packages/ui/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx new file mode 100644 index 00000000..3a62e005 --- /dev/null +++ b/packages/ui/src/components/button.tsx @@ -0,0 +1,80 @@ +import { ComponentProps, ElementType, PropsWithChildren } from "react"; +import classNames from "classnames"; +import { twMerge } from "tailwind-merge"; +import { Slot } from "@radix-ui/react-slot"; + +export interface ButtonProps extends ComponentProps<"button"> { + asChild?: boolean; + size?: keyof (typeof variants)["size"]; + variant?: keyof (typeof variants)["variant"]; +} + +const variants = { + size: { + xs: "h-3 px-0.5 py-2 text-xs rounded-sm", + sm: "h-6 px-1 py-2 rounded-sm", + default: "h6 px-4 py-2 rounded-md", + md: "h-10 px-4 py-2 rounded-md", + lg: "h-14 px-8 py-4 text-md rounded-md", + }, + variant: { + primary: "bg-primary-base hover:bg-primary-hover active:bg-primary-pressed", + secondary: + "bg-secondary-base hover:bg-secondary-hover active:bg-secondary-pressed", + ghost: + "bg-transparent hover:bg-secondary-pressed active:bg-secondary-hover text-primary hover:text-textBase", + outline: + "border border-secondary-base hover:bg-secondary-pressed active:bg-secondary-hover ", + }, +}; + +const Base = ({ + className, + asChild = false, + size = "default", + variant = "primary", + children, + ...props +}: PropsWithChildren) => { + const Rendercomponent: ElementType = asChild ? Slot : "button"; + return ( + + {children} + + ); +}; + +const Primary = (props: PropsWithChildren>) => ( + +); + +const Secondary = (props: PropsWithChildren>) => ( + +); + +const Ghost = (props: PropsWithChildren>) => ( + +); + +const Outline = (props: PropsWithChildren>) => ( + +); + +export const Button = { + Primary, + Secondary, + Ghost, + Outline, +}; diff --git a/packages/ui/src/components/copy.tsx b/packages/ui/src/components/copy.tsx new file mode 100644 index 00000000..a812527c --- /dev/null +++ b/packages/ui/src/components/copy.tsx @@ -0,0 +1,53 @@ +import { ComponentProps, MouseEvent, PropsWithChildren, useState } from "react"; +import { DocumentDuplicateIcon } from "@heroicons/react/24/solid"; +import classNames from "classnames"; +import { TooltipContentProps } from "@radix-ui/react-tooltip"; +import { twMerge } from "tailwind-merge"; + +import { Tooltip } from "./tooltip"; + +interface CopyProps extends ComponentProps<"div"> { + value: string | number; + side?: TooltipContentProps["side"]; +} + +export const Copy = ({ + value, + className, + side = "top", + children, +}: PropsWithChildren) => { + const [open, setOpen] = useState(false); + const [state, setState] = useState(false); + + const onCopy = async (e: MouseEvent) => { + e.preventDefault(); + if (!value) return; + try { + await navigator.clipboard.writeText(value.toString()); + if (!state) setState(true); + } catch (error) { + console.error("Error copying to clipboard:", error); + } + }; + + const onMouseOut = () => state && setState(false); + + return ( + + + {children ?? ( + + )} + + e.preventDefault()} + > + {state ? "Copied" : "Copy"} + + + ); +}; diff --git a/packages/ui/src/components/dropdown.tsx b/packages/ui/src/components/dropdown.tsx new file mode 100644 index 00000000..bf24e22f --- /dev/null +++ b/packages/ui/src/components/dropdown.tsx @@ -0,0 +1,236 @@ +import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; +import { Children, PropsWithChildren } from "react"; +import { CheckIcon } from "@heroicons/react/24/solid"; +import { twMerge } from "tailwind-merge"; +import classNames from "classnames"; + +import { isValidComponent } from "../helpers"; + +const Radio = ({ + children, + ...props +}: PropsWithChildren) => { + const items = Children.toArray(children); + + return {items}; +}; +interface ItemRadioProps extends DropdownMenu.MenuRadioItemProps { + active?: boolean; +} + +const ItemRadio = ({ + children, + className, + active, + ...props +}: PropsWithChildren) => { + return ( + +
+ {children} + + ); +}; + +const ItemCheckbox = ({ + children, + className, + ...props +}: PropsWithChildren) => { + return ( + + + + + {children} + + ); +}; + +interface ItemProps extends DropdownMenu.MenuItemProps { + shortcut?: string; +} + +const Item = ({ + children, + shortcut, + className, + ...props +}: PropsWithChildren) => { + return ( + + {children} + {shortcut && {shortcut}} + + ); +}; + +const Trigger = ({ + children, + asChild, + ...props +}: PropsWithChildren) => { + return ( + + {asChild ?
{children}
: children} +
+ ); +}; + +const Content = ({ + children, + className, + ...props +}: PropsWithChildren) => { + return ( + + {children} + + ); +}; + +const Sub = ({ + children, + ...props +}: PropsWithChildren) => { + const [SubTriggerComponent] = isValidComponent(children, SubTrigger); + const [SubContentComponent] = isValidComponent(children, SubContent); + + return ( + + {SubTriggerComponent} + {SubContentComponent} + + ); +}; + +const SubTrigger = ({ + children, + ...props +}: PropsWithChildren) => { + return ( + {children} + ); +}; + +const SubContent = ({ + children, + ...props +}: PropsWithChildren) => { + return ( + {children} + ); +}; + +const Separator = ({ + children, + className, + ...props +}: PropsWithChildren) => { + return ( + + {children} + + ); +}; +const Label = ({ + children, + className, + ...props +}: PropsWithChildren) => { + return ( + + {children} + + ); +}; + +const Dropdown = ({ + children, + ...props +}: PropsWithChildren) => { + const [TriggerComponent] = isValidComponent(children, Trigger); + const [ContentComponent] = isValidComponent(children, Content); + + return ( + + {TriggerComponent} + {ContentComponent} + + ); +}; + +Dropdown.Trigger = Trigger; +Dropdown.Content = Content; +Dropdown.Separator = Separator; +Dropdown.Label = Label; + +Dropdown.Sub = Sub; +Dropdown.SubTrigger = SubTrigger; +Dropdown.SubContent = SubContent; + +Dropdown.Item = Item; +Dropdown.ItemCheckbox = ItemCheckbox; + +Dropdown.Radio = Radio; +Dropdown.ItemRadio = ItemRadio; + +export { Dropdown }; diff --git a/packages/ui/src/components/genericMessage.tsx b/packages/ui/src/components/genericMessage.tsx new file mode 100644 index 00000000..159e0570 --- /dev/null +++ b/packages/ui/src/components/genericMessage.tsx @@ -0,0 +1,48 @@ +import { ComponentProps, PropsWithChildren } from "react"; +import classNames from "classnames"; +import { twMerge } from "tailwind-merge"; + +import * as Vectors from "../illustrations"; + +interface GenericMessageProps extends ComponentProps<"div"> { + title: string; + illustration: keyof typeof Vectors; + inverted?: boolean; + imageProps?: ComponentProps<"svg">; +} + +export const GenericMessage = ({ + title, + illustration, + inverted, + children, + imageProps, + className, + ...props +}: PropsWithChildren) => { + const IllustrationComponent = Vectors[illustration]; + return ( +
+
+ +

{title}

+
+ {children} +
+ ); +}; diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx new file mode 100644 index 00000000..3d886074 --- /dev/null +++ b/packages/ui/src/components/icon.tsx @@ -0,0 +1,16 @@ +import { ComponentProps } from "react"; + +import * as Icons from "../icons"; + +interface Props extends ComponentProps<"svg"> { + name: string; +} +export const Icon = ({ name, ...props }: Props) => { + const iconUppercase = name.toUpperCase(); + const iconTicker = ( + iconUppercase in Icons ? iconUppercase : "Wallet" + ) as keyof typeof Icons; + + const IconComponent = Icons[iconTicker]; + return ; +}; diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts new file mode 100644 index 00000000..47528738 --- /dev/null +++ b/packages/ui/src/components/index.ts @@ -0,0 +1,16 @@ +// component exports +export * from "./button"; +export * from "./logo"; +export * from "./typography"; +export * from "./modal"; +export * from "./interaction"; +export * from "./dropdown"; +export * from "./popover"; +export * from "./skeleton"; +export * from "./spinner"; +export * from "./genericMessage"; +export * from "./multistep"; +export * from "./input"; +export * from "./tooltip"; +export * from "./copy"; +export * from "./icon"; diff --git a/packages/ui/src/components/input.tsx b/packages/ui/src/components/input.tsx new file mode 100644 index 00000000..3fd1e989 --- /dev/null +++ b/packages/ui/src/components/input.tsx @@ -0,0 +1,97 @@ +import { MagnifyingGlassIcon } from "@heroicons/react/24/solid"; +import { InputHTMLAttributes, PropsWithChildren, useRef } from "react"; + +import { Button } from "./button"; + +interface PrimaryInputProps extends InputHTMLAttributes { + increase: () => void; + decrease: () => void; + ticker: string; + label: string; +} + +const Primary = ({ + label, + increase, + decrease, + ticker, + ...props +}: PropsWithChildren) => { + const ref = useRef(null); + return ( +
ref?.current?.focus()} + > + {label} + +
+ {ticker} +
+ + +
+
+
+ ); +}; + +const Search = (props: InputHTMLAttributes) => ( +
+ + +
+); + +interface VerticalProps extends InputHTMLAttributes { + label: string; + optional?: boolean; + action?: () => void; +} +const Vertical = ({ label, optional, action, ...props }: VerticalProps) => ( +
+
+ + {label} {optional && (Optional)} + + +
+ {action && ( + + Change + + )} +
+); + +export const Input = { + Primary, + Search, + Vertical, +}; diff --git a/packages/ui/src/components/interaction.tsx b/packages/ui/src/components/interaction.tsx new file mode 100644 index 00000000..4d3516ec --- /dev/null +++ b/packages/ui/src/components/interaction.tsx @@ -0,0 +1,169 @@ +import { ComponentProps, PropsWithChildren } from "react"; +import classNames from "classnames"; +import { ArrowLeftIcon, XMarkIcon } from "@heroicons/react/24/solid"; +import { twMerge } from "tailwind-merge"; + +import { isValidComponent } from "../helpers"; + +import { Typography } from "./typography"; +import { Button, ButtonProps } from "./button"; + +interface TitleProps extends ComponentProps<"div"> { + onBack?: () => void; + onClose?: () => void; + withPadding?: boolean; +} +const Title = ({ + children, + withPadding = true, + onBack, + onClose, + className, + ...props +}: PropsWithChildren) => { + const hasBack = typeof onBack === "function"; + const hasClose = typeof onClose === "function"; + + return ( +
+ {hasBack && ( + + )} + + {children} + + {hasClose && ( + + )} +
+ ); +}; + +interface FooterProps extends ComponentProps<"div"> { + withPadding?: boolean; +} + +const Footer = ({ + children, + className, + withPadding = true, + ...props +}: PropsWithChildren) => { + const [ActionComponent] = isValidComponent(children, Action); + const [CloseComponent] = isValidComponent(children, Close); + + const customClassNames = twMerge( + classNames(withPadding && "px-7", "flex flex-col gap-3"), + className + ); + + if (!ActionComponent || (CloseComponent && children)) + return ( +
+ {children} +
+ ); + return ( +
+ {ActionComponent} + {CloseComponent} +
+ ); +}; + +interface ActionProps extends ButtonProps, ComponentProps<"button"> {} + +const Action = ({ children, ...props }: PropsWithChildren) => { + return ( + + {children} + + ); +}; + +const Close = ({ + children, + ...props +}: PropsWithChildren>) => { + return ( + + {children} + + ); +}; + +interface ContentProps extends ComponentProps<"div"> { + onBack?: () => void; + onClose?: () => void; + withPadding?: boolean; +} + +const Content = ({ + children, + withPadding = true, + className, + ...props +}: PropsWithChildren) => { + return ( +
+ {children} +
+ ); +}; +const Interaction = ({ + children, + className, + ...props +}: PropsWithChildren>) => { + const [TitleCompontent] = isValidComponent(children, Title); + const [ContentCompontent] = isValidComponent(children, Content); + const [FooterCompontent] = isValidComponent(children, Footer); + + return ( +
+ {TitleCompontent} + {ContentCompontent} + {FooterCompontent} +
+ ); +}; + +Interaction.Title = Title; +Interaction.Content = Content; +Interaction.Footer = Footer; +Interaction.Action = Action; +Interaction.Close = Close; + +export { Interaction }; diff --git a/packages/ui/src/components/logo.tsx b/packages/ui/src/components/logo.tsx new file mode 100644 index 00000000..bca39e1f --- /dev/null +++ b/packages/ui/src/components/logo.tsx @@ -0,0 +1,236 @@ +import { ComponentProps } from "react"; + +const Thea = (props: ComponentProps<"svg">) => ( + + + + + + + + + + + + +); + +const Orderbook = (props: ComponentProps<"svg">) => ( + + + + + + + + + + + + + + + + + +); + +const Polkadex = (props: ComponentProps<"svg">) => ( + + + + + + + + + + + + + + + + +); + +const Ux = (props: ComponentProps<"svg">) => ( + + + + + + + + + + +); + +export const Logo = { + Thea, + Orderbook, + Polkadex, + Ux, +}; diff --git a/packages/ui/src/components/modal.tsx b/packages/ui/src/components/modal.tsx new file mode 100644 index 00000000..d6442359 --- /dev/null +++ b/packages/ui/src/components/modal.tsx @@ -0,0 +1,114 @@ +import { ComponentProps, PropsWithChildren } from "react"; +import * as AlertDialog from "@radix-ui/react-alert-dialog"; +import classNames from "classnames"; +import { twMerge } from "tailwind-merge"; + +import { isValidComponent, placements } from "../helpers"; + +interface TitleProps extends AlertDialog.DialogTitleProps { + onBack?: () => void; +} + +const Title = ({ + children, + className, + ...props +}: PropsWithChildren) => { + return ( + + {children} + + ); +}; + +const Footer = ({ + children, + ...props +}: PropsWithChildren>) => { + return
{children}
; +}; + +const Content = ({ + children, + ...props +}: PropsWithChildren) => { + return ( + {children} + ); +}; + +type ModalProps = { + closeOnClickOutside?: boolean; + placement?: (typeof placements)[number]; +} & Pick & + AlertDialog.DialogContentProps; + +const modalPlace = { + center: "left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%]", + "center left": "left-[1%] top-[50%] translate-y-[-50%]", + "center right": "right-[1%] top-[50%] translate-y-[-50%]", + "top center": "left-[50%] top-[1%] translate-x-[-50%]", + "top left": "left-[1%] top-[1%]", + "top right": "right-[1%] top-[1%]", + "bottom center": "left-[50%] bottom-[1%] translate-x-[-50%]", + "bottom left": "left-[1%] bottom-[1%]", + "bottom right": "right-[1%] bottom-[1%]", +}; + +const Modal = ({ + children, + open, + onOpenChange, + defaultOpen, + closeOnClickOutside, + className, + placement = "center", + ...props +}: PropsWithChildren) => { + const [TitleComponent] = isValidComponent(children, Title); + const [ContentComponent] = isValidComponent(children, Content); + const [FooterComponent] = isValidComponent(children, Footer); + + return ( + + + onOpenChange?.(!open) : undefined + } + /> + + {TitleComponent} + {ContentComponent} + {FooterComponent} + + + + ); +}; + +Modal.Title = Title; +Modal.Content = Content; +Modal.Footer = Footer; + +export { Modal }; diff --git a/packages/ui/src/components/multistep.tsx b/packages/ui/src/components/multistep.tsx new file mode 100644 index 00000000..ba4abb75 --- /dev/null +++ b/packages/ui/src/components/multistep.tsx @@ -0,0 +1,56 @@ +import { + Children, + Key, + PropsWithChildren, + ReactElement, + ReactNode, + isValidElement, + useState, +} from "react"; +import { usePrevious } from "react-use"; + +export type Actions = { + onBack: () => void; + onNext: () => void; + onPage: (id: string) => void; + current: number; +}; + +export const Multistep = ({ + defaultIndex = 0, + children, +}: { + defaultIndex?: number; + children: ((value?: Actions) => ReactNode) | ReactNode; +}) => { + const [current, setCurrent] = useState(defaultIndex); + const prevCount = usePrevious(current); + + let RenderComponent: ReactNode; + + if (typeof children === "function") { + const [child] = Children.toArray( + children({ + onNext: () => { + const childCount = Children.count(child?.props?.children); + setCurrent((current) => (current + 1) % childCount); + }, + onBack: () => setCurrent(prevCount ?? 0), + onPage: (key: Key) => { + const childIndex = ( + child?.props?.children as ReactElement[] + )?.findIndex((e) => e.key === key); + setCurrent(childIndex >= 0 ? childIndex : 0); + }, + current, + }) + ).filter(isValidElement) as ReactElement>[]; + + RenderComponent = (child?.props?.children as ReactNode[])?.[current]; + } else { + const allElements = Children.toArray(children).filter(isValidElement); + RenderComponent = allElements[current] ??
MultiStep error
; + } + + return <>{RenderComponent}; +}; diff --git a/packages/ui/src/components/popover.tsx b/packages/ui/src/components/popover.tsx new file mode 100644 index 00000000..1168a550 --- /dev/null +++ b/packages/ui/src/components/popover.tsx @@ -0,0 +1,74 @@ +import * as PopoverRadix from "@radix-ui/react-popover"; +import { PropsWithChildren } from "react"; +import { twMerge } from "tailwind-merge"; +import classNames from "classnames"; + +import { isValidComponent } from "../helpers"; + +const Close = ({ + children, + asChild, + ...props +}: PropsWithChildren) => { + return ( + + {asChild ?
{children}
: children} +
+ ); +}; + +const Trigger = ({ + children, + asChild, + ...props +}: PropsWithChildren) => { + return ( + + {asChild ?
{children}
: children} +
+ ); +}; + +const Content = ({ + children, + className, + ...props +}: PropsWithChildren) => { + return ( + + {children} + + ); +}; + +const Popover = ({ + children, + ...props +}: PropsWithChildren) => { + const [TriggerComponent] = isValidComponent(children, Trigger); + const [ContentComponent] = isValidComponent(children, Content); + + return ( + + {TriggerComponent} + {ContentComponent} + + ); +}; + +Popover.Trigger = Trigger; +Popover.Content = Content; +Popover.Close = Close; + +export { Popover }; diff --git a/packages/ui/src/components/skeleton.tsx b/packages/ui/src/components/skeleton.tsx new file mode 100644 index 00000000..6371a5df --- /dev/null +++ b/packages/ui/src/components/skeleton.tsx @@ -0,0 +1,27 @@ +import classNames from "classnames"; +import { ComponentProps, Fragment, PropsWithChildren } from "react"; +import { twMerge } from "tailwind-merge"; +// import { twMerge } from "tailwind-merge"; // TODO: Merge is not working + +interface SkeletonProps extends ComponentProps<"div"> { + loading?: boolean; +} + +export const Skeleton = ({ + children, + loading, + className, + ...props +}: PropsWithChildren) => { + if (!loading) return {children}; + + return ( +
+ ); +}; diff --git a/packages/ui/src/components/spinner.tsx b/packages/ui/src/components/spinner.tsx new file mode 100644 index 00000000..ecc2f40f --- /dev/null +++ b/packages/ui/src/components/spinner.tsx @@ -0,0 +1,161 @@ +import { ComponentProps } from "react"; + +const Keyboard = (props: ComponentProps<"svg">) => { + return ( + + + + + + + + + + + + + + + + + + ); +}; + +const Loading = (props: ComponentProps<"svg">) => ( + + + + + + + + + + +); +const Spinner = { + Keyboard, + Loading, +}; + +export { Spinner }; diff --git a/packages/ui/src/components/token.tsx b/packages/ui/src/components/token.tsx new file mode 100644 index 00000000..13321cce --- /dev/null +++ b/packages/ui/src/components/token.tsx @@ -0,0 +1,16 @@ +import { ComponentProps } from "react"; + +import * as Tokens from "../tokens"; + +interface Props extends ComponentProps<"svg"> { + name: string; +} +export const Token = ({ name, ...props }: Props) => { + const tokenUppercase = name.toUpperCase(); + const tokenTicker = ( + tokenUppercase in Tokens ? tokenUppercase : "UNKN" + ) as keyof typeof Tokens; + + const IconComponent = Tokens[tokenTicker]; + return ; +}; diff --git a/packages/ui/src/components/tooltip.tsx b/packages/ui/src/components/tooltip.tsx new file mode 100644 index 00000000..7d6e7ef5 --- /dev/null +++ b/packages/ui/src/components/tooltip.tsx @@ -0,0 +1,66 @@ +import * as TooltipRadix from "@radix-ui/react-tooltip"; +import { PropsWithChildren } from "react"; +import { twMerge } from "tailwind-merge"; +import classNames from "classnames"; + +import { isValidComponent } from "../helpers"; + +const Trigger = ({ + children, + asChild, + ...props +}: PropsWithChildren) => { + return ( + + {asChild ?
{children}
: children} +
+ ); +}; + +const Content = ({ + children, + className, + sideOffset = 12, + ...props +}: PropsWithChildren) => { + return ( + + {children} + + ); +}; + +const Tooltip = ({ + children, + delayDuration = 150, + ...props +}: PropsWithChildren) => { + const [TriggerComponent] = isValidComponent(children, Trigger); + const [ContentComponent] = isValidComponent(children, Content); + + return ( + + + {TriggerComponent} + {ContentComponent} + + + ); +}; + +Tooltip.Trigger = Trigger; +Tooltip.Content = Content; + +export { Tooltip }; diff --git a/packages/ui/src/components/typography.tsx b/packages/ui/src/components/typography.tsx new file mode 100644 index 00000000..b5bf4b13 --- /dev/null +++ b/packages/ui/src/components/typography.tsx @@ -0,0 +1,135 @@ +import { + Children, + ComponentProps, + ElementType, + PropsWithChildren, + ReactElement, + cloneElement, +} from "react"; +import classNames from "classnames"; +import { twMerge } from "tailwind-merge"; + +import { componentIsTypeof } from "../helpers"; +interface TextProps extends ParagraphProps { + type?: "span" | "small" | "strong"; + bold?: boolean; +} + +const Text = ({ + children, + className, + variant = "base", + size = "sm", + type = "span", + bold, + ...props +}: PropsWithChildren) => { + const ElementRender = type; + + return ( + + {children} + + ); +}; + +interface ParagraphProps extends ComponentProps<"p"> { + variant?: keyof typeof paragraphVariants; + size?: keyof typeof paragraphSize; +} + +const paragraphVariants = { + base: "text-textBase", + primary: "text-primary", + secondary: "text-secondary", +}; + +const paragraphSize = { + xs: "text-xs", + sm: "text-sm", + base: "text-base", + md: "text-md", + lg: "text-lg", + xl: "text-xl", +}; + +const Paragraph = ({ + children, + className, + variant = "base", + size = "md", + ...props +}: PropsWithChildren) => { + const isChildrenParagraph = Children.toArray(children).some((child) => + componentIsTypeof(child, "p") + ); + const customClassNames = twMerge( + paragraphVariants[variant], + paragraphSize[size], + classNames("leading-5"), + className + ); + if (isChildrenParagraph) { + const childElement = Children.only(children) as ReactElement; + return cloneElement(childElement, { + className: customClassNames, + ...props, + }); + } + return ( +

+ {children} +

+ ); +}; + +interface HeadingProps extends ComponentProps<"h1"> { + type?: (typeof headingTypes)[number]; + size?: keyof typeof headingSizes; +} + +const headingTypes = ["h1", "h2", "h3", "h4", "h5", "h6"] as const; +const headingSizes = { + "2xl": "text-[2rem] leading-[2.25rem]", + xl: "text-[1.75rem] leading-[2rem]", + lg: "text-[1.5rem] leading-[1.75rem]", + md: "text-[1.25rem] leading-[1.5rem]", + sm: "text-[1.125rem] leading-[1.75rem]", + xs: "text-[1rem] leading-[1.25rem]", +}; + +const Heading = ({ + children, + className, + type = "h1", + size = "xl", + ...props +}: PropsWithChildren) => { + const ElementRender = type as ElementType; + return ( + + {children} + + ); +}; + +export const Typography = { + Paragraph, + Text, + Heading, +}; diff --git a/packages/ui/src/helpers/componentIsTypeof.ts b/packages/ui/src/helpers/componentIsTypeof.ts new file mode 100644 index 00000000..39b6ab53 --- /dev/null +++ b/packages/ui/src/helpers/componentIsTypeof.ts @@ -0,0 +1,14 @@ +import { ReactElement, ReactNode, isValidElement } from "react"; + +export const componentIsTypeof = ( + child: ReactNode, + type: keyof JSX.IntrinsicElements +) => { + if (!isValidElement(child)) return false; + const dynamicType = + typeof child.type === "function" && (child.type as () => ReactElement)(); + const isDynamicType = + isValidElement(dynamicType) && dynamicType.type === type; + const isStringType = typeof child.type === "string" && child.type === type; + return isDynamicType || isStringType; +}; diff --git a/packages/ui/src/helpers/index.ts b/packages/ui/src/helpers/index.ts new file mode 100644 index 00000000..efa21a41 --- /dev/null +++ b/packages/ui/src/helpers/index.ts @@ -0,0 +1,3 @@ +export * from "./isValidComponent"; +export * from "./variants"; +export * from "./componentIsTypeof"; diff --git a/packages/ui/src/helpers/isValidComponent.ts b/packages/ui/src/helpers/isValidComponent.ts new file mode 100644 index 00000000..9ff7e988 --- /dev/null +++ b/packages/ui/src/helpers/isValidComponent.ts @@ -0,0 +1,18 @@ +// TODO:Check Why comparision works but dissaper +import { Children, ElementType, ReactNode, isValidElement } from "react"; + +export const isValidComponent = ( + children: T, + targetChild: ElementType +) => { + const target: T[] = []; + + Children.forEach(children, (item) => { + if (isValidElement(item) && item.type === targetChild) { + target.push(item as T); + } + return null; + }); + + return target ?? undefined; +}; diff --git a/packages/ui/src/helpers/variants.ts b/packages/ui/src/helpers/variants.ts new file mode 100644 index 00000000..58464040 --- /dev/null +++ b/packages/ui/src/helpers/variants.ts @@ -0,0 +1,11 @@ +export const placements = [ + "center", + "center left", + "center right", + "top center", + "top left", + "top right", + "bottom center", + "bottom left", + "bottom right", +] as const; diff --git a/packages/ui/src/icons/activity.tsx b/packages/ui/src/icons/activity.tsx new file mode 100644 index 00000000..e49f485c --- /dev/null +++ b/packages/ui/src/icons/activity.tsx @@ -0,0 +1,21 @@ +import { ComponentProps } from "react"; + +export function Activity(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/ask.tsx b/packages/ui/src/icons/ask.tsx new file mode 100644 index 00000000..34ad8d52 --- /dev/null +++ b/packages/ui/src/icons/ask.tsx @@ -0,0 +1,19 @@ +import { ComponentProps } from "react"; + +export function Ask(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/askAndBid.tsx b/packages/ui/src/icons/askAndBid.tsx new file mode 100644 index 00000000..b6f5a809 --- /dev/null +++ b/packages/ui/src/icons/askAndBid.tsx @@ -0,0 +1,23 @@ +import { ComponentProps } from "react"; + +export function AskAndBid(props: ComponentProps<"svg">) { + return ( + + + + + + ); +} diff --git a/packages/ui/src/icons/avatar.tsx b/packages/ui/src/icons/avatar.tsx new file mode 100644 index 00000000..e79ce396 --- /dev/null +++ b/packages/ui/src/icons/avatar.tsx @@ -0,0 +1,102 @@ +import { ComponentProps } from "react"; + +export function Avatar(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/icons/balance.tsx b/packages/ui/src/icons/balance.tsx new file mode 100644 index 00000000..a82b2438 --- /dev/null +++ b/packages/ui/src/icons/balance.tsx @@ -0,0 +1,25 @@ +import { ComponentProps } from "react"; + +export function Balance(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/bid.tsx b/packages/ui/src/icons/bid.tsx new file mode 100644 index 00000000..90ce071f --- /dev/null +++ b/packages/ui/src/icons/bid.tsx @@ -0,0 +1,19 @@ +import { ComponentProps } from "react"; + +export function Bid(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/deposit.tsx b/packages/ui/src/icons/deposit.tsx new file mode 100644 index 00000000..1ff3b790 --- /dev/null +++ b/packages/ui/src/icons/deposit.tsx @@ -0,0 +1,15 @@ +import { ComponentProps } from "react"; + +export function Deposit(props: ComponentProps<"svg">) { + return ( + + + + ); +} diff --git a/packages/ui/src/icons/enkrypt.tsx b/packages/ui/src/icons/enkrypt.tsx new file mode 100644 index 00000000..b38070dd --- /dev/null +++ b/packages/ui/src/icons/enkrypt.tsx @@ -0,0 +1,33 @@ +import { ComponentProps } from "react"; + +export function ENKRYPT(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + ); +} diff --git a/packages/ui/src/icons/history.tsx b/packages/ui/src/icons/history.tsx new file mode 100644 index 00000000..a631fc57 --- /dev/null +++ b/packages/ui/src/icons/history.tsx @@ -0,0 +1,24 @@ +import { ComponentProps } from "react"; + +export function History(props: ComponentProps<"svg">) { + return ( + + + + + + + ); +} diff --git a/packages/ui/src/icons/index.ts b/packages/ui/src/icons/index.ts new file mode 100644 index 00000000..e076db0e --- /dev/null +++ b/packages/ui/src/icons/index.ts @@ -0,0 +1,17 @@ +export * from "./ask"; +export * from "./bid"; +export * from "./askAndBid"; +export * from "./range"; +export * from "./polkadotjs"; +export * from "./subWallet"; +export * from "./talisman"; +export * from "./wallet"; +export * from "./avatar"; +export * from "./deposit"; +export * from "./withdraw"; +export * from "./history"; +export * from "./transfer"; +export * from "./activity"; +export * from "./balance"; +export * from "./shutdown"; +export * from "./enkrypt"; diff --git a/packages/ui/src/icons/polkadotjs.tsx b/packages/ui/src/icons/polkadotjs.tsx new file mode 100644 index 00000000..1b564674 --- /dev/null +++ b/packages/ui/src/icons/polkadotjs.tsx @@ -0,0 +1,13 @@ +import { ComponentProps } from "react"; + +export function POLKADOTJS(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/range.tsx b/packages/ui/src/icons/range.tsx new file mode 100644 index 00000000..5b0ed94d --- /dev/null +++ b/packages/ui/src/icons/range.tsx @@ -0,0 +1,37 @@ +import { ComponentProps } from "react"; + +export function Range(props: ComponentProps<"svg">) { + return ( + + + + + + + + ); +} diff --git a/packages/ui/src/icons/shutdown.tsx b/packages/ui/src/icons/shutdown.tsx new file mode 100644 index 00000000..4da7be61 --- /dev/null +++ b/packages/ui/src/icons/shutdown.tsx @@ -0,0 +1,17 @@ +import { ComponentProps } from "react"; + +export function Shutdown(props: ComponentProps<"svg">) { + return ( + + + + ); +} diff --git a/packages/ui/src/icons/subWallet.tsx b/packages/ui/src/icons/subWallet.tsx new file mode 100644 index 00000000..8caa66af --- /dev/null +++ b/packages/ui/src/icons/subWallet.tsx @@ -0,0 +1,13 @@ +import { ComponentProps } from "react"; + +export function SUBWALLET(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/talisman.tsx b/packages/ui/src/icons/talisman.tsx new file mode 100644 index 00000000..70937247 --- /dev/null +++ b/packages/ui/src/icons/talisman.tsx @@ -0,0 +1,15 @@ +import { ComponentProps } from "react"; + +export function TALISMAN(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/transfer.tsx b/packages/ui/src/icons/transfer.tsx new file mode 100644 index 00000000..83834718 --- /dev/null +++ b/packages/ui/src/icons/transfer.tsx @@ -0,0 +1,24 @@ +import { ComponentProps } from "react"; + +export function Transfer(props: ComponentProps<"svg">) { + return ( + + + + + + + ); +} diff --git a/packages/ui/src/icons/wallet.tsx b/packages/ui/src/icons/wallet.tsx new file mode 100644 index 00000000..a4143fc5 --- /dev/null +++ b/packages/ui/src/icons/wallet.tsx @@ -0,0 +1,23 @@ +import { ComponentProps } from "react"; + +export function Wallet(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/src/icons/withdraw.tsx b/packages/ui/src/icons/withdraw.tsx new file mode 100644 index 00000000..ab9bf1f4 --- /dev/null +++ b/packages/ui/src/icons/withdraw.tsx @@ -0,0 +1,14 @@ +import { ComponentProps } from "react"; + +export function Withdraw(props: ComponentProps<"svg">) { + return ( + + + + ); +} diff --git a/packages/ui/src/illustrations/centralizedExchange.tsx b/packages/ui/src/illustrations/centralizedExchange.tsx new file mode 100644 index 00000000..a1084594 --- /dev/null +++ b/packages/ui/src/illustrations/centralizedExchange.tsx @@ -0,0 +1,73 @@ +import { ComponentProps } from "react"; + +export function CentralizedExchange(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/connectAccount.tsx b/packages/ui/src/illustrations/connectAccount.tsx new file mode 100644 index 00000000..b1d184e4 --- /dev/null +++ b/packages/ui/src/illustrations/connectAccount.tsx @@ -0,0 +1,48 @@ +import { ComponentProps } from "react"; + +export function ConnectAccount(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/decentralizedBridge.tsx b/packages/ui/src/illustrations/decentralizedBridge.tsx new file mode 100644 index 00000000..51ca6a85 --- /dev/null +++ b/packages/ui/src/illustrations/decentralizedBridge.tsx @@ -0,0 +1,37 @@ +import { ComponentProps } from "react"; + +export function DecentralizedBridge(props: ComponentProps<"svg">) { + return ( + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/happy.tsx b/packages/ui/src/illustrations/happy.tsx new file mode 100644 index 00000000..aeb6a577 --- /dev/null +++ b/packages/ui/src/illustrations/happy.tsx @@ -0,0 +1,211 @@ +import { ComponentProps } from "react"; + +export function Happy(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/index.ts b/packages/ui/src/illustrations/index.ts new file mode 100644 index 00000000..c4a332b6 --- /dev/null +++ b/packages/ui/src/illustrations/index.ts @@ -0,0 +1,9 @@ +export * from "./walletNotFound"; +export * from "./insufficientBalance"; +export * from "./centralizedExchange"; +export * from "./decentralizedBridge"; +export * from "./connectAccount"; +export * from "./noData"; +export * from "./noResultFound"; +export * from "./happy"; +export * from "./newUser"; diff --git a/packages/ui/src/illustrations/insufficientBalance.tsx b/packages/ui/src/illustrations/insufficientBalance.tsx new file mode 100644 index 00000000..aeff0347 --- /dev/null +++ b/packages/ui/src/illustrations/insufficientBalance.tsx @@ -0,0 +1,102 @@ +import { ComponentProps } from "react"; + +export function InsufficientBalance(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/newUser.tsx b/packages/ui/src/illustrations/newUser.tsx new file mode 100644 index 00000000..27b31dc1 --- /dev/null +++ b/packages/ui/src/illustrations/newUser.tsx @@ -0,0 +1,364 @@ +import { ComponentProps } from "react"; + +export function NewUser(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/noData.tsx b/packages/ui/src/illustrations/noData.tsx new file mode 100644 index 00000000..349dff35 --- /dev/null +++ b/packages/ui/src/illustrations/noData.tsx @@ -0,0 +1,163 @@ +import { ComponentProps } from "react"; + +export function NoData(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/noResultFound.tsx b/packages/ui/src/illustrations/noResultFound.tsx new file mode 100644 index 00000000..05c53a9d --- /dev/null +++ b/packages/ui/src/illustrations/noResultFound.tsx @@ -0,0 +1,112 @@ +import { ComponentProps } from "react"; + +export function NoResultFound(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/thea.tsx b/packages/ui/src/illustrations/thea.tsx new file mode 100644 index 00000000..8d6fda31 --- /dev/null +++ b/packages/ui/src/illustrations/thea.tsx @@ -0,0 +1,88 @@ +import { ComponentProps } from "react"; + +export function Thea(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/illustrations/walletNotFound.tsx b/packages/ui/src/illustrations/walletNotFound.tsx new file mode 100644 index 00000000..f2192778 --- /dev/null +++ b/packages/ui/src/illustrations/walletNotFound.tsx @@ -0,0 +1,90 @@ +import { ComponentProps } from "react"; + +export function WalletNotFound(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/astr.tsx b/packages/ui/src/tokens/astr.tsx new file mode 100755 index 00000000..b42b23e3 --- /dev/null +++ b/packages/ui/src/tokens/astr.tsx @@ -0,0 +1,459 @@ +import { ComponentProps } from "react"; + +export function ASTR(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/btc.tsx b/packages/ui/src/tokens/btc.tsx new file mode 100755 index 00000000..4f794df2 --- /dev/null +++ b/packages/ui/src/tokens/btc.tsx @@ -0,0 +1,19 @@ +import { ComponentProps } from "react"; + +export function BTC(props: ComponentProps<"svg">) { + return ( + + + + ); +} diff --git a/packages/ui/src/tokens/dot.tsx b/packages/ui/src/tokens/dot.tsx new file mode 100644 index 00000000..817a3949 --- /dev/null +++ b/packages/ui/src/tokens/dot.tsx @@ -0,0 +1,32 @@ +import { ComponentProps } from "react"; + +export function DOT(props: ComponentProps<"svg">) { + return ( + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/eqb.tsx b/packages/ui/src/tokens/eqb.tsx new file mode 100755 index 00000000..c9fe6120 --- /dev/null +++ b/packages/ui/src/tokens/eqb.tsx @@ -0,0 +1,279 @@ +import { ComponentProps } from "react"; + +export function EQB(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/eth.tsx b/packages/ui/src/tokens/eth.tsx new file mode 100755 index 00000000..76559c2a --- /dev/null +++ b/packages/ui/src/tokens/eth.tsx @@ -0,0 +1,37 @@ +import { ComponentProps } from "react"; + +export function ETH(props: ComponentProps<"svg">) { + return ( + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/glmr.tsx b/packages/ui/src/tokens/glmr.tsx new file mode 100644 index 00000000..9b8d58ee --- /dev/null +++ b/packages/ui/src/tokens/glmr.tsx @@ -0,0 +1,69 @@ +import { ComponentProps } from "react"; + +export function GLMR(props: ComponentProps<"svg">) { + return ( + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/ibtc.tsx b/packages/ui/src/tokens/ibtc.tsx new file mode 100755 index 00000000..678b78fc --- /dev/null +++ b/packages/ui/src/tokens/ibtc.tsx @@ -0,0 +1,41 @@ +import { ComponentProps } from "react"; + +export function IBTC(props: ComponentProps<"svg">) { + return ( + + {"IBTC"} + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/index.ts b/packages/ui/src/tokens/index.ts new file mode 100644 index 00000000..c8960116 --- /dev/null +++ b/packages/ui/src/tokens/index.ts @@ -0,0 +1,10 @@ +export * from "./btc"; +export * from "./dot"; +export * from "./eth"; +export * from "./pdex"; +export * from "./usdt"; +export * from "./ibtc"; +export * from "./unkn"; +export * from "./glmr"; +export * from "./astr"; +export * from "./eqb"; diff --git a/packages/ui/src/tokens/pdex.tsx b/packages/ui/src/tokens/pdex.tsx new file mode 100755 index 00000000..617fb4a1 --- /dev/null +++ b/packages/ui/src/tokens/pdex.tsx @@ -0,0 +1,38 @@ +import { ComponentProps } from "react"; + +export function PDEX(props: ComponentProps<"svg">) { + return ( + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/unkn.tsx b/packages/ui/src/tokens/unkn.tsx new file mode 100755 index 00000000..70e8029e --- /dev/null +++ b/packages/ui/src/tokens/unkn.tsx @@ -0,0 +1,31 @@ +import { ComponentProps } from "react"; + +export function UNKN(props: ComponentProps<"svg">) { + return ( + + + + + + + + + ); +} diff --git a/packages/ui/src/tokens/usdt.tsx b/packages/ui/src/tokens/usdt.tsx new file mode 100755 index 00000000..2baacc20 --- /dev/null +++ b/packages/ui/src/tokens/usdt.tsx @@ -0,0 +1,25 @@ +import { ComponentProps } from "react"; + +export function USDT(props: ComponentProps<"svg">) { + return ( + + + + + ); +} diff --git a/packages/ui/tailwind.config.ts b/packages/ui/tailwind.config.ts new file mode 100644 index 00000000..2327406b --- /dev/null +++ b/packages/ui/tailwind.config.ts @@ -0,0 +1,7 @@ +import { themeConfig } from "../../themeConfig"; + +export const config = { + ...themeConfig, + plugins: [require("tailwindcss-animate")], +}; +export default config; diff --git a/packages/ui/turbo/generators/config.ts b/packages/ui/turbo/generators/config.ts deleted file mode 100644 index f8dc6e87..00000000 --- a/packages/ui/turbo/generators/config.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { PlopTypes } from "@turbo/gen"; - -// Learn more about Turborepo Generators at https://turbo.build/repo/docs/core-concepts/monorepos/code-generation - -// eslint-disable-next-line import/no-default-export -- Turbo generators require default export -export default function generator(plop: PlopTypes.NodePlopAPI): void { - // A simple generator to add a new React component to the internal UI library - plop.setGenerator("react-component", { - description: "Adds a new react component", - prompts: [ - { - type: "input", - name: "name", - message: "What is the name of the component?", - }, - ], - actions: [ - { - type: "add", - path: "{{pascalCase name}}.tsx", - templateFile: "templates/component.hbs", - }, - { - type: "append", - path: "index.tsx", - pattern: /(?\/\/ component exports)/g, - template: 'export * from "./{{pascalCase name}}";', - }, - ], - }); -} diff --git a/packages/ui/turbo/generators/templates/component.hbs b/packages/ui/turbo/generators/templates/component.hbs deleted file mode 100644 index cf7b6369..00000000 --- a/packages/ui/turbo/generators/templates/component.hbs +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; - -interface Props { - children?: React.ReactNode; -} - -export const {{ pascalCase name }} = ({ children }: Props) => { - return ( -
-

{{ name }}

- {children} -
- ); -}; diff --git a/themeConfig.ts b/themeConfig.ts new file mode 100644 index 00000000..45bba9ac --- /dev/null +++ b/themeConfig.ts @@ -0,0 +1,119 @@ +export const commom = { + "primary-base": "#E6007A", + "primary-hover": "#EA268E", + "primary-pressed": "#9F005F", + "primary-ghost": "#EA268E22", + "primary-disabled": "#2B303A", + "secondary-base": "#252932", + "secondary-hover": "#373E4A", + "secondary-pressed": "#2B303A", + "danger-base": "#EB5757", + "danger-hover": "#EE6D6D", + "danger-pressed": "#A41313", + "success-base": "#02B671", + "success-hover": "#02CA7D", + "success-pressed": "#018D58", + "attention-base": "#F08205", + "attention-hover": "#FA8C0F", + "attention-pressed": "#DC7704", + "info-base": "#077EED", + "info-hover": "#4DA6F9", + "info-pressed": "#065FB2", +}; + +const commomBg = { + "level-0": "#0D0D10", + "level-1": "#131419", + "level-2": "#252932", + "level-3": "#1F2229", + "level-4": "#2B303A", +}; + +export const themeConfig = { + theme: { + extend: { + backgroundImage: { + "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", + "gradient-conic": + "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", + skeleton: `linear-gradient( + -90deg, + rgba(255, 255, 255, 0.1) 0%, + rgba(255, 255, 255, 0.12) 25%, + rgba(255, 255, 255, 0.20) 50%, + rgba(255, 255, 255, 0.14) 75%, + rgba(255, 255, 255, 0.1) 100% + )`, + }, + colors: { + ...commom, + textBase: "#FFFFFF", + primary: "#8B909A", + secondary: "#575A60", + placeholder: "#FFFFFF7F", + actionInput: "#FFFFFF33", + disabled: "#2B303A", + }, + backgroundColor: { + ...commom, + ...commomBg, + backgroundBase: "#06070A", + "overlay-1": "#0000007F", + "overlay-2": "##00000033", + "overlay-3": "##000000CC", + }, + backgroundSize: { + skeletonSize: "400% 400%", + }, + fill: { + ...commom, + ...commomBg, + }, + boxShadow: { + baseShadow: "0px 20px 23px rgba(0, 0, 0, 0.05)", + }, + borderColor: { + ...commom, + ...commomBg, + primary: "#1F2229", + secondary: "#2B303A", + }, + backdropBlur: { + primary: "5px", + secondary: "40px", + }, + maxWidth: { + "8xl": "90rem", + }, + fontSize: { + heading: "0.95rem", + md: "0.9rem", + base: "0.80rem", + }, + animation: { + infiniteHorizontalScroll: "30s linear infinite infiniteHorizontal ", + skeletonAnimation: + "skeletonPulse 2s cubic-bezier(0.2, 0.8, 0.2, 1) infinite", + }, + keyframes: { + infiniteHorizontal: { + "0%": { + transform: "translate3d(0px, 0px, 0px)", + }, + "100%": { + transform: "translate3d(-50%, 0px, 0px)", + }, + }, + skeletonPulse: { + "0%": { + backgroundPosition: "0% 0%", + }, + "100%": { + backgroundPosition: "-135% 0%", + }, + }, + }, + }, + }, + plugins: [], +};