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

Admin UI: restructured sidebar to made dev actions more noticeable #2798

Merged
merged 9 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions .changeset/late-seals-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@arch-ui/navbar': patch
'@keystonejs/app-admin-ui': minor
---

Revamped sidebar design.
38 changes: 0 additions & 38 deletions packages/app-admin-ui/client/components/Nav/NavIcons.js

This file was deleted.

141 changes: 103 additions & 38 deletions packages/app-admin-ui/client/components/Nav/index.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';
Expand All @@ -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,
Expand Down Expand Up @@ -88,6 +94,7 @@ const GrabHandle = styled.div(({ isActive }) => ({
top: -gridSize,
},
}));

const CollapseExpand = styled.button(({ isCollapsed, mouseIsOverNav }) => {
const size = 32;
const offsetTop = 20;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 (
<div css={{ marginBottom: `${PRIMARY_NAV_GUTTER}px` }}>
{entries.map(({ label, to, icon: ActionIcon, target }) => (
<PrimaryNavItem
key={to}
href={to}
target={target}
mouseIsOverNav={mouseIsOverNav}
css={{ display: 'flex', alignItems: 'center' }}
>
<ActionIcon css={{ flexShrink: 0 }} />
<span css={{ padding: `0 ${PRIMARY_NAV_GUTTER}px` }}>{label}</span>
</PrimaryNavItem>
))}
</div>
);
};

const PrimaryNavContent = ({ mouseIsOverNav }) => {
const {
adminPath,
Expand All @@ -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}
</Title>
{authListKey && (
<UserInfo
authListKey={authListKey}
authListPath={`${adminPath}/${getListByKey(authListKey).path}`}
/>
)}
<ActionItems mouseIsOverNav={mouseIsOverNav} />
<PrimaryNavItems
adminPath={adminPath}
authListKey={authListKey}
Expand All @@ -392,13 +464,6 @@ const PrimaryNavContent = ({ mouseIsOverNav }) => {
pages={pages}
mouseIsOverNav={mouseIsOverNav}
/>
{authListKey && (
<UserInfo
authListKey={authListKey}
authListPath={`${adminPath}/${getListByKey(authListKey).path}`}
/>
)}
<NavIcons />
</Inner>
);
};
Expand Down
4 changes: 3 additions & 1 deletion packages/arch/packages/navbar/src/PrimaryNav.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ export const NavGroupIcons = styled.div({
});

export const PrimaryNav = styled.nav({
backgroundColor: colors.page,
boxSizing: 'border-box',
display: 'flex',
flexDirection: 'column',
height: '100vh',
position: 'fixed',
zIndex: 2,
});

export const PrimaryNavScrollArea = styled.div(({ hasScroll, isBottom, isScrollable }) => {
const divider = {
backgroundColor: 'rgba(9, 30, 66, 0.1)',
Expand Down Expand Up @@ -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',
Expand Down
4 changes: 2 additions & 2 deletions test-projects/basic/cypress/integration/nav-bar_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down