Reduce AppBar sizing and add Project Name to breadcrumbs (#4159)

This commit is contained in:
Dimitri Mitropoulos authored and GitHub committed 2021-11-03 11:10:53 +13:00
1 parent 6c34d9088e
commit 5c02273757
12 files changed
+165 -128

No files matched your search

@@ -6,7 +6,6 @@ export interface StringInfo {
type StringId =
| 'collection'
| 'document'
| 'home'
| 'project'
| 'workspace'
| 'defaultProject'
@@ -23,10 +22,6 @@ export const strings: Record<StringId, StringInfo> = {
singular: 'Document',
plural: 'Documents',
},
home: {
singular: 'Dashboard',
plural: 'Dashboards',
},
project: {
singular: 'Project',
plural: 'Projects',
@@ -0,0 +1,54 @@
import { Breadcrumb, BreadcrumbProps, Header as _Header } from 'insomnia-components';
import React, { FC, Fragment, ReactNode } from 'react';
import styled from 'styled-components';
import coreLogo from '../images/insomnia-core-logo.png';
import { SettingsButton } from './buttons/settings-button';
import { AccountDropdownButton } from './dropdowns/account-dropdown';
const Header = styled(_Header)({
whiteSpace: 'nowrap',
});
const RightWrapper = styled.div({
transformOrigin: 'right',
transform: 'scale(0.85)',
display: 'flex',
justifySelf: 'flex-end',
alignItems: 'center',
'& .tooltip': {
display: 'flex',
alignItems: 'center',
},
});
export interface AppHeaderProps {
breadcrumbProps: BreadcrumbProps;
gridCenter?: ReactNode;
gridRight?: ReactNode;
}
export const AppHeader: FC<AppHeaderProps> = ({
breadcrumbProps,
gridCenter,
gridRight,
}) => {
return (
<Header
gridLeft={(
<Fragment>
<img src={coreLogo} alt="Insomnia" width="28" height="28" />
<Breadcrumb {...breadcrumbProps} />
</Fragment>
)}
gridCenter={gridCenter}
gridRight={(
<RightWrapper>
{gridRight}
<SettingsButton />
<AccountDropdownButton />
</RightWrapper>
)}
/>
);
};
@@ -1,36 +1,35 @@
import { CircleButton, SvgIcon, Tooltip } from 'insomnia-components';
import React, { FunctionComponent } from 'react';
import { connect } from 'react-redux';
import { useSelector } from 'react-redux';
import styled from 'styled-components';
import { hotKeyRefs } from '../../../common/hotkeys';
import type { Settings } from '../../../models/settings';
import { selectSettings } from '../../redux/selectors';
import { Hotkey } from '../hotkey';
import { showSettingsModal } from '../modals/settings-modal';
interface Props {
className?: string;
settings: Settings;
}
const Wrapper = styled.div({
marginLeft: 'var(--padding-md)',
});
const SettingsButton: FunctionComponent<Props> = ({ className, settings }) => (
<Tooltip
delay={1000}
position="bottom"
message={
<>
Preferences (
<Hotkey keyBindings={settings.hotKeyRegistry[hotKeyRefs.PREFERENCES_SHOW_GENERAL.id]} />)
</>
}
>
<CircleButton className={className} onClick={showSettingsModal}>
<SvgIcon icon="gear" />
</CircleButton>
</Tooltip>
);
export default connect((state, props) => ({
// @ts-expect-error -- TSCONVERSION
settings: selectSettings(state, props),
}))(SettingsButton);
export const SettingsButton: FunctionComponent = () => {
const { hotKeyRegistry } = useSelector(selectSettings);
return (
<Wrapper>
<Tooltip
delay={1000}
position="bottom"
message={
<>
Preferences (
<Hotkey keyBindings={hotKeyRegistry[hotKeyRefs.PREFERENCES_SHOW_GENERAL.id]} />)
</>
}
>
<CircleButton onClick={showSettingsModal}>
<SvgIcon icon="gear" />
</CircleButton>
</Tooltip>
</Wrapper>
);
};
@@ -1,3 +1,4 @@
import classNames from 'classnames';
import { CircleButton, SvgIcon, Tooltip } from 'insomnia-components';
import React, { Fragment, FunctionComponent } from 'react';
import { useSelector } from 'react-redux';
@@ -12,24 +13,30 @@ import { Link } from '../base/link';
import { PromptButton } from '../base/prompt-button';
import { showLoginModal } from '../modals/login-modal';
interface Props {
className?: string;
const Wrapper = styled.div({
display: 'flex',
marginLeft: 'var(--padding-md)',
});
interface StyledIconProps {
faIcon: string;
}
const StyledIconContainer = styled.div`
display: flex;
align-items: center;
padding-left: var(--padding-xs);
padding-right: var(--padding-md);
i {
width: unset !important;
}
`;
const StyledIcon = styled.i.attrs<StyledIconProps>(props => ({
className: classNames('fa', props.faIcon),
}))<StyledIconProps>({
marginleft: 'var(--padding-md)',
display: 'flex',
alignItems: 'center',
paddingLeft: 'var(--padding-xs)',
paddingRight: 'var(--padding-md)',
width: 'unset !important',
});
export const AccountDropdown: FunctionComponent<Props> = ({ className }) => {
export const AccountDropdownButton: FunctionComponent = () => {
const { disablePaidFeatureAds } = useSelector(selectSettings);
return (
<div className={className}>
<Wrapper>
<Dropdown>
<DropdownButton noWrap>
<Tooltip delay={1000} position="bottom" message="Account">
@@ -45,18 +52,12 @@ export const AccountDropdown: FunctionComponent<Props> = ({ className }) => {
buttonClass={PromptButton}
onClick={session.logout}
>
<StyledIconContainer>
<i className="fa fa-sign-out" />
</StyledIconContainer>
Logout
<StyledIcon faIcon="fa-sign-out" />Logout
</DropdownItem>
) : (
<Fragment>
<DropdownItem key="login" onClick={showLoginModal}>
<StyledIconContainer>
<i className="fa fa-sign-in" />
</StyledIconContainer>
Log In
<StyledIcon faIcon="fa-sign-in" />Log In
</DropdownItem>
{!disablePaidFeatureAds && (
<DropdownItem
@@ -66,16 +67,13 @@ export const AccountDropdown: FunctionComponent<Props> = ({ className }) => {
href="https://insomnia.rest/pricing"
button
>
<StyledIconContainer>
<i className="fa fa-users" />
</StyledIconContainer>{' '}
Upgrade to Plus
<StyledIcon faIcon="fa-users" />{' '}Upgrade to Plus
<i className="fa fa-star surprise fa-outline" />
</DropdownItem>
)}
</Fragment>
)}
</Dropdown>
</div>
</Wrapper>
);
};
@@ -437,7 +437,7 @@ class UnconnectedSyncDropdown extends PureComponent<Props, State> {
<i className="fa fa-code-fork space-right" />{' '}
{initializing ? 'Initializing...' : currentBranch}
</div>
<div className="space-left">
<div className="flex space-left">
<Tooltip message={snapshotToolTipMsg} delay={800} position="bottom">
<i
className={classnames('fa fa-cube fa--fixed-width', {
@@ -1,13 +1,11 @@
import { Breadcrumb, Header } from 'insomnia-components';
import React, { Fragment, FunctionComponent, ReactNode, useCallback } from 'react';
import React, { FunctionComponent, ReactNode, useCallback } from 'react';
import { useSelector } from 'react-redux';
import { ACTIVITY_HOME, GlobalActivity } from '../../common/constants';
import { strings } from '../../common/strings';
import { isDesign } from '../../models/workspace';
import coreLogo from '../images/insomnia-core-logo.png';
import { selectActiveProjectName } from '../redux/selectors';
import { ActivityToggle } from './activity-toggle';
import SettingsButton from './buttons/settings-button';
import { AccountDropdown } from './dropdowns/account-dropdown';
import { AppHeader } from './app-header';
import { WorkspaceDropdown } from './dropdowns/workspace-dropdown';
import type { WrapperProps } from './wrapper';
@@ -35,6 +33,7 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
() => handleActivityChange({ workspaceId: activeWorkspace?._id, nextActivity: ACTIVITY_HOME }),
[activeWorkspace, handleActivityChange],
);
const activeProjectName = useSelector(selectActiveProjectName);
if (!activeWorkspace || !activeWorkspaceName || !activeApiSpec || !activity) {
return null;
@@ -42,6 +41,7 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
const workspace = (
<WorkspaceDropdown
key="workspace-dd"
activeEnvironment={activeEnvironment}
activeWorkspace={activeWorkspace}
activeWorkspaceName={activeWorkspaceName}
@@ -53,19 +53,13 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
);
const crumbs = [
{ id: 'home', node: strings.home.singular, onClick: homeCallback },
{ id: 'workspace', node: <Fragment key="workspace-dd">{workspace}</Fragment> },
{ id: 'project', node: activeProjectName, onClick: homeCallback },
{ id: 'workspace', node: workspace },
];
return (
<Header
className="app-header theme--app-header"
gridLeft={
<Fragment>
<img src={coreLogo} alt="Insomnia" width="24" height="24" />
<Breadcrumb crumbs={crumbs}/>
</Fragment>
}
<AppHeader
breadcrumbProps={{ crumbs }}
gridCenter={
isDesign(activeWorkspace) && (
<ActivityToggle
@@ -75,13 +69,7 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
/>
)
}
gridRight={
<>
{gridRight}
<SettingsButton className="margin-left" />
<AccountDropdown className="margin-left" />
</>
}
gridRight={gridRight}
/>
);
};
@@ -2,15 +2,13 @@ import 'swagger-ui-react/swagger-ui.css';
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import {
Breadcrumb,
Button,
CardContainer,
Dropdown,
DropdownDivider,
DropdownItem,
Header,
} from 'insomnia-components';
import React, { Fragment, PureComponent } from 'react';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { unreachableCase } from 'ts-assert-unreachable';
@@ -31,15 +29,13 @@ import { isDesign, Workspace, WorkspaceScopeKeys } from '../../models/workspace'
import { WorkspaceMeta } from '../../models/workspace-meta';
import { MemClient } from '../../sync/git/mem-client';
import { initializeLocalBackendProjectAndMarkForSync } from '../../sync/vcs/initialize-backend-project';
import coreLogo from '../images/insomnia-core-logo.png';
import { cloneGitRepository } from '../redux/modules/git';
import { setDashboardSortOrder } from '../redux/modules/global';
import { ForceToWorkspace } from '../redux/modules/helpers';
import { importClipBoard, importFile, importUri } from '../redux/modules/import';
import { activateWorkspace, createWorkspace } from '../redux/modules/workspace';
import { selectDashboardSortOrder } from '../redux/selectors';
import SettingsButton from './buttons/settings-button';
import { AccountDropdown } from './dropdowns/account-dropdown';
import { AppHeader } from './app-header';
import { DashboardSortDropdown } from './dropdowns/dashboard-sort-dropdown';
import { ProjectDropdown } from './dropdowns/project-dropdown';
import { RemoteWorkspacesDropdown } from './dropdowns/remote-workspaces-dropdown';
@@ -352,30 +348,16 @@ class WrapperHome extends PureComponent<Props, State> {
<PageLayout
wrapperProps={this.props.wrapperProps}
renderPageHeader={() => (
<Header
className="app-header theme--app-header"
gridLeft={
<Fragment>
<img src={coreLogo} alt="Insomnia" width="24" height="24" />
<Breadcrumb
crumbs={[
{
id: 'project',
node: <ProjectDropdown vcs={vcs || undefined} />,
},
]}
/>
{isLoading ? (
<i className="fa fa-refresh fa-spin space-left" />
) : null}
</Fragment>
}
gridRight={
<>
<SettingsButton className="margin-left" />
<AccountDropdown className="margin-left" />
</>
}
<AppHeader
breadcrumbProps={{
crumbs: [
{
id: 'project',
node: <ProjectDropdown vcs={vcs || undefined} />,
},
],
isLoading,
}}
/>
)}
renderPageBody={() => (
@@ -7,6 +7,10 @@
&:focus {
outline: none;
}
& button {
cursor: pointer;
}
}
.dropdown__backdrop {
@@ -1,7 +1,7 @@
import React, { FC, ReactNode } from 'react';
import React, { FC, Fragment, ReactNode } from 'react';
import styled from 'styled-components';
interface CrumbProps {
export interface CrumbProps {
id: string;
node: ReactNode;
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
@@ -10,11 +10,11 @@ interface CrumbProps {
export interface BreadcrumbProps {
crumbs: CrumbProps[];
className?: string;
isLoading?: boolean;
}
const StyledBreadcrumb = styled.ul`
font-size: var(--font-size-lg);
font-weight: 600;
font-size: var(--font-size-md);
color: var(--color-font);
grid-area: breadcrumbs;
display: flex;
@@ -24,7 +24,7 @@ const StyledBreadcrumb = styled.ul`
a,
a::before,
li > ::before {
color: var(--color-font);
color: var(--color-font) !important;
}
li {
@@ -32,11 +32,20 @@ const StyledBreadcrumb = styled.ul`
flex-direction: row;
a {
font-weight: 400 !important;
cursor: pointer;
opacity: 0.5;
&:hover {
color: var(--color-font);
opacity: 1;
text-decoration: none;
}
}
&::before {
margin: 0 var(--padding-xs);
font-weight: 300;
opacity: 0.5;
content: '/';
}
@@ -50,8 +59,13 @@ const Crumb: FC<CrumbProps> = ({ id, node, onClick }) => <li key={id}>
{onClick ? <a href="#" onClick={onClick}>{node}</a> : node}
</li>;
export const Breadcrumb: FC<BreadcrumbProps> = ({ crumbs, className }) => (
<StyledBreadcrumb className={className}>
{crumbs.map(Crumb)}
</StyledBreadcrumb>
export const Breadcrumb: FC<BreadcrumbProps> = ({ crumbs, className, isLoading }) => (
<Fragment>
<StyledBreadcrumb className={className}>
{crumbs.map(Crumb)}
</StyledBreadcrumb>
{isLoading ? (
<i className="fa fa-refresh fa-spin space-left" />
) : null}
</Fragment>
);
+3 -2
View File
@@ -1,3 +1,4 @@
import classNames from 'classnames';
import React, { FC, memo, ReactNode } from 'react';
import styled from 'styled-components';
@@ -10,7 +11,7 @@ export interface HeaderProps {
const StyledHeader = styled.div`
border-bottom: 1px solid var(--hl-md);
padding: var(--padding-md);
padding: var(--padding-xxs) var(--padding-sm);
display: grid;
grid-template-columns: 2fr 1.5fr 2fr;
grid-template-rows: 1fr;
@@ -37,7 +38,7 @@ const StyledHeader = styled.div`
`;
export const Header: FC<HeaderProps> = memo(({ className, gridLeft, gridCenter, gridRight }) => (
<StyledHeader className={className}>
<StyledHeader className={classNames('app-header theme--app-header', className)}>
<div className="header_left">{gridLeft}</div>
<div className="header_center">{gridCenter}</div>
<div className="header_right">{gridRight}</div>
+1 -1
View File
@@ -3,7 +3,7 @@ export * from './dropdown';
export * from './sidebar';
export * from './list-group';
export { Breadcrumb, BreadcrumbProps } from './breadcrumb';
export { Breadcrumb, BreadcrumbProps, CrumbProps } from './breadcrumb';
export { CardContainer } from './card-container';
export { Card, CardProps } from './card';
export { Header, HeaderProps } from './header';
@@ -5,12 +5,15 @@ import type { RadioButtonGroupProps } from './radio-button-group';
import { RadioButtonGroup } from './radio-button-group';
const ThemedButtonGroup = styled(RadioButtonGroup)<RadioButtonGroupProps>`
font-weight: bold;
font-weight: 500;
background: var(--hl-xs);
color: var(--color-font);
border: 0;
border-radius: 100px;
align-content: space-evenly;
padding: var(--padding-xxs);
transform: scale(0.9);
transformOrigin: 'center';
label {
padding: 0;
@@ -18,17 +21,16 @@ const ThemedButtonGroup = styled(RadioButtonGroup)<RadioButtonGroupProps>`
span {
text-transform: uppercase;
padding: var(--padding-xxs) var(--padding-md);
padding: var(--padding-xs) var(--padding-xxs);
color: var(--hl);
background: transparent;
font-size: var(--font-size-sm);
font-size: var(--font-size-xs);
margin: 0 auto;
min-width: 4rem;
}
input:checked + span {
color: var(--color-font);
text-shadow: 0 1px rgba(255, 255, 255, 0.25);
background: var(--color-bg);
}
`;