├── .changeset
├── README.md
└── config.json
├── .eslintrc.js
├── .gitignore
├── .npmrc
├── README.md
├── apps
└── docs
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── .prettierignore
│ ├── README.md
│ ├── components
│ ├── Code.tsx
│ ├── ColorTables.tsx
│ ├── ComponentsList.tsx
│ ├── Introduction copy.tsx
│ ├── LandingPage
│ │ ├── ButtonExample.tsx
│ │ ├── LandingPage.tsx
│ │ ├── ToDoExample.tsx
│ │ └── index.tsx
│ ├── Logo.tsx
│ ├── ThemeGenerator
│ │ ├── ColorSelector.tsx
│ │ ├── ColorSelectorWithName.tsx
│ │ ├── Preview
│ │ │ ├── AlertDialogExample.tsx
│ │ │ ├── Alerts.tsx
│ │ │ ├── Buttons.tsx
│ │ │ ├── Card.tsx
│ │ │ ├── DropdownExample.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── Landing.tsx
│ │ │ ├── Preview.tsx
│ │ │ ├── SelectExample.tsx
│ │ │ └── index.ts
│ │ ├── ThemeGenerator.tsx
│ │ └── index.ts
│ └── demo
│ │ ├── ButtonDemo.tsx
│ │ ├── CollapsibleDemo.tsx
│ │ ├── ContextMenuDemo.tsx
│ │ └── NavigationMenuDemo.tsx
│ ├── cypress.config.ts
│ ├── cypress
│ ├── e2e
│ │ └── spec.cy.ts
│ └── fixtures
│ │ └── example.json
│ ├── next.config.js
│ ├── package.json
│ ├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── _meta.json
│ ├── api
│ │ └── hello.ts
│ ├── docs
│ │ ├── FAQ.mdx
│ │ ├── _meta.json
│ │ ├── components
│ │ │ ├── Accordion.mdx
│ │ │ ├── AlertDialog.mdx
│ │ │ ├── AspectRatio.mdx
│ │ │ ├── Avatar.mdx
│ │ │ ├── Button.mdx
│ │ │ ├── Checkbox.mdx
│ │ │ ├── Collapsible.mdx
│ │ │ ├── ContextMenu.mdx
│ │ │ ├── Copy.mdx
│ │ │ ├── Dialog.mdx
│ │ │ ├── DropdownMenu.mdx
│ │ │ ├── Input.mdx
│ │ │ ├── Label.mdx
│ │ │ ├── Menubar.mdx
│ │ │ ├── NavigationMenu.mdx
│ │ │ ├── Popover.mdx
│ │ │ ├── Progress.mdx
│ │ │ ├── RadioGroup.mdx
│ │ │ ├── Select.mdx
│ │ │ ├── Switch.mdx
│ │ │ ├── Tabs.mdx
│ │ │ ├── TextArea.mdx
│ │ │ ├── Toggle.mdx
│ │ │ ├── Tooltip.mdx
│ │ │ ├── _meta.json
│ │ │ └── index.mdx
│ │ ├── credits.mdx
│ │ ├── install.md
│ │ ├── introduction.mdx
│ │ ├── key-concepts
│ │ │ ├── _meta.json
│ │ │ ├── accessibility.mdx
│ │ │ ├── colors.mdx
│ │ │ ├── customization.mdx
│ │ │ └── themeing.mdx
│ │ └── theme.mdx
│ └── index.mdx
│ ├── postcss.config.js
│ ├── public
│ ├── 100-900-example.png
│ ├── avatar_sally.png
│ ├── avatar_steve.png
│ ├── bonapp_color_study.jpeg
│ ├── chimera-og-image-old.png
│ ├── chimera-og-image.png
│ ├── chimera-theme-gen-image.png
│ ├── content-example.png
│ ├── favicon.ico
│ ├── logo.svg
│ ├── next.svg
│ ├── on-example.jpeg
│ ├── prominence-example.png
│ ├── subtle-example.png
│ ├── thirteen.svg
│ ├── vercel.svg
│ └── vercel_color_study.png
│ ├── styles
│ └── globals.css
│ ├── tailwind.config.js
│ ├── theme.config.jsx
│ ├── tsconfig.json
│ └── utils
│ ├── colors.tsx
│ ├── themestyles.tsx
│ ├── updateColors.js
│ └── utils.tsx
├── package.json
├── packages
├── components
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── docgen.js
│ ├── package.json
│ ├── postcss.config.js
│ ├── src
│ │ ├── Accordion.tsx
│ │ ├── AlertDialog.tsx
│ │ ├── AspectRatio.tsx
│ │ ├── Avatar.tsx
│ │ ├── Button.tsx
│ │ ├── Checkbox.tsx
│ │ ├── Collapsible.tsx
│ │ ├── ContextMenu.tsx
│ │ ├── Copy.tsx
│ │ ├── Dialog.tsx
│ │ ├── DropdownMenu.tsx
│ │ ├── HoverCard.tsx
│ │ ├── Input.tsx
│ │ ├── Label.tsx
│ │ ├── Menubar.tsx
│ │ ├── NavigationMenu.tsx
│ │ ├── Popover.tsx
│ │ ├── Progress.tsx
│ │ ├── RadioGroup.tsx
│ │ ├── ScrollArea.tsx
│ │ ├── Select.tsx
│ │ ├── Separator.tsx
│ │ ├── Showcase.tsx
│ │ ├── Slider.tsx
│ │ ├── Switch.tsx
│ │ ├── Tabs.tsx
│ │ ├── Test.tsx
│ │ ├── TextArea.tsx
│ │ ├── ThemePicker.tsx
│ │ ├── Toggle.tsx
│ │ ├── Tooltip.tsx
│ │ └── index.tsx
│ ├── styles.css
│ ├── tailwind.config.js
│ ├── test.json
│ ├── tsconfig.json
│ ├── tsdocSync.js
│ ├── tsup.config.ts
│ └── utils
│ │ └── index.tsx
├── eslint-config-chimera
│ ├── index.js
│ └── package.json
├── tailwind-config
│ ├── package.json
│ ├── postcss.config.js
│ └── tailwind.config.js
├── tsconfig
│ ├── base.json
│ ├── nextjs.json
│ ├── node16.json
│ ├── package.json
│ └── react-library.json
└── tw-plugin
│ ├── index.js
│ └── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── turbo.json
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json",
3 | "changelog": "@changesets/cli/changelog",
4 | "commit": false,
5 | "fixed": [],
6 | "linked": [],
7 | "access": "public",
8 | "baseBranch": "main",
9 | "updateInternalDependencies": "patch",
10 | "ignore": ["docs"]
11 | }
12 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | // This tells ESLint to load the config from the package `eslint-config-chimera`
4 | extends: ["chimera"],
5 | settings: {
6 | next: {
7 | rootDir: ["apps/*/"],
8 | },
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | .turbo
4 | *.log
5 | .next
6 | dist
7 | dist-ssr
8 | *.local
9 | .env
10 | .cache
11 | server/dist
12 | public/dist
13 | storybook-static/
14 | apps/docs/cypress/videos/
15 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers = true
2 | node-linker=hoisted
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
16 |
59 |
60 |
61 |
Chimera UI
62 |
63 |
64 | Beautiful, accessible, and fully customizable with Tailwind.
65 |
66 | ## Features
67 |
68 | - Fully accessible components, with Radix Primitives under the hood.
69 | - Includes additional components beyond Radix, such as Button and Input.
70 | - Components come pre-styled. Styles can be easily overwritten with Tailwind (Chimera uses tw-merge under the hood).
71 | - Semantic color system built in. No more guessing what color to use, just use the same semantic color names across all your projects.
72 | - Theme generator that quickly generates CSS themes for you.
73 | - Tailwind plugin to keep tailwind.config.js nice and clean.
74 | - Tree-shakeable. Use named imports without worrying about bundle-size!
75 |
76 | ## Installation
77 |
78 | See official docs for more information
79 |
80 | 1. `npm install @chimera-ui/components @chimera-ui/tw-plugin`
81 | 2. Modify your `tailwind.config.js` to include:
82 |
83 | - `"./node_modules/@chimera-ui/components/dist/**/*.{js,mjs}",` in the `content` array
84 | - `require("@chimera-ui/tw-plugin")` in the `plugins` array
85 | - ```js
86 | module.exports = {
87 | content: [
88 | "./pages/**/*.{js,ts,jsx,tsx,md,mdx}",
89 | "./components/**/*.{js,ts,jsx,tsx}",
90 | "./node_modules/@chimera-ui/components/dist/**/*.{js,mjs}", // This line is important! If you don't include this, Chimera's styles will be purged
91 | ,
92 | ],
93 | plugins: [
94 | require("@chimera-ui/tw-plugin"), // This is important! This extends your tailwind theme to consume the CSS variables.
95 | ],
96 | };
97 | ```
98 |
99 | 3. Use the theme generator to generate CSS themes. Add the CSS variables to your global css file.
100 |
101 | ## Repository
102 |
103 | `npm run build` will trigger `prebuild`. In `prebuild`, @chimera-ui/components will run tsdocSync.js, which syncs the classNames from each component to a tsdoc comment above it.
104 |
--------------------------------------------------------------------------------
/apps/docs/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["eslint-config-chimera"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/docs/.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 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/apps/docs/.prettierignore:
--------------------------------------------------------------------------------
1 | /components/LandingPage
--------------------------------------------------------------------------------
/apps/docs/README.md:
--------------------------------------------------------------------------------
1 | # To be completed
2 |
--------------------------------------------------------------------------------
/apps/docs/components/Code.tsx:
--------------------------------------------------------------------------------
1 | import { Button, Copy } from "@chimera-ui/components";
2 | import React from "react";
3 |
4 | export const Code = ({ children }: { children: string }) => {
5 | const [copied, setCopied] = React.useState(false);
6 |
7 | return (
8 |
13 |
17 | {children}
18 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/apps/docs/components/ColorTables.tsx:
--------------------------------------------------------------------------------
1 | import { ThemePicker } from "@chimera-ui/components";
2 | import { ColorType, ColorsType } from "@/utils/colors";
3 | import { colors } from "@/utils/colors";
4 |
5 | const ColorTableItem = ({ color }: { color: ColorType }) => {
6 | return (
7 |
8 |
13 |
14 |
15 |
{color.name}
16 |
{color.usage}
17 |
18 |
19 |
{color.description}
20 |
{color.cssVariable}
21 |
22 | );
23 | };
24 |
25 | export const ColorTable = ({ colorPrefix }: { colorPrefix: string }) => {
26 | return (
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Name & Usage
36 |
Description
37 |
CSS Variable
38 |
39 |
40 |
41 | {Object.keys(colors).map((colorName) => {
42 | if (colorName.startsWith(colorPrefix)) {
43 | return (
44 |
48 | );
49 | }
50 | })}
51 |
52 |
53 | );
54 | };
55 |
--------------------------------------------------------------------------------
/apps/docs/components/ComponentsList.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 | import ComponentsMetaJson from "../pages/docs/components/_meta.json";
3 |
4 | export const ComponentsList = () => {
5 | return (
6 |
7 | {Object.entries(ComponentsMetaJson).map((componentEntry) => {
8 | const [fileName, componentName] = componentEntry;
9 | if (fileName === "index") return;
10 | return (
11 |
12 |
13 | {componentName as string}
14 |
15 |
16 | );
17 | })}
18 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/apps/docs/components/LandingPage/ButtonExample.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@chimera-ui/components";
2 |
3 | export const ButtonExample = () => {
4 | return (
5 |
6 | Boop
7 |
8 | );
9 | };
10 |
--------------------------------------------------------------------------------
/apps/docs/components/LandingPage/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./LandingPage";
2 |
--------------------------------------------------------------------------------
/apps/docs/components/Logo.tsx:
--------------------------------------------------------------------------------
1 | export const Logo = () => {
2 | return (
3 |
4 |
5 |
12 |
17 |
60 |
61 |
62 |
63 |
Chimera UI
64 |
65 | );
66 | };
67 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/ColorSelector.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { ColorType } from "@/utils/colors";
3 | import { Popover } from "@chimera-ui/components";
4 | import clsx from "clsx";
5 | import { ChromePicker } from "react-color";
6 | export const ColorSelector = ({
7 | color,
8 | handleColorChange,
9 | }: {
10 | color: ColorType;
11 | handleColorChange: (color: string, value: string) => void;
12 | }) => {
13 | const handleChange = (pickerValue: any) => {
14 | handleColorChange(color.name, pickerValue.hex);
15 | };
16 |
17 | return (
18 |
19 |
20 |
21 |
27 |
35 |
{color.name}
36 |
{color.value}
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | {color.name}
47 |
48 |
49 | {" "}
50 | {color.description}
51 |
52 |
53 |
54 |
59 |
60 |
61 |
62 |
63 |
64 | );
65 | };
66 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/ColorSelectorWithName.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { ColorType } from "@/utils/colors";
3 | import { Popover } from "@chimera-ui/components";
4 | import clsx from "clsx";
5 | import { ChromePicker } from "react-color";
6 | export const ColorSelector = ({
7 | color,
8 | handleColorChange,
9 | }: {
10 | color: ColorType;
11 | handleColorChange: (color: string, value: string) => void;
12 | }) => {
13 | const handleChange = (pickerValue: any) => {
14 | handleColorChange(color.name, pickerValue.hex);
15 | };
16 |
17 | return (
18 |
19 |
20 |
21 |
22 |
28 | {color.displayName}
29 |
30 |
38 |
{color.name}
39 |
{color.value}
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | {color.name}
50 |
51 |
52 | {" "}
53 | {color.description}
54 |
55 |
56 |
57 |
62 |
63 |
64 |
65 |
66 |
67 | );
68 | };
69 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/AlertDialogExample.tsx:
--------------------------------------------------------------------------------
1 | import { AlertDialog, Button } from "@chimera-ui/components";
2 |
3 | export const AlertDialogExample = () => {
4 | return (
5 |
6 |
7 | Delete Account
8 |
9 |
10 |
11 |
12 |
13 | Are you absolutely sure?
14 |
15 |
16 | This action cannot be undone. This will permanently delete your
17 | account and remove your data from our servers.
18 |
19 |
20 |
21 | Cancel
22 |
23 |
24 | Yes, delete account
25 |
26 |
27 |
28 |
29 |
30 | );
31 | };
32 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/Alerts.tsx:
--------------------------------------------------------------------------------
1 | export const Alerts = () => {
2 | return (
3 |
4 |
5 | success alert
6 |
7 |
8 | success alert inverse
9 |
10 |
11 | danger alert
12 |
13 |
14 | danger alert inverse
15 |
16 |
17 | warning alert
18 |
19 |
20 | warning alert inverse
21 |
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/Buttons.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@chimera-ui/components";
2 |
3 | export const Buttons = () => {
4 | return (
5 |
6 | Primary
7 | Subtle
8 | Outline
9 | Secondary
10 | Secondary Subtle
11 | Secondary Outline
12 | Gradient
13 | Destructive
14 | Success
15 | Info
16 | Warning
17 |
18 | );
19 | };
20 |
21 | // default: "bg-primary text-primary-content hover:bg-primary-focus",
22 | // secondary:
23 | // "bg-secondary text-secondary-content hover:bg-secondary-focus",
24 | // "secondary-outline":
25 | // "bg-transparent border border-secondary text-secondary hover:bg-secondary-focus hover:text-secondary-content",
26 | // destructive: "bg-danger text-danger-content hover:bg-danger-focus",
27 | // outline: "bg-transparent border border-primary-200 hover:bg-base-2",
28 | // subtle:
29 | // "bg-primary-subtle text-primary-subtle-content hover:bg-primary hover:text-primary-content",
30 | // ghost:
31 | // "bg-transparent hover:bg-base-2 data-[state=open]:bg-transparent ",
32 | // link: "bg-transparent underline-offset-4 hover:underline text-slate-900 hover:bg-transparent ",
33 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/Card.tsx:
--------------------------------------------------------------------------------
1 | export const Card = () => {
2 | return (
3 |
7 |
8 |
13 |
14 |
15 |
16 | {`A random blog post title (text-base-content)`}
17 |
18 |
{`Some description that you'd find for a blog post. This one is using text-base-content-2 to provide some contrast with the title.`}
19 |
20 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/DropdownExample.tsx:
--------------------------------------------------------------------------------
1 | import { HamburgerMenuIcon } from "@radix-ui/react-icons";
2 | import { Button, DropdownMenu } from "@chimera-ui/components";
3 | import {
4 | Cloud,
5 | CreditCard,
6 | Github,
7 | Keyboard,
8 | LifeBuoy,
9 | LogOut,
10 | Mail,
11 | MessageSquare,
12 | Plus,
13 | PlusCircle,
14 | Settings,
15 | User,
16 | UserPlus,
17 | Users,
18 | } from "lucide-react";
19 |
20 | export const DropDownExample = () => {
21 | return (
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | My Account
30 |
31 |
32 |
33 |
34 | Profile
35 | ⇧⌘P
36 |
37 |
38 |
39 | Billing
40 | ⌘B
41 |
42 |
43 |
44 | Settings
45 | ⌘S
46 |
47 |
48 |
49 | Keyboard shortcuts
50 | ⌘K
51 |
52 |
53 |
54 |
55 |
56 |
57 | Team
58 |
59 |
60 |
61 |
62 | Invite users
63 |
64 |
65 |
66 |
67 |
68 | Email
69 |
70 |
71 |
72 | Message
73 |
74 |
75 |
76 |
77 | More...
78 |
79 |
80 |
81 |
82 |
83 |
84 | New Team
85 | ⌘+T
86 |
87 |
88 |
89 |
90 |
91 | GitHub
92 |
93 |
94 |
95 | Support
96 |
97 |
98 |
99 | API
100 |
101 |
102 |
103 |
104 | Log out
105 | ⇧⌘Q
106 |
107 |
108 |
109 | );
110 | };
111 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/Header.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable @next/next/no-img-element */
2 |
3 | import { DropDownExample } from "./DropdownExample";
4 | import { Sprout } from "lucide-react";
5 | import { Input } from "@chimera-ui/components";
6 |
7 | export const Header = () => {
8 | return (
9 |
10 |
11 | logo
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/Landing.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@chimera-ui/components";
2 | export const Landing = () => {
3 | return (
4 |
5 |
6 | Scroll{" "}
7 |
8 | down
9 | {" "}
10 | to see more examples
11 |
12 |
13 | Secondary
14 | Primary
15 |
16 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/Preview.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable @next/next/no-img-element */
2 | import { Button } from "@chimera-ui/components";
3 | import { AlertDialogExample } from "./AlertDialogExample";
4 | import { Alerts } from "./Alerts";
5 | import { Buttons } from "./Buttons";
6 | import { Card } from "./Card";
7 | import { DropDownExample } from "./DropdownExample";
8 | import { Header } from "./Header";
9 | import { Landing } from "./Landing";
10 | import { SelectExample } from "./SelectExample";
11 |
12 | export const Preview = () => {
13 | return (
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Text Examples
27 |
28 |
29 | Title (text-base-content-2)
30 |
31 |
32 | 11/11/2040 (text-base-content-3)
33 |
34 |
35 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
36 | condimentum, nisl ut aliquam aliquet, nunc nisl aliquet nisl, nec
37 | tincidunt nisl nunc vel nunc. Sed condimentum, nisl ut aliquam
38 | aliquet, nunc nisl aliquam nisl, nec tincidunt nisl nunc vel nunc.
39 | (text-base-content).
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Overlays (Click them)
51 |
52 |
57 |
58 |
59 |
60 |
61 | Buttons
62 |
63 |
64 |
65 |
66 |
67 |
68 | Callouts
69 |
70 |
71 |
72 |
73 |
74 | );
75 | };
76 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/SelectExample.tsx:
--------------------------------------------------------------------------------
1 | import { Select } from "@chimera-ui/components";
2 |
3 | export const SelectExample = () => {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 | Fruits
12 | Apple
13 | Banana
14 | Blueberry
15 | Grapes
16 | Pineapple
17 |
18 |
19 |
20 | Vegetables
21 | Aubergine
22 | Broccoli
23 |
24 | Carrot
25 |
26 | Courgette
27 | Leek
28 |
29 |
30 |
31 | Meat
32 | Beef
33 | Chicken
34 | Lamb
35 | Pork
36 |
37 |
38 |
39 | );
40 | };
41 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/Preview/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./Preview";
2 |
--------------------------------------------------------------------------------
/apps/docs/components/ThemeGenerator/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./ThemeGenerator";
2 |
--------------------------------------------------------------------------------
/apps/docs/components/demo/ButtonDemo.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@chimera-ui/components";
2 |
3 | export const ButtonDemo = () => {
4 | return (
5 |
6 | Button
7 |
8 | );
9 | };
10 |
--------------------------------------------------------------------------------
/apps/docs/components/demo/CollapsibleDemo.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { RowSpacingIcon, Cross2Icon } from "@radix-ui/react-icons";
3 | import { Button, Showcase, Collapsible } from "@chimera-ui/components";
4 |
5 | export const CollapsibleDemo = () => {
6 | const [open, setOpen] = React.useState(false);
7 | return (
8 |
13 |
20 | @peduarte starred 3 repositories
21 |
22 |
23 | {open ? : }
24 |
25 |
26 |
27 |
28 |
29 | @radix-ui/primitives
30 |
31 |
32 |
33 |
34 | @radix-ui/colors
35 |
36 |
37 | @stitches/react
38 |
39 |
40 |
41 | );
42 | };
43 |
44 | export default CollapsibleDemo;
45 |
--------------------------------------------------------------------------------
/apps/docs/components/demo/ContextMenuDemo.tsx:
--------------------------------------------------------------------------------
1 | import { Button, ContextMenu } from "@chimera-ui/components";
2 | import { useState } from "react";
3 | import {
4 | CheckIcon,
5 | ChevronRightIcon,
6 | DotFilledIcon,
7 | } from "@radix-ui/react-icons";
8 |
9 | export function ContextMenuDemo() {
10 | const [bookmarksChecked, setBookmarksChecked] = useState(true);
11 | const [urlsChecked, setUrlsChecked] = useState(false);
12 | const [person, setPerson] = useState("pedro");
13 |
14 | return (
15 |
16 |
17 | Right click here
18 |
19 |
20 |
21 | Back
22 | ⌘[
23 |
24 |
25 | Forward
26 | ⌘]
27 |
28 |
29 | Reload
30 | ⌘R
31 |
32 |
33 | More Tools
34 |
35 |
36 | Save Page As...
37 | ⇧⌘S
38 |
39 | Create Shortcut...
40 | Name Window...
41 |
42 | Developer Tools
43 |
44 |
45 |
46 |
47 | Show Bookmarks Bar
48 | ⌘⇧B
49 |
50 | Show Full URLs
51 |
52 |
53 | People
54 |
55 |
56 | Pedro Duarte
57 |
58 | Colm Tuite
59 |
60 |
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/apps/docs/components/demo/NavigationMenuDemo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import Link from "next/link";
3 | import { NavigationMenu, cn, Showcase } from "@chimera-ui/components";
4 |
5 | const components: { title: string; href: string; description: string }[] = [
6 | {
7 | title: "Alert Dialog",
8 | href: "/docs/components/AlertDialog ",
9 | description:
10 | "A modal dialog that interrupts the user with important content and expects a response.",
11 | },
12 | {
13 | title: "Hover Card",
14 | href: "/docs/primitives/hover-card",
15 | description:
16 | "For sighted users to preview content available behind a link.",
17 | },
18 | {
19 | title: "Progress",
20 | href: "/docs/components/Progress",
21 | description:
22 | "Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.",
23 | },
24 | {
25 | title: "Scroll-area",
26 | href: "/docs/primitives/scroll-area",
27 | description: "Visually or semantically separates content.",
28 | },
29 | {
30 | title: "Tabs",
31 | href: "/docs/components/Tabs",
32 | description:
33 | "A set of layered sections of content—known as tab panels—that are displayed one at a time.",
34 | },
35 | {
36 | title: "Tooltip",
37 | href: "/docs/components/Tooltip",
38 | description:
39 | "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.",
40 | },
41 | ];
42 |
43 | export const NavigationMenuDemo = () => {
44 | return (
45 |
46 |
47 |
48 |
49 |
50 | Getting started
51 |
52 |
53 |
80 |
81 |
82 |
83 | Components
84 |
85 |
86 | {components.map((component) => (
87 |
92 | {component.description}
93 |
94 | ))}
95 |
96 |
97 |
98 |
99 |
100 | Documentation
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | );
109 | };
110 |
111 | const ListItem = React.forwardRef<
112 | React.ElementRef<"a">,
113 | React.ComponentPropsWithoutRef<"a">
114 | >(({ className, title, children, ...props }, ref) => {
115 | return (
116 |
117 |
118 |
126 | {title}
127 |
128 | {children}
129 |
130 |
131 |
132 |
133 | );
134 | });
135 | ListItem.displayName = "ListItem";
136 |
--------------------------------------------------------------------------------
/apps/docs/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "cypress";
2 |
3 | export default defineConfig({
4 | e2e: {
5 | setupNodeEvents(on, config) {
6 | // implement node event listeners here
7 | },
8 | experimentalStudio: true,
9 | baseUrl: "http://localhost:3000",
10 | supportFile: false,
11 | },
12 | });
13 |
--------------------------------------------------------------------------------
/apps/docs/cypress/e2e/spec.cy.ts:
--------------------------------------------------------------------------------
1 | import MetaJson from "../../pages/docs/components/_meta.json";
2 |
3 | describe("Docs", () => {
4 | it("loads homepage", () => {
5 | cy.visit("/");
6 | });
7 |
8 | const pages = Object.keys(MetaJson).map((meta) => meta);
9 | pages.forEach((page) => {
10 | if (page === "index") return;
11 | it(`loads ${page} page`, () => {
12 | cy.visit(`docs/components/${page}`);
13 | it("Should not contain NoDisplayName or ", () => {
14 | cy.contains("").should("not.exist");
15 | cy.contains(" ").should("not.exist"); // can show up if you assign displayname to parent component but not subcomponents.
16 | });
17 | });
18 | });
19 |
20 | // it("loads all component pages", () => {
21 | // const pages = Object.keys(MetaJson).map((meta) => meta);
22 | // pages.forEach((page) => {
23 | // if (page === "index") return;
24 | // cy.visit(`docs/components/${page}`);
25 |
26 | // cy.contains("NoDisplayName").should("not.exist");
27 | // });
28 | // });
29 |
30 | it("theme generator generates can click through", () => {
31 | /* ==== Generated with Cypress Studio ==== */
32 | cy.visit("http://localhost:3000/docs/theme");
33 | cy.get(":nth-child(1) > .justify-center > .group > .flex > .px-2").click();
34 | cy.get(".saturation-white").click();
35 | cy.get(".hidden.\\@\\[50px\\]\\:block > .text-sm").click();
36 | cy.get(".transition-all > .gap-4 > .items-center").click();
37 | cy.get(".transition-all > .gap-4 > .bg-primary").click();
38 | /* ==== End Cypress Studio ==== */
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/apps/docs/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/apps/docs/next.config.js:
--------------------------------------------------------------------------------
1 | const withNextra = require("nextra")({
2 | theme: "nextra-theme-docs",
3 | themeConfig: "./theme.config.jsx",
4 | images: {
5 | remotePatterns: [
6 | {
7 | hostname: "images.unsplash.com",
8 | },
9 | ],
10 | },
11 | });
12 |
13 | module.exports = withNextra();
14 |
--------------------------------------------------------------------------------
/apps/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint",
10 | "test": "cypress run"
11 | },
12 | "dependencies": {
13 | "@chimera-ui/components": "workspace:*",
14 | "@chimera-ui/tw-plugin": "workspace:*",
15 | "@headlessui/react": "^1.7.7",
16 | "@heroicons/react": "^2.0.13",
17 | "@next/font": "13.1.1",
18 | "@radix-ui/react-icons": "^1.1.1",
19 | "@tailwindcss/container-queries": "^0.1.0",
20 | "@tailwindcss/line-clamp": "^0.4.2",
21 | "@types/node": "18.11.18",
22 | "@types/react": "18.0.26",
23 | "@types/react-color": "^3.0.6",
24 | "@types/react-dom": "18.0.10",
25 | "@vercel/analytics": "^0.1.10",
26 | "clsx": "^1.2.1",
27 | "color": "^4.2.3",
28 | "eslint": "8.30.0",
29 | "eslint-config-next": "13.1.1",
30 | "framer-motion": "^10.2.4",
31 | "next": "13.1.1",
32 | "nextra": "^2.0.1",
33 | "nextra-theme-docs": "^2.0.1",
34 | "raw-loader": "^4.0.2",
35 | "react": "18.2.0",
36 | "react-color": "^2.19.3",
37 | "react-dom": "18.2.0",
38 | "react-element-to-jsx-string": "^15.0.0",
39 | "typescript": "4.9.4"
40 | },
41 | "devDependencies": {
42 | "@types/color": "^3.0.3",
43 | "@types/react-resizable": "^3.0.3",
44 | "autoprefixer": "^10.4.13",
45 | "cypress": "^12.7.0",
46 | "postcss": "^8.4.20",
47 | "react-docgen": "6.0.0-beta.5",
48 | "tailwindcss": "^3.2.4"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/apps/docs/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import "../styles/globals.css";
2 | import type { AppProps } from "next/app";
3 | import { Analytics } from "@vercel/analytics/react";
4 |
5 | export default function App({ Component, pageProps }: AppProps) {
6 | return (
7 | <>
8 |
9 |
10 | >
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/apps/docs/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from "next/document";
2 |
3 | export default function Document() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/apps/docs/pages/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "docs": {
3 | "title": "Documentation",
4 | "type": "page"
5 | },
6 | "theme": {
7 | "title": "Theme Generator",
8 | "type": "page",
9 | "href": "/docs/theme"
10 | },
11 | "components": {
12 | "title": "Components",
13 | "type": "page",
14 | "href": "/docs/components"
15 | },
16 | "index": {
17 | "title": "Introduction",
18 | "type": "page",
19 | "display": "hidden",
20 | "theme": {
21 | "layout": "raw"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/apps/docs/pages/api/hello.ts:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 | import type { NextApiRequest, NextApiResponse } from 'next'
3 |
4 | type Data = {
5 | name: string
6 | }
7 |
8 | export default function handler(
9 | req: NextApiRequest,
10 | res: NextApiResponse
11 | ) {
12 | res.status(200).json({ name: 'John Doe' })
13 | }
14 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/FAQ.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: "FAQ"
3 | ---
4 |
5 |
6 |
7 | {
8 | "A component library built on top of another component library? Why would you do such a thing?"
9 | }
10 |
11 | Radix is great for accessible & interactive components, but they come completely
12 | unstyled. No point in rebuilding that, because I wouldn't be able to do it better
13 | than the Radix team. Many Chimera components are essentially Radix components that
14 | have been pre-styled a Chimera flavored Tailwind.
15 |
16 |
17 | This looks really similar to shadcn/ui. What is the difference?
18 | You would be right! I used many of the components from shadcn/ui as a starting
19 | point. The key differences are:
20 | - Chimera components are styled with a semantic color system.
21 | - With shadcn/ui, you copy and paste components
22 | into your library. Chimera is a library that you can import components from.
23 | - Small semantic differences. Shadcn renames components from Radix. Chimera uses
24 | the same naming conventions as Radix.
25 |
26 |
27 |
28 |
29 | Why did you choose to use a semantic color system? I wanted
30 | to create a library that would be easy to use for people who are new to design
31 | systems. I chose to use a semantic color system because it is easy to
32 | understand and use. It also allows for a lot of flexibility in how you want to
33 | use colors in your project. For example, you can use the same color for
34 | multiple components or you can use different colors for the same component.
35 |
36 |
37 |
38 |
39 | {
40 | "Seems like a pretty big package size and requires named exports. Will this bloat my app?"
41 | }
42 |
43 | Chimera is tree-shakeable. If you are using Next 12+ or a bundler that supports
44 | tree shaking, you should be fine.
45 |
46 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "introduction": "Introduction",
3 | "install": "Installation",
4 | "theme": {
5 | "title": "Theme Generator",
6 | "theme": {
7 | "layout": "full",
8 | "pagination": true,
9 | "breadcrumb": true,
10 | "sidebar": true
11 | }
12 | },
13 | "key-concepts": "Key Concepts",
14 | "components": "Components",
15 | "FAQ": {
16 | "title": "FAQ"
17 | },
18 |
19 | "credits": "Credits",
20 | "index": {
21 | "title": "Home",
22 | "display": "hidden"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Accordion.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Accordion
3 | description: A vertically stacked set of interactive headings that each reveal an associated section of content.
4 | component: Accordion
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/accordion
7 | api: https://www.radix-ui.com/docs/primitives/components/accordion#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Accordion, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
24 |
25 | Is it accessible?
26 |
27 | Yes. It adheres to the WAI-ARIA design pattern.
28 |
29 |
30 |
31 | Is it unstyled?
32 |
33 | Yes. It's unstyled by default, giving you freedom over the look and
34 | feel.
35 |
36 |
37 |
38 | Can it be animated?
39 |
40 |
41 | Yes! You can animate the Accordion with CSS or JavaScript.
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/AlertDialog.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Alert Dialog
3 | description: A modal dialog that interrupts the user with important content and expects a response.
4 | component: AlertDialog
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/alert-dialog
7 | api: https://www.radix-ui.com/docs/primitives/components/alert-dialog#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { AlertDialog, Button, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 | Delete Account
21 |
22 |
23 |
24 |
25 |
26 | Are you absolutely sure?
27 |
28 |
29 | This action cannot be undone. This will permanently delete your
30 | account and remove your data from our servers.
31 |
32 |
36 |
37 | Cancel
38 |
39 |
40 | Yes, delete account
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/AspectRatio.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Aspect Ratio
3 | description: Displays content within a desired ratio.
4 | component: AspectRatio
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/aspect-ratio
7 | api: https://www.radix-ui.com/docs/primitives/components/aspect-ratio#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { AspectRatio, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Avatar.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Avatar
3 | description: An image element with a fallback for representing the user.
4 | component: Avatar
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/avatar
7 | api: https://www.radix-ui.com/docs/primitives/components/avatar#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Avatar, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
27 | CT
28 |
29 |
30 |
31 |
36 |
37 | JD
38 |
39 |
40 |
41 | PD
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Button.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Button
3 | description: It's just a button.
4 | component: Button
5 | ---
6 |
7 | import { Button, Showcase } from "@chimera-ui/components";
8 | import ButtonDemo from "!!raw-loader!@/components/demo/ButtonDemo";
9 |
10 | ## Basic Usage
11 |
12 |
13 |
14 | Click Me
15 |
16 |
17 |
18 | ## Variants
19 |
20 |
21 |
22 |
23 | Primary
24 | Subtle
25 | Outline
26 | Secondary
27 | Secondary Subtle
28 | Secondary Outline
29 | Gradient
30 | Destructive
31 | Success
32 | Info
33 | Warning
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Checkbox.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Checkbox
3 | description: A control that allows the user to toggle between checked and not checked.
4 | component: Checkbox
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/checkbox
7 | api: https://www.radix-ui.com/docs/primitives/components/checkbox#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Checkbox, Showcase } from "@chimera-ui/components";
12 | import { CheckIcon } from "@radix-ui/react-icons";
13 |
14 | ## Simple Usage
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 | Accept terms and conditions
26 |
27 |
28 |
29 |
30 |
31 | ## Subcomponent Usage
32 |
33 |
34 |
35 |
36 |
37 | X
38 |
39 | See how the indicator can be customized?
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Collapsible.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Collapsible
3 | description: An interactive component which expands/collapses a panel.
4 | component: Collapsible
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/collapsible
7 | api: https://www.radix-ui.com/docs/primitives/components/collapsible#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Showcase } from "@chimera-ui/components";
12 | import { CollapsibleDemo as CollapsibleDemoComponent } from "../../../components/demo/CollapsibleDemo";
13 | import CollapsibleDemo from "!!raw-loader!../../../components/demo/CollapsibleDemo.tsx";
14 |
15 | ## Usage
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/ContextMenu.mdx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Showcase, ContextMenu } from "@chimera-ui/components";
3 | import { ContextMenuDemo as ContextMenuDemoComponent } from "@/components/demo/ContextMenuDemo";
4 | import ContextMenuDemo from "!!raw-loader!@/components/demo/ContextMenuDemo.tsx";
5 |
6 | ## Usage
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Copy.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Copy
3 | description: It's just a Copy.
4 | component: Copy
5 | ---
6 |
7 | import { Copy, Showcase } from "@chimera-ui/components";
8 |
9 | ## Usage
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 | ## Props
21 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Dialog.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Dialog
3 | description: A modal dialog that interrupts the user with important content and expects a response.
4 | component: Dialog
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/dialog
7 | api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference
8 | ---
9 |
10 | import { Dialog, Button, Input, Showcase } from "@chimera-ui/components";
11 | import { Cross2Icon } from "@radix-ui/react-icons";
12 |
13 | ## Usage
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Edit profile
22 |
23 |
24 |
25 |
26 |
27 | Edit profile
28 |
29 | Make changes to your profile here. Click save when you're done.
30 |
31 |
32 |
33 | Name
34 |
35 |
36 |
37 |
38 |
39 | Username
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ## Extending Radix Anatomy
52 |
53 | ### Dialog.Confirm
54 |
55 | Chimera adds `Dialog.Confirm`, which is a `Dialog.Close`, except it positions a button in the bottom right corner. You can pass children to it, or use ` ` to use the default button.
56 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/DropdownMenu.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Dropdown Menu
3 | description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
4 | component: DropdownMenu
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/dropdown-menu
7 | api: https://www.radix-ui.com/docs/primitives/components/dropdown-menu#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Showcase, DropdownMenu, Button } from "@chimera-ui/components";
12 | import {
13 | Cloud,
14 | CreditCard,
15 | Github,
16 | Keyboard,
17 | LifeBuoy,
18 | LogOut,
19 | Mail,
20 | MessageSquare,
21 | Plus,
22 | PlusCircle,
23 | Settings,
24 | User,
25 | UserPlus,
26 | Users,
27 | } from "lucide-react";
28 |
29 | ## Usage
30 |
31 |
32 |
33 |
34 |
35 |
36 | Open
37 |
38 |
39 | My Account
40 |
41 |
42 |
43 |
44 | Profile
45 | ⇧⌘P
46 |
47 |
48 |
49 | Billing
50 | ⌘B
51 |
52 |
53 |
54 | Settings
55 | ⌘S
56 |
57 |
58 |
59 | Keyboard shortcuts
60 | ⌘K
61 |
62 |
63 |
64 |
65 |
66 |
67 | Team
68 |
69 |
70 |
71 |
72 | Invite users
73 |
74 |
75 |
76 |
77 |
78 | Email
79 |
80 |
81 |
82 | Message
83 |
84 |
85 |
86 |
87 | More...
88 |
89 |
90 |
91 |
92 |
93 |
94 | New Team
95 | ⌘+T
96 |
97 |
98 |
99 |
100 |
101 | GitHub
102 |
103 |
104 |
105 | Support
106 |
107 |
108 |
109 | API
110 |
111 |
112 |
113 |
114 | Log out
115 | ⇧⌘Q
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Input.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Input
3 | description: It's just an input field with some styling.
4 | component: Input
5 | ---
6 |
7 | import React from "react";
8 | import { Input, Label, Showcase } from "@chimera-ui/components";
9 | import { InfoCircledIcon } from "@radix-ui/react-icons";
10 |
11 | ## Usage
12 |
13 |
14 |
15 |
16 | Email
17 |
18 |
19 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Label.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Label
3 | description: Renders an accessible label associated with controls.
4 | component: Label
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/label
7 | api: https://www.radix-ui.com/docs/primitives/components/label#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Checkbox, Showcase, Label } from "@chimera-ui/components";
12 | import { CheckIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Accept terms and conditions
24 |
25 |
26 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Menubar.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Menubar
3 | description: A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
4 | component: Menubar
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/menubar
7 | api: https://www.radix-ui.com/docs/primitives/components/menubar#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Menubar, Showcase } from "@chimera-ui/components";
12 |
13 | ## Usage
14 |
15 |
16 |
17 |
18 |
19 | File
20 |
21 |
22 | New Tab ⌘T
23 |
24 |
25 | New Window ⌘N
26 |
27 | New Incognito Window
28 |
29 |
30 | Share
31 |
32 | Email link
33 | Messages
34 | Notes
35 |
36 |
37 |
38 |
39 | Print... ⌘P
40 |
41 |
42 |
43 |
44 | Edit
45 |
46 |
47 | Undo ⌘Z
48 |
49 |
50 | Redo ⇧⌘Z
51 |
52 |
53 |
54 | Find
55 |
56 | Search the web
57 |
58 | Find...
59 | Find Next
60 | Find Previous
61 |
62 |
63 |
64 | Cut
65 | Copy
66 | Paste
67 |
68 |
69 |
70 | View
71 |
72 | Always Show Bookmarks Bar
73 |
74 | Always Show Full URLs
75 |
76 |
77 |
78 | Reload ⌘R
79 |
80 |
81 | Force Reload ⇧⌘R
82 |
83 |
84 | Toggle Fullscreen
85 |
86 | Hide Sidebar
87 |
88 |
89 |
90 | Profiles
91 |
92 |
93 | Andy
94 | Benoit
95 | Luis
96 |
97 |
98 | Edit...
99 |
100 | Add Profile...
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/NavigationMenu.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Navigation Menu
3 | description: A collection of links for navigating websites.
4 | component: NavigationMenu
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/navigation-menu
7 | api: https://www.radix-ui.com/docs/primitives/components/navigation-menu#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Showcase } from "@chimera-ui/components";
12 | import { NavigationMenuDemo as NavigationMenuDemoComponent } from "../../../components/demo/NavigationMenuDemo";
13 | import NavigationMenuDemo from "!!raw-loader!../../../components/demo/NavigationMenuDemo.tsx";
14 |
15 | ## Usage
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Popover.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Popover
3 | description: Displays rich content in a portal, triggered by a button.
4 | component: Popover
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/popover
7 | api: https://www.radix-ui.com/docs/primitives/components/popover#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Popover, Input, Showcase } from "@chimera-ui/components";
12 | import {
13 | InfoCircledIcon,
14 | Cross2Icon,
15 | MixerHorizontalIcon,
16 | } from "@radix-ui/react-icons";
17 |
18 | ## Usage
19 |
20 |
21 |
22 | }>
23 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | ## Subcomponent Usage
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Progress.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Progress
3 | description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
4 | component: Progress
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/progress
7 | api: https://www.radix-ui.com/docs/primitives/components/progress#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Progress, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/RadioGroup.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Radio Group
3 | description: A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
4 | component: RadioGroup
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/radio-group
7 | api: https://www.radix-ui.com/docs/primitives/components/radio-group#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { RadioGroup, Showcase, Label } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Select.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Select
3 | description: Displays a list of options for the user to pick from—triggered by a button.
4 | component: Select
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/select
7 | api: https://www.radix-ui.com/docs/primitives/components/select#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Select, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Fruits
25 | Apple
26 | Banana
27 | Blueberry
28 | Grapes
29 | Pineapple
30 |
31 |
32 |
33 | Vegetables
34 | Aubergine
35 | Broccoli
36 |
37 | Carrot
38 |
39 | Courgette
40 | Leek
41 |
42 |
43 |
44 | Meat
45 | Beef
46 | Chicken
47 | Lamb
48 | Pork
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Switch.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Switch
3 | description: A control that allows the user to toggle between checked and not checked.
4 | component: Switch
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/switch
7 | api: https://www.radix-ui.com/docs/primitives/components/switch#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Switch, Label, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 | Airplane Mode
20 |
21 |
22 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Tabs.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Tabs
3 | description: A set of layered sections of content—known as tab panels—that are displayed one at a time.
4 | component: Tabs
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/tabs
7 | api: https://www.radix-ui.com/docs/primitives/components/tabs#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Tabs, Input, Button, Label, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 | Account
21 | Password
22 |
23 |
24 |
25 | Make changes to your account here. Click save when you're done.
26 |
27 |
37 |
38 | Save changes
39 |
40 |
41 |
42 |
43 | Change your password here. After saving, you'll be logged out.
44 |
45 |
55 |
56 | Save password
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/TextArea.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: TextArea
3 | description: It's just an TextArea field with some styling.
4 | component: TextArea
5 | ---
6 |
7 | import React from "react";
8 | import { TextArea, Label, Showcase } from "@chimera-ui/components";
9 | import { InfoCircledIcon } from "@radix-ui/react-icons";
10 |
11 | ## Usage
12 |
13 |
14 |
15 |
16 | Description
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Toggle.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Toggle
3 | description: A two-state button that can be either on or off.
4 | component: Toggle
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/toggle
7 | api: https://www.radix-ui.com/docs/primitives/components/toggle#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Switch, Label, Toggle, Showcase } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 | Click to Toggle Me
19 |
20 |
21 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/Tooltip.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Tooltip
3 | description: A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
4 | component: Tooltip
5 | radix:
6 | link: https://www.radix-ui.com/docs/primitives/components/tooltip
7 | api: https://www.radix-ui.com/docs/primitives/components/tooltip#api-reference
8 | ---
9 |
10 | import React from "react";
11 | import { Tooltip, Showcase, Button } from "@chimera-ui/components";
12 | import { InfoCircledIcon } from "@radix-ui/react-icons";
13 |
14 | ## Usage
15 |
16 |
17 |
18 |
19 |
20 |
21 | Add
22 |
23 |
24 | Add to library
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "Accordion": "Accordion",
3 | "AlertDialog": "Alert Dialog",
4 | "AspectRatio": "Aspect Ratio",
5 | "Avatar": "Avatar",
6 | "Button": "Button",
7 | "Checkbox": "Checkbox",
8 | "Collapsible": "Collapsible",
9 | "ContextMenu": "Context Menu",
10 | "Copy": "Copy",
11 | "Dialog": "Dialog",
12 | "DropdownMenu": "Dropdown Menu",
13 | "Input": "Input",
14 | "Label": "Label",
15 | "Menubar": "Menubar",
16 | "NavigationMenu": "Navigation Menu",
17 | "Popover": "Popover",
18 | "Tooltip": "Tooltip",
19 | "Progress": "Progress",
20 | "RadioGroup": "Radio Group",
21 | "Select": "Select",
22 | "Switch": "Switch",
23 | "Tabs": "Tabs",
24 | "Toggle": "Toggle",
25 | "index": {
26 | "title": "Components",
27 | "display": "hidden"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/components/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Components
3 | description: A list of all the components available in Chimera UI.
4 | ---
5 |
6 | import { ComponentsList } from "@/components/ComponentsList";
7 |
8 |
9 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/credits.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Credits
3 | ---
4 |
5 | - [Shadcn/ui](https://ui.shadcn.com/). As I started working on Chimera, I came across shadnc/ui and was surprised to see how similar our ideas were. Shadcn/ui was much further along, so I was able to adapt a lot of the work that he did. Huge shout out to him!
6 | - [Daisy UI](https://daisyui.com/), for inspiring the semantic color system
7 | - [Adam Wathan](https://twitter.com/adamwathan) and [Steve Schoger](https://twitter.com/steveschoger) for creating [Tailwind](https://tailwindcss.com/) and writing [Refactoring UI](https://www.refactoringui.com/). A book that has helped me a lot in designing this library!
8 | - [Vercel](https://vercel.com/), for hosting all of my projects and making it easy to share them with the world
9 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/introduction.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | ---
4 |
5 | import { Button, Showcase } from "@chimera-ui/components";
6 | import { Callout } from "nextra-theme-docs";
7 |
8 | Chimera is a UI library designed for React and Tailwind. It aims to address the following problems:
9 |
10 | - Component libraries like MUI, Chakra, and Bootstrap look great out of the box, but can hard to customize
11 | - Themeing can be tedious with Vanilla Tailwind and libraries like Flowbite. I dislike needing to define the light mode color and dark mode color for every component
12 | - Vanilla Tailwind is not very reusable across projects with different styles
13 | - CSS only libraries such as Daisy UI can have accessibility issues
14 | - Headless libraries like Radix and Headless UI are.. headless. The whole point is that they come unstyled, but that means you spend a lot of time styling them.
15 |
16 | That being said, there's a lot I love about each of those libraries too. The speed and customizability of Tailwind, the themeability of Daisy UI, the accessibility of Radix, and the works straight out of the box experience of MUI. Chimera an attempt to combine all of the parts I love about these libraries while minimizing the problems.
17 |
18 |
19 | Huge shout out to
20 | Shadcn
21 | for creating
22 | shadcn/ui . I used many of the components from
23 | shadcn/ui as a starting point. If you are looking for a similar library without
24 | a color system, I recommend checking it out!
25 |
26 |
27 | ## Key Features
28 |
29 | ### Themeable & Reusable
30 |
31 | Chimera extends Tailwind by adding a semantic color system with which components come pre-styled with. This makes it easy to switch themes and re-use components across apps. Learn more: [Color System](colors).
32 |
33 | ### Accessibility
34 |
35 | Chimera uses Radix Primitives under the hood for interactive components like accordions and selects. Learn more: [Accessibility](accessibility).
36 |
37 | ### Customizable
38 |
39 | Components come with sensible default styles that look great out of the box, but can be completely customized with Tailwind utility classes. Chimera uses [tailwind-merge](https://www.npmjs.com/package/tailwind-merge) under the hood to handle this. Learn more: [Customization](customization)
40 |
41 | ## Example
42 |
43 | Change the theme in the preview below. See how the Button can take on different styles with the same JSX? The second Button is an example of how the default styles can be easily overwritten.
44 |
45 |
46 |
47 | Click Me
48 | Click Me
49 |
50 |
51 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/key-concepts/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors": "Color System",
3 | "themeing": "Themeing",
4 | "customization": "Customization",
5 | "accessibility": "Accessibility"
6 | }
7 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/key-concepts/accessibility.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | ---
4 |
5 | Chimera uses [Radix Primitives](https://www.radix-ui.com/docs/primitives/overview/introduction) under the hood for most interactive components where accessibility is a concern. Radix is an open-source UI component library for building high-quality, accessible design systems and web apps.
6 |
7 | You can see in the example below that Chimera is providing a thin wrapper of default classes around Radix components. The default classes are easily overridden by passing in your own classes thanks to tailwind-merge.
8 |
9 | ```jsx
10 | import * as RadixPopover from "@radix-ui/react-popover";
11 | import * as React from "react";
12 | import { twMerge } from "tailwind-merge";
13 |
14 | // Pattern: Extract all of the subcomponents from RadixComponent -> Component i.e RadixPopover.Root -> Popover.Root
15 | // Handle twMerge in the subcomponents
16 | // In the parent component, use the Chimera subcomponents instead of the Radix subcomponents, this way the Tailwind classes are merged
17 | export const Popover = ({
18 | buttonContent,
19 | children,
20 | onClick,
21 | }: {
22 | buttonContent: React.ReactNode;
23 | children: React.ReactNode | React.ReactNode[];
24 | onClick?: () => void;
25 | }) => {
26 | return (
27 |
28 | {
30 | if (onClick) {
31 | onClick();
32 | }
33 | }}
34 | >
35 | {buttonContent}
36 |
37 |
38 |
39 | {children}
40 |
41 |
42 |
43 |
44 | );
45 | };
46 |
47 | Popover.displayName = "Popover";
48 |
49 | const Root = ({ children }: { children: React.ReactNode }) => {
50 | return {children} ;
51 | };
52 | Root.displayName = "Popover.Root";
53 | Popover.Root = Root;
54 |
55 | /**
56 | *
57 | * @param className Default: `px-2 py-1 w-fit bg-primary hover:bg-primary-darker text-on-primary rounded-theme`
58 | * @returns
59 | */
60 |
61 | const Trigger = React.forwardRef<
62 | React.ElementRef,
63 | React.ComponentPropsWithoutRef
64 | >((props, forwardedRef) => {
65 | return (
66 |
74 | {props.children}
75 |
76 | );
77 | });
78 |
79 | Trigger.displayName = "Popover.Trigger";
80 | Popover.Trigger = Trigger;
81 |
82 | const Portal = ({ children }: { children: React.ReactNode }) => {
83 | return {children} ;
84 | };
85 | Portal.displayName = "Popover.Portal";
86 | Popover.Portal = Portal;
87 |
88 | const Content = React.forwardRef<
89 | React.ElementRef,
90 | React.ComponentPropsWithoutRef
91 | >((props, forwardedRef) => {
92 | return (
93 |
101 | {props.children}
102 |
103 | );
104 | });
105 | Content.displayName = "Popover.Content";
106 | Popover.Content = Content;
107 |
108 | const Arrow = ({ className }: { className?: string }) => {
109 | return ;
110 | };
111 |
112 | Arrow.displayName = "Popover.Arrow";
113 | Popover.Arrow = Arrow;
114 |
115 | const Close = React.forwardRef<
116 | React.ElementRef,
117 | React.ComponentPropsWithoutRef
118 | >((props, forwardedRef) => {
119 | return (
120 |
125 | {props.children}
126 |
127 | );
128 | });
129 |
130 | Close.displayName = "Popover.Close";
131 | Popover.Close = Close;
132 | ```
133 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/key-concepts/colors.mdx:
--------------------------------------------------------------------------------
1 | import { ColorTable } from "@/components/ColorTables";
2 | import { ThemePicker } from "@chimera-ui/components";
3 |
4 | # Color System
5 |
6 | ## Overview
7 |
8 | This semantic color system was designed so that a single class makes sense for themes that go from lighter to darker colors, as well as themes that go from darker to lighter colors. This is why Chimera does not use the 100-900 scale for colors, since those signify a fixed light->dark scale.
9 |
10 | The choices for the semantic color names came from studying the color/element patterns on many websites. It allows for a lot of flexibility but at the same time, but makes it really easy to change specific groups of colors on your site.
11 |
12 | This color system was heavily inspired by [DaisyUI's color system](https://daisyui.com/docs/colors).
13 |
14 | ## Color Modifiers
15 |
16 |
17 | **1-3 (prominence)** (e.g., base-2 or base-3)
18 |
19 | 1 being the most prominent color and 3 being least prominent color Used for backgrounds,
20 | text, or other elements where you need to create subtle contrast.
21 |
22 | 
23 |
24 | So why don't
25 | we use 100-900 for these colors too? Let's say your background is base-100 and
26 | a card on the background is base-200. This makes total sense in light mode,
27 | where white is the background and a light grey layers on top of that. It no
28 | longer makes sense if you want to switch to a dark mode where the background
29 | is black and the card is supposed to be dark grey.
30 |
31 |
32 |
33 |
34 | **100-900 (light to dark)** (e.g., primary-100, secondary-800)
35 | 100 is the lightest color and 900 is the darkest color. This is the scale that Tailwind uses for colors. The components in Chimera **do not** use these for default styles, but they are available for use from the default Tailwind theme. I suggest keeping these in your arsenal for when you really need to use a color that is not in the color system!
36 |
37 | Fun thing I stumbled upon while researching, [this is the Tweet thread](https://twitter.com/adamwathan/status/920706866283364352?lang=en) Adam Wathan started when he was researching the same thing!
38 |
39 | 
40 | [From Tailwind's Customizing Colors](https://tailwindcss.com/docs/customizing-colors)
41 |
42 |
43 |
44 | **content** (e.g., primary-content, text-base-content-)
45 | This is used for text or other content that is on top of a background color.
46 | On background colors like `base` and `overlay`, a content modifier can be used with either the prominence modifier.
47 |
48 | Examples:
49 |
50 | - `base-content`
51 | - `base-content-2`
52 |
53 | 
54 |
55 |
56 |
57 |
58 | **focus** (e.g., secondary-focus, success-focus)
59 | Focus colors are used for elements like buttons, alerts, icons, etc. They are used
60 | when the element is focused or hovered.
61 |
62 |
63 |
64 | **subtle** (e.g., hover:bg-secondary-subtle)
65 | Subtle colors are used for elements like buttons, alerts, icons, etc. They are
66 | often used for background colors when the element is hovered or focused. 
68 |
69 |
70 | ## Colors
71 |
72 | This system was designed to work for themes that go from lighter background colors to darker foreground colors, as well as themes that do the inverse. This is why Chimera does not use the 100-900 scale for colors, since those signify a fixed light->dark scale.
73 |
74 | You'll notice there are a LOT of colors in this color system. Don't be afraid! Most of these colors, you won't need to change. A lot of these colors will also be the same. For example, you might use the same color for primary-content and secondary-content.
75 |
76 | ### Base
77 |
78 | Base colors are used for backgrounds.
79 |
80 |
81 |
82 | ### Overlay
83 |
84 | Overlay colors are used for background colors of floating elements like modals, dropdowns, menus, etc. They should be similar but distinct from base colors that they will be on top of.
85 |
86 |
87 |
88 | ### Input
89 |
90 | Input colors are used for input elements like text inputs, textareas, etc. They should be similar but distinct from base colors that they will be on top of.
91 |
92 |
93 |
94 | ### Line
95 |
96 | Line colors are used for borders, dividers, etc. They should be similar but distinct from base colors that they will be on top of.
97 |
98 |
99 |
100 | ### Primary
101 |
102 | Primary colors are used for the main actions in your interface, think call to action buttons, links, etc. Primary should be distinct, and is most likely one of your brand colors.
103 |
104 |
105 |
106 | ### Secondary
107 |
108 | Secondary colors are used for actions of lower priority than primary. Secondary is also good for other elements that you want to highlight, such as tags, less important buttons, icons, etc.
109 |
110 |
111 |
112 | ### Info
113 |
114 | Info colors are used for informational elements, such as alerts, icons, etc.
115 |
116 |
117 |
118 | ### Success
119 |
120 | Success colors are used for success elements, such as alerts, icons, etc.
121 |
122 |
123 |
124 | ### Error
125 |
126 | Error colors are used for error elements, such as alerts, icons, etc.
127 |
128 |
129 |
130 | ### Warning
131 |
132 | Warning colors are used for warning elements, such as alerts, icons, etc.
133 |
134 |
135 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/key-concepts/customization.mdx:
--------------------------------------------------------------------------------
1 | # Customization
2 |
3 | In order to provide out of the box styles and full Tailwind customization, Chimera components use tailwind-merge to allow you to write new styles and overide the defaults in one go.
4 |
5 | ## Usage
6 |
7 | ```typescript
8 | import { twMerge } from "tailwind-merge";
9 |
10 |
11 | export const ExampleComponent = ({className}:{className:string}) => {
12 | return I'm an example!
13 | }
14 |
15 | ```
16 |
17 | When you use the component
18 |
19 | ```typescript
20 | import { ExampleComponent } from "@chimera-ui/components";
21 |
22 | ;
23 | // p-4 will override the p-2 in the block above, final style resulting in "p-4 bg-base"
24 | ```
25 |
26 | ## Styling components with subcomponents
27 |
28 | Chimera seeks to give you as much control as possible via a single `className` prop. However, it is not always possible to customize a component with a single prop, especially in cases where there are subcomponents (e.g., a `` inside of ``). In these cases, Chimera exposes all of the same subcomponents that Radix does and you can use the `className` props on the subcomponents to customize them.
29 |
30 | ```typescript
31 | // The default classes will be exposed in the intellisense for each component,
32 | // so you will be able to see what styles you are overwriting.
33 |
34 |
35 |
36 |
37 |
38 |
39 |
41 | `This is an example of a popover with custom styles!`
42 |
43 |
44 |
45 |
46 | ```
47 |
--------------------------------------------------------------------------------
/apps/docs/pages/docs/theme.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Theme Generator
3 | description: Theme your components super quickly by picking 3 colors. The generator will automatically create all of the other shades for you!
4 | image: "/chimera-theme-gen-image.png"
5 | ---
6 |
7 | import { ThemeGenerator } from "@/components/ThemeGenerator";
8 | import { Callout } from "nextra-theme-docs";
9 |
10 |
11 | Check out the Color System docs for more information on how to
12 | use Chimera's semantic color system.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/docs/pages/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Chimera UI"
3 | description: "An open source UI library built for React + Tailwind. Beautiful, accessible, themeable, and fully customizable."
4 | ---
5 |
6 | import { LandingPage } from "@/components/LandingPage";
7 |
8 |
9 |
--------------------------------------------------------------------------------
/apps/docs/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/apps/docs/public/100-900-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/100-900-example.png
--------------------------------------------------------------------------------
/apps/docs/public/avatar_sally.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/avatar_sally.png
--------------------------------------------------------------------------------
/apps/docs/public/avatar_steve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/avatar_steve.png
--------------------------------------------------------------------------------
/apps/docs/public/bonapp_color_study.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/bonapp_color_study.jpeg
--------------------------------------------------------------------------------
/apps/docs/public/chimera-og-image-old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/chimera-og-image-old.png
--------------------------------------------------------------------------------
/apps/docs/public/chimera-og-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/chimera-og-image.png
--------------------------------------------------------------------------------
/apps/docs/public/chimera-theme-gen-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/chimera-theme-gen-image.png
--------------------------------------------------------------------------------
/apps/docs/public/content-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/content-example.png
--------------------------------------------------------------------------------
/apps/docs/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/favicon.ico
--------------------------------------------------------------------------------
/apps/docs/public/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.12, written by Peter Selinger 2001-2015
9 |
10 |
12 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/apps/docs/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/docs/public/on-example.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/on-example.jpeg
--------------------------------------------------------------------------------
/apps/docs/public/prominence-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/prominence-example.png
--------------------------------------------------------------------------------
/apps/docs/public/subtle-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/subtle-example.png
--------------------------------------------------------------------------------
/apps/docs/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/docs/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/docs/public/vercel_color_study.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/apps/docs/public/vercel_color_study.png
--------------------------------------------------------------------------------
/apps/docs/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 |
3 | module.exports = {
4 | important: true,
5 | theme: {
6 | extend: {
7 | animation: {
8 | blob: "blob 7s infinite",
9 | },
10 | keyframes: {
11 | blob: {
12 | "0%": {
13 | transform: "translate(0px, 0px) scale(1)",
14 | },
15 | "33%": {
16 | transform: "translate(30px, -50px) scale(1.1)",
17 | },
18 | "66%": {
19 | transform: "translate(-20px, 20px) scale(0.9)",
20 | },
21 | "100%": {
22 | transform: "tranlate(0px, 0px) scale(1)",
23 | },
24 | },
25 | },
26 | },
27 | },
28 | content: [
29 | "./pages/**/*.{js,ts,jsx,tsx,md,mdx}",
30 | "./components/**/*.{js,ts,jsx,tsx,mdx}",
31 | "./utils/**/*.{js,ts,jsx,tsx,mdx}",
32 | "./examples/**/*.{js,ts,jsx,tsx,mdx}",
33 | "./nextra-theme-docs/**/*.{js,tsx}",
34 | "./theme.config.jsx",
35 | "../../packages/ui/**/*{.js,.ts,.jsx,.tsx}",
36 | "../../packages/components/**/*{.js,.ts,.jsx,.tsx,.mjs}",
37 | ],
38 | plugins: [
39 | require("@tailwindcss/container-queries"),
40 | require("@chimera-ui/tw-plugin"),
41 | require("@tailwindcss/line-clamp"),
42 | ],
43 | };
44 |
--------------------------------------------------------------------------------
/apps/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "strict": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "noEmit": true,
14 | "esModuleInterop": true,
15 | "module": "esnext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "jsx": "preserve",
20 | "incremental": true,
21 | "baseUrl": "./",
22 | "paths": {
23 | "@/components/*": [
24 | "./components/*"
25 | ],
26 | "@/pages/*": [
27 | "./pages/*"
28 | ],
29 | "@/public/*": [
30 | "./public/*"
31 | ],
32 | "@/styles/*": [
33 | "./styles/*"
34 | ],
35 | "@/utils/*": [
36 | "./utils/*"
37 | ]
38 | }
39 | },
40 | "include": [
41 | "next-env.d.ts",
42 | "**/*.ts",
43 | "**/*.tsx"
44 | ],
45 | "exclude": [
46 | "node_modules"
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/apps/docs/utils/themestyles.tsx:
--------------------------------------------------------------------------------
1 | export type themeStyles = {
2 | "theme-border-width": String;
3 | "theme-rounded": String;
4 | "theme-rounded-sm": String;
5 | "theme-rounded-md": String;
6 | "theme-rounded-lg": String;
7 | "theme-rounded-xl": String;
8 | "theme-shadow": String;
9 | "theme-shadow-sm": String;
10 | "theme-shadow-md": String;
11 | "theme-shadow-lg": String;
12 | "theme-shadow-xl": String;
13 | "theme-shadow-inner": String;
14 | };
15 |
--------------------------------------------------------------------------------
/apps/docs/utils/utils.tsx:
--------------------------------------------------------------------------------
1 | type ClassesObject = {
2 | [key: string]: string[];
3 | };
4 |
5 | export const handleTailwindClassOverrides = (
6 | defaultClasses: string,
7 | userClasses?: string
8 | ): string => {
9 | if (!userClasses) return defaultClasses;
10 |
11 | const defaultClassesArray = defaultClasses.split(" ");
12 | const userClassesArray = userClasses.split(" ");
13 |
14 | // If the default is border-theme border-black, and a user passes in border-2 border-red-500 border-dotted, the result should be border-2 border-red-500 border-dotted
15 | const defaultClassesObject = defaultClassesArray.reduce(
16 | (acc: ClassesObject, curr) => {
17 | const splitClass = curr.split("-");
18 | // create a nested object with [0] as the key and the full class as a value in an array
19 | // { border: ["border-theme", "border-black"] }
20 | if (acc[splitClass?.[0]]) {
21 | acc[splitClass?.[0]].push(curr);
22 | } else {
23 | acc[splitClass[0]] = [curr];
24 | }
25 | return acc;
26 | },
27 | {}
28 | );
29 | const userClassesObject = userClassesArray.reduce(
30 | (acc: ClassesObject, curr) => {
31 | const splitClass = curr.split("-");
32 | // create a nested object with [0] as the key and the full class as a value in an array
33 | // { border: ["border-2", "border-red-500", "border-dotted"] }
34 | if (acc[splitClass?.[0]]) {
35 | acc[splitClass[0]].push(curr);
36 | } else {
37 | acc[splitClass[0]] = [curr];
38 | }
39 | return acc;
40 | },
41 | {}
42 | );
43 |
44 | for (const key in userClassesObject) {
45 | if (defaultClassesObject[key]) {
46 | defaultClassesObject[key] = userClassesObject[key];
47 | } else {
48 | defaultClassesObject[key] = userClassesObject[key];
49 | }
50 | }
51 | const result = Object.values(defaultClassesObject).flat();
52 | return result.join(" ");
53 | };
54 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "build": "turbo run build",
5 | "dev": "turbo run dev --no-cache --parallel --continue",
6 | "lint": "turbo run lint",
7 | "web": "turbo run dev --filter",
8 | "clean": "turbo run clean && rm -rf node_modules",
9 | "format": "prettier --write \"**/*.{ts,tsx,md}\"",
10 | "prebuild": "turbo run prebuild --filter=@chimera-ui/components",
11 | "changeset": "changeset",
12 | "test": "turbo run test --filter=docs",
13 | "version-packages": "changeset version",
14 | "release": "turbo run build --filter=docs^... && changeset publish"
15 | },
16 | "devDependencies": {
17 | "@changesets/cli": "^2.25.2",
18 | "eslint": "^8.29.0",
19 | "eslint-config-chimera": "workspace:0.0.0",
20 | "prettier": "^2.8.0",
21 | "turbo": "^1.6.3"
22 | },
23 | "packageManager": "pnpm@7.15.0"
24 | }
25 |
--------------------------------------------------------------------------------
/packages/components/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["chimera"],
4 | };
5 |
--------------------------------------------------------------------------------
/packages/components/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # @chimera-ui/components
2 |
3 | ## 0.4.0
4 |
5 | ### Minor Changes
6 |
7 | - Added more detail to button intellisense
8 |
9 | ## 0.3.0
10 |
11 | ### Minor Changes
12 |
13 | - 1874a09: Fixed issue with Remix where exports in package.json was breaking remix builds
14 |
15 | ## 0.1.0
16 |
17 | ### Minor Changes
18 |
19 | - d9fa560: Initial publish
20 |
21 | ## 0.2.0
22 |
23 | ### Minor Changes
24 |
25 | - Added default classes to intellisense for any subcomponents that have them.
26 |
--------------------------------------------------------------------------------
/packages/components/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Chimera UI
4 |
5 | To see the full documentation, visit [chimera-ui.com](https://chimera-ui.com).
6 |
7 | ## Features
8 |
9 | - Fully accessible components, with Radix Primitives under the hood.
10 | - Includes additinal components beyond Radix, such as Button and Input.
11 | - Components come pre-styled. Styles can be easily overwritten with Tailwind (Chimera uses tw-merge under the hood).
12 | - Semantic color system built in. No more guessing what color to use, just use the same semantic color names across all your projects.
13 | - Theme generator that quickly generates CSS themes for you.
14 | - Tailwind plugin to keep tailwind.config.js nice and clean.
15 | - Tree-shakeable. Use named imports without worrying about bundle-size!
16 |
17 | ## Installation
18 |
19 | See [official docs](https://chimera-ui.com) for more information
20 |
21 | 1. `npm install @chimera-ui/components @chimera-ui/tw-plugin`
22 | 2. Modify your `tailwind.config.js` to include:
23 |
24 | - `"./node_modules/@chimera-ui/components/dist/**/*.{js,mjs}",` in the `content` array
25 | - `require("@chimera-ui/tw-plugin")` in the `plugins` array
26 | - ```js
27 | module.exports = {
28 | content: [
29 | "./pages/**/*.{js,ts,jsx,tsx,md,mdx}",
30 | "./components/**/*.{js,ts,jsx,tsx}",
31 | "./node_modules/@chimera-ui/components/dist/**/*.{js,mjs}", // This line is important! If you don't include this, Chimera's styles will be purged
32 | ,
33 | ],
34 | plugins: [
35 | require("@chimera-ui/tw-plugin"), // This is important! This extends your tailwind theme to consume the CSS variables.
36 | ],
37 | };
38 | ```
39 |
40 | 3. Use the theme generator to generate CSS themes. Add the CSS variables to your global css file.
41 |
--------------------------------------------------------------------------------
/packages/components/docgen.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const reactDocs = require("react-docgen");
4 |
5 | const code = `
6 | import * as React from "react";
7 | import * as AccordionPrimitive from "@radix-ui/react-accordion";
8 |
9 | import { cn } from "../utils";
10 |
11 | export const Accordion = (
12 | props: React.ComponentProps
13 | ) => {
14 | return <>>;
15 | };
16 |
17 | const Root = AccordionPrimitive.Root;
18 | Root.displayName = AccordionPrimitive.Root.displayName;
19 | Accordion.Root = Root;
20 |
21 | /**
22 | * Default Classes: ~ "border-b border-b-line" ~
23 | * sdiofh
24 | */
25 | const Item = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, ...props }, ref) => (
29 |
34 | ));
35 | Item.displayName = "Accordion.Item";
36 | Accordion.Item = Item;
37 | `;
38 |
39 | console.log(reactDocs.parse(code));
40 |
--------------------------------------------------------------------------------
/packages/components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@chimera-ui/components",
3 | "version": "0.4.0",
4 | "main": "./dist/index.js",
5 | "module": "./dist/index.mjs",
6 | "types": "./dist/index.d.ts",
7 | "sideEffects": [
8 | "**/*.css"
9 | ],
10 | "license": "MIT",
11 | "files": [
12 | "dist/**"
13 | ],
14 | "scripts": {
15 | "prebuild": "node tsdocSync.js",
16 | "build": "tsup",
17 | "dev": "tsup --watch",
18 | "check-types": "tsc --noEmit"
19 | },
20 | "devDependencies": {
21 | "@types/react": "^18.0.9",
22 | "@types/react-dom": "^18.0.4",
23 | "autoprefixer": "^10.4.13",
24 | "eslint": "^8.15.0",
25 | "eslint-config-chimera": "workspace:*",
26 | "postcss": "^8.4.20",
27 | "react": "^18.1.0",
28 | "tailwind-config": "workspace:*",
29 | "tailwindcss": "^3.2.4",
30 | "tsconfig": "workspace:*",
31 | "tsup": "^6.5.0",
32 | "react-docgen": "^5.4.3",
33 | "typescript": "^4.5.3"
34 | },
35 | "publishConfig": {
36 | "access": "public"
37 | },
38 | "dependencies": {
39 | "@radix-ui/react-accessible-icon": "^1.0.1",
40 | "@radix-ui/react-accordion": "^1.1.0",
41 | "@radix-ui/react-alert-dialog": "^1.0.2",
42 | "@radix-ui/react-aspect-ratio": "^1.0.1",
43 | "@radix-ui/react-avatar": "^1.0.1",
44 | "@radix-ui/react-checkbox": "^1.0.1",
45 | "@radix-ui/react-collapsible": "^1.0.1",
46 | "@radix-ui/react-context-menu": "^2.1.1",
47 | "@radix-ui/react-dialog": "^1.0.2",
48 | "@radix-ui/react-dropdown-menu": "^2.0.1",
49 | "@radix-ui/react-hover-card": "^1.0.3",
50 | "@radix-ui/react-label": "^2.0.0",
51 | "@radix-ui/react-menubar": "^1.0.0",
52 | "@radix-ui/react-navigation-menu": "^1.1.1",
53 | "@radix-ui/react-popover": "^1.0.2",
54 | "@radix-ui/react-progress": "^1.0.1",
55 | "@radix-ui/react-radio-group": "^1.1.0",
56 | "@radix-ui/react-scroll-area": "^1.0.2",
57 | "@radix-ui/react-select": "^1.2.0",
58 | "@radix-ui/react-separator": "^1.0.1",
59 | "@radix-ui/react-slider": "^1.1.0",
60 | "@radix-ui/react-slot": "^1.0.1",
61 | "@radix-ui/react-switch": "^1.0.1",
62 | "@radix-ui/react-tabs": "^1.0.2",
63 | "@radix-ui/react-toggle": "^1.0.1",
64 | "@radix-ui/react-toggle-group": "^1.0.1",
65 | "@radix-ui/react-tooltip": "^1.0.3",
66 | "class-variance-authority": "^0.4.0",
67 | "clsx": "^1.2.1",
68 | "jsx-to-string": "^1.4.0",
69 | "lucide-react": "^0.109.0",
70 | "tailwind-merge": "^1.8.1"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/packages/components/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require("tailwind-config/postcss.config");
2 |
--------------------------------------------------------------------------------
/packages/components/src/Accordion.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import * as React from "react";
3 | import * as AccordionPrimitive from "@radix-ui/react-accordion";
4 | import { ChevronDown } from "lucide-react";
5 |
6 | import { cn } from "../utils";
7 |
8 | export const Accordion = (
9 | props: React.ComponentProps
10 | ) => {
11 | return <>>;
12 | };
13 |
14 | const Root = AccordionPrimitive.Root;
15 | Root.displayName = "Accordion.Root";
16 | Accordion.Root = Root;
17 |
18 | /**
19 | * Default Classes: ~ "border-b border-b-line" ~
20 | * sdiofh
21 | */
22 | const Item = React.forwardRef<
23 | React.ElementRef,
24 | React.ComponentPropsWithoutRef
25 | >(({ className, ...props }, ref) => (
26 |
31 | ));
32 | Item.displayName = "Accordion.Item";
33 | Accordion.Item = Item;
34 |
35 | /**
36 | * Default Classes: ~ "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180 w-fit" ~
37 | *
38 | */
39 | const Trigger = React.forwardRef<
40 | React.ElementRef,
41 | React.ComponentPropsWithoutRef
42 | >(({ className, children, ...props }, ref) => (
43 |
44 | svg]:rotate-180 w-fit",
48 | className
49 | )}
50 | {...props}
51 | >
52 | {children}
53 |
54 |
55 |
56 | ));
57 | Trigger.displayName = "Accordion.Trigger";
58 | Accordion.Trigger = Trigger;
59 |
60 | /**
61 | * Default Classes: ~ "overflow-hidden text-sm transition-all data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up w-fit" ~
62 | * Some other content
63 | */
64 | const Content = React.forwardRef<
65 | React.ElementRef,
66 | React.ComponentPropsWithoutRef
67 | >(({ className, children, ...props }, ref) => (
68 |
76 | {children}
77 |
78 | ));
79 | Content.displayName = "Accordion.Content";
80 | Accordion.Content = Content;
81 |
--------------------------------------------------------------------------------
/packages/components/src/AspectRatio.tsx:
--------------------------------------------------------------------------------
1 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio";
2 |
3 | const AspectRatio = ({ children }: { children: React.ReactNode }) => {
4 | return (
5 | {}
6 | );
7 | };
8 |
9 | const Root = AspectRatioPrimitive.Root;
10 | Root.displayName = "AspectRatio.Root";
11 | AspectRatio.Root = Root;
12 |
13 | export { AspectRatio };
14 |
--------------------------------------------------------------------------------
/packages/components/src/Avatar.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as AvatarPrimitive from "@radix-ui/react-avatar";
3 |
4 | import { cn } from "../utils";
5 |
6 | export const Avatar = ({
7 | src,
8 | fallback,
9 | }: {
10 | src: string;
11 | fallback: string;
12 | }) => {
13 | return (
14 |
15 |
16 | {fallback}
17 |
18 | );
19 | };
20 |
21 | type RootElement = React.ElementRef;
22 | type RootProps = React.ComponentPropsWithoutRef & {
23 | ignoreDefaultStyles?: boolean;
24 | };
25 |
26 | const Root = React.forwardRef((props, forwardedRef) => {
27 | const { className, ignoreDefaultStyles, ...rest } = props;
28 | return (
29 |
40 | );
41 | });
42 |
43 | Root.displayName = "Avatar.Root";
44 | Avatar.Root = Root;
45 |
46 | /**
47 | * Default Classes: ~ "aspect-square object-cover h-full w-full" ~
48 | *
49 | */
50 | const Image = React.forwardRef<
51 | React.ElementRef,
52 | React.ComponentPropsWithoutRef
53 | >(({ className, ...props }, ref) => (
54 |
59 | ));
60 | Image.displayName = "Avatar.Image";
61 | Avatar.Image = Image;
62 |
63 | /**
64 | * Default Classes: ~ "flex h-full w-full items-center justify-center rounded-full bg-base-content text-base" ~
65 | *
66 | */
67 | const Fallback = React.forwardRef<
68 | React.ElementRef,
69 | React.ComponentPropsWithoutRef
70 | >(({ className, ...props }, ref) => (
71 |
79 | ));
80 | Fallback.displayName = "Avatar.Fallback";
81 | Avatar.Fallback = Fallback;
82 |
--------------------------------------------------------------------------------
/packages/components/src/Button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { VariantProps, cva } from "class-variance-authority";
3 |
4 | import { cn } from "../utils";
5 |
6 | const buttonVariants = cva(
7 | "inline-flex w-fit items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-line focus:ring-offset-2",
8 | {
9 | variants: {
10 | variant: {
11 | default: "bg-primary text-primary-content hover:bg-primary-focus",
12 | secondary:
13 | "bg-secondary text-secondary-content hover:bg-secondary-focus",
14 | "secondary-outline":
15 | "bg-transparent border border-secondary text-secondary hover:bg-secondary-focus hover:text-secondary-content",
16 | "secondary-subtle":
17 | "bg-secondary-subtle text-secondary-subtle-content hover:bg-secondary hover:text-secondary-content",
18 | destructive: "bg-danger text-danger-content hover:bg-danger-focus",
19 | info: "bg-info text-info-content hover:bg-info-focus",
20 | success: "bg-success text-success-content hover:bg-success-focus",
21 | warning: "bg-warning text-warning-content hover:bg-warning-focus",
22 | outline:
23 | "bg-transparent border border-primary text-primary hover:bg-primary-focus hover:text-primary-content",
24 | subtle:
25 | "bg-primary-subtle text-primary-subtle-content hover:bg-primary hover:text-primary-content",
26 | ghost:
27 | "bg-transparent hover:bg-base-2 data-[state=open]:bg-transparent ",
28 | link: "bg-transparent underline-offset-4 hover:underline text-slate-900 hover:bg-transparent ",
29 | gradient:
30 | "bg-gradient-to-r from-primary to-secondary text-primary-content",
31 | gray: "bg-gray-200 text-gray-700 hover:bg-gray-300",
32 | },
33 | size: {
34 | default: "h-10 py-2 px-4",
35 | sm: "h-9 px-2 rounded-md",
36 | xs: "h-fit py-1 px-2 rounded-md",
37 | lg: "h-11 px-8 rounded-md",
38 | },
39 | },
40 | defaultVariants: {
41 | variant: "default",
42 | size: "default",
43 | },
44 | }
45 | );
46 |
47 | export interface ButtonProps
48 | extends React.ButtonHTMLAttributes,
49 | VariantProps {}
50 |
51 | /**
52 | * Defaults Classes: "inline-flex w-fit items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-line focus:ring-offset-2"
53 | *
54 | * Variants
55 | * ----
56 | * default: bg-primary text-primary-content hover:bg-primary-focus
57 | *
58 | * secondary: bg-secondary text-secondary-content hover:bg-secondary-focus
59 | *
60 | * secondary-outline: bg-transparent border border-secondary text-secondary hover:bg-secondary-focus hover:text-secondary-content
61 | *
62 | * secondary-subtle: bg-secondary-subtle text-secondary-subtle-content hover:bg-secondary hover:text-secondary-content
63 | *
64 | * destructive: bg-danger text-danger-content hover:bg-danger-focus
65 | *
66 | * info: bg-info text-info-content hover:bg-info-focus
67 | *
68 | * success: bg-success text-success-content hover:bg-success-focus
69 | *
70 | * warning: bg-warning text-warning-content hover:bg-warning-focus
71 | *
72 | * outline: bg-transparent border border-primary text-primary hover:bg-primary-focus hover:text-primary-content
73 | *
74 | * subtle: bg-primary-subtle text-primary-subtle-content hover:bg-primary hover:text-primary-content
75 | *
76 | * ghost: bg-transparent hover:bg-base-2 data-[state=open]:bg-transparent
77 | *
78 | * link: bg-transparent underline-offset-4 hover:underline text-slate-900 hover:bg-transparent
79 | *
80 | * gradient: bg-gradient-to-r from-primary to-secondary text-primary-content
81 | *
82 | * gray: bg-gray-200 text-gray-700 hover:bg-gray-300
83 | *
84 | * Sizes
85 | * ----
86 | * default: h-10 py-2 px-4
87 | *
88 | * sm: h-9 px-2 rounded-md
89 | *
90 | * xs: h-fit py-1 px-2 rounded-md
91 | *
92 | * lg: h-11 px-8 rounded-md
93 | */
94 | const Button = React.forwardRef(
95 | ({ className, variant, size, ...props }, ref) => {
96 | return (
97 |
102 | );
103 | }
104 | );
105 | Button.displayName = "Button";
106 |
107 | export { Button, buttonVariants };
108 |
--------------------------------------------------------------------------------
/packages/components/src/Checkbox.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
3 | import { Check } from "lucide-react";
4 |
5 | import { cn } from "../utils";
6 |
7 | export const Checkbox = ({ className }: { className: string }) => {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 | );
15 | };
16 |
17 | Checkbox.displayName = "Checkbox";
18 |
19 | /**
20 | * Default Classes: ~ "peer h-4 w-4 shrink-0 rounded-sm border border-line focus:outline-none focus:ring-2 focus:ring-line-focus focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 bg-input" ~
21 | *
22 | */
23 | const Root = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, ...props }, ref) => (
27 |
35 | {props.children}
36 |
37 | ));
38 |
39 | Root.displayName = "Checkbox.Root";
40 | Checkbox.Root = Root;
41 |
42 | /**
43 | * Default Classes: ~ "flex items-center justify-center" ~
44 | *
45 | */
46 | const Indicator = React.forwardRef<
47 | React.ElementRef,
48 | React.ComponentPropsWithoutRef
49 | >(({ className, children, ...props }, ref) => (
50 |
55 | {children || }
56 |
57 | ));
58 |
59 | Indicator.displayName = "Checkbox.Indicator";
60 | Checkbox.Indicator = Indicator;
61 |
--------------------------------------------------------------------------------
/packages/components/src/Collapsible.tsx:
--------------------------------------------------------------------------------
1 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
2 | import { CrossIcon, ExpandIcon } from "lucide-react";
3 |
4 | export const Collapsible = () => {
5 | return <>>;
6 | };
7 |
8 | const Root = CollapsiblePrimitive.Root;
9 | Root.displayName = "Collapsible.Root";
10 | Collapsible.Root = Root;
11 |
12 | const Trigger = CollapsiblePrimitive.Trigger;
13 | Trigger.displayName = "Collapsible.Trigger";
14 | Collapsible.Trigger = Trigger;
15 |
16 | const Content = CollapsiblePrimitive.Content;
17 | Content.displayName = "Collapsible.Content";
18 | Collapsible.Content = Content;
19 |
--------------------------------------------------------------------------------
/packages/components/src/Copy.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Button } from "./Button";
3 | import { Copy as CopyIcon, Check } from "lucide-react";
4 | import { cn } from "../utils";
5 |
6 | /**
7 | * This is a description
8 | * @param param0
9 | * @returns
10 | */
11 | export const Copy = ({
12 | className,
13 | defaultClassName = "absolute top-2 right-2 text-xs p-2 h-fit rounded-md bg-transparent",
14 | contentToCopy,
15 | copyIcon,
16 | successIcon,
17 | }: {
18 | className?: string;
19 | defaultClassName?: string;
20 | contentToCopy: string;
21 | copyIcon?: React.ReactNode;
22 | successIcon?: React.ReactNode;
23 | }) => {
24 | const [copied, setCopied] = React.useState(false);
25 | return (
26 | {
28 | navigator.clipboard.writeText(contentToCopy || "");
29 | setCopied(true);
30 | setTimeout(() => {
31 | setCopied(false);
32 | }, 1000);
33 | }}
34 | className={cn(defaultClassName, className)}
35 | >
36 | {copied
37 | ? successIcon ||
38 | : copyIcon || }
39 |
40 | );
41 | };
42 |
43 | Copy.displayName = "Copy";
44 |
--------------------------------------------------------------------------------
/packages/components/src/HoverCard.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
3 |
4 | import { cn } from "../utils";
5 |
6 | const HoverCard = HoverCardPrimitive.Root;
7 |
8 | const HoverCardTrigger = HoverCardPrimitive.Trigger;
9 |
10 | /**
11 | * Default Classes: ~ "z-50 w-64 rounded-md border border-line bg-white p-4 shadow-theme-md outline-none animate-in zoom-in-90 " ~
12 | *
13 | */
14 | const HoverCardContent = React.forwardRef<
15 | React.ElementRef,
16 | React.ComponentPropsWithoutRef
17 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
18 |
28 | ));
29 | HoverCardContent.displayName = "HoverCard.Content";
30 |
31 | export { HoverCard, HoverCardTrigger, HoverCardContent };
32 |
--------------------------------------------------------------------------------
/packages/components/src/Input.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | import { cn } from "../utils";
4 |
5 | export interface InputProps
6 | extends React.InputHTMLAttributes {}
7 |
8 | /**
9 | * Default Classes: ~ "flex h-10 w-full rounded-md border text-input-content border-line bg-input py-2 px-3 text-sm placeholder:text-input-content-2 placeholder:font-medium focus:outline-none focus:ring-2 focus:ring-line-focus focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" ~
10 | *
11 | */
12 | const Input = React.forwardRef(
13 | ({ className, ...props }, ref) => {
14 | return (
15 |
23 | );
24 | }
25 | );
26 | Input.displayName = "Input";
27 |
28 | export { Input };
29 |
--------------------------------------------------------------------------------
/packages/components/src/Label.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as LabelPrimitive from "@radix-ui/react-label";
3 | import { cn } from "../utils";
4 |
5 | export const Label = ({
6 | className,
7 | children,
8 | }: {
9 | className: string;
10 | children: React.ReactNode;
11 | }) => (
12 |
18 | {children}
19 |
20 | );
21 | Label.displayName = "Label";
22 |
23 | /**
24 | * Default Classes: ~ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" ~
25 | *
26 | */
27 | const Root = React.forwardRef<
28 | React.ElementRef,
29 | React.ComponentPropsWithoutRef
30 | >(({ className, ...props }, ref) => (
31 |
39 | ));
40 | Root.displayName = "Label.Root";
41 | Label.Root = Root;
42 |
--------------------------------------------------------------------------------
/packages/components/src/Popover.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import * as RadixPopover from "@radix-ui/react-popover";
3 | import * as React from "react";
4 | import { cn } from "../utils";
5 |
6 | export const Popover = ({
7 | buttonContent,
8 | children,
9 | onClick,
10 | className,
11 | }: {
12 | buttonContent: React.ReactNode;
13 | children: React.ReactNode | React.ReactNode[];
14 | onClick?: () => void;
15 | className?: string;
16 | }) => {
17 | return (
18 |
19 | {
21 | if (onClick) {
22 | onClick();
23 | }
24 | }}
25 | className={className}
26 | >
27 | {buttonContent}
28 |
29 |
30 |
31 | {children}
32 |
33 |
34 |
35 |
36 | );
37 | };
38 |
39 | Popover.displayName = "Popover";
40 |
41 | const Root = ({ children }: { children: React.ReactNode }) => {
42 | return {children} ;
43 | };
44 | Root.displayName = "Popover.Root";
45 | Popover.Root = Root;
46 |
47 | /**
48 | * Default Classes: ~ "px-2 py-1 w-fit bg-primary hover:bg-primary-focus text-primary-content rounded-md" ~
49 | *
50 | * @param className Default: `px-2`
51 | * @returns
52 | */
53 | const Trigger = React.forwardRef<
54 | React.ElementRef,
55 | React.ComponentPropsWithoutRef
56 | >((props, forwardedRef) => {
57 | return (
58 |
66 | {props.children}
67 |
68 | );
69 | });
70 | Trigger.displayName = "Popover.Trigger";
71 | Popover.Trigger = Trigger;
72 |
73 | const Portal = ({ children }: { children: React.ReactNode }) => {
74 | return {children} ;
75 | };
76 | Portal.displayName = "Popover.Portal";
77 | Popover.Portal = Portal;
78 |
79 | /**
80 | * Default Classes: ~ "p-4 flex items-center justify-center bg-overlay text-overlay-content mx-2 max-w-[300px] rounded-md" ~
81 | *
82 | */
83 | const Content = React.forwardRef<
84 | React.ElementRef,
85 | React.ComponentPropsWithoutRef
86 | >((props, forwardedRef) => {
87 | return (
88 |
96 | {props.children}
97 |
98 | );
99 | });
100 | Content.displayName = "Popover.Content";
101 | Popover.Content = Content;
102 |
103 | /**
104 | * Default Classes: ~ "fill-overlay" ~
105 | *
106 | */
107 | const Arrow = ({ className }: { className?: string }) => {
108 | return ;
109 | };
110 | Arrow.displayName = "Popover.Arrow";
111 | Popover.Arrow = Arrow;
112 |
113 | /**
114 | * Default Classes: ~ "absolute top-1 right-3" ~
115 | *
116 | */
117 | const Close = React.forwardRef<
118 | React.ElementRef,
119 | React.ComponentPropsWithoutRef
120 | >((props, forwardedRef) => {
121 | return (
122 |
127 | {props.children}
128 |
129 | );
130 | });
131 |
132 | Close.displayName = "Popover.Close";
133 | Popover.Close = Close;
134 |
--------------------------------------------------------------------------------
/packages/components/src/Progress.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as ProgressPrimitive from "@radix-ui/react-progress";
3 |
4 | import { cn } from "../utils";
5 |
6 | /**
7 | * To change indicator color, pass in bg-[color] to the color prop.
8 | */
9 | export const Progress = React.forwardRef<
10 | React.ElementRef,
11 | React.ComponentPropsWithoutRef
12 | >(({ className, value, color, ...props }, ref) => (
13 |
21 |
25 |
26 | ));
27 | Progress.displayName = "Progress";
28 |
--------------------------------------------------------------------------------
/packages/components/src/RadioGroup.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
3 | import { Circle } from "lucide-react";
4 |
5 | import { cn } from "../utils";
6 |
7 | export const RadioGroup = () => {
8 | return <>>;
9 | };
10 |
11 | /**
12 | * Default Classes: ~ "grid gap-2" ~
13 | *
14 | */
15 | const Root = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, ...props }, ref) => {
19 | return (
20 |
25 | );
26 | });
27 | Root.displayName = "RadioGroup.Root";
28 | RadioGroup.Root = Root;
29 |
30 | /**
31 | * Default Classes: ~ " h-4 w-4 rounded-full border border-line text-base-content hover:border-primary focus:outline-none focus:ring-2 focus:ring-line-focus focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" ~
32 | *
33 | */
34 | const Item = React.forwardRef<
35 | React.ElementRef,
36 | React.ComponentPropsWithoutRef
37 | >(({ className, children, ...props }, ref) => {
38 | return (
39 |
47 | {children}
48 |
49 | );
50 | });
51 | Item.displayName = "RadioGroup.Item";
52 | RadioGroup.Item = Item;
53 |
54 | /**
55 | * Default Classes: ~ "h-2.5 w-2.5 fill-primary" ~
56 | *
57 | */
58 | const Indicator = React.forwardRef<
59 | React.ElementRef,
60 | React.ComponentPropsWithoutRef
61 | >(({ className, children, ...props }, ref) => {
62 | return (
63 |
64 |
65 |
66 | );
67 | });
68 | Indicator.displayName = "RadioGroup.Indicator";
69 | RadioGroup.Indicator = Indicator;
70 |
--------------------------------------------------------------------------------
/packages/components/src/ScrollArea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
3 |
4 | import { cn } from "../utils";
5 |
6 | /**
7 | * Default Classes: ~ "relative overflow-hidden" ~
8 | *
9 | */
10 | const ScrollArea = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, children, ...props }, ref) => (
14 |
19 |
20 | {children}
21 |
22 |
23 |
24 |
25 | ));
26 | ScrollArea.displayName = "ScrollArea";
27 |
28 | /**
29 | * Default Classes: ~ "flex touch-none select-none transition-colors" ~
30 | *
31 | */
32 | const ScrollBar = React.forwardRef<
33 | React.ElementRef,
34 | React.ComponentPropsWithoutRef
35 | >(({ className, orientation = "vertical", ...props }, ref) => (
36 |
49 |
50 |
51 | ));
52 | ScrollBar.displayName = "ScrollBar";
53 |
54 | export { ScrollArea, ScrollBar };
55 |
--------------------------------------------------------------------------------
/packages/components/src/Select.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as SelectPrimitive from "@radix-ui/react-select";
5 | import { Check, ChevronDown } from "lucide-react";
6 |
7 | import { cn } from "../utils";
8 |
9 | export const Select = () => {
10 | return <>>;
11 | };
12 |
13 | const Root = SelectPrimitive.Root;
14 | Root.displayName = "Select.Root";
15 | Select.Root = Root;
16 |
17 | const Group = SelectPrimitive.Group;
18 | Group.displayName = "Select.Group";
19 | Select.Group = Group;
20 |
21 | const Value = SelectPrimitive.Value;
22 | Value.displayName = "Select.Value";
23 | Select.Value = Value;
24 |
25 | /**
26 | * Default Classes: ~ "flex h-10 w-full items-center justify-between rounded-md border border-line bg-input py-2 px-3 text-sm text-input-content placeholder:text-input-content-2 focus:outline-none focus:ring-2 focus:ring-line focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 " ~
27 | *
28 | */
29 | const Trigger = React.forwardRef<
30 | React.ElementRef,
31 | React.ComponentPropsWithoutRef
32 | >(({ className, children, ...props }, ref) => (
33 |
41 | {children}
42 | {/* */}
43 |
44 | ));
45 | Trigger.displayName = "Select.Trigger";
46 | Select.Trigger = Trigger;
47 |
48 | /**
49 | * Default Classes: ~ "h-4 w-4 opacity-50" ~
50 | *
51 | */
52 | const Icon = React.forwardRef<
53 | React.ElementRef,
54 | React.ComponentPropsWithoutRef
55 | >(({ className, ...props }, ref) => (
56 |
61 | {props.children || }
62 |
63 | ));
64 | Icon.displayName = "Select.Icon";
65 | Select.Icon = Icon;
66 |
67 | /**
68 | * Default Classes: ~ "relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-line bg-overlay text-overlay-content shadow-md animate-in fade-in-80" ~
69 | *
70 | */
71 | const Content = React.forwardRef<
72 | React.ElementRef,
73 | React.ComponentPropsWithoutRef
74 | >(({ className, children, ...props }, ref) => (
75 |
76 |
84 |
85 | {children}
86 |
87 |
88 |
89 | ));
90 | Content.displayName = "Select.Content";
91 | Select.Content = Content;
92 |
93 | /**
94 | * Default Classes: ~ "py-1.5 pr-2 pl-8 text-md font-semibold text-overlay-content-3" ~
95 | *
96 | */
97 | const Label = React.forwardRef<
98 | React.ElementRef,
99 | React.ComponentPropsWithoutRef
100 | >(({ className, ...props }, ref) => (
101 |
109 | ));
110 | Label.displayName = "Select.Label";
111 | Select.Label = Label;
112 |
113 | /**
114 | * Default Classes: ~ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm font-medium outline-none focus:bg-primary focus:text-primary-content data-[disabled]:pointer-events-none data-[disabled]:opacity-50" ~
115 | *
116 | */
117 | const Item = React.forwardRef<
118 | React.ElementRef,
119 | React.ComponentPropsWithoutRef
120 | >(({ className, children, ...props }, ref) => (
121 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | {children}
136 |
137 | ));
138 | Item.displayName = "Select.Item";
139 | Select.Item = Item;
140 |
141 | /**
142 | * Default Classes: ~ "-mx-1 my-1 h-px bg-line" ~
143 | *
144 | */
145 | const Separator = React.forwardRef<
146 | React.ElementRef,
147 | React.ComponentPropsWithoutRef
148 | >(({ className, ...props }, ref) => (
149 |
154 | ));
155 | Separator.displayName = "Select.Separator";
156 | Select.Separator = Separator;
157 |
--------------------------------------------------------------------------------
/packages/components/src/Separator.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as SeparatorPrimitive from "@radix-ui/react-separator";
3 |
4 | import { cn } from "../utils";
5 |
6 | /**
7 | * Default Classes: ~ "bg-slate-200 " ~
8 | *
9 | */
10 | const Separator = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(
14 | (
15 | { className, orientation = "horizontal", decorative = true, ...props },
16 | ref
17 | ) => (
18 |
29 | )
30 | );
31 | Separator.displayName = SeparatorPrimitive.Root.displayName;
32 |
33 | export { Separator };
34 |
--------------------------------------------------------------------------------
/packages/components/src/Showcase.tsx:
--------------------------------------------------------------------------------
1 | // Import raw text of DaisySelect.tsx
2 | // @ts-ignore
3 | // Leaving this here as a reference for using raw-loader
4 | // import ButtonRaw from "!!raw-loader!../../../packages/ui/src/Button.tsx";
5 | import React from "react";
6 | // @ts-ignore
7 | import reactElementToJSXString from "react-element-to-jsx-string";
8 | import { twMerge } from "tailwind-merge";
9 | import { findSubcomponent } from "../utils";
10 | import { ThemePicker } from "./ThemePicker";
11 | import { Copy } from "./Copy";
12 |
13 | export const Showcase = ({
14 | children,
15 | }: {
16 | children: React.ReactNode | React.ReactNode[];
17 | }) => {
18 | const childrenArray = Array.isArray(children) ? children : [children];
19 | // Get the individual subcomponents, Preview, Code, Children by checking name property
20 | const title = findSubcomponent(childrenArray, "Showcase.Title");
21 | const preview = findSubcomponent(childrenArray, "Showcase.Preview");
22 |
23 | return (
24 |
25 |
{title}
26 |
{preview}
27 |
28 | );
29 | };
30 |
31 | Showcase.displayName = "Showcase";
32 |
33 | /**
34 | *
35 | * @param componentPreviewClassName Default: bg-gradient-to-tr from-pink-300 via-orange-200 to-red-300 text-on-surface p-4 rounded-md flex items-center justify-center gap-4 mb-4
36 | * @param codePreviewClassName Default: bg-gray-800 p-4 rounded-md
37 | * @param code If code is provided, it will be displayed. Otherwise, it will be generated from children.
38 | * @returns
39 | */
40 | const Preview = ({
41 | children,
42 | componentPreviewClassName,
43 | codePreviewClassName,
44 | code,
45 | }: {
46 | children: React.ReactNode;
47 | componentPreviewClassName: string;
48 | codePreviewClassName: string;
49 | code?: string;
50 | }) => {
51 | const [copied, setCopied] = React.useState(false);
52 |
53 | const childrenArray = Array.isArray(children) ? children : [children];
54 | let childrenCode: string;
55 | if (!code) {
56 | // Generate code from children
57 | code = childrenArray
58 | .map((child) => {
59 | if (React.isValidElement(child)) {
60 | return reactElementToJSXString(child, {
61 | displayName: (element) => {
62 | if (React.isValidElement(element)) {
63 | // Check if type of element is a string
64 | if (typeof element?.type === "string") {
65 | return element?.type;
66 | }
67 | // @ts-ignore
68 | if (typeof element?.type?.displayName === "string") {
69 | // @ts-ignore
70 | return element?.type.displayName;
71 | }
72 | if (typeof element?.type.name === "string") {
73 | return element?.type.name;
74 | }
75 |
76 | return "NoDisplayName";
77 | }
78 | },
79 | });
80 | }
81 | })
82 | .join("\n") as string;
83 | }
84 |
85 | return (
86 |
87 |
93 |
94 |
95 |
96 | {children}
97 |
98 |
104 |
105 | {code}
106 |
107 |
108 | );
109 | };
110 | Preview.displayName = "Showcase.Preview";
111 | Showcase.Preview = Preview;
112 |
113 | const Code = ({ children }: { children: React.ReactNode }) => {
114 | return (
115 | {children}
116 | );
117 | };
118 | Code.displayName = "Showcase.Code";
119 | Showcase.Code = Code;
120 |
121 | const Title = ({ children }: { children: React.ReactNode }) => {
122 | return {children}
;
123 | };
124 |
125 | Title.displayName = "Showcase.Title";
126 | Showcase.Title = Title;
127 |
--------------------------------------------------------------------------------
/packages/components/src/Slider.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as SliderPrimitive from "@radix-ui/react-slider";
3 |
4 | import { cn } from "../utils";
5 |
6 | /**
7 | * Default Classes: ~ "relative flex w-full touch-none select-none items-center" ~
8 | *
9 | */
10 | const Slider = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, ...props }, ref) => (
14 |
22 |
23 |
24 |
25 |
26 |
27 | ));
28 | Slider.displayName = "Slider";
29 |
30 | export { Slider };
31 |
--------------------------------------------------------------------------------
/packages/components/src/Switch.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as SwitchPrimitives from "@radix-ui/react-switch";
3 |
4 | import { cn } from "../utils";
5 |
6 | export const Switch = ({
7 | className,
8 | children,
9 | }: {
10 | className: string;
11 | children: React.ReactNode;
12 | }) => (
13 |
19 |
24 |
25 | );
26 | Switch.displayName = "Switch";
27 |
28 | /**
29 | * Default Classes: ~ "peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=unchecked]:bg-slate-200 data-[state=checked]:bg-primary" ~
30 | *
31 | */
32 | const Root = React.forwardRef<
33 | React.ElementRef,
34 | React.ComponentPropsWithoutRef
35 | >(({ className, ...props }, ref) => (
36 |
44 | {props.children}
45 |
46 | ));
47 | Root.displayName = "Switch.Root";
48 | Switch.Root = Root;
49 |
50 | /**
51 | * Default Classes: ~ "pointer-events-none block h-5 w-5 rounded-full bg-white shadow-lg ring-0 transition-transform data-[state=unchecked]:translate-x-0 data-[state=checked]:translate-x-5" ~
52 | *
53 | */
54 | const Thumb = React.forwardRef<
55 | React.ElementRef,
56 | React.ComponentPropsWithoutRef
57 | >(({ className, ...props }, ref) => (
58 |
63 | ));
64 | Thumb.displayName = "Switch.Thumb";
65 | Switch.Thumb = Thumb;
66 |
--------------------------------------------------------------------------------
/packages/components/src/Tabs.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as TabsPrimitive from "@radix-ui/react-tabs";
3 |
4 | import { cn } from "../utils";
5 |
6 | export const Tabs = ({
7 | className,
8 | children,
9 | }: {
10 | className: string;
11 | children: React.ReactNode;
12 | }) => {
13 | return <>>;
14 | };
15 | Tabs.displayName = "Tabs";
16 |
17 | const Root = TabsPrimitive.Root;
18 | Root.displayName = "Tabs.Root";
19 | Tabs.Root = Root;
20 |
21 | /**
22 | * Default Classes: ~ "mt-2 rounded-md border border-line p-6 " ~
23 | *
24 | */
25 | const Content = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, ...props }, ref) => (
29 |
34 | ));
35 | Content.displayName = "Tabs.Content";
36 | Tabs.Content = Content;
37 |
38 | /**
39 | * Default Classes: ~ "inline-flex items-center justify-center rounded-md bg-base-2 p-1" ~
40 | *
41 | */
42 | const List = React.forwardRef<
43 | React.ElementRef,
44 | React.ComponentPropsWithoutRef
45 | >(({ className, ...props }, ref) => (
46 |
54 | ));
55 | List.displayName = "Tabs.List";
56 | Tabs.List = List;
57 |
58 | /**
59 | * Default Classes: ~ "inline-flex min-w-[100px] items-center justify-center rounded-[0.185rem] px-3 py-1.5 text-sm font-medium text-base-content-2 transition-all disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-base data-[state=active]:text-base-content data-[state=active]:shadow-sm" ~
60 | *
61 | */
62 | const Trigger = React.forwardRef<
63 | React.ElementRef,
64 | React.ComponentPropsWithoutRef
65 | >(({ className, ...props }, ref) => (
66 |
74 | ));
75 |
76 | Trigger.displayName = "Tabs.Trigger";
77 | Tabs.Trigger = Trigger;
78 |
--------------------------------------------------------------------------------
/packages/components/src/Test.tsx:
--------------------------------------------------------------------------------
1 | export const Copy = () => {};
2 |
--------------------------------------------------------------------------------
/packages/components/src/TextArea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | import { cn } from "../utils";
4 |
5 | export interface TextareaProps
6 | extends React.TextareaHTMLAttributes {}
7 |
8 | /**
9 | * Default Classes: ~ "flex h-20 w-full rounded-md border border-line bg-input py-2 px-3 text-sm placeholder:text-input-content-2 focus:outline-none focus:ring-2 focus:ring-line-focus focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 " ~
10 | *
11 | */
12 | const TextArea = React.forwardRef(
13 | ({ className, ...props }, ref) => {
14 | return (
15 |
23 | );
24 | }
25 | );
26 | TextArea.displayName = "TextArea";
27 |
28 | export { TextArea };
29 |
--------------------------------------------------------------------------------
/packages/components/src/ThemePicker.tsx:
--------------------------------------------------------------------------------
1 | import { CheckIcon } from "@radix-ui/react-icons";
2 | import { useEffect, useState } from "react";
3 | import { Popover } from "./Popover";
4 | import * as RadioGroup from "@radix-ui/react-radio-group";
5 | import { twMerge } from "tailwind-merge";
6 | // This component is super hacky.. using local storage to store the theme, and then using useEffect to set the theme on mount
7 |
8 | export type Item = {
9 | value: string;
10 | label: string;
11 | disabled?: boolean;
12 | };
13 |
14 | export type Group = {
15 | groupLabel: string;
16 | items: Item[];
17 | };
18 |
19 | export type Items = Item[] | Group[];
20 |
21 | const ThemeButton = ({
22 | theme,
23 | setSelectedTheme,
24 | selectedTheme,
25 | className,
26 | }: {
27 | theme: Item;
28 | setSelectedTheme: Function;
29 | selectedTheme: Item;
30 | className?: string;
31 | }) => {
32 | return (
33 | {
43 | setSelectedTheme(theme);
44 | }}
45 | >
46 | {theme.value === selectedTheme.value && (
47 |
48 | )}{" "}
49 | {theme.label}
50 |
51 | );
52 | };
53 |
54 | const themes = [
55 | {
56 | value: "chimera",
57 | label: "Chimera",
58 | },
59 | {
60 | value: "zookeper",
61 | label: "Zookeper",
62 | },
63 | {
64 | value: "gunmetal",
65 | label: "Gunmetal",
66 | },
67 | ];
68 |
69 | export const ThemePicker = ({ className }: { className?: string }) => {
70 | const [selectedTheme, setSelectedTheme] = useState(themes[0]);
71 |
72 | useEffect(() => {
73 | const themeFromLocalStorage = localStorage.getItem("theme");
74 | // Set the theme if it exists in localStorage
75 | if (themeFromLocalStorage) {
76 | setSelectedTheme({
77 | value: themeFromLocalStorage,
78 |
79 | label:
80 | themeFromLocalStorage.charAt(0).toUpperCase() +
81 | themeFromLocalStorage.slice(1),
82 | });
83 | }
84 | }, []);
85 |
86 | useEffect(() => {
87 | document.documentElement.setAttribute("data-theme", selectedTheme.value);
88 | localStorage.setItem("theme", selectedTheme.value);
89 | }, [selectedTheme]);
90 |
91 | return (
92 | {
94 | // get the current theme from localStorage
95 | const themeFromLocalStorage = localStorage.getItem("theme");
96 | // set the theme if it exists in localStorage
97 | if (themeFromLocalStorage) {
98 | setSelectedTheme({
99 | value: themeFromLocalStorage,
100 | label:
101 | themeFromLocalStorage.charAt(0).toUpperCase() +
102 | themeFromLocalStorage.slice(1),
103 | });
104 | }
105 | }}
106 | buttonContent={
107 |
115 |
120 |
121 | }
122 | className={className}
123 | >
124 |
125 | {themes.map((theme) => {
126 | return (
127 |
134 | );
135 | })}
136 |
137 |
138 | );
139 | };
140 |
--------------------------------------------------------------------------------
/packages/components/src/Toggle.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as TogglePrimitive from "@radix-ui/react-toggle";
3 | import { VariantProps, cva } from "class-variance-authority";
4 |
5 | import { cn } from "../utils";
6 |
7 | const toggleVariants = cva(
8 | "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors data-[state=on]:bg-primary-subtle",
9 | {
10 | variants: {
11 | variant: {
12 | default: "bg-transparent",
13 | outline: "bg-transparent border border-line hover:bg-base-2",
14 | },
15 | size: {
16 | default: "h-10 px-3",
17 | sm: "h-9 px-2.5",
18 | lg: "h-11 px-5",
19 | },
20 | },
21 | defaultVariants: {
22 | variant: "default",
23 | size: "default",
24 | },
25 | }
26 | );
27 |
28 | const Toggle = ({
29 | className,
30 | variant,
31 | size,
32 | ...props
33 | }: {
34 | className?: string;
35 | variant?: VariantProps["variant"];
36 | size?: VariantProps["size"];
37 | props: React.ComponentPropsWithoutRef;
38 | }) => (
39 |
43 | );
44 |
45 | Toggle.displayName = "Toggle";
46 |
47 | const Root = React.forwardRef<
48 | React.ElementRef,
49 | React.ComponentPropsWithoutRef &
50 | VariantProps
51 | >(({ className, variant, size, ...props }, ref) => (
52 |
57 | ));
58 | Root.displayName = "Toggle.Root";
59 | Toggle.Root = Root;
60 |
61 | export { Toggle, toggleVariants };
62 |
--------------------------------------------------------------------------------
/packages/components/src/Tooltip.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import * as React from "react";
3 | import * as TooltipPrimitive from "@radix-ui/react-tooltip";
4 |
5 | import { cn } from "../utils";
6 |
7 | export const Tooltip = ({ ...props }) => ;
8 | Tooltip.displayName = "Tooltip";
9 |
10 | const Root = TooltipPrimitive.Root;
11 | Root.displayName = "Tooltip.Root";
12 | Tooltip.Root = Root;
13 |
14 | const Provider = TooltipPrimitive.Provider;
15 | Provider.displayName = "Tooltip.Provider";
16 | Tooltip.Provider = Provider;
17 |
18 | const Trigger = TooltipPrimitive.Trigger;
19 | Trigger.displayName = "Tooltip.Trigger";
20 | Tooltip.Trigger = Trigger;
21 |
22 | /**
23 | * Default Classes: ~ "fill-overlay-2" ~
24 | *
25 | */
26 | const Arrow = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >((props, forwardedRef) => {
30 | return (
31 |
36 | );
37 | });
38 | Arrow.displayName = "Tooltip.Arrow";
39 | Tooltip.Arrow = Arrow;
40 |
41 | /**
42 | * Default Classes: ~ "z-50 overflow-hidden rounded-md bg-overlay-2 px-3 py-1.5 text-sm text-overlay-content shadow-theme-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 " ~
43 | *
44 | */
45 | const Content = React.forwardRef<
46 | React.ElementRef,
47 | React.ComponentPropsWithoutRef
48 | >(({ className, sideOffset = 4, ...props }, ref) => (
49 |
58 | ));
59 | Content.displayName = "Tooltip.Content";
60 | Tooltip.Content = Content;
61 |
--------------------------------------------------------------------------------
/packages/components/src/index.tsx:
--------------------------------------------------------------------------------
1 | export { Accordion } from "./Accordion";
2 | export { AlertDialog } from "./AlertDialog";
3 | export { AspectRatio } from "./AspectRatio";
4 | export { Avatar } from "./Avatar";
5 | export { Copy } from "./Copy";
6 | export { Button } from "./Button";
7 | export { Checkbox } from "./Checkbox";
8 | export { Collapsible } from "./Collapsible";
9 | export { Dialog } from "./Dialog";
10 | export { Popover } from "./Popover";
11 | export { Showcase } from "./Showcase";
12 | export { ThemePicker } from "./ThemePicker";
13 | export { Tooltip } from "./Tooltip";
14 | export { DropdownMenu } from "./DropdownMenu";
15 | export { ContextMenu } from "./ContextMenu";
16 | export { Progress } from "./Progress";
17 | export { Menubar } from "./Menubar";
18 | export { NavigationMenu } from "./NavigationMenu";
19 | export { cn } from "../utils";
20 | export { RadioGroup } from "./RadioGroup";
21 | export { Label } from "./Label";
22 | export { Select } from "./Select";
23 | export { Switch } from "./Switch";
24 | export { TextArea } from "./TextArea";
25 | export { Tabs } from "./Tabs";
26 | export { Input } from "./Input";
27 | export { Toggle } from "./Toggle";
28 |
--------------------------------------------------------------------------------
/packages/components/styles.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | :root,
7 | .granola {
8 | /* primary */
9 | --primary: hsl(38, 88%, 48%);
10 | --primary-lighter: hsl(195, 100%, 72%);
11 | --primary-darker: hsl(195, 94%, 38%);
12 | /* secondary */
13 | --secondary: hsl(0, 0%, 14%);
14 | --secondary-lighter: hsl(0, 0%, 22%);
15 | --secondary-darker: hsl(0, 0%, 3%);
16 | /* info */
17 | --info: hsl(180, 2%, 98%);
18 | --info-lighter: hsl(180, 2%, 94%);
19 | --info-darker: hsl(180, 2%, 90%);
20 | /* success */
21 | --success: hsl(142, 71%, 45%);
22 | --success-lighter: hsl(141, 75%, 73%);
23 | --success-darker: hsl(142, 71%, 29%);
24 | /* warning */
25 | --warning: hsl(180, 2%, 98%);
26 | --warning-lighter: hsl(180, 2%, 94%);
27 | --warning-darker: hsl(180, 2%, 90%);
28 | /* danger */
29 | --danger: hsl(180, 2%, 98%);
30 | --danger-lighter: hsl(180, 2%, 94%);
31 | --danger-darker: hsl(180, 2%, 90%);
32 | /* surfaces */
33 | --base: hsl(43, 64%, 98%);
34 | --base: hsl(45, 36%, 96%);
35 | --base-2: hsl(0, 0%, 20%);
36 | --base-3: hsl(45, 36%, 96%);
37 | --overlay: hsl(43, 64%, 98%);
38 | --input: hsl(180, 2%, 98%);
39 |
40 | /* borders */
41 | --line: hsl(0, 0%, 15%);
42 | --line-1: hsl(0, 0%, 30%);
43 | --line-2: hsl(180, 2%, 89%);
44 |
45 | /* on surface */
46 | --on-surface: hsl(0, 0%, 14%);
47 | --on-surface-1: hsl(0, 0%, 22%);
48 | --on-surface-2: hsl(0, 0%, 43%);
49 | --on-surface-3: hsl(0, 0%, 69%);
50 | --clickable: hsl(0, 3%, 7%);
51 | --clickable-hover: hsl(195, 100%, 44%);
52 |
53 | --on-primary: hsl(180, 2%, 98%);
54 | --on-primary-contrast: hsl(0, 0%, 3%);
55 |
56 | --on-info: hsl(0, 2%, 8%);
57 | --on-info-contrast: hsl(180, 2%, 70%);
58 |
59 | --on-success: hsl(0, 0%, 100%);
60 | --on-success-contrast: hsl(144, 61%, 20%);
61 |
62 | --on-warning: hsl(180, 2%, 98%);
63 | --on-warning-contrast: hsl(180, 2%, 70%);
64 |
65 | --on-danger: hsl(180, 2%, 98%);
66 | --on-danger-contrast: hsl(180, 2%, 70%);
67 |
68 | /* Other styles */
69 | --theme-rounded: 1rem;
70 | --theme-rounded-sm: 0.3rem;
71 | --theme-rounded-md: 0.4rem;
72 | --theme-rounded-lg: 0.5rem;
73 | --theme-rounded-xl: 0.6rem;
74 | --theme-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1),
75 | 0 1px 2px -1px rgb(0 0 0 / 0.1);
76 | --theme-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
77 | --theme-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1),
78 | 0 2px 4px -2px rgb(0 0 0 / 0.1);
79 | --theme-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1),
80 | 0 4px 6px -4px rgb(0 0 0 / 0.1);
81 | --theme-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1),
82 | 0 8px 10px -6px rgb(0 0 0 / 0.1);
83 | --theme-shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
84 | }
85 |
86 | .cool {
87 | /* primary */
88 | --primary: hsl(195, 100%, 44%);
89 | --primary-lighter: hsl(195, 100%, 72%);
90 | --primary-darker: hsl(195, 94%, 38%);
91 | /* secondary */
92 | --secondary: hsl(0, 0%, 14%);
93 | --secondary-lighter: hsl(0, 0%, 22%);
94 | --secondary-darker: hsl(0, 0%, 3%);
95 | /* info */
96 | --info: hsl(180, 2%, 98%);
97 | --info-lighter: hsl(180, 2%, 94%);
98 | --info-darker: hsl(180, 2%, 90%);
99 | /* success */
100 | --success: hsl(142, 71%, 45%);
101 | --success-lighter: hsl(141, 75%, 73%);
102 | --success-darker: hsl(142, 71%, 29%);
103 | /* warning */
104 | --warning: hsl(180, 2%, 98%);
105 | --warning-lighter: hsl(180, 2%, 94%);
106 | --warning-darker: hsl(180, 2%, 90%);
107 | /* danger */
108 | --danger: hsl(180, 2%, 98%);
109 | --danger-lighter: hsl(180, 2%, 94%);
110 | --danger-darker: hsl(180, 2%, 90%);
111 | /* surfaces */
112 | --base: hsl(43, 64%, 98%);
113 | --base: hsl(45, 36%, 96%);
114 | --base-2: hsl(0, 0%, 20%);
115 | --base-3: hsl(45, 36%, 96%);
116 | --overlay: hsl(43, 64%, 98%);
117 | --input: hsl(180, 2%, 98%);
118 |
119 | /* borders */
120 | --line: hsl(0, 0%, 15%);
121 | --line-1: hsl(0, 0%, 30%);
122 | --line-2: hsl(180, 2%, 89%);
123 |
124 | /* on surface */
125 | --on-surface: hsl(0, 0%, 14%);
126 | --on-surface-1: hsl(0, 0%, 22%);
127 | --on-surface-2: hsl(0, 0%, 43%);
128 | --on-surface-3: hsl(0, 0%, 69%);
129 | --clickable: hsl(0, 3%, 7%);
130 | --clickable-hover: hsl(195, 100%, 44%);
131 |
132 | --on-primary: hsl(180, 2%, 98%);
133 | --on-primary-contrast: hsl(0, 0%, 3%);
134 |
135 | --on-info: hsl(0, 2%, 8%);
136 | --on-info-contrast: hsl(180, 2%, 70%);
137 |
138 | --on-success: hsl(0, 0%, 100%);
139 | --on-success-contrast: hsl(144, 61%, 20%);
140 |
141 | --on-warning: hsl(180, 2%, 98%);
142 | --on-warning-contrast: hsl(180, 2%, 70%);
143 |
144 | --on-danger: hsl(180, 2%, 98%);
145 | --on-danger-contrast: hsl(180, 2%, 70%);
146 |
147 | /* Other styles */
148 | --theme-rounded: 1rem;
149 | --theme-rounded-sm: 0.3rem;
150 | --theme-rounded-md: 0.4rem;
151 | --theme-rounded-lg: 0.5rem;
152 | --theme-rounded-xl: 0.6rem;
153 | --theme-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1),
154 | 0 1px 2px -1px rgb(0 0 0 / 0.1);
155 | --theme-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
156 | --theme-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1),
157 | 0 2px 4px -2px rgb(0 0 0 / 0.1);
158 | --theme-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1),
159 | 0 4px 6px -4px rgb(0 0 0 / 0.1);
160 | --theme-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1),
161 | 0 8px 10px -6px rgb(0 0 0 / 0.1);
162 | --theme-shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
163 | }
164 | }
165 | @layer utilities {
166 | .flex-center {
167 | display: flex;
168 | justify-content: center;
169 | align-items: center;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/packages/components/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./pages/**/*.{js,ts,jsx,tsx,md,}",
5 | "./components/**/*.{js,ts,jsx,tsx}",
6 | "./examples/**/*.{js,ts,jsx,tsx}",
7 | "./src/**/*.{js,ts,jsx,tsx, mdx}",
8 | "../packages/ui/**/*{.js,.ts,.jsx,.tsx}",
9 | "../../packages/ui/**/*{.js,.ts,.jsx,.tsx,.mjs}",
10 | ],
11 | plugins: [],
12 | };
13 |
--------------------------------------------------------------------------------
/packages/components/test.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/williamlmao/chimera-ui/78d8d29b49301f6f3b935663f00dcf81f67464b5/packages/components/test.json
--------------------------------------------------------------------------------
/packages/components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tsconfig/react-library.json",
3 | "include": ["."],
4 | "exclude": ["dist", "build", "node_modules"]
5 | }
6 |
--------------------------------------------------------------------------------
/packages/components/tsdocSync.js:
--------------------------------------------------------------------------------
1 | // This script looks at each subcomponent, extracts the default styling, and adds it to a tsdoc above the component.
2 | // Requires that the code is properly formatted, with a line break between each subcomponent.
3 |
4 | const fs = require("fs");
5 | const path = require("path");
6 |
7 | const files = fs.readdirSync(path.join(__dirname, "src"));
8 |
9 | files.forEach((file) => {
10 | const componentName = file.split(".")[0];
11 | console.log("\n ---- \n");
12 | console.log("Syncing tsdocs for: ~~~", componentName, "~~~");
13 | const code = fs.readFileSync(
14 | path.join(__dirname, `src/${componentName}.tsx`),
15 | "utf8"
16 | );
17 | const codeblocks = code.split(";\n\n");
18 | let updatesMade = [];
19 | const updatedCodeBlocks = codeblocks.map((codeblock) => {
20 | // If codeblock contains more than two const statements, then the code was not properly formatted and split
21 | blockName = codeblock.match(/(?<=const ).*?(?= =)/g)?.[0];
22 | const blockNameFirstLetterIsUppercase =
23 | blockName?.charAt(0) === blockName?.charAt(0).toUpperCase();
24 | const isComponent =
25 | codeblock.includes("const") &&
26 | codeblock.includes(componentName) &&
27 | blockNameFirstLetterIsUppercase;
28 | const containsTsDoc = codeblock.includes("/**");
29 | const containsDefaultClassName = codeblock.includes("cn(");
30 | const isMainComponent = codeblock.includes("export const");
31 | // Do not run any updates on main components, as users do not need to know the default styling since they would be unable to edit it at deeper levels anyways
32 | if (!isComponent || !containsDefaultClassName || isMainComponent)
33 | return codeblock;
34 | const constCount = (codeblock.match(/const/g) || []).length;
35 | if (constCount >= 2) {
36 | console.log(
37 | `${componentName}.tsx - ${blockName} --- CODE IS NOT PROPERLY FORMATTED. Make sure there is a line break between subcomponents, otherwise tsdocs cannot be synced. \n`
38 | );
39 | return codeblock;
40 | }
41 | const tsDoc = codeblock.match(/\/\*\*[\s\S]*?\*\//g)?.[0];
42 | let updatedTsDoc = tsDoc;
43 | // cnBlock is the cn() function call
44 | const cnBlock = codeblock.match(/cn\([\s\S]*?\)/g)?.[0];
45 | // Extract the classes
46 | const defaultStyles = cnBlock?.match(/"([^"]*)"/g)?.[0];
47 | // TODO add the classNames into the tsdoc
48 | if (isComponent && containsDefaultClassName) {
49 | if (containsTsDoc) {
50 | // Get text between " ~ " and " ~ " in tsDoc, then the text between the quotes
51 | const existingTsDocStyles = tsDoc
52 | .match(/~([^~]*)~/g)?.[0]
53 | .match(/"([^"]*)"/g)?.[0];
54 | if (existingTsDocStyles) {
55 | updatedTsDoc = tsDoc.replace(existingTsDocStyles, defaultStyles);
56 | updatesMade.push(
57 | `${componentName}.${blockName} - defaultStyles synced`
58 | );
59 | }
60 | if (!existingTsDocStyles && defaultStyles) {
61 | updatedTsDoc = tsDoc.replace(
62 | "/**",
63 | `/**\n * Default Classes: ~ ${defaultStyles} ~`
64 | );
65 | updatesMade.push(
66 | `${componentName}.${blockName} - defaultStyles added`
67 | );
68 | }
69 | } else {
70 | if (!defaultStyles) return codeblock;
71 | updatedTsDoc = `/**\n * Default Classes: ~ ${defaultStyles} ~\n *\n */`;
72 | updatesMade.push(`${componentName}.${blockName} - tsDoc added`);
73 | }
74 | }
75 | if (containsTsDoc) {
76 | codeblock = codeblock.replace(tsDoc, updatedTsDoc);
77 | } else if (!containsTsDoc && containsDefaultClassName) {
78 | codeblock = codeblock.replace("const", `${updatedTsDoc}\nconst`);
79 | }
80 | return codeblock;
81 | });
82 |
83 | if (updatesMade.length > 0) {
84 | console.log(updatesMade.join("\n"));
85 | const updatedCode = updatedCodeBlocks.join(";\n\n");
86 |
87 | fs.writeFileSync(
88 | path.join(__dirname, `src/${componentName}.tsx`),
89 | updatedCode,
90 | "utf8"
91 | );
92 | console.log(`${componentName}.tsx - updated! 🎉`);
93 | }
94 | });
95 |
--------------------------------------------------------------------------------
/packages/components/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, Options } from "tsup";
2 |
3 | export default defineConfig((options: Options) => ({
4 | treeshake: true,
5 | splitting: true,
6 | entry: ["src/**/*.tsx"],
7 | format: ["esm"],
8 | dts: true,
9 | minify: true,
10 | clean: true,
11 | external: ["react"],
12 | ...options,
13 | }));
14 |
--------------------------------------------------------------------------------
/packages/components/utils/index.tsx:
--------------------------------------------------------------------------------
1 | import clsx, { ClassValue } from "clsx";
2 | import React from "react";
3 | import { twMerge } from "tailwind-merge";
4 |
5 | export function findSubcomponent(
6 | children: React.ReactNode | React.ReactNode[],
7 | displayName: string
8 | ) {
9 | return React.Children.map(children, (child) => {
10 | if (!React.isValidElement(child)) return null;
11 | // @ts-ignore
12 | return child?.type?.displayName === displayName ? child : null;
13 | });
14 | }
15 |
16 | export function cn(...inputs: ClassValue[]) {
17 | return twMerge(clsx(inputs));
18 | }
19 |
--------------------------------------------------------------------------------
/packages/eslint-config-chimera/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["next", "turbo", "prettier"],
3 | rules: {
4 | "@next/next/no-html-link-for-pages": "off",
5 | "react/jsx-key": "off",
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/packages/eslint-config-chimera/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eslint-config-chimera",
3 | "version": "0.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "private": true,
7 | "dependencies": {
8 | "eslint-config-next": "latest",
9 | "eslint-config-prettier": "^8.3.0",
10 | "eslint-plugin-react": "7.29.4",
11 | "eslint-config-turbo": "latest"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/tailwind-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwind-config",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "index.js",
6 | "devDependencies": {
7 | "tailwindcss": "^3.2.4"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/tailwind-config/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/packages/tailwind-config/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./pages/**/*.{js,ts,jsx,tsx,md,}",
5 | "./components/**/*.{js,ts,jsx,tsx}",
6 | "./examples/**/*.{js,ts,jsx,tsx}",
7 | "./src/**/*.{js,ts,jsx,tsx, mdx}",
8 | "./stories/**/*.{js,ts,jsx,tsx,mdx}",
9 | "../packages/ui/**/*{.js,.ts,.jsx,.tsx}",
10 | "../../packages/ui/**/*{.js,.ts,.jsx,.tsx}",
11 | ],
12 | theme: {
13 | extend: {
14 | transitionProperty: {
15 | width: "width",
16 | },
17 | colors: {
18 | test: "var(--primary)",
19 | primary: "var(--primary)",
20 | "primary-lighter": "var(--primary-lighter)",
21 | "primary-darker": "var(--primary-darker)",
22 | secondary: "var(--secondary)",
23 | "secondary-lighter": "var(--secondary-lighter)",
24 | "secondary-darker": "var(--secondary-darker)",
25 | info: "var(--info)",
26 | "info-lighter": "var(--info-lighter)",
27 | "info-darker": "var(--info-darker)",
28 | success: "var(--success)",
29 | "success-lighter": "var(--success-lighter)",
30 | "success-darker": "var(--success-darker)",
31 | warning: "var(--warning)",
32 | "warning-lighter": "var(--warning-lighter)",
33 | "warning-darker": "var(--warning-darker)",
34 | danger: "var(--danger)",
35 | "danger-lighter": "var(--danger-lighter)",
36 | "danger-darker": "var(--danger-darker)",
37 | base: "var(--base)",
38 | "base-1": "var(--base)",
39 | "base-2": "var(--base-2)",
40 | "base-3": "var(--base-3)",
41 | overlay: "var(--overlay)",
42 | input: "var(--input)",
43 | line: "var(--line)",
44 | "line-1": "var(--line-1)",
45 | "line-2": "var(--line-2)",
46 | "on-surface": "var(--on-surface)",
47 | "on-surface-1": "var(--on-surface-1)",
48 | "on-surface-2": "var(--on-surface-2)",
49 | "on-surface-3": "var(--on-surface-3)",
50 | clickable: "var(--clickable)",
51 | "clickable-hover": "var(--clickable-hover)",
52 | "on-primary": "var(--on-primary)",
53 | "on-primary-contrast": "var(--on-primary-contrast)",
54 | "on-info": "var(--on-info)",
55 | "on-info-contrast": "var(--on-info-contrast)",
56 | "on-success": "var(--on-success)",
57 | "on-success-contrast": "var(--on-success-contrast)",
58 | "on-warning": "var(--on-warning)",
59 | "on-warning-contrast": "var(--on-warning-contrast)",
60 | "on-danger": "var(--on-danger)",
61 | "on-danger-contrast": "var(--on-danger-contrast)",
62 | },
63 | borderWidth: {
64 | "width-theme": "var(--theme-border-width)",
65 | },
66 | borderColor: {
67 | "color-theme": "var(--line)",
68 | },
69 | borderRadius: {
70 | theme: "var(--theme-rounded)",
71 | "theme-md": "var(--theme-rounded-md)",
72 | "theme-lg": "var(--theme-rounded-lg)",
73 | },
74 | boxShadow: {
75 | theme: "var(--theme-shadow)",
76 | "theme-lg": "var(--theme-shadow-lg)",
77 | "theme-sm": "var(--theme-shadow-sm)",
78 | "theme-xs": "var(--theme-shadow-xs)",
79 | "theme-md": "var(--theme-shadow-md)",
80 | },
81 | outlineWidth: {
82 | "width-theme": "var(--theme-border-width)",
83 | },
84 | outlineColor: {
85 | "color-theme": "var(--line)",
86 | },
87 | divideWidth: {
88 | theme: "var(--theme-border-width)",
89 | },
90 | divideColor: {
91 | theme: "var(--theme-border-color)",
92 | },
93 | },
94 | },
95 | plugins: [],
96 | };
97 |
--------------------------------------------------------------------------------
/packages/tsconfig/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Default",
4 | "compilerOptions": {
5 | "composite": false,
6 | "declaration": true,
7 | "declarationMap": true,
8 | "esModuleInterop": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "inlineSources": false,
11 | "isolatedModules": true,
12 | "moduleResolution": "node",
13 | "noUnusedLocals": false,
14 | "noUnusedParameters": false,
15 | "preserveWatchOutput": true,
16 | "skipLibCheck": true,
17 | "strict": true
18 | },
19 | "exclude": ["node_modules"]
20 | }
21 |
--------------------------------------------------------------------------------
/packages/tsconfig/nextjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Next.js",
4 | "extends": "./base.json",
5 | "compilerOptions": {
6 | "target": "es5",
7 | "lib": ["dom", "dom.iterable", "esnext"],
8 | "allowJs": true,
9 | "skipLibCheck": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noEmit": true,
13 | "incremental": true,
14 | "esModuleInterop": true,
15 | "module": "esnext",
16 | "resolveJsonModule": true,
17 | "isolatedModules": true,
18 | "jsx": "preserve"
19 | },
20 | "include": ["src", "next-env.d.ts"],
21 | "exclude": ["node_modules"]
22 | }
23 |
--------------------------------------------------------------------------------
/packages/tsconfig/node16.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Node 16",
4 | "extends": "./base.json",
5 | "compilerOptions": {
6 | "lib": ["ES2020"],
7 | "module": "commonjs",
8 | "target": "ES2020"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/tsconfig/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tsconfig",
3 | "version": "0.0.0",
4 | "private": true,
5 | "files": [
6 | "base.json",
7 | "nextjs.json",
8 | "react-library.json",
9 | "nextjs.json"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/packages/tsconfig/react-library.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "React Library",
4 | "extends": "./base.json",
5 | "compilerOptions": {
6 | "jsx": "react-jsx",
7 | "lib": ["dom", "ES2015"],
8 | "module": "ESNext",
9 | "target": "es6"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/tw-plugin/index.js:
--------------------------------------------------------------------------------
1 | const plugin = require("tailwindcss/plugin");
2 |
3 | module.exports = plugin(
4 | function ({ matchUtilities, theme }) {
5 | matchUtilities(
6 | {
7 | color: (value) => ({
8 | color: value,
9 | }),
10 | },
11 | { values: theme("color") }
12 | );
13 | },
14 | {
15 | theme: {
16 | extend: {
17 | colors: {
18 | base: "var(--base)",
19 | "base-focus": "var(--base-focus)",
20 | "base-2": "var(--base-2)",
21 | "base-2-focus": "var(--base-2-focus)",
22 | "base-content": "var(--base-content)",
23 | "base-content-2": "var(--base-content-2)",
24 | "base-content-3": "var(--base-content-3)",
25 | "base-content-inverse": "var(--base-content-inverse)",
26 | overlay: "var(--overlay)",
27 | "overlay-focus": "var(--overlay-focus)",
28 | "overlay-2": "var(--overlay-2)",
29 | "overlay-2-focus": "var(--overlay-2-focus)",
30 | "overlay-content": "var(--overlay-content)",
31 | "overlay-content-2": "var(--overlay-content-2)",
32 | "overlay-content-3": "var(--overlay-content-3)",
33 | "overlay-content-inverse": "var(--overlay-content-inverse)",
34 | line: "var(--line)",
35 | "line-focus": "var(--line-focus)",
36 | input: "var(--input)",
37 | "input-focus": "var(--input-focus)",
38 | "input-content": "var(--input-content)",
39 | "input-content-2": "var(--input-content-2)",
40 | primary: "var(--primary)",
41 | "primary-focus": "var(--primary-focus)",
42 | "primary-subtle": "var(--primary-subtle)",
43 | "primary-content": "var(--primary-content)",
44 | "primary-content-inverse": "var(--primary-content-inverse)",
45 | "primary-subtle-content": "var(--primary-subtle-content)",
46 | secondary: "var(--secondary)",
47 | "secondary-focus": "var(--secondary-focus)",
48 | "secondary-subtle": "var(--secondary-subtle)",
49 | "secondary-subtle-content": "var(--secondary-subtle-content)",
50 | "secondary-content": "var(--secondary-content)",
51 | "secondary-content-inverse": "var(--secondary-content-inverse)",
52 | info: "var(--info)",
53 | "info-focus": "var(--info-focus)",
54 | "info-subtle": "var(--info-subtle)",
55 | "info-subtle-content": "var(--info-subtle-content)",
56 | "info-content": "var(--info-content)",
57 | "info-content-inverse": "var(--info-content-inverse)",
58 | danger: "var(--danger)",
59 | "danger-focus": "var(--danger-focus)",
60 | "danger-subtle": "var(--danger-subtle)",
61 | "danger-subtle-content": "var(--danger-subtle-content)",
62 | "danger-content": "var(--danger-content)",
63 | "danger-content-inverse": "var(--danger-content-inverse)",
64 | success: "var(--success)",
65 | "success-focus": "var(--success-focus)",
66 | "success-subtle": "var(--success-subtle)",
67 | "success-subtle-content": "var(--success-subtle-content)",
68 | "success-content": "var(--success-content)",
69 | "success-content-inverse": "var(--success-content-inverse)",
70 | warning: "var(--warning)",
71 | "warning-focus": "var(--warning-focus)",
72 | "warning-subtle": "var(--warning-subtle)",
73 | "warning-subtle-content": "var(--warning-subtle-content)",
74 | "warning-content": "var(--warning-content)",
75 | "warning-content-inverse": "var(--warning-content-inverse)",
76 | },
77 | },
78 | },
79 | }
80 | );
81 |
--------------------------------------------------------------------------------
/packages/tw-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@chimera-ui/tw-plugin",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Will",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "tailwindcss": "^3.2.4"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "apps/*"
3 | - "packages/*"
4 |
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turbo.build/schema.json",
3 | "pipeline": {
4 | "prebuild": {
5 | "outputs": [],
6 | "dependsOn": []
7 | },
8 | "build": {
9 | "outputs": ["dist/**", ".next/**"],
10 | "dependsOn": ["^prebuild", "^build"]
11 | },
12 | "test": {
13 | "outputs": ["coverage/**"],
14 | "dependsOn": []
15 | },
16 | "lint": {
17 | "outputs": []
18 | },
19 | "dev": {
20 | "cache": false
21 | },
22 | "clean": {
23 | "cache": false
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------