├── .eslintrc.json ├── .gitattributes ├── .github └── pull_request_template.md ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .yarnrc.yml ├── CONTRIBUTING.md ├── README.md ├── app ├── (docs) │ ├── docs │ │ ├── [[...slug]] │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ └── not-found.tsx │ └── layout.tsx ├── (marketing) │ ├── [...slug] │ │ └── page.tsx │ ├── layout.tsx │ └── page.tsx ├── favicon.ico ├── layout.tsx ├── not-found.tsx ├── robots.ts └── sitemap.ts ├── assets ├── fonts │ ├── Inter-Bold.ttf │ └── Inter-SemiBold.ttf └── images │ └── og-bg-2.jpg ├── components.json ├── components ├── code-block-wrapper.tsx ├── coming-soon.tsx ├── command-menu.tsx ├── commit-list.tsx ├── component-preview.tsx ├── component-source.tsx ├── component-wrapper.tsx ├── contribute.tsx ├── copy-button.tsx ├── gradient-blur.tsx ├── icons.tsx ├── main-nav.tsx ├── mdx-components.tsx ├── mobile-nav.tsx ├── mode-toggle.tsx ├── pager.tsx ├── sections │ └── hero.tsx ├── sidebar-nav.tsx ├── site-footer.tsx ├── site-header.tsx ├── tech-stack.tsx ├── template-preview.tsx ├── theme-provider.tsx ├── toc.tsx └── ui │ ├── accordion.tsx │ ├── alert.tsx │ ├── avatar.tsx │ ├── badge.tsx │ ├── button.tsx │ ├── calendar.tsx │ ├── card.tsx │ ├── collapsible.tsx │ ├── command.tsx │ ├── dialog.tsx │ ├── dropdown-menu.tsx │ ├── form.tsx │ ├── hover-card.tsx │ ├── input.tsx │ ├── label.tsx │ ├── popover.tsx │ ├── scroll-area.tsx │ ├── separator.tsx │ ├── sheet.tsx │ ├── skeleton.tsx │ ├── sonner.tsx │ ├── switch.tsx │ ├── table.tsx │ ├── tabs.tsx │ ├── toast.tsx │ ├── toaster.tsx │ ├── tooltip.tsx │ └── use-toast.ts ├── config ├── docs.ts └── site.ts ├── content ├── docs │ ├── blinks │ │ └── blinks-starter.mdx │ ├── cli.mdx │ ├── components │ │ ├── ipfs-upload-demo.mdx │ │ ├── nft-card-demo.mdx │ │ ├── priority-modal.mdx │ │ ├── slippage-settings-modal.mdx │ │ ├── swap-ui-demo.mdx │ │ ├── token-dropdown-demo.mdx │ │ └── wallet-connect-demo.mdx │ ├── hooks │ │ └── index.mdx │ ├── index.mdx │ └── installation.mdx └── pages │ ├── home.mdx │ ├── privacy.mdx │ └── terms.mdx ├── contentlayer.config.ts ├── env.mjs ├── lib ├── events.ts ├── fonts.ts ├── github.ts ├── octokit.ts ├── rehype-component.ts ├── rehype-npm-command.ts ├── toc.ts ├── types.ts ├── use-mounted.ts └── utils.ts ├── middleware.ts ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public ├── logo.svg └── registry │ ├── .gitignore │ ├── connect-wallet │ └── more-wallets.svg │ └── nft │ ├── nft-sol.svg │ └── nft.svg ├── registry ├── components │ ├── example │ │ ├── blinks-demo.tsx │ │ ├── ipfs-upload-demo.tsx │ │ ├── nft-card-demo.tsx │ │ ├── priority-modal-demo.tsx │ │ ├── slippage-settings-demo.tsx │ │ ├── swap-ui-demo.tsx │ │ ├── token-dropdown-demo.tsx │ │ └── wallet-connect-demo.tsx │ └── solui │ │ ├── blinks │ │ ├── actions.ts │ │ └── blinks.ts │ │ ├── ipfs-upload.tsx │ │ ├── nft-card.tsx │ │ ├── priority-modal.tsx │ │ ├── slippage-settings-modal.tsx │ │ ├── swap-ui.tsx │ │ ├── token-dropdown.tsx │ │ └── wallet-connect.tsx ├── index.tsx └── schema.ts ├── scripts └── build-registry.ts ├── styles ├── globals.css └── mdx.css ├── tailwind.config.ts ├── tsconfig.json ├── tsconfig.scripts.json ├── turbo.json └── types ├── index.d.ts ├── next-auth.d.ts └── unist.ts /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/eslintrc", 3 | "root": true, 4 | "extends": [ 5 | "next/core-web-vitals", 6 | "prettier", 7 | "plugin:@next/next/recommended", 8 | "plugin:tailwindcss/recommended" 9 | ], 10 | "plugins": ["tailwindcss"], 11 | "rules": { 12 | "tailwindcss/no-contradicting-classname":"off", 13 | "react/no-unescaped-entities": "off", 14 | "@next/next/no-page-custom-font": "off", 15 | "@next/next/no-html-link-for-pages": "off", 16 | "tailwindcss/no-custom-classname": "off", 17 | "tailwindcss/classnames-order": "off", 18 | "no-multiple-empty-lines": [ 19 | "error", 20 | { 21 | "max": 1 22 | } 23 | ], 24 | "semi": "error", 25 | "no-var": "error" 26 | // "react/display-name": [false, { 27 | // "ignoreTranspilerName": false, "checkContextObjects": false 28 | // }] 29 | }, 30 | "settings": { 31 | "tailwindcss": { 32 | "callees": ["cn", "cva"], 33 | "config": "tailwind.config.ts" 34 | }, 35 | "next": { 36 | "rootDir": ["app/*/"] 37 | } 38 | }, 39 | "overrides": [ 40 | { 41 | "files": ["*.ts", "*.tsx"], 42 | "parser": "@typescript-eslint/parser" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### PR Fixes: 2 | 3 | - 1 4 | - 2 5 | 6 | Fix #[Issue Number if there] 7 | 8 | ### Checklist before requesting a review 9 | 10 | - [ ] I have performed a self-review of my code 11 | - [ ] I assure there is no similar/duplicate pull request regarding same issue 12 | 13 | ### Screenshots or Videos (if applicable) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # IDE Files 23 | .idea 24 | 25 | # debug 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | 30 | # local env files 31 | .env* 32 | .env*.local 33 | !.env.example 34 | 35 | # vercel 36 | .vercel 37 | 38 | # typescript 39 | *.tsbuildinfo 40 | next-env.d.ts 41 | 42 | .contentlayer 43 | .react-email 44 | .turbo 45 | 46 | .husky 47 | .commitlintrc.json -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | yarn.lock 2 | node_modules 3 | .next 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "semi": true, 4 | "trailingComma": "all", 5 | "printWidth": 80, 6 | "tabWidth": 2, 7 | "endOfLine": "lf", 8 | "singleQuote": false, 9 | "importOrder": [ 10 | "^(react/(.*)$)|^(react$)", 11 | "^(next/(.*)$)|^(next$)", 12 | "", 13 | "", 14 | "^types$", 15 | "^@/types/(.*)$", 16 | "^@/config/(.*)$", 17 | "^@/lib/(.*)$", 18 | "^@/hooks/(.*)$", 19 | "^@/components/ui/(.*)$", 20 | "^@/components/(.*)$", 21 | "^@/registry/(.*)$", 22 | "^@/styles/(.*)$", 23 | "^@/app/(.*)$", 24 | "", 25 | "^[./]" 26 | ], 27 | "plugins": [ 28 | "prettier-plugin-tailwindcss", 29 | "@ianvs/prettier-plugin-sort-imports" 30 | ] 31 | } -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | os: ["arm64", "x64"] 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to SolUI 2 | 3 | Thank you for your interest in contributing to SolUI! We appreciate your support and look forward to your contributions. This guide will help you understand the directory structure and provide detailed instructions on how to add a new component to SolUI. 4 | 5 | **You only need to change 5 files to add a new component or effect** and it only takes around 10 minutes of work! 6 | 7 | Once done, open a pull request from your forked repo to the main repo [here](https://github.com/Not-Sarthak/sol-ui/compare). 8 | 9 | ## Getting Started 10 | 11 | ### Fork and Clone the Repository 12 | 13 | 1. **Fork this repository** 14 | Click [here](https://github.com/Not-Sarthak/sol-ui/fork) to fork the repository. 15 | 16 | 2. **Clone your forked repository to your local machine** 17 | 18 | ```bash 19 | git clone https://github.com//sol-ui.git 20 | ``` 21 | 22 | 3. **Navigate to the project directory** 23 | 24 | ```bash 25 | cd sol-ui 26 | ``` 27 | 28 | 4. **Create a new branch for your changes** 29 | 30 | ```bash 31 | git checkout -b my-new-branch 32 | ``` 33 | 34 | 5. **Install dependencies** 35 | 36 | ```bash 37 | pnpm i 38 | ``` 39 | 40 | 6. **Create a `.env.local` file** 41 | 42 | ```bash 43 | touch .env.local && echo "NEXT_PUBLIC_APP_URL=http://localhost:3000" > .env.local 44 | ``` 45 | 46 | 7. **Run the project** 47 | ```bash 48 | pnpm dev 49 | ``` 50 | 51 | ## Adding a New Component 52 | 53 | To add a new component to SolUI, you will need to modify several files. Follow these steps: 54 | 55 | ### 1. Create Component 56 | 57 | Create the main component in `registry/components/solui/example-component.tsx` 58 | 59 | ```typescript 60 | import React from 'react' 61 | 62 | export default function ExampleComponent() { 63 | return ( 64 |
65 | OPOS. 66 |
67 | ) 68 | } 69 | ``` 70 | 71 | ### 2. Create Component Demo 72 | 73 | Provide a basic example to showcase your component in `registry/components/example/example-component-demo.tsx` 74 | 75 | ```typescript 76 | import ExampleComponent from '@/registry/components/solui/example-component' 77 | 78 | export default function ExampleComponentDemo() { 79 | return ( 80 |
81 | 82 |
83 | ) 84 | } 85 | ``` 86 | 87 | ### 3. Update Sidebar 88 | 89 | Add your component to the sidebar in `config/docs.ts` 90 | 91 | ```typescript 92 | { 93 | title: "Example Component", 94 | href: `/docs/components/example-component`, 95 | items: [], 96 | label: "New", 97 | } 98 | ``` 99 | 100 | ### 4. Create docs 101 | 102 | Create an MDX file for documenting your component in `content/docs/components/example-component.mdx` 103 | 104 | ````md 105 | --- 106 | title: Example Component 107 | date: 2024-09-02 108 | description: Example component for Sol UI 109 | author: sarthak 110 | published: true 111 | --- 112 | 113 | 114 | 115 | ## Installation 116 | 117 | 118 | 119 | 120 | CLI 121 | Manual 122 | 123 | 124 | 125 | ```bash 126 | npx solui-cli add example-component 127 | ``` 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | Copy and paste the following code into your project. 136 | 137 | 138 | 139 | Update the import paths to match your project setup. 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | ## Props 152 | 153 | | Prop | Type | Description | Default | 154 | | ----- | ------ | -------------------------- | ------- | 155 | | color | String | The color of the component | "blue" | 156 | ```` 157 | 158 | ### 5. Update Registry 159 | 160 | Export your component and example in the registry in `registry/index.tsx` 161 | 162 | ```typescript 163 | const ui: Registry = { 164 | "example-component": { 165 | name: "example-component", 166 | type: "components:ui", 167 | files: ["registry/components/solui/example-component.tsx"], 168 | }, 169 | }; 170 | 171 | const example: Registry = { 172 | "example-component-demo": { 173 | name: "example-component", 174 | type: "components:example", 175 | files: ["registry/components/example/example-component-demo.tsx"], 176 | component: React.lazy( 177 | () => import("@/registry/components/example/example-component-demo"), 178 | ), 179 | }, 180 | }; 181 | ``` 182 | ### 6. Pull Request 183 | 184 | Provide a clear and concise title for your PR. 185 | 186 | ### PR Fixes: 187 | - 1 188 | - 2 189 | 190 | Fix #[Issue Number if there] 191 | 192 | ### Checklist before requesting a review: 193 | - [ ] I have performed a self-review of my code. 194 | - [ ] I assure there is no similar/duplicate pull request regarding the same issue. 195 | 196 | ### Attach Screenshots or Videos (if applicable) 197 | 198 | ## Ask for Help 199 | 200 | For any help or questions, please open a new GitHub issue. 201 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solana UI Component Library 2 | 3 | **Build Solana Websites, at Warp Speed** 4 | 5 | ![image](https://github.com/user-attachments/assets/05dc4ff0-1054-4c70-bbeb-f596eea7985e) 6 | 7 | 8 | [**Try it out**](https://sol-ui.vercel.app/) 👀 9 | 10 | ## Table of Contents 11 | 12 | 1. [Using the Components](#using-the-components) 13 | 2. [Contributing](#contributing) 14 | 3. [Upcoming Features](#upcoming-features) 15 | 16 | ## Using the Components 17 | 18 | 1. **Search for the component** on the [website](https://sol-ui.vercel.app/). 19 | 2. **Select the component code** under the manual tab. 20 | 3. **Update the import statements**, and voilà 🎉, you are ready to use the components! 21 | 22 | ## Contributing 23 | 24 | We welcome contributions! Please see [CONTRIBUTING.md](Contributing.md) for guidelines on how to get started. 25 | 26 | ## Upcoming Features 27 | 28 | We're always looking to improve! Here are some features we're considering adding: 29 | 30 | 1. **npm Package**: Easily install the component library via npm. 31 | 2. **Solana Icon Set**: Icons for tokens, protocols, wallets, etc. 32 | 3. **Abstracted Hooks**: Reusable hooks for common Solana interactions. 33 | 34 | ## License 35 | 36 | Licensed under the MIT license. 37 | 38 | --- 39 | Brought to you by [sarthak](https://x.com/0xSarthak13). 40 | -------------------------------------------------------------------------------- /app/(docs)/docs/[[...slug]]/page.tsx: -------------------------------------------------------------------------------- 1 | import { siteConfig } from "@/config/site"; 2 | import { getTableOfContents } from "@/lib/toc"; 3 | import { absoluteUrl, cn } from "@/lib/utils"; 4 | import { badgeVariants } from "@/components/ui/badge"; 5 | import { ScrollArea } from "@/components/ui/scroll-area"; 6 | import { Mdx } from "@/components/mdx-components"; 7 | import { DocPager } from "@/components/pager"; 8 | 9 | import "@/styles/mdx.css"; 10 | 11 | import type { Metadata } from "next"; 12 | import Link from "next/link"; 13 | import { notFound } from "next/navigation"; 14 | import { ChevronRightIcon, ExternalLinkIcon } from "@radix-ui/react-icons"; 15 | import { allDocs } from "contentlayer/generated"; 16 | 17 | import { Contribute } from "@/components/contribute"; 18 | import { TableOfContents } from "@/components/toc"; 19 | 20 | interface DocPageProps { 21 | params: { 22 | slug: string[]; 23 | }; 24 | } 25 | 26 | async function getDocFromParams({ params }: DocPageProps) { 27 | const slug = params.slug?.join("/") || ""; 28 | const doc = allDocs.find((doc) => doc.slugAsParams === slug); 29 | 30 | if (!doc) { 31 | return null; 32 | } 33 | 34 | return doc; 35 | } 36 | 37 | export async function generateMetadata({ 38 | params, 39 | }: DocPageProps): Promise { 40 | const doc = await getDocFromParams({ params }); 41 | 42 | if (!doc) { 43 | return {}; 44 | } 45 | 46 | return { 47 | title: `${doc.title} | Sol UI`, 48 | description: doc.description, 49 | openGraph: { 50 | title: doc.title, 51 | description: doc.description, 52 | type: "article", 53 | url: absoluteUrl(doc.slug), 54 | images: [ 55 | { 56 | url: doc.image, 57 | width: 1200, 58 | height: 630, 59 | alt: siteConfig.name, 60 | }, 61 | ], 62 | }, 63 | twitter: { 64 | card: "summary_large_image", 65 | title: doc.title, 66 | description: doc.description, 67 | images: [doc.image], 68 | creator: "@sarthak", 69 | }, 70 | }; 71 | } 72 | 73 | export async function generateStaticParams(): Promise< 74 | DocPageProps["params"][] 75 | > { 76 | return allDocs.map((doc) => ({ 77 | slug: doc.slugAsParams.split("/"), 78 | })); 79 | } 80 | 81 | export default async function DocPage({ params }: DocPageProps) { 82 | const doc = await getDocFromParams({ params }); 83 | 84 | if (!doc || !doc.published) { 85 | notFound(); 86 | } 87 | 88 | const toc = await getTableOfContents(doc.body.raw); 89 | 90 | return ( 91 |
96 |
97 |
98 |
Docs
99 | 100 |
{doc.title}
101 |
102 |
103 |

104 | {doc.title} 105 |

106 | {doc.description && ( 107 |

108 | {doc.description} 109 |

110 | )} 111 |
112 | {doc.links ? ( 113 |
114 | {doc.links?.doc && ( 115 | 121 | Docs 122 | 123 | 124 | )} 125 | {doc.links?.api && ( 126 | 132 | API Reference 133 | 134 | 135 | )} 136 |
137 | ) : null} 138 |
139 | 140 |
141 | 142 |
143 | {doc.toc && ( 144 |
145 |
146 | 147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | )} 155 | 156 |