[ENG-631] TopBar improvements & misc fixes (#837)

* fix things

* added back/forward buttons to settings

* split top bar context into left and right

* hook up path

* fix background jobs hidden from job manager

* core

* fix type + quick preview transition

* fix selected item color contrast

* fix close button on quick preview

* clean up job ui for light theme

* Improve media view overscan

---------

Co-authored-by: Brendan Allan <brendonovich@outlook.com>
This commit is contained in:
Jamie Pine
2023-05-20 17:17:27 -07:00
committed by GitHub
parent ce1cf7f495
commit 158366b69e
30 changed files with 270 additions and 182 deletions

View File

@@ -1,22 +1,30 @@
import { RefObject, createContext, useRef } from 'react';
import { RefObject, createContext, useContext, useRef } from 'react';
import { Outlet } from 'react-router';
import TopBar from '.';
interface TopBarContext {
topBarChildrenRef: RefObject<HTMLDivElement> | null;
left: RefObject<HTMLDivElement>;
right: RefObject<HTMLDivElement>;
}
export const TopBarContext = createContext<TopBarContext>({
topBarChildrenRef: null
});
const TopBarContext = createContext<TopBarContext | null>(null);
export const Component = () => {
const ref = useRef<HTMLDivElement>(null);
const left = useRef<HTMLDivElement>(null);
const right = useRef<HTMLDivElement>(null);
return (
<TopBarContext.Provider value={{ topBarChildrenRef: ref }}>
<TopBar ref={ref} />
<TopBarContext.Provider value={{ left, right }}>
<TopBar leftRef={left} rightRef={right} />
<Outlet />
</TopBarContext.Provider>
);
};
export function useTopBarContext() {
const ctx = useContext(TopBarContext);
if (!ctx) throw new Error('TopBarContext not found!');
return ctx;
}

View File

@@ -0,0 +1,36 @@
import { Tooltip } from '@sd/ui';
import { ArrowLeft, ArrowRight } from 'phosphor-react';
import { useNavigate } from 'react-router';
import { useSearchStore } from '~/hooks';
import TopBarButton from './TopBarButton';
export const NavigationButtons = () => {
const navigate = useNavigate();
const { isFocused } = useSearchStore();
const idx = history.state.idx as number;
return (
<div data-tauri-drag-region className="flex">
<Tooltip label="Navigate back">
<TopBarButton
rounding='left'
// className="text-[14px] text-ink-dull"
onClick={() => navigate(-1)}
disabled={isFocused || idx === 0}
>
<ArrowLeft size={14} className='m-[4px]' weight="bold" />
</TopBarButton>
</Tooltip>
<Tooltip label="Navigate forward">
<TopBarButton
rounding='right'
// className="text-[14px] text-ink-dull"
onClick={() => navigate(1)}
disabled={isFocused || idx === history.length - 1}
>
<ArrowRight size={14} className='m-[4px]' weight="bold" />
</TopBarButton>
</Tooltip>
</div>
);
};

View File

@@ -0,0 +1,18 @@
import { ReactNode } from 'react';
import { createPortal } from 'react-dom';
import { useTopBarContext } from './Layout';
interface Props {
left?: ReactNode;
right?: ReactNode;
}
export const TopBarPortal = ({ left, right }: Props) => {
const ctx = useTopBarContext();
return (
<>
{left && ctx.left.current && createPortal(left, ctx.left.current)}
{right && ctx.right.current && createPortal(right, ctx.right.current)}
</>
);
};

View File

@@ -1,8 +1,8 @@
import { DotsThreeCircle } from 'phosphor-react';
import React, { HTMLAttributes, forwardRef } from 'react';
import { Popover } from '@sd/ui';
import { TOP_BAR_ICON_STYLE, ToolOption } from '.';
import TopBarButton, { TopBarButtonProps } from './TopBarButton';
import { TOP_BAR_ICON_STYLE, ToolOption } from './TopBarOptions';
const GroupTool = forwardRef<
HTMLButtonElement,

View File

@@ -1,21 +1,29 @@
import clsx from 'clsx';
import { useContext, useLayoutEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { useLayoutEffect, useState } from 'react';
import { Popover, Tooltip } from '@sd/ui';
import { ToolOption } from '.';
import { TopBarContext } from './Layout';
import TopBarButton from './TopBarButton';
import TopBarMobile from './TopBarMobile';
interface TopBarChildrenProps {
toolOptions?: ToolOption[][];
export interface ToolOption {
icon: JSX.Element;
onClick?: () => void;
individual?: boolean;
toolTipLabel: string;
topBarActive?: boolean;
popOverComponent?: JSX.Element;
showAtResolution: ShowAtResolution;
}
export default ({ toolOptions }: TopBarChildrenProps) => {
const ctx = useContext(TopBarContext);
const target = ctx.topBarChildrenRef?.current;
export type ShowAtResolution = 'sm:flex' | 'md:flex' | 'lg:flex' | 'xl:flex' | '2xl:flex';
interface TopBarChildrenProps {
options?: ToolOption[][];
}
export const TOP_BAR_ICON_STYLE = 'm-0.5 w-[18px] h-[18px] text-ink-dull';
export default ({ options }: TopBarChildrenProps) => {
const [windowSize, setWindowSize] = useState(0);
const toolsNotSmFlex = toolOptions
const toolsNotSmFlex = options
?.flatMap((group) => group)
.filter((t) => t.showAtResolution !== 'sm:flex');
@@ -28,14 +36,10 @@ export default ({ toolOptions }: TopBarChildrenProps) => {
return () => window.removeEventListener('resize', handleResize);
}, []);
if (!target) {
return null;
}
return createPortal(
return (
<div data-tauri-drag-region className="flex w-full flex-row justify-end">
<div data-tauri-drag-region className={`flex gap-0`}>
{toolOptions?.map((group, groupIndex) => {
{options?.map((group, groupIndex) => {
return group.map(
(
{
@@ -49,14 +53,14 @@ export default ({ toolOptions }: TopBarChildrenProps) => {
},
index
) => {
const groupCount = toolOptions.length;
const groupCount = options.length;
const roundingCondition = individual
? 'both'
: index === 0
? 'left'
: index === group.length - 1
? 'right'
: 'none';
? 'left'
: index === group.length - 1
? 'right'
: 'none';
return (
<div
data-tauri-drag-region
@@ -109,12 +113,11 @@ export default ({ toolOptions }: TopBarChildrenProps) => {
})}
</div>
<TopBarMobile
toolOptions={toolOptions}
className={`${
toolOptions={options}
className={
windowSize <= 1279 && (toolsNotSmFlex?.length as number) > 0 ? 'flex' : 'hidden'
}`}
}
/>
</div>,
target
</div>
);
};

View File

@@ -1,37 +1,33 @@
import { forwardRef } from 'react';
import { RefObject } from 'react';
import { NavigationButtons } from './NavigationButtons';
import SearchBar from './SearchBar';
export interface ToolOption {
icon: JSX.Element;
onClick?: () => void;
individual?: boolean;
toolTipLabel: string;
topBarActive?: boolean;
popOverComponent?: JSX.Element;
showAtResolution: ShowAtResolution;
}
export type ShowAtResolution = 'sm:flex' | 'md:flex' | 'lg:flex' | 'xl:flex' | '2xl:flex';
export const TOP_BAR_ICON_STYLE = 'm-0.5 w-5 h-5 text-ink-dull';
export const TOP_BAR_HEIGHT = 46;
const TopBar = forwardRef<HTMLDivElement>((_, ref) => {
interface Props {
leftRef?: RefObject<HTMLDivElement>;
rightRef?: RefObject<HTMLDivElement>;
}
const TopBar = (props: Props) => {
return (
<div
data-tauri-drag-region
className="
duration-250 top-bar-blur absolute left-0 top-0 z-50 flex
h-[46px] w-full flex-row items-center justify-center overflow-hidden
border-b border-sidebar-divider bg-app/90 px-5
border-b border-sidebar-divider bg-app/90 px-3.5
transition-[background-color,border-color] ease-out
"
>
<div className="flex-1" />
<div data-tauri-drag-region className="flex flex-1 flex-row items-center">
<NavigationButtons />
<div ref={props.leftRef} />
</div>
<SearchBar />
<div className="flex-1" ref={ref} />
<div className="flex-1" ref={props.rightRef} />
</div>
);
});
};
export default TopBar;