Skip to content

Commit

Permalink
⌘ + K | Other UI Changes (#91)
Browse files Browse the repository at this point in the history
* 🚧 Add baseline command bar

* 🚧 Fix small things

* Add command bar

* 🚧  Add og_image

* 🚧 Update og url

* 🚧 Tweak functions

* 🚧 Bunch more changes

* 🚧 Fix padding

* 🚧 Small changes

* 🚧 🚧 Add CommandBar to container and small fixes

* 🚧 Fix padding

* 🚧 Change placeholder name

* 🚧 Clean code final
  • Loading branch information
preetjdp authored Nov 2, 2021
1 parent d2d2a57 commit 62cee3e
Show file tree
Hide file tree
Showing 15 changed files with 1,041 additions and 143 deletions.
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"cSpell.words": [
"Devfolio",
"kbar",
"LIVEKIT"
],
"editor.codeActionsOnSave": {
Expand Down
73 changes: 51 additions & 22 deletions components/Aside.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,74 @@
import React from "react";

import Logo from "./Logo";
import Image from "next/image";
import { useRouter } from "next/router";
import Signup from "./Signup";

import Preet from "../public/assets/preet.jpg";
import PreetImage from "../public/assets/preet.jpg";
import { SimpleTooltip } from "@/components/Tooltip";

const Aside = () => {
const router = useRouter();
const isIndex = router.pathname === "/";

return (
<aside>
{!isIndex && (
<>
<Signup />
<div className="mb-7">
<Logo />
</div>
</>
)}
<div className="flex mb-12 items-center text-base">
<div className=" rounded-full">
<div
className="flex mb-12 items-center text-base py-16 px-5"
style={{
backgroundImage:
"linear-gradient(319deg, rgb(251, 241, 253) 17%, rgba(255, 255, 255, 0) 58%), linear-gradient(34deg, rgb(236, 242, 180) 27%, rgba(255, 255, 255, 0) 71%), radial-gradient(at 2% 188%, rgb(241, 229, 106) 8%, rgba(255, 255, 255, 0) 80%), radial-gradient(at -46% -19%, rgb(29, 122, 79) 35%, rgba(255, 255, 255, 0) 62%), linear-gradient(212deg, rgb(239, 182, 52) 21%, rgba(255, 255, 255, 0) 53%), linear-gradient(328deg, rgb(155, 155, 155) 18%, rgba(255, 255, 255, 0) 60%);",
}}
>
<div className="rounded-full self-start mt-2 sm:self-center sm:mt-0">
<Image
src={Preet}
alt="Al Joseph Condino"
src={PreetImage}
alt="Preet Parekh"
width={48}
height={48}
className=" rounded-full"
quality={100}
placeholder="blur"
/>
</div>
<p className="ml-3.5 max-w-xs">
Personal blog by Preet Parekh.
<span className="block">I&nbsp;explain with words and code.</span>
<p className="ml-3.5 font-serif text-black text-lg flex flex-col whitespace-pre-wrap max-w-prose">
<span>I'm Preet Parekh, a compulsive builder based in Bombay.</span>
<span>
Currently helping with Engineering at{" "}
<SimpleTooltip
tooltip={
<span className="flex flex-row whitespace-nowrap">
<DevfolioLogo height={15} width={15} /> &nbsp; 🚀
</span>
}
>
Devfolio.
</SimpleTooltip>
</span>
</p>
</div>
</aside>
);
};

/**
* The Devfolio Logo
*/
export const DevfolioLogo = (
props: React.SVGProps<SVGSVGElement>
): JSX.Element => (
<svg
width="1em"
height="1em"
viewBox="0 0 30 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M29.702 17.62a14.219 14.219 0 01-12.84 14.275s-9.218.236-12.268 0a3.186 3.186 0 01-2.557-1.928c.43.189.889.299 1.357.325.998.09 2.703.134 5.08.134 3.487 0 7.29-.1 7.323-.1h.067a14.97 14.97 0 009.88-4.924 15.7 15.7 0 003.958-8.657v.875z"
fill="#3770FF"
/>
<path
d="M28.58 14.491a14.22 14.22 0 01-12.862 14.264s-9.218.236-12.268 0A3.432 3.432 0 01.545 25.28V3.557A3.432 3.432 0 013.517.115c3.062-.258 12.268 0 12.268 0A14.22 14.22 0 0128.581 14.49z"
fill="#3770FF"
/>
</svg>
);

export default Aside;
255 changes: 255 additions & 0 deletions components/CommandBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
import React from "react";

import { NextRouter, useRouter } from "next/router";
import { useTheme } from "next-themes";
import {
KBarProvider,
KBarPortal,
KBarPositioner,
KBarAnimator,
KBarSearch,
KBarResults,
useMatches,
Action,
useKBar,
createAction,
} from "kbar";
import {
TwitterLogoIcon,
HomeIcon,
GitHubLogoIcon,
CrumpledPaperIcon,
LightningBoltIcon,
ArrowLeftIcon,
} from "@radix-ui/react-icons";
import { Command } from "react-feather";

import { classNames } from "@/utils/helpers";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/Tooltip";

interface CommandBarProps {
children: React.ReactNode;
}

const actions = (
toggleTheme: (theme: string) => void,
router: NextRouter
): Action[] => {
const actions = [
{
id: "homeAction",
name: "Home",
shortcut: ["h"],
keywords: "back",
section: "Navigation",
perform: () => router.push("/"),
icon: <HomeIcon />,
},
{
id: "contactAction",
name: "Contact",
shortcut: ["c"],
keywords: "email hello",
section: "Social",
icon: <CrumpledPaperIcon />,
perform: () => window.open("mailto:[email protected]", "_blank"),
},
{
id: "twitterAction",
name: "Twitter",
shortcut: ["t"],
keywords: "social contact dm",
section: "Social",
icon: <TwitterLogoIcon />,
perform: () => window.open("https://twitter.com/TmPreet", "_blank"),
},
createAction({
name: "Github",
shortcut: ["g", "h"],
keywords: "sourcecode",
section: "Social",
icon: <GitHubLogoIcon />,
perform: () => window.open("https://github.com/preetjdp", "_blank"),
}),
{
id: "theme",
name: "Change Theme",
shortcut: [],
keywords: "interface color dark light",
section: "Preferences",
icon: <LightningBoltIcon />,
children: ["darkTheme", "lightTheme"],
},
{
id: "darkTheme",
name: "Dark",
shortcut: [],
keywords: "dark",
section: "",
perform: () => toggleTheme("dark"),
parent: "theme",
},
{
id: "lightTheme",
name: "Light",
shortcut: [],
keywords: "light",
section: "",
perform: () => toggleTheme("light"),
parent: "theme",
},
];

if (router.pathname !== "/") {
actions.push({
id: "backAction",
name: "Back",
shortcut: ["b"],
keywords: "go back last page",
section: "Navigation",
perform: () => router.back(),
icon: <ArrowLeftIcon />,
});
}

return actions;
};

/**
* Returns the results for the Command Bar
*
* @returns JSX.Element
*/
const RenderResults = () => {
const groups = useMatches();
const flattened = React.useMemo(
() =>
groups.reduce((acc, curr) => {
acc.push(curr.name);
acc.push(...curr.actions);
return acc;
}, []),
[groups]
);

return (
<KBarResults
items={flattened.filter((i) => i !== "none")}
onRender={({ item, active }) => (
<div className="px-4">
{typeof item === "string" ? (
<div className="py-4 text-xs uppercase opacity-50 font-mono">
{item}
</div>
) : (
<ResultItem action={item} active={active} />
)}
</div>
)}
/>
);
};

// eslint-disable-next-line react/display-name
const ResultItem = React.forwardRef(
(
{
action,
active,
}: {
action: Action;
active: boolean;
},
ref: React.Ref<HTMLDivElement>
) => {
return (
<div
ref={ref}
className={classNames(
"px-3 py-4 flex align-middle justify-between cursor-pointer font-mono text-gray-700 opacity-80 rounded-md transition-colors duration-75 dark:text-white",
active ? "bg-gray-200 dark:bg-gray-600" : "dark:bg-gray-custom-1"
)}
>
<div className="flex gap-2 items-center">
{action.icon && action.icon}
<div className="flex flex-col ml-2">
<span className="font-semibold text-lg">{action.name}</span>
{action.subtitle && (
<span className="text-xs">{action.subtitle}</span>
)}
</div>
</div>
{action.shortcut?.length ? (
<div className="grid grid-flow-col gap-4 items-center">
{action.shortcut.map((sc) => (
<kbd
key={sc}
className="flex items-center justify-center p-2 bg-gray-300 rounded-sm font-bold text-xs min-h-3 min-w-3 dark:bg-gray-500"
>
{sc}
</kbd>
))}
</div>
) : null}
</div>
);
}
);

/**
* The command bar component
*
* @param props The command-bar props
* @returns JSX.Element
*/
const CommandBar = (props: CommandBarProps) => {
const { setTheme } = useTheme();
const router = useRouter();

return (
<KBarProvider actions={actions(setTheme, router)}>
<KBarPortal>
<KBarPositioner>
<KBarAnimator className="max-w-xl w-full bg-gray-50 rounded-lg shadow-3xl overflow-hidden dark:bg-gray-custom-1">
<KBarSearch
placeholder="Search the Website ..."
className="px-4 py-4 text-xl w-full box-border outline-none border-none bg-gray-50 font-mono dark:bg-gray-custom-1"
/>
<div className="pb-4">
<RenderResults />
</div>
</KBarAnimator>
</KBarPositioner>
</KBarPortal>
{props.children}
</KBarProvider>
);
};

/**
* The command bar toggle
*
* @returns JSX.Element
*/
export const CommandBarToggle = () => {
const { query } = useKBar();

return (
<Tooltip delayDuration={0}>
<TooltipTrigger
className="appearance-none"
asChild
onClick={() => query.toggle()}
>
<div className="p-2 rounded-md hover:bg-gray-200 dark:hover:bg-gray-700">
<Command className="text-gray-custom-1 dark:text-white" />
</div>
</TooltipTrigger>
<TooltipContent className="bg-gray-300 dark:bg-gray-500" sideOffset={10}>
⌘K
</TooltipContent>
</Tooltip>
);
};

export default CommandBar;
21 changes: 17 additions & 4 deletions components/Container.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import React from "react";
import CommandBar from "./CommandBar";

const Container = ({ children }) => {
interface ContainerProps {
children: React.ReactNode;
}

/**
* The container for all the pages
*
* @param props The props for the page
* @returns JSX.Element
*/
const Container = (props: ContainerProps) => {
return (
<div className="bg-gray-50 dark:bg-gray-custom-1 text-gray-900 dark:text-gray-200 min-h-screen font-serif ">
<div className="max-w-2xl mx-auto py-10 px-6">{children}</div>
</div>
<CommandBar>
<div className="bg-gray-50 dark:bg-gray-custom-1 text-gray-900 dark:text-gray-200 min-h-screen font-serif">
<div className="max-w-2xl mx-auto py-10 px-6">{props.children}</div>
</div>
</CommandBar>
);
};

Expand Down
Loading

1 comment on commit 62cee3e

@vercel
Copy link

@vercel vercel bot commented on 62cee3e Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.