Setings Page Side Navigation

Utilizing previous work in d8787cb4 for anchor navigation, navigate to the specific card in the settings page when clicked.

I like this model mainly because in Mobile, users don't need to keep opening the drawer to navigate -- they just need to scroll. This allows us to use the same design for Mobile and App.

# Conflicts:
#	ui/page/settings/view.jsx
This commit is contained in:
infinite-persistence 2021-08-08 16:13:35 +08:00
parent 7695af6a59
commit e9034a03c2
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
13 changed files with 240 additions and 30 deletions

View file

@ -10,6 +10,7 @@ type Props = {
title?: string | Node,
subtitle?: string | Node,
titleActions?: string | Node,
id?: string,
body?: string | Node,
actions?: string | Node,
icon?: string,
@ -30,6 +31,7 @@ export default function Card(props: Props) {
title,
subtitle,
titleActions,
id,
body,
actions,
icon,
@ -53,6 +55,7 @@ export default function Card(props: Props) {
className={classnames(className, 'card', {
'card__multi-pane': Boolean(secondPane),
})}
id={id}
onClick={(e) => {
if (onClick) {
onClick();

View file

@ -2318,6 +2318,23 @@ export const icons = {
<path d="M.75 19.497a3.75 3.75 0 107.5 0 3.75 3.75 0 10-7.5 0zM.75 8.844a11.328 11.328 0 0114.4 14.4M.75 1.113a18.777 18.777 0 0122.139 22.123" />
</g>
),
[ICONS.APPEARANCE]: buildIcon(
<g>
<path d="M16.022,15.624c.3,3.856,6.014,1.2,5.562,2.54-2.525,7.481-12.648,5.685-16.966,1.165A10.9,10.9,0,0,1,4.64,4.04C8.868-.188,16.032-.495,19.928,4.018,27.56,12.858,15.758,12.183,16.022,15.624Z" />
<path d="M5.670 13.309 A1.520 1.520 0 1 0 8.710 13.309 A1.520 1.520 0 1 0 5.670 13.309 Z" />
<path d="M9.430 18.144 A1.520 1.520 0 1 0 12.470 18.144 A1.520 1.520 0 1 0 9.430 18.144 Z" />
<path d="M13.066 5.912 A1.520 1.520 0 1 0 16.106 5.912 A1.520 1.520 0 1 0 13.066 5.912 Z" />
<path d="M6.620 7.524 A1.520 1.520 0 1 0 9.660 7.524 A1.520 1.520 0 1 0 6.620 7.524 Z" />
</g>
),
[ICONS.CONTENT]: buildIcon(
<g>
<path d="M15.750 16.500 A1.500 1.500 0 1 0 18.750 16.500 A1.500 1.500 0 1 0 15.750 16.500 Z" />
<path d="M18.524,10.7l.442,1.453a.994.994,0,0,0,1.174.681l1.472-.341a1.339,1.339,0,0,1,1.275,2.218l-1.031,1.111a1,1,0,0,0,0,1.362l1.031,1.111a1.339,1.339,0,0,1-1.275,2.218l-1.472-.341a.994.994,0,0,0-1.174.681L18.524,22.3a1.33,1.33,0,0,1-2.548,0l-.442-1.453a.994.994,0,0,0-1.174-.681l-1.472.341a1.339,1.339,0,0,1-1.275-2.218l1.031-1.111a1,1,0,0,0,0-1.362l-1.031-1.111a1.339,1.339,0,0,1,1.275-2.218l1.472.341a.994.994,0,0,0,1.174-.681l.442-1.453A1.33,1.33,0,0,1,18.524,10.7Z" />
<path d="M8.25,20.25h-6a1.5,1.5,0,0,1-1.5-1.5V2.25A1.5,1.5,0,0,1,2.25.75H12.879a1.5,1.5,0,0,1,1.06.439l2.872,2.872a1.5,1.5,0,0,1,.439,1.06V6.75" />
<path d="M6.241,12.678a.685.685,0,0,1-.991-.613V7.435a.685.685,0,0,1,.991-.613l4.631,2.316a.684.684,0,0,1,0,1.224Z" />
</g>
),
[ICONS.STAR]: buildIcon(
<g>
<path d="M12.729 1.2l3.346 6.629 6.44.638a.805.805 0 01.5 1.374l-5.3 5.253 1.965 7.138a.813.813 0 01-1.151.935L12 19.934l-6.52 3.229a.813.813 0 01-1.151-.935l1.965-7.138L.99 9.837a.805.805 0 01.5-1.374l6.44-.638L11.271 1.2a.819.819 0 011.458 0z" />

View file

@ -23,6 +23,7 @@ type Props = {
isUpgradeAvailable: boolean,
authPage: boolean,
filePage: boolean,
settingsPage?: boolean,
noHeader: boolean,
noFooter: boolean,
noSideNavigation: boolean,
@ -45,6 +46,7 @@ function Page(props: Props) {
children,
className,
filePage = false,
settingsPage,
authPage = false,
fullWidthPage = false,
noHeader = false,
@ -114,6 +116,7 @@ function Page(props: Props) {
'main--full-width': fullWidthPage,
'main--auth-page': authPage,
'main--file-page': filePage,
'main--settings-page': settingsPage,
'main--markdown': isMarkdown,
'main--theater-mode': isOnFilePage && videoTheaterMode && !livestream,
'main--livestream': livestream && !chatDisabled,

View file

@ -1,6 +1,7 @@
// @flow
import * as ICONS from 'constants/icons';
import * as PAGES from 'constants/pages';
import { SETTINGS_GRP } from 'constants/settings';
import React from 'react';
import Button from 'component/button';
import Card from 'component/common/card';
@ -37,6 +38,7 @@ export default function SettingAccount(props: Props) {
return (
<Card
id={SETTINGS_GRP.ACCOUNT}
title={__('Account')}
subtitle=""
isBodyList

View file

@ -1,4 +1,5 @@
// @flow
import { SETTINGS_GRP } from 'constants/settings';
import React from 'react';
import { SETTINGS } from 'lbry-redux';
import Card from 'component/common/card';
@ -24,6 +25,7 @@ export default function SettingAppearance(props: Props) {
return (
<Card
id={SETTINGS_GRP.APPEARANCE}
title={__('Appearance')}
subtitle=""
isBodyList

View file

@ -6,6 +6,7 @@ import { SETTINGS } from 'lbry-redux';
import { Lbryio } from 'lbryinc';
import { SIMPLE_SITE } from 'config';
import * as MODALS from 'constants/modal_types';
import { SETTINGS_GRP } from 'constants/settings';
import Button from 'component/button';
import Card from 'component/common/card';
import { FormField, FormFieldPrice } from 'component/common/form';
@ -52,6 +53,7 @@ export default function SettingContent(props: Props) {
return (
<Card
id={SETTINGS_GRP.CONTENT}
title={__('Content settings')}
subtitle=""
isBodyList

View file

@ -1,5 +1,6 @@
// @flow
import { ALERT } from 'constants/icons';
import { SETTINGS_GRP } from 'constants/settings';
import React from 'react';
import Button from 'component/button';
import Card from 'component/common/card';
@ -120,6 +121,7 @@ export default function SettingSystem(props: Props) {
return (
<Card
id={SETTINGS_GRP.SYSTEM}
title={__('System')}
subtitle=""
isBodyList

View file

@ -0,0 +1,3 @@
import SettingsSideNavigation from './view';
export default SettingsSideNavigation;

View file

@ -0,0 +1,134 @@
// @flow
import * as PAGES from 'constants/pages';
import * as ICONS from 'constants/icons';
import type { Node } from 'react';
import React from 'react';
import classnames from 'classnames';
import Button from 'component/button';
// @if TARGET='app'
import { IS_MAC } from 'component/app/view';
// @endif
import { useIsMediumScreen } from 'effects/use-screensize';
type SideNavLink = {
title: string,
link?: string,
route?: string,
onClick?: () => any,
icon: string,
extra?: Node,
};
export default function SettingsSideNavigation() {
const sidebarOpen = true;
const isMediumScreen = useIsMediumScreen();
const SIDE_LINKS: Array<SideNavLink> = [
{
title: 'Appearance',
link: `/$/${PAGES.SETTINGS}#appearance`,
icon: ICONS.APPEARANCE,
},
{
title: 'Account',
link: `/$/${PAGES.SETTINGS}#account`,
icon: ICONS.ACCOUNT,
},
{
title: 'Content settings',
link: `/$/${PAGES.SETTINGS}#content`,
icon: ICONS.CONTENT,
},
{
title: 'System',
link: `/$/${PAGES.SETTINGS}#system`,
icon: ICONS.SETTINGS,
},
];
const isAbsolute = isMediumScreen;
const microNavigation = !sidebarOpen || isMediumScreen;
if (isMediumScreen) {
// I think it's ok to hide it for now on medium/small screens given that
// we are using a scrolling Settings Page that displays everything. If we
// really need this, most likely we can display it as a Tab at the top
// of the page.
return null;
}
return (
<div
className={classnames('navigation__wrapper', {
'navigation__wrapper--micro': microNavigation,
'navigation__wrapper--absolute': isAbsolute,
})}
>
<nav
aria-label={'Sidebar'}
className={classnames('navigation', {
'navigation--micro': microNavigation,
// @if TARGET='app'
'navigation--mac': IS_MAC,
// @endif
})}
>
<div>
<ul className={classnames('navigation-links', { 'navigation-links--micro': !sidebarOpen })}>
{SIDE_LINKS.map((linkProps) => {
// $FlowFixMe
return (
<li key={linkProps.route || linkProps.link}>
<Button
{...linkProps}
label={__(linkProps.title)}
title={__(linkProps.title)}
// $FlowFixMe
navigate={linkProps.route || linkProps.link}
icon={linkProps.icon}
className={classnames('navigation-link', {})}
/>
{linkProps.extra && linkProps.extra}
</li>
);
})}
</ul>
</div>
</nav>
{isMediumScreen && sidebarOpen && (
<>
<nav
className={classnames('navigation--absolute', {
// @if TARGET='app'
'navigation--mac': IS_MAC,
// @endif
})}
>
<div>
<ul className="navigation-links--absolute">
{SIDE_LINKS.map((linkProps) => {
// $FlowFixMe
const { link, route, ...passedProps } = linkProps;
return (
<li key={route || link}>
<Button
{...passedProps}
navigate={route || link}
label={__(linkProps.title)}
title={__(linkProps.title)}
icon={linkProps.icon}
className={classnames('navigation-link', {})}
/>
{linkProps.extra && linkProps.extra}
</li>
);
})}
</ul>
</div>
</nav>
</>
)}
</div>
);
}

View file

@ -163,5 +163,7 @@ export const STACK = 'stack';
export const TIME = 'time';
export const GLOBE = 'globe';
export const RSS = 'rss';
export const APPEARANCE = 'Appearance';
export const CONTENT = 'Content';
export const STAR = 'star';
export const MUSIC = 'MusicCategory';

View file

@ -26,3 +26,10 @@ export const ENABLE_SYNC = 'enable_sync';
export const TO_TRAY_WHEN_CLOSED = 'to_tray_when_closed';
export const ENABLE_PUBLISH_PREVIEW = 'enable-publish-preview';
export const DESKTOP_WINDOW_ZOOM = 'desktop_window_zoom';
export const SETTINGS_GRP = {
APPEARANCE: 'appearance',
ACCOUNT: 'account',
CONTENT: 'content',
SYSTEM: 'system',
};

View file

@ -8,6 +8,7 @@ import Page from 'component/page';
import SettingAccount from 'component/settingAccount';
import SettingAppearance from 'component/settingAppearance';
import SettingContent from 'component/settingContent';
import SettingsSideNavigation from 'component/settingsSideNavigation';
import SettingSystem from 'component/settingSystem';
import SettingUnauthenticated from 'component/settingUnauthenticated';
import Yrbl from 'component/yrbl';
@ -40,7 +41,16 @@ class SettingsPage extends React.PureComponent<Props> {
const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0;
return (
<Page noFooter noSideNavigation backout={{ title: __('Settings'), backLabel: __('Done') }} className="card-stack">
<Page
noFooter
settingsPage
noSideNavigation
backout={{ title: __('Settings'), backLabel: __('Done') }}
className="card-stack"
>
<SettingsSideNavigation />
<div>
{!isAuthenticated && IS_WEB && (
<>
<SettingUnauthenticated />
@ -51,7 +61,12 @@ class SettingsPage extends React.PureComponent<Props> {
subtitle={__('Unlock new buttons that change things.')}
actions={
<div className="section__actions">
<Button button="primary" icon={ICONS.SIGN_UP} label={__('Sign Up')} navigate={`/$/${PAGES.AUTH}`} />
<Button
button="primary"
icon={ICONS.SIGN_UP}
label={__('Sign Up')}
navigate={`/$/${PAGES.AUTH}`}
/>
</div>
}
/>
@ -71,6 +86,7 @@ class SettingsPage extends React.PureComponent<Props> {
<SettingSystem />
</div>
)}
</div>
</Page>
);
}

View file

@ -221,6 +221,23 @@
}
}
.main--settings-page {
width: 100%;
max-width: 70rem;
margin-left: auto;
margin-right: auto;
margin-top: var(--spacing-m);
padding: 0 var(--spacing-m);
display: flex;
flex-direction: row;
align-items: flex-start;
position: relative;
@media (min-width: $breakpoint-small) {
width: 80%;
}
}
.main--markdown {
flex-direction: column;
}