Skip to content

Commit fe16f1d

Browse files
committed
Sidebar facelift
1 parent 0cd7868 commit fe16f1d

File tree

6 files changed

+97
-81
lines changed

6 files changed

+97
-81
lines changed

browser/data-browser/src/components/IconButton/IconButton.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export enum IconButtonVariant {
77
Outline,
88
Fill,
99
Colored,
10+
Square,
1011
}
1112

1213
type ColorProp = keyof DefaultTheme['colors'] | 'inherit';
@@ -56,7 +57,7 @@ export const IconButtonLink = React.forwardRef<
5657
HTMLAnchorElement,
5758
React.PropsWithChildren<IconButtonLinkProps>
5859
>(({ variant, children, color, ...props }, ref) => {
59-
const Comp = ComponentMap.get(variant!) ?? SimpleIconButton;
60+
const Comp = ComponentMap.get(variant ?? IconButtonVariant.Simple)!;
6061

6162
return (
6263
<Comp ref={ref} color={color!} as='a' {...props}>
@@ -84,8 +85,8 @@ const IconButtonBase = styled.button<ButtonBaseProps>`
8485
border: none;
8586
8687
padding: var(--button-padding);
87-
width: calc(1em + var(--button-padding) * 2);
88-
height: calc(1em + var(--button-padding) * 2);
88+
width: calc(${p => p.size} + var(--button-padding) * 2);
89+
height: calc(${p => p.size} + var(--button-padding) * 2);
8990
9091
&[disabled] {
9192
opacity: 0.5;
@@ -134,6 +135,27 @@ const OutlineIconButton = styled(IconButtonBase)<ButtonStyleProps>`
134135
}
135136
`;
136137

138+
const SquareIconButton = styled(IconButtonBase)<ButtonStyleProps>`
139+
color: ${p => (p.color === 'inherit' ? 'inherit' : p.theme.colors[p.color])};
140+
background-color: ${p => p.theme.colors.bg};
141+
border-radius: ${p => p.theme.radius};
142+
border: 1px solid ${p => p.theme.colors.bg2};
143+
144+
&:not([disabled]) {
145+
&:hover,
146+
&:focus-visible {
147+
color: ${p => p.theme.colors.main};
148+
border-color: ${p => p.theme.colors.main};
149+
box-shadow: ${p => p.theme.boxShadowSoft};
150+
}
151+
}
152+
153+
&&:active {
154+
background-color: ${p => p.theme.colors.main};
155+
color: white;
156+
}
157+
`;
158+
137159
const FillIconButton = styled(IconButtonBase)<ButtonStyleProps>`
138160
color: ${p => (p.color === 'inherit' ? 'inherit' : p.theme.colors[p.color])};
139161
background-color: unset;
@@ -164,4 +186,5 @@ const ComponentMap = new Map([
164186
[IconButtonVariant.Outline, OutlineIconButton],
165187
[IconButtonVariant.Fill, FillIconButton],
166188
[IconButtonVariant.Colored, ColoredIconButton],
189+
[IconButtonVariant.Square, SquareIconButton],
167190
]);

browser/data-browser/src/components/SideBar/About.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Logo } from '../Logo';
33
import { SideBarHeader } from './SideBarHeader';
44
import React from 'react';
55
import { FaGithub, FaDiscord, FaBook } from 'react-icons/fa';
6-
import { IconButtonLink } from '../IconButton/IconButton';
6+
import { IconButtonLink, IconButtonVariant } from '../IconButton/IconButton';
77

88
interface AboutItem {
99
icon: React.ReactNode;
@@ -32,9 +32,9 @@ const aboutMenuItems: AboutItem[] = [
3232
export function About() {
3333
return (
3434
<>
35-
<SideBarHeader>
35+
{/* <SideBarHeader>
3636
<Logo style={{ height: '1.1rem', maxWidth: '100%' }} />
37-
</SideBarHeader>
37+
</SideBarHeader> */}
3838
<AboutWrapper>
3939
{aboutMenuItems.map(({ href, icon, helper }) => (
4040
<IconButtonLink
@@ -45,6 +45,7 @@ export function About() {
4545
title={helper}
4646
size='1.2em'
4747
color='textLight'
48+
variant={IconButtonVariant.Square}
4849
>
4950
{icon}
5051
</IconButtonLink>
@@ -57,7 +58,6 @@ export function About() {
5758
const AboutWrapper = styled.div`
5859
--inner-padding: 0.5rem;
5960
display: flex;
60-
/* flex-direction: column; */
6161
align-items: center;
6262
gap: 0.5rem;
6363
margin-left: calc(1rem - var(--inner-padding));
Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import React, {
2-
useCallback,
3-
useEffect,
4-
useMemo,
5-
useRef,
6-
useState,
7-
} from 'react';
8-
import { FaPlusCircle } from 'react-icons/fa';
1+
import React, { useCallback, useEffect, useRef, useState } from 'react';
2+
import {
3+
FaCog,
4+
FaInfo,
5+
FaKeyboard,
6+
FaPlusCircle,
7+
FaUser,
8+
} from 'react-icons/fa';
99
import { constructOpenURL } from '../../helpers/navigation';
1010
import { useCurrentSubject } from '../../helpers/useCurrentSubject';
11-
import { appMenuItems } from './menuItems';
12-
import { SideBarHeader } from './SideBarHeader';
1311
import { SideBarMenuItem } from './SideBarMenuItem';
12+
import styled from 'styled-components';
13+
import { paths } from '../../routes/paths';
14+
import { unknownSubject, useCurrentAgent, useResource } from '@tomic/react';
1415

1516
// Non standard event type so we have to type it ourselfs for now.
1617
type BeforeInstallPromptEvent = {
@@ -26,6 +27,8 @@ export function AppMenu({ onItemClick }: AppMenuProps): JSX.Element {
2627
const event = useRef<BeforeInstallPromptEvent | null>(null);
2728
const [subject] = useCurrentSubject();
2829
const [showInstallButton, setShowInstallButton] = useState(false);
30+
const [agent] = useCurrentAgent();
31+
const agentResource = useResource(agent?.subject ?? unknownSubject);
2932

3033
const install = useCallback(() => {
3134
if (!event.current) {
@@ -53,33 +56,50 @@ export function AppMenu({ onItemClick }: AppMenuProps): JSX.Element {
5356
return () => window.removeEventListener('beforeinstallprompt', listener);
5457
}, []);
5558

56-
const items = useMemo(() => {
57-
if (!showInstallButton) {
58-
return appMenuItems;
59-
}
60-
61-
return [
62-
{
63-
icon: <FaPlusCircle />,
64-
label: 'Install App',
65-
helper: 'Install app to desktop',
66-
handleClickItem: install,
67-
path: constructOpenURL(subject ?? window.location.href),
68-
},
69-
...appMenuItems,
70-
];
71-
}, [appMenuItems, showInstallButton, subject]);
72-
7359
return (
74-
<>
75-
<SideBarHeader>App</SideBarHeader>
76-
{items.map(p => (
60+
<Section aria-label='App menu'>
61+
<SideBarMenuItem
62+
icon={<FaUser />}
63+
label={agent ? agentResource.title : 'Login'}
64+
helper='See and edit the current Agent / User (u)'
65+
path={paths.agentSettings}
66+
onClick={onItemClick}
67+
/>
68+
<SideBarMenuItem
69+
icon={<FaCog />}
70+
label='Settings'
71+
helper='Edit the theme (t)'
72+
path={paths.themeSettings}
73+
onClick={onItemClick}
74+
/>
75+
<SideBarMenuItem
76+
icon={<FaKeyboard />}
77+
label='Keyboard Shortcuts'
78+
helper='View the keyboard shortcuts (?)'
79+
path={paths.shortcuts}
80+
onClick={onItemClick}
81+
/>
82+
<SideBarMenuItem
83+
icon={<FaInfo />}
84+
label='About'
85+
helper='Welcome page, tells about this app'
86+
path={paths.about}
87+
onClick={onItemClick}
88+
/>
89+
{showInstallButton && (
7790
<SideBarMenuItem
78-
key={p.label}
79-
{...p}
80-
handleClickItem={p.handleClickItem ?? onItemClick}
91+
icon={<FaPlusCircle />}
92+
label='Install App'
93+
helper='Install app to desktop'
94+
path={constructOpenURL(subject ?? window.location.href)}
95+
onClick={install}
8196
/>
82-
))}
83-
</>
97+
)}
98+
</Section>
8499
);
85100
}
101+
102+
const Section = styled.section`
103+
border-top: 1px solid ${p => p.theme.colors.bg2};
104+
padding-top: ${p => p.theme.margin}rem;
105+
`;

browser/data-browser/src/components/SideBar/SideBarMenuItem.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export interface SideBarMenuItemProps extends AtomicLinkProps {
99
icon?: React.ReactNode;
1010
disabled?: boolean;
1111
/** Is called when clicking on the item. Used for closing the menu. */
12-
handleClickItem?: () => void;
12+
onClick?: () => void;
1313
}
1414

1515
export function SideBarMenuItem({
@@ -19,11 +19,11 @@ export function SideBarMenuItem({
1919
path,
2020
href,
2121
subject,
22-
handleClickItem,
22+
onClick,
2323
}: SideBarMenuItemProps) {
2424
return (
2525
<AtomicLink href={href} subject={subject} path={path} clean>
26-
<SideBarItem key={label} title={helper} onClick={handleClickItem}>
26+
<SideBarItem key={label} title={helper} onClick={onClick}>
2727
{icon && <SideBarIcon>{icon}</SideBarIcon>}
2828
{label}
2929
</SideBarItem>

browser/data-browser/src/components/SideBar/index.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { NavBarSpacer } from '../NavBarSpacer';
99
import { AppMenu } from './AppMenu';
1010
import { About } from './About';
1111
import { useMediaQuery } from '../../hooks/useMediaQuery';
12+
import { Column } from '../Row';
1213

1314
/** Amount of pixels where the sidebar automatically shows */
1415
export const SIDEBAR_TOGGLE_WIDTH = 600;
@@ -47,6 +48,7 @@ export function SideBar(): JSX.Element {
4748

4849
return (
4950
<SideBarContainer>
51+
{/* @ts-ignore */}
5052
<SideBarStyled
5153
ref={mountRefs}
5254
size={size}
@@ -59,8 +61,10 @@ export function SideBar(): JSX.Element {
5961
{/* The key is set to make sure the component is re-loaded when the baseURL changes */}
6062
<SideBarDriveMemo handleClickItem={closeSideBar} key={drive} />
6163
<MenuWrapper>
62-
<AppMenu onItemClick={closeSideBar} />
63-
<About />
64+
<Column>
65+
<AppMenu onItemClick={closeSideBar} />
66+
<About />
67+
</Column>
6468
</MenuWrapper>
6569
<NavBarSpacer baseMargin='1rem' position='bottom' />
6670
<SideBarDragArea ref={dragAreaRef} isDragging={isDragging} />
@@ -83,12 +87,12 @@ interface SideBarOverlayProps {
8387
visible: boolean;
8488
}
8589

86-
// eslint-disable-next-line prettier/prettier
87-
const SideBarStyled = styled('nav').attrs<SideBarStyledProps>(p => ({
90+
//@ts-ignore
91+
const SideBarStyled = styled.nav.attrs<SideBarStyledProps>(p => ({
8892
style: {
8993
'--width': p.size,
9094
},
91-
}))<SideBarStyledProps>`
95+
}))`
9296
z-index: ${p => p.theme.zIndex.sidebar};
9397
box-sizing: border-box;
9498
background: ${p => p.theme.colors.bg};

browser/data-browser/src/components/SideBar/menuItems.tsx

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)