diff --git a/.changeset/late-seals-report.md b/.changeset/late-seals-report.md
new file mode 100644
index 00000000000..7e528c31d83
--- /dev/null
+++ b/.changeset/late-seals-report.md
@@ -0,0 +1,6 @@
+---
+'@arch-ui/navbar': patch
+'@keystonejs/app-admin-ui': minor
+---
+
+Revamped sidebar design.
diff --git a/packages/app-admin-ui/client/components/Nav/NavIcons.js b/packages/app-admin-ui/client/components/Nav/NavIcons.js
deleted file mode 100644
index ec52ee4952e..00000000000
--- a/packages/app-admin-ui/client/components/Nav/NavIcons.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* global ENABLE_DEV_FEATURES */
-/** @jsx jsx */
-
-import { Fragment } from 'react';
-import { jsx } from '@emotion/core';
-
-import { TerminalIcon, MarkGithubIcon, SignOutIcon } from '@arch-ui/icons';
-import { NavIcon, NavGroupIcons } from '@arch-ui/navbar';
-import { A11yText } from '@arch-ui/typography';
-import { useAdminMeta } from '../../providers/AdminMeta';
-
-const GITHUB_PROJECT = 'https://github.com/keystonejs/keystone';
-
-export function NavIcons() {
- let { graphiqlPath, signoutPath, authStrategy } = useAdminMeta();
- return ENABLE_DEV_FEATURES || authStrategy ? (
-
- {authStrategy ? (
-
-
- Sign Out
-
- ) : null}
- {ENABLE_DEV_FEATURES ? (
-
-
-
- GitHub
-
-
-
- Graphiql Console
-
-
- ) : null}
-
- ) : null;
-}
diff --git a/packages/app-admin-ui/client/components/Nav/index.js b/packages/app-admin-ui/client/components/Nav/index.js
index bb5ccfe245a..0747cc72236 100644
--- a/packages/app-admin-ui/client/components/Nav/index.js
+++ b/packages/app-admin-ui/client/components/Nav/index.js
@@ -1,6 +1,7 @@
+/* global ENABLE_DEV_FEATURES */
/** @jsx jsx */
-import React, { useState } from 'react'; // eslint-disable-line no-unused-vars
+import React, { useState, useMemo } from 'react'; // eslint-disable-line no-unused-vars
import { Link, useRouteMatch } from 'react-router-dom';
import PropToggle from 'react-prop-toggle';
import { uid } from 'react-uid';
@@ -19,11 +20,10 @@ import {
import { Title, Truncate } from '@arch-ui/typography';
import Tooltip from '@arch-ui/tooltip';
import { FlexGroup } from '@arch-ui/layout';
-import { PersonIcon } from '@arch-ui/icons';
+import { PersonIcon, SignOutIcon, TerminalIcon, MarkGithubIcon } from '@arch-ui/icons';
import { useAdminMeta } from '../../providers/AdminMeta';
import ResizeHandler, { KEYBOARD_SHORTCUT } from './ResizeHandler';
-import { NavIcons } from './NavIcons';
import ScrollQuery from '../ScrollQuery';
import { useQuery } from '@apollo/react-hooks';
@@ -36,30 +36,36 @@ function camelToKebab(string) {
return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
-const Col = styled.div({
- alignItems: 'flex-start',
- display: 'flex',
- flex: 1,
- flexDirection: 'column',
- justifyContent: 'flex-start',
- overflow: 'hidden',
- width: '100%',
-});
-const Inner = styled(Col)({
- height: ' 100vh',
-});
-const Page = styled.div({
- flex: 1,
- minHeight: '100vh',
- position: 'relative',
-});
-const PageWrapper = styled.div({
- display: 'flex',
-});
-const Relative = styled(Col)({
- height: ' 100%',
- position: 'relative',
-});
+const Col = styled.div`
+ align-items: flex-start;
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ justify-content: flex-start;
+ overflow: hidden;
+ width: 100%;
+`;
+
+const Inner = styled(Col)`
+ height: 100vh;
+ align-items: stretch;
+`;
+
+const Page = styled.div`
+ flex: 1;
+ min-height: 100vh;
+ position: relative;
+`;
+
+const PageWrapper = styled.div`
+ display: flex;
+`;
+
+const Relative = styled(Col)`
+ height: 100%;
+ position: relative;
+`;
+
const GrabHandle = styled.div(({ isActive }) => ({
backgroundColor: alpha(colors.text, 0.06),
height: isActive ? '100%' : 0,
@@ -88,6 +94,7 @@ const GrabHandle = styled.div(({ isActive }) => ({
top: -gridSize,
},
}));
+
const CollapseExpand = styled.button(({ isCollapsed, mouseIsOverNav }) => {
const size = 32;
const offsetTop = 20;
@@ -293,9 +300,8 @@ function PrimaryNavItems({
}
const UserInfoContainer = styled.div`
- align-self: stretch;
- padding: ${PRIMARY_NAV_GUTTER}px 0;
- margin: 0 ${PRIMARY_NAV_GUTTER}px;
+ padding-bottom: ${PRIMARY_NAV_GUTTER}px;
+ margin: ${PRIMARY_NAV_GUTTER}px;
border-bottom: 2px solid ${colors.N10};
display: flex;
align-items: center;
@@ -358,6 +364,65 @@ const UserInfo = ({ authListKey, authListPath }) => {
);
};
+const GITHUB_PROJECT = 'https://github.com/keystonejs/keystone';
+
+const ActionItems = ({ mouseIsOverNav }) => {
+ const { signoutPath, graphiqlPath, authStrategy } = useAdminMeta();
+
+ const entries = useMemo(
+ () => [
+ ...(authStrategy
+ ? [
+ {
+ label: 'Sign out',
+ to: signoutPath,
+ icon: SignOutIcon,
+ },
+ ]
+ : []),
+ ...(ENABLE_DEV_FEATURES
+ ? [
+ {
+ label: 'GraphiQL Playground',
+ to: graphiqlPath,
+ icon: TerminalIcon,
+ target: '_blank',
+ },
+ {
+ label: 'Keystone on GitHub',
+ to: GITHUB_PROJECT,
+ icon: MarkGithubIcon,
+ target: '_blank',
+ },
+ ]
+ : []),
+ ],
+ [] // The admin meta never changes between server restarts
+ );
+
+ // No items to show
+ if (!entries.length) {
+ return null;
+ }
+
+ return (
+
+ {entries.map(({ label, to, icon: ActionIcon, target }) => (
+
+
+ {label}
+
+ ))}
+
+ );
+};
+
const PrimaryNavContent = ({ mouseIsOverNav }) => {
const {
adminPath,
@@ -375,15 +440,22 @@ const PrimaryNavContent = ({ mouseIsOverNav }) => {
margin="both"
crop
css={{
+ fontSize: '1.6em',
color: colors.N90,
textDecoration: 'none',
- alignSelf: 'stretch',
marginLeft: PRIMARY_NAV_GUTTER,
marginRight: PRIMARY_NAV_GUTTER,
}}
>
{name}
+ {authListKey && (
+
+ )}
+
{
pages={pages}
mouseIsOverNav={mouseIsOverNav}
/>
- {authListKey && (
-
- )}
-
);
};
diff --git a/packages/arch/packages/navbar/src/PrimaryNav.js b/packages/arch/packages/navbar/src/PrimaryNav.js
index 08db2428dac..02b9d42b3fe 100644
--- a/packages/arch/packages/navbar/src/PrimaryNav.js
+++ b/packages/arch/packages/navbar/src/PrimaryNav.js
@@ -13,6 +13,7 @@ export const NavGroupIcons = styled.div({
});
export const PrimaryNav = styled.nav({
+ backgroundColor: colors.page,
boxSizing: 'border-box',
display: 'flex',
flexDirection: 'column',
@@ -20,6 +21,7 @@ export const PrimaryNav = styled.nav({
position: 'fixed',
zIndex: 2,
});
+
export const PrimaryNavScrollArea = styled.div(({ hasScroll, isBottom, isScrollable }) => {
const divider = {
backgroundColor: 'rgba(9, 30, 66, 0.1)',
@@ -71,7 +73,7 @@ export const PrimaryNavItem = styled(ItemElement)(({ depth, isSelected, mouseIsO
display: 'block',
marginBottom: 2,
overflow: 'hidden',
- padding: PRIMARY_NAV_GUTTER,
+ padding: `${gridSize * 1.5}px`,
paddingLeft: depth ? PRIMARY_NAV_GUTTER * depth : PRIMARY_NAV_GUTTER,
position: 'relative',
textDecoration: 'none',
diff --git a/test-projects/basic/cypress/integration/nav-bar_spec.js b/test-projects/basic/cypress/integration/nav-bar_spec.js
index 7f88040ab67..bb909cbe35e 100644
--- a/test-projects/basic/cypress/integration/nav-bar_spec.js
+++ b/test-projects/basic/cypress/integration/nav-bar_spec.js
@@ -10,11 +10,11 @@ describe('Nav Bar', () => {
{ text: 'Posts', target: '/admin/posts' },
{ text: 'Post Categories', target: '/admin/post-categories' },
{
- text: 'GitHub',
+ text: 'Keystone on GitHub',
target: 'https://github.com/keystonejs/keystone',
newTab: true,
},
- { text: 'Graphiql', target: '/admin/graphiql', newTab: true },
+ { text: 'GraphiQL Playground', target: '/admin/graphiql', newTab: true },
].forEach(({ text, target, newTab = false }) => {
it(`${newTab ? 'Check' : 'Click'} ${text}`, () => {
cy.visit('/admin');