diff --git a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js
index 461a9b7e..86cbad5f 100644
--- a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js
+++ b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js
@@ -30,7 +30,7 @@ const TriggerIcon = styled(ChevronDownIcon).attrs({
`;
const Flyout = styled.div.attrs(({ open }) => ({
- className: `absolute top-full right-0 p-0
+ className: `absolute top-full right-0 p-0 z-10
border rounded border-palette-100
bg-white shadow-md shadow-palette-200/50
${open ? "visible" : "invisible"}`,
diff --git a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js
index 45a86483..426501c4 100644
--- a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js
+++ b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js
@@ -3,18 +3,16 @@ import PropTypes from "prop-types";
const DropdownLink = styled.a.attrs({
className: `m-0 border-t border-palette-200/50 h-[60px]
- whitespace-nowrap transition-colors text-current
+ whitespace-nowrap transition-colors
hover:bg-palette-100/50 flex items-center
pr-8 pl-6 py-4 gap-4 first:border-0`,
})``;
export const DropdownMenuLink = ({ active, icon: Icon, label, ...props }) => (
- <>
-
- {Icon ? : null}
- {label}
-
- >
+
+ {Icon ? : null}
+ {label}
+
);
DropdownMenuLink.propTypes = {
diff --git a/packages/dashboard-v2/src/components/Icons/icons/SimpleUploadIcon.js b/packages/dashboard-v2/src/components/Icons/icons/SimpleUploadIcon.js
new file mode 100644
index 00000000..0406f012
--- /dev/null
+++ b/packages/dashboard-v2/src/components/Icons/icons/SimpleUploadIcon.js
@@ -0,0 +1,10 @@
+import { withIconProps } from "../withIconProps";
+
+export const SimpleUploadIcon = withIconProps(({ size, ...props }) => (
+
+));
diff --git a/packages/dashboard-v2/src/components/Icons/index.js b/packages/dashboard-v2/src/components/Icons/index.js
index 05d9b832..611acef4 100644
--- a/packages/dashboard-v2/src/components/Icons/index.js
+++ b/packages/dashboard-v2/src/components/Icons/index.js
@@ -12,3 +12,4 @@ export * from "./icons/PlusIcon";
export * from "./icons/SearchIcon";
export * from "./icons/CopyIcon";
export * from "./icons/ShareIcon";
+export * from "./icons/SimpleUploadIcon";
diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js
index 2b53f2be..1db72dda 100644
--- a/packages/dashboard-v2/src/components/NavBar/NavBar.js
+++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js
@@ -9,7 +9,7 @@ import { PageContainer } from "../PageContainer";
import { NavBarLink, NavBarSection } from ".";
const NavBarContainer = styled.div.attrs({
- className: `grid sticky top-0 bg-white`,
+ className: `grid sticky top-0 bg-white z-10 shadow-sm`,
})``;
const NavBarBody = styled.nav.attrs({
@@ -68,8 +68,21 @@ export const NavBar = () => (
-
-
+
+
diff --git a/packages/dashboard-v2/src/components/Switch/Switch.js b/packages/dashboard-v2/src/components/Switch/Switch.js
index ed24bc92..892692be 100644
--- a/packages/dashboard-v2/src/components/Switch/Switch.js
+++ b/packages/dashboard-v2/src/components/Switch/Switch.js
@@ -21,7 +21,7 @@ const Label = styled.label.attrs({
`;
const Toggle = styled.span.attrs({
- className: `flex flex-row items-center justify-between
+ className: `flex flex-row items-center justify-between shrink-0
w-[44px] h-[22px] bg-white rounded-full
border border-palette-200 relative cursor-pointer`,
})`
@@ -45,7 +45,7 @@ const TogglePin = styled.span.attrs(({ $checked }) => ({
}
`;
-export const Switch = ({ children, defaultChecked, onChange, ...props }) => {
+export const Switch = ({ children, defaultChecked, labelClassName, onChange, ...props }) => {
const id = useMemo(nanoid, [onChange]);
const [checked, setChecked] = useState(defaultChecked);
@@ -56,11 +56,11 @@ export const Switch = ({ children, defaultChecked, onChange, ...props }) => {
return (
setChecked(ev.target.checked)} id={id} />
-
);
@@ -74,7 +74,11 @@ Switch.propTypes = {
/**
* Element to be rendered as the switch label
*/
- children: PropTypes.element,
+ children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
+ /**
+ * Pass additional CSS classes to the `label` element.
+ */
+ labelClassName: PropTypes.string,
/**
* Function to execute on change
*/
@@ -83,4 +87,5 @@ Switch.propTypes = {
Switch.defaultProps = {
defaultChecked: false,
+ labelClassName: "",
};
diff --git a/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js b/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js
index 9fa7f670..6b9531b4 100644
--- a/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js
+++ b/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js
@@ -1,18 +1,20 @@
+import { nanoid } from "nanoid";
import PropTypes from "prop-types";
+import { useMemo } from "react";
+
+export const TextInputBasic = ({ label, placeholder, ...props }) => {
+ const id = useMemo(() => `input-${nanoid()}`, []);
-/**
- * Primary UI component for user interaction
- */
-export const TextInputBasic = ({ label, placeholder }) => {
return (
-
-
{label}
+
+
+ {label}
+
);
diff --git a/packages/dashboard-v2/src/layouts/UserSettingsLayout.js b/packages/dashboard-v2/src/layouts/UserSettingsLayout.js
new file mode 100644
index 00000000..9fda613d
--- /dev/null
+++ b/packages/dashboard-v2/src/layouts/UserSettingsLayout.js
@@ -0,0 +1,87 @@
+import * as React from "react";
+import { Link } from "gatsby";
+import styled from "styled-components";
+import { SWRConfig } from "swr";
+
+import { authenticatedOnly } from "../lib/swrConfig";
+
+import { PageContainer } from "../components/PageContainer";
+import { NavBar } from "../components/Navbar";
+import { Footer } from "../components/Footer";
+import { UserProvider, useUser } from "../contexts/user";
+import { ContainerLoadingIndicator } from "../components/LoadingIndicator";
+
+const Wrapper = styled.div.attrs({
+ className: "min-h-screen overflow-hidden",
+})`
+ background-image: url(/images/dashboard-bg.svg);
+ background-position: center -280px;
+ background-repeat: no-repeat;
+`;
+
+const Layout = ({ children }) => {
+ const { user } = useUser();
+
+ // Prevent from flashing the dashboard screen to unauthenticated users.
+ return (
+
+ {!user && (
+
+
+
+ )}
+ {user && <>{children}>}
+
+ );
+};
+
+const Sidebar = () => (
+
+);
+
+const SidebarLink = styled(Link).attrs({
+ className: `h-12 py-3 px-6 h-full w-full flex
+ border-l-2 border-l-palette-200
+ border-b border-b-palette-100 last:border-b-transparent`,
+})``;
+
+const Content = styled.main.attrs({
+ className: "relative bg-white rounded px-6 py-6 sm:px-16 sm:py-14 mt-6 lg:mt-0 bg-none xl:bg-corner-circle",
+})`
+ background-repeat: no-repeat;
+`;
+
+const UserSettingsLayout = ({ children }) => (
+
+
+
+
+
+ Settings
+
+
+ {children}
+
+
+
+
+
+
+);
+
+export default UserSettingsLayout;
diff --git a/packages/dashboard-v2/src/pages/settings/api-keys.js b/packages/dashboard-v2/src/pages/settings/api-keys.js
new file mode 100644
index 00000000..56d6977e
--- /dev/null
+++ b/packages/dashboard-v2/src/pages/settings/api-keys.js
@@ -0,0 +1,15 @@
+import * as React from "react";
+
+import UserSettingsLayout from "../../layouts/UserSettingsLayout";
+
+const APIKeysPage = () => {
+ return (
+ <>
+
API Keys
+ >
+ );
+};
+
+APIKeysPage.Layout = UserSettingsLayout;
+
+export default APIKeysPage;
diff --git a/packages/dashboard-v2/src/pages/settings/export.js b/packages/dashboard-v2/src/pages/settings/export.js
new file mode 100644
index 00000000..feac6719
--- /dev/null
+++ b/packages/dashboard-v2/src/pages/settings/export.js
@@ -0,0 +1,15 @@
+import * as React from "react";
+
+import UserSettingsLayout from "../../layouts/UserSettingsLayout";
+
+const ExportPage = () => {
+ return (
+ <>
+
Import / export
+ >
+ );
+};
+
+ExportPage.Layout = UserSettingsLayout;
+
+export default ExportPage;
diff --git a/packages/dashboard-v2/src/pages/settings/index.js b/packages/dashboard-v2/src/pages/settings/index.js
new file mode 100644
index 00000000..459cf8c0
--- /dev/null
+++ b/packages/dashboard-v2/src/pages/settings/index.js
@@ -0,0 +1,81 @@
+import * as React from "react";
+import { useMedia } from "react-use";
+import styled from "styled-components";
+
+import theme from "../../lib/theme";
+import UserSettingsLayout from "../../layouts/UserSettingsLayout";
+import { TextInputBasic } from "../../components/TextInputBasic/TextInputBasic";
+import { Button } from "../../components/Button";
+import { AvatarUploader } from "../../components/AvatarUploader";
+
+const FormGroup = styled.div.attrs({
+ className: "grid sm:grid-cols-[1fr_min-content] w-full gap-y-2 gap-x-4 items-end",
+})``;
+
+const AccountPage = () => {
+ const isLargeScreen = useMedia(`(min-width: ${theme.screens.xl})`);
+ return (
+ <>
+
+
+
+ Account
+
+ Tum dicere exorsus est laborum et quasi involuta aperiri, altera prompta et expedita. Primum igitur,
+ inquit, modo ista sis aequitate.
+
+
+
+ {!isLargeScreen && (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The password must be at least 6 characters long. Significantly different from the email and old
+ password.
+
+
+
+
+
+ Delete account
+ This will completely delete your account. This process can't be undone.
+
+
+
+
+
+ >
+ );
+};
+
+AccountPage.Layout = UserSettingsLayout;
+
+export default AccountPage;
diff --git a/packages/dashboard-v2/src/pages/settings/notifications.js b/packages/dashboard-v2/src/pages/settings/notifications.js
new file mode 100644
index 00000000..b46a1da4
--- /dev/null
+++ b/packages/dashboard-v2/src/pages/settings/notifications.js
@@ -0,0 +1,51 @@
+import * as React from "react";
+
+import UserSettingsLayout from "../../layouts/UserSettingsLayout";
+
+import { Switch } from "../../components/Switch";
+import { StaticImage } from "gatsby-plugin-image";
+
+const NotificationsPage = () => {
+ return (
+ <>
+
+
+
Notifications
+
+ {/* TODO: saves on change */}
+
+ I agreee to get the latest news, updates and special offers delivered to my email inbox.
+
+
+
+
+ Statistics
+ {/* TODO: proper content :) */}
+
+ Si sine causa, nollem me tamen laudandis maioribus meis corrupisti nec in malis. Si sine causa, mox
+ videro.
+
+
+
+ -
+ {/* TODO: saves on change */}
+ Storage limit
+
+ -
+ {/* TODO: saves on change */}
+ File limit
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+NotificationsPage.Layout = UserSettingsLayout;
+
+export default NotificationsPage;
diff --git a/packages/dashboard-v2/src/styles/global.css b/packages/dashboard-v2/src/styles/global.css
index ae86596a..e0238aad 100644
--- a/packages/dashboard-v2/src/styles/global.css
+++ b/packages/dashboard-v2/src/styles/global.css
@@ -39,7 +39,14 @@
font-size: 1rem;
}
h6 {
- @apply uppercase;
- font-size: 0.875rem;
+ @apply uppercase text-xs;
+ }
+
+ p {
+ @apply mt-2;
+ }
+
+ hr {
+ @apply border-t-palette-200;
}
}
diff --git a/packages/dashboard-v2/static/images/avatar-bg.svg b/packages/dashboard-v2/static/images/avatar-bg.svg
new file mode 100644
index 00000000..4095e0a0
--- /dev/null
+++ b/packages/dashboard-v2/static/images/avatar-bg.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/dashboard-v2/static/images/avatar-placeholder.svg b/packages/dashboard-v2/static/images/avatar-placeholder.svg
new file mode 100644
index 00000000..8fae86b7
--- /dev/null
+++ b/packages/dashboard-v2/static/images/avatar-placeholder.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/dashboard-v2/static/images/inbox.svg b/packages/dashboard-v2/static/images/inbox.svg
new file mode 100644
index 00000000..389be116
--- /dev/null
+++ b/packages/dashboard-v2/static/images/inbox.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/dashboard-v2/tailwind.config.js b/packages/dashboard-v2/tailwind.config.js
index 6f4242d9..076d6912 100644
--- a/packages/dashboard-v2/tailwind.config.js
+++ b/packages/dashboard-v2/tailwind.config.js
@@ -39,6 +39,10 @@ module.exports = {
tab: ["18px", "28px"],
},
backgroundColor: ["disabled"],
+ backgroundImage: {
+ "corner-circle":
+ "radial-gradient(circle at calc(100% - 60px) -50px, #F5F5F7 0%, #f5f5f7 250px,rgba(0,0,0,0) 250px)",
+ },
textColor: ["disabled"],
keyframes: {
wiggle: {
@@ -54,6 +58,8 @@ module.exports = {
"page-md": "640px",
"page-lg": "896px",
"page-xl": "1312px",
+ "settings-lg": "704px",
+ "settings-xl": "928px",
},
minWidth: {
button: "112px",