diff --git a/app/src/pages/_app.tsx b/app/src/pages/_app.tsx index fe9aeeb..0163fde 100644 --- a/app/src/pages/_app.tsx +++ b/app/src/pages/_app.tsx @@ -7,7 +7,7 @@ import "@/styles/globals.css"; import "@/styles/prism.css"; // SuperUI Provider -> -import { SuperUIProvider } from "superui"; +import { SuperUIProvider, CommandMenu } from "superui"; // Chakra UI & Docs Theme -> import { ChakraProvider } from "@chakra-ui/react"; @@ -33,6 +33,7 @@ function MyApp({ Component, pageProps }: AppProps) { + diff --git a/packages/ui/CommandMenu/cmdk.types.ts b/packages/ui/CommandMenu/cmdk.types.ts new file mode 100644 index 0000000..af1aba4 --- /dev/null +++ b/packages/ui/CommandMenu/cmdk.types.ts @@ -0,0 +1 @@ +export interface CommandMenuProps {} diff --git a/packages/ui/CommandMenu/index.tsx b/packages/ui/CommandMenu/index.tsx new file mode 100644 index 0000000..0d54f50 --- /dev/null +++ b/packages/ui/CommandMenu/index.tsx @@ -0,0 +1,55 @@ +import React from "react"; +import { CommandMenuProps } from "./cmdk.types"; +import { Command } from "cmdk"; +import * as Dialog from "@radix-ui/react-dialog"; + +export const CommandMenu = (props: CommandMenuProps) => { + const [open, setOpen] = React.useState(false); + + React.useEffect(() => { + const down = (e: KeyboardEvent) => { + if (e.key === "k" && (e.metaKey || e.ctrlKey)) { + e.preventDefault(); + setOpen((open) => !open); + } + }; + + document.addEventListener("keydown", down); + return () => document.removeEventListener("keydown", down); + }, []); + + return ( + + + + +
+ +
+ Home +
+ + + Apple + Banana + Orange + +
+
+
+
+
+ ); +}; diff --git a/packages/ui/CommandMenu/style.css b/packages/ui/CommandMenu/style.css new file mode 100644 index 0000000..b1e7693 --- /dev/null +++ b/packages/ui/CommandMenu/style.css @@ -0,0 +1,264 @@ +.vercel [cmdk-root] { + max-width: 1000px; + width: 100%; + padding: 8px; + background: #fff; + border-radius: 12px; + overflow: hidden; + font-family: var(--font-sans); + border: 1px solid var(--gray6); + box-shadow: var(--cmdk-shadow); + transition: transform 0.1s ease; +} + +.vercel [cmdk-root] { + background: hsla(0, 0%, 9%, 0.8); +} + +.vercel [cmdk-input] { + font-family: var(--font-sans); + border: none; + width: 100%; + font-size: 17px; + padding: 8px 8px 16px; + outline: none; + background: var(--bg); + color: white; + border-bottom: 1px solid var(--gray6); + margin-bottom: 16px; + border-radius: 0; +} + +.vercel [cmdk-input]::-moz-placeholder { + color: hsla(0, 0%, 100%, 0.8); +} + +.vercel [cmdk-input]:-ms-input-placeholder { + color: hsla(0, 0%, 100%, 0.8); +} + +.vercel [cmdk-input]::placeholder { + color: hsla(0, 0%, 100%, 0.8); +} + +.vercel [cmdk-vercel-badge] { + height: 20px; + background: hsl(0, 4%, 29%); + display: inline-flex; + padding: 0 8px; + font-size: 12px; + color: white; + border-radius: 4px; + margin: 4px 0 4px 4px; + text-transform: capitalize; + font-weight: 500; +} + +.vercel [cmdk-item], +.vercel [cmdk-vercel-badge] { + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.vercel [cmdk-item] { + content-visibility: auto; + cursor: pointer; + height: 48px; + border-radius: 8px; + font-size: 14px; + display: flex; + gap: 8px; + padding: 0 16px; + color: white; + will-change: background, color; + transition: all 0.15s ease; + transition-property: none; +} + +.vercel [cmdk-item][aria-selected="true"] { + background: var(--grayA3); + color: white; +} + +.vercel [cmdk-item][aria-disabled="true"] { + color: var(--gray8); + cursor: not-allowed; +} + +.vercel [cmdk-item]:active { + transition-property: background; + background: var(--gray4); +} + +.vercel [cmdk-item] + [cmdk-item] { + margin-top: 4px; +} + +.vercel [cmdk-item] svg { + width: 18px; + height: 18px; +} + +.vercel [cmdk-list] { + height: min(330px, var(--cmdk-list-height)); + max-height: 400px; + overflow: auto; + -ms-scroll-chaining: none; + overscroll-behavior: contain; + transition: 0.1s ease; + transition-property: height; +} + +.vercel [cmdk-vercel-shortcuts] { + display: flex; + margin-left: auto; + gap: 8px; +} + +.vercel [cmdk-vercel-shortcuts] kbd { + font-family: var(--font-sans); + font-size: 12px; + min-width: 20px; + padding: 4px; + height: 20px; + border-radius: 4px; + color: var(--gray11); + background: var(--gray4); + display: inline-flex; + align-items: center; + justify-content: center; + text-transform: uppercase; +} + +.vercel [cmdk-separator] { + height: 1px; + width: 100%; + background: var(--gray5); + margin: 4px 0; +} + +.vercel :not([hidden]) + [cmdk-group] { + margin-top: 8px; +} + +.vercel [cmdk-group-heading] { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + font-size: 12px; + padding: 0 8px; + margin-bottom: 8px; +} + +.vercel [cmdk-empty], +.vercel [cmdk-group-heading] { + color: var(--gray11); + display: flex; + align-items: center; +} + +.vercel [cmdk-empty] { + font-size: 14px; + justify-content: center; + height: 48px; + white-space: pre-wrap; +} + +:root { + --font-sans: "Inter", --apple-system, BlinkMacSystemFont, Segoe UI, Roboto, + Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + --app-bg: var(--gray1); + --cmdk-shadow: 0 16px 70px rgb(0 0 0 / 20%); + + --lowContrast: #ffffff; + --highContrast: #000000; + + --gray1: hsl(0, 0%, 99%); + --gray2: hsl(0, 0%, 97.3%); + --gray3: hsl(0, 0%, 95.1%); + --gray4: hsl(0, 0%, 93%); + --gray5: hsl(0, 0%, 90.9%); + --gray6: hsl(0, 0%, 88.7%); + --gray7: hsl(0, 0%, 85.8%); + --gray8: hsl(0, 0%, 78%); + --gray9: hsl(0, 0%, 56.1%); + --gray10: hsl(0, 0%, 52.3%); + --gray11: hsl(0, 0%, 43.5%); + --gray12: hsl(0, 0%, 9%); + + --grayA1: hsla(0, 0%, 0%, 0.012); + --grayA2: hsla(0, 0%, 0%, 0.027); + --grayA3: hsla(0, 0%, 0%, 0.047); + --grayA4: hsla(0, 0%, 0%, 0.071); + --grayA5: hsla(0, 0%, 0%, 0.09); + --grayA6: hsla(0, 0%, 0%, 0.114); + --grayA7: hsla(0, 0%, 0%, 0.141); + --grayA8: hsla(0, 0%, 0%, 0.22); + --grayA9: hsla(0, 0%, 0%, 0.439); + --grayA10: hsla(0, 0%, 0%, 0.478); + --grayA11: hsla(0, 0%, 0%, 0.565); + --grayA12: hsla(0, 0%, 0%, 0.91); + + --blue1: hsl(206, 100%, 99.2%); + --blue2: hsl(210, 100%, 98%); + --blue3: hsl(209, 100%, 96.5%); + --blue4: hsl(210, 98.8%, 94%); + --blue5: hsl(209, 95%, 90.1%); + --blue6: hsl(209, 81.2%, 84.5%); + --blue7: hsl(208, 77.5%, 76.9%); + --blue8: hsl(206, 81.9%, 65.3%); + --blue9: hsl(206, 100%, 50%); + --blue10: hsl(208, 100%, 47.3%); + --blue11: hsl(211, 100%, 43.2%); + --blue12: hsl(211, 100%, 15%); +} + +.dark { + --app-bg: var(--gray1); + + --lowContrast: #000000; + --highContrast: #ffffff; + + --gray1: hsl(0, 0%, 8.5%); + --gray2: hsl(0, 0%, 11%); + --gray3: hsl(0, 0%, 13.6%); + --gray4: hsl(0, 0%, 15.8%); + --gray5: hsl(0, 0%, 17.9%); + --gray6: hsl(0, 0%, 20.5%); + --gray7: hsl(0, 0%, 24.3%); + --gray8: hsl(0, 0%, 31.2%); + --gray9: hsl(0, 0%, 43.9%); + --gray10: hsl(0, 0%, 49.4%); + --gray11: hsl(0, 0%, 62.8%); + --gray12: hsl(0, 0%, 93%); + + --grayA1: hsla(0, 0%, 100%, 0); + --grayA2: hsla(0, 0%, 100%, 0.026); + --grayA3: hsla(0, 0%, 100%, 0.056); + --grayA4: hsla(0, 0%, 100%, 0.077); + --grayA5: hsla(0, 0%, 100%, 0.103); + --grayA6: hsla(0, 0%, 100%, 0.129); + --grayA7: hsla(0, 0%, 100%, 0.172); + --grayA8: hsla(0, 0%, 100%, 0.249); + --grayA9: hsla(0, 0%, 100%, 0.386); + --grayA10: hsla(0, 0%, 100%, 0.446); + --grayA11: hsla(0, 0%, 100%, 0.592); + --grayA12: hsla(0, 0%, 100%, 0.923); + + --blue1: hsl(212, 35%, 9.2%); + --blue2: hsl(216, 50%, 11.8%); + --blue3: hsl(214, 59.4%, 15.3%); + --blue4: hsl(214, 65.8%, 17.9%); + --blue5: hsl(213, 71.2%, 20.2%); + --blue6: hsl(212, 77.4%, 23.1%); + --blue7: hsl(211, 85.1%, 27.4%); + --blue8: hsl(211, 89.7%, 34.1%); + --blue9: hsl(206, 100%, 50%); + --blue10: hsl(209, 100%, 60.6%); + --blue11: hsl(210, 100%, 66.1%); + --blue12: hsl(206, 98%, 95.8%); +} diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index ba92227..99fea69 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -9,3 +9,4 @@ export * from "./Overlay"; export * from "./Modal"; export * from "./Checkbox"; export * from "./AvatarGroup"; +export * from "./CommandMenu"; diff --git a/packages/ui/package.json b/packages/ui/package.json index 8fb8d81..ca2830d 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -29,7 +29,10 @@ }, "dependencies": { "@heroicons/react": "1.0.6", + "@radix-ui/react-dialog": "^1.0.0", + "@radix-ui/react-popover": "^1.0.0", "@react-aria/overlays": "3.10.0", + "cmdk": "^0.1.18", "react-aria": "3.18.0", "react-transition-group": "4.4.5", "tailwind-merge": "1.5.1" diff --git a/packages/ui/styles/main.css b/packages/ui/styles/main.css index 9d4478f..a931309 100644 --- a/packages/ui/styles/main.css +++ b/packages/ui/styles/main.css @@ -1 +1,2 @@ @import "../Checkbox/style.css"; +@import "../CommandMenu/style.css";