Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add UserSettings component to design system #788

Merged
merged 18 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions components/atoms/Button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ interface ButtonProps extends React.ComponentProps<typeof SupabaseButtonComponen
//Add additional prop definitions here
}

const Button: React.FC<ButtonProps> = ( props ) => {

const Button: React.FC<ButtonProps> = (props) => {
const style = {
primary: "!bg-orange-500 !border-orange-500 hover:!bg-orange-600",
primary: "!bg-light-orange-9 !text-light-orange-2 !border-light-orange-9 hover:!bg-light-orange-10",
default: "!bg-slate-50 !border-slate-300 text-slate-800 hover:!bg-slate-100",
outline: "!bg-orange-50 !border-orange-500 !text-orange-600 hover:!bg-orange-100",
link: "!text-orange-600 hover:!bg-orange-100"
Expand All @@ -18,12 +17,15 @@ const Button: React.FC<ButtonProps> = ( props ) => {
<SupabaseButtonComponent
{...props}
className={
`${props.className && props.className} !text-sm !font-semibold !tracking-tight !py-1 !px-3 !rounded-md focus-visible:!border-orange-500 focus:outline-none focus-visible:ring focus-visible:!ring-orange-200 ` +
`${
props.className && props.className
} !text-sm !font-semibold !tracking-tight !py-1 !px-3 !rounded-md focus-visible:!border-orange-500 focus:outline-none focus-visible:ring focus-visible:!ring-orange-200 ` +
`${props.type === "primary" ? style.primary : ""}` +
`${props.type === "default" ? style.default : ""}` +
`${props.type === "outline" ? style.outline : ""}` +
`${props.type === "link" ? style.link : ""}`
}>
}
>
{props.children}
</SupabaseButtonComponent>
);
Expand Down
11 changes: 8 additions & 3 deletions components/atoms/Checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { Checkbox as SupbaseCheckboxComponent } from "@supabase/ui";

interface CheckboxProps extends React.ComponentProps<typeof SupbaseCheckboxComponent> {
//Add additional prop definitions here
title: string
title: string;
}

const Checkbox: React.FC<CheckboxProps> = ( props ) => {
return <SupbaseCheckboxComponent {...props} />;
const Checkbox: React.FC<CheckboxProps> = (props) => {
return (
<SupbaseCheckboxComponent
className={`checked:[&>*]:!bg-orange-500 !text-orange-500 ${props.className || ""}`}
{...props}
/>
);
};

export default Checkbox;
42 changes: 42 additions & 0 deletions components/atoms/LanguagePill/LanguagePill.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react";
import Image, { StaticImageData } from "next/image";

import JavascriptIcon from "img/icons/β˜•οΈ.svg";
import ReactIcon from "/img/icons/βš›οΈ.svg";
import PythonIcon from "/img/icons/🐍.svg";
import AIIcon from "/img/icons/πŸ€–.svg";
import MLIcon from "/img/icons/🧠.svg";
import RustIcon from "/img/icons/πŸ¦€.svg";

interface LanguagePillProps {
topic: "react" | "javascript" | "python" | "ML" | "AI" | "rust" | string;
classNames?: string;
onClick?: () => void;
}
const LanguagePill = ({ topic, classNames, onClick }: LanguagePillProps) => {
const renderTopicIcon = (name: string) => {
OgDev-01 marked this conversation as resolved.
Show resolved Hide resolved
const iconMap: { [name: string]: StaticImageData } = {
react: ReactIcon,
rust: RustIcon,
javascript: JavascriptIcon,
AI: AIIcon,
ML: MLIcon,
python: PythonIcon
};

return iconMap[name] || "";
};
return (
<div
onClick={onClick}
className={`cursor-pointer text-xs text-light-slate-11 rounded-[1.875rem] w-max flex items-center gap-1 py-2 px-4 bg-light-slate-6 ${
classNames || ""
}`}
>
<Image src={renderTopicIcon(topic)} alt={topic} />
<span className="font-normal capitalize">{topic}</span>
</div>
);
};

export default LanguagePill;
2 changes: 1 addition & 1 deletion components/atoms/Pill/pill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const Pill: React.FC<PillProps> = ({ className, text, color = "slate", size = "b
: "bg-light-slate-4 "
}
${size === "small" ? "py-1 px-1.5 " : "py-1.5 px-2 "}
inline-flex items-center rounded-full gap-1`}
inline-flex items-center rounded-full gap-1 ${className}`}
>
{icon}

Expand Down
6 changes: 3 additions & 3 deletions components/atoms/TextInput/text-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ const TextInput = ({
{label && <p className="mb-2 text-light-slate-9 text-sm">{label}</p>}
<div
className={clsx(
classNames,
"flex-1 px-3 text-light-slate-12 bg-white shadow-input border transition rounded-lg py-1 flex items-center",
borderless && "!border-none",
state === "invalid" ? " focus-within:border-light-red-10 " : "focus-within:border-light-orange-9 ",
disabled && "bg-light-slate-3"
disabled && "bg-light-slate-3",
classNames
)}
>
<input
Expand All @@ -57,7 +57,7 @@ const TextInput = ({
placeholder={placeholder || ""}
onChange={onChange}
value={value}
className="flex-1 focus:outline-none "
className={`flex-1 focus:outline-none ${classNames}`}
autoFocus={autoFocus}
disabled={disabled}
/>
Expand Down
121 changes: 121 additions & 0 deletions components/organisms/UserSettingsPage/user-settings-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React, { useState } from "react";

import Button from "components/atoms/Button/button";
import Checkbox from "components/atoms/Checkbox/checkbox";
import TextInput from "components/atoms/TextInput/text-input";
import Title from "components/atoms/Typography/title";
import Select from "components/atoms/Select/select";
import SelectOption from "components/atoms/Select/select-option";
import LanguagePill from "components/atoms/LanguagePill/LanguagePill";

const UserSettingsPage = () => {
const [selectedInterest, setSelectedInterest] = useState<string[]>([]);
const interestArray = ["javascript", "python", "rust", "ML", "AI", "react"];

const handleSelectInterest = (interest: string) => {
if (selectedInterest.length > 0 && selectedInterest.includes(interest)) {
setSelectedInterest((prev) => prev.filter((item) => item !== interest));
} else {
setSelectedInterest((prev) => [...prev, interest]);
}
};

return (
<div>
<div className="flex flex-col md:flex-row md:justify-between gap-4 text-sm text-light-slate-11">
<div>
<Title className="!text-2xl !text-light-slate-11" level={2}>
Public profile
</Title>
<form className="flex flex-col gap-6 mt-6">
<TextInput
classNames="bg-light-slate-4 text-light-slate-11 font-medium"
OgDev-01 marked this conversation as resolved.
Show resolved Hide resolved
label="Name*"
placeholder="April O'Neil"
/>
<TextInput
classNames="bg-light-slate-4 text-light-slate-11 font-medium"
placeholder="[email protected]"
label="Email*"
/>

{/* Bio section */}
<div className="flex flex-col gap-2">
<label className="text-light-slate-11 text-sm font-normal">Bio</label>
<textarea
rows={4}
placeholder="Tell us about yourself."
className="bg-light-slate-4 rounded-lg px-3 py-2 "
></textarea>
</div>
<TextInput
classNames="bg-light-slate-4 text-light-slate-11 font-medium"
placeholder="https://turtlepower.pizza"
label="URL"
/>
<TextInput
classNames="bg-light-slate-4 text-light-slate-11"
placeholder="@aprilcodes"
label="Twitter Username"
/>
<TextInput
classNames="bg-light-slate-4 text-light-slate-11 font-medium"
placeholder="StockGen"
label="Company"
/>
<TextInput
classNames="bg-light-slate-4 text-light-slate-11 font-medium"
placeholder="USA"
label="Location"
/>
<div>
<Checkbox value={"true"} title="profile email" label="Display current local time" />
<span className="ml-7 text-light-slate-9 text-sm font-normal">
Other users will see the time difference from their local time.
</span>
</div>
<div className="flex flex-col gap-2">
<label>Time zone*</label>
<Select>
<SelectOption value="Wat+1">Select time zone</SelectOption>
</Select>
</div>
<Button type="primary">Update profile</Button>
</form>
</div>
<div className="flex flex-col-reverse md:flex-col gap-6">
<div className="flex flex-col gap-6">
<Title className="!text-2xl !font-normal !text-light-slate-11" level={2}>
Interests
</Title>
<div className="flex gap-3 w-72 flex-wrap">
{interestArray.map((topic, index) => (
<LanguagePill
onClick={() => handleSelectInterest(topic)}
classNames={`${selectedInterest.includes(topic) && "bg-light-orange-10 text-white"}`}
topic={topic}
key={index}
/>
))}
</div>
<button className="px-4 w-max py-2 rounded-lg bg-light-slate-4 border border-light-slate-8">
Update Interest
OgDev-01 marked this conversation as resolved.
Show resolved Hide resolved
</button>
</div>
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-3 ">
<label className="text-light-slate-11 text-2xl font-normal">Email Preferences</label>
<Checkbox value={"true"} title="profile email" label="Display Email On Profile" />
<Checkbox value={"true"} title="collaboration requests" label="Receive collaboration requests" />
</div>
<button className="px-4 w-max py-2 rounded-lg bg-light-slate-4 border border-light-slate-8">
Update Preferences
</button>
</div>
</div>
</div>
</div>
);
};

export default UserSettingsPage;
9 changes: 9 additions & 0 deletions img/icons/β˜•οΈ.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions img/icons/βš›οΈ.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions img/icons/🐍.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions img/icons/πŸ€–.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions img/icons/πŸ¦€.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions img/icons/🧠.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@nivo/pie": "^0.80.0",
"@nivo/scatterplot": "^0.80.0",
"@primer/octicons-react": "^17.5.0",
"@radix-ui/react-checkbox": "^1.0.1",
"@radix-ui/react-context-menu": "^1.0.0",
"@radix-ui/react-dropdown-menu": "^1.0.0",
"@radix-ui/react-hover-card": "^1.0.2",
Expand Down
22 changes: 22 additions & 0 deletions stories/atoms/language-pill.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import LanguagePill from "components/atoms/LanguagePill/LanguagePill";
import { ComponentStory } from "@storybook/react";

const Storyconfig = {
title: "Design System/Atoms/LanguagePill"
};
export default Storyconfig;

const LanguagePillTemplate: ComponentStory<typeof LanguagePill> = (args) => <LanguagePill {...args} />;

export const LanguagePillDefault = LanguagePillTemplate.bind({});
export const LanguagePillSelected = LanguagePillTemplate.bind({});

LanguagePillDefault.args = {
topic: "javascript"
};

LanguagePillSelected.args = {
topic: "python",

classNames: "bg-light-orange-10 text-white"
};
11 changes: 11 additions & 0 deletions stories/organisms/user-settings-page.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import UserSettingsPage from "components/organisms/UserSettingsPage/user-settings-page";
import { ComponentStory } from "@storybook/react";

const StoryConfig = {
title: "Design System/Organisms/UserSettingsPage"
};
export default StoryConfig;

const UserSettingsPageTemplate: ComponentStory<typeof UserSettingsPage> = () => <UserSettingsPage />;

export const Default = UserSettingsPageTemplate.bind({});
3 changes: 3 additions & 0 deletions styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
border: 1px solid #f76808 !important ;
box-shadow: 0px 0px 0px 2px #ffcca7, 0px 1px 2px rgba(0, 0, 0, 0.1) !important;
}
.sbui-checkbox:hover {
border-color: #f76808 !important;
}
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none !important;
}
Expand Down