Skip to content

cleaner top bar #8422

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
61 changes: 24 additions & 37 deletions src/packages/frontend/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { useAppContext } from "./context";
import { FullscreenButton } from "./fullscreen-button";
import { I18NBanner, useShowI18NBanner } from "./i18n-banner";
import InsecureTestModeBanner from "./insecure-test-mode-banner";
import { AppLogo } from "./logo";
// import { AppLogo } from "./logo";
import { NavTab } from "./nav-tab";
import { Notification } from "./notifications";
import PopconfirmModal from "./popconfirm-modal";
Expand Down Expand Up @@ -80,7 +80,7 @@ export const Page: React.FC = () => {
const page_actions = useActions("page");

const { pageStyle } = useAppContext();
const { isNarrow, fileUseStyle, topBarStyle, projectsNavStyle } = pageStyle;
const { isNarrow, fileUseStyle, topBarStyle } = pageStyle;

const intl = useIntl();

Expand Down Expand Up @@ -203,7 +203,6 @@ export const Page: React.FC = () => {
return (
<NavTab
name="admin"
label={"Admin"}
label_class={NAV_CLASS}
icon={"users"}
active_top_tab={active_top_tab}
Expand Down Expand Up @@ -248,10 +247,6 @@ export const Page: React.FC = () => {
<NavTab
name={undefined} // does not open a tab, just a popup
active_top_tab={active_top_tab} // it's never supposed to be active!
label={intl.formatMessage({
id: "page.help.label",
defaultMessage: "Help",
})}
label_class={NAV_CLASS}
icon={"medkit"}
on_click={openSupportTab}
Expand Down Expand Up @@ -315,25 +310,25 @@ export const Page: React.FC = () => {
);
}

function render_project_nav_button(): React.JSX.Element {
return (
<NavTab
style={{
height: `${pageStyle.height}px`,
margin: "0",
overflow: "hidden",
}}
name={"projects"}
active_top_tab={active_top_tab}
tooltip={intl.formatMessage({
id: "page.project_nav.tooltip",
defaultMessage: "Show all the projects on which you collaborate.",
})}
icon="edit"
label={intl.formatMessage(labels.projects)}
/>
);
}
// function render_project_nav_button(): React.JSX.Element {
// return (
// <NavTab
// style={{
// height: `${pageStyle.height}px`,
// margin: "0",
// overflow: "hidden",
// }}
// name={"projects"}
// active_top_tab={active_top_tab}
// tooltip={intl.formatMessage({
// id: "page.project_nav.tooltip",
// defaultMessage: "Show all the projects on which you collaborate.",
// })}
// icon="edit"
// label={intl.formatMessage(labels.projects)}
// />
// );
// }

// register a default drag and drop handler, that prevents
// accidental file drops
Expand Down Expand Up @@ -378,21 +373,13 @@ export const Page: React.FC = () => {
<VerifyEmail />
{!fullscreen && (
<nav className="smc-top-bar" style={topBarStyle}>
<AppLogo size={pageStyle.height} />
{is_logged_in && render_project_nav_button()}
{!isNarrow ? (
<ProjectsNav height={pageStyle.height} style={projectsNavStyle} />
) : (
// we need an expandable placeholder, otherwise the right-nav-buttons won't align to the right
<div style={{ flex: "1 1 auto" }} />
)}
{/* <AppLogo size={pageStyle.height} /> */}
{/* is_logged_in && render_project_nav_button()*/}
<ProjectsNav height={pageStyle.height} />
{render_right_nav()}
</nav>
)}
{fullscreen && render_fullscreen()}
{isNarrow && (
<ProjectsNav height={pageStyle.height} style={projectsNavStyle} />
)}
<ActiveContent />
<PayAsYouGoModal />
<PopconfirmModal />
Expand Down
8 changes: 2 additions & 6 deletions src/packages/frontend/app/top-nav-consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ export const NARROW_THRESHOLD_PX = 550;
// show labels of projects, if there are less than this many
export const HIDE_LABEL_THRESHOLD = 6;

// the width of the top bar
export const NAV_HEIGHT_PX = 36;

// … and on narrower screens, a bit tighter
export const NAV_HEIGHT_NARROW_PX = 28;
export const NAV_HEIGHT_PX = 46;
export const NAV_HEIGHT_NARROW_PX = 46;

export const NAV_CLASS = "hidden-xs";

Expand All @@ -30,7 +27,6 @@ export const TOP_BAR_ELEMENT_CLASS = "cocalc-top-bar-element";
export interface PageStyle {
topBarStyle: CSS;
fileUseStyle: CSS;
projectsNavStyle: CSS | undefined;
fontSizeIcons: string; // {n}px
topPaddingIcons: string; // {n}px
sidePaddingIcons: string; // {n}px
Expand Down
14 changes: 1 addition & 13 deletions src/packages/frontend/app/use-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export function calcStyle(isNarrow: boolean): PageStyle {

const topBarStyle = {
height: `${height}px`,
background: "#fafafa",
} as const;

const fileUseStyle = {
Expand All @@ -75,22 +76,9 @@ export function calcStyle(isNarrow: boolean): PageStyle {
zIndex: 110,
} as const;

const projectsNavStyle = isNarrow
? ({
/* this makes it so the projects tabs are on a separate row; otherwise, there is literally no room for them at all... */
width: "100vw",
marginTop: "4px",
height: `${height}px`,
// no flex!
} as const)
: ({
flex: "1 1 auto", // necessary to stretch out to the full width
} as const);

return {
topBarStyle,
fileUseStyle,
projectsNavStyle,
isNarrow,
sidePaddingIcons,
topPaddingIcons,
Expand Down
14 changes: 12 additions & 2 deletions src/packages/frontend/components/sortable-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface Props {
items: (string | number)[];
children?: ReactNode;
style?: CSSProperties;
tabWidth?: number;
}

interface ItemContextType {
Expand All @@ -52,8 +53,14 @@ export function useItemContext() {
return useContext(ItemContext);
}

export function SortableTabs(props: Props) {
const { onDragStart, onDragEnd, items, children, style } = props;
export function SortableTabs({
onDragStart,
onDragEnd,
items,
children,
style,
tabWidth,
}: Props) {
const mouseSensor = useSensor(MouseSensor, {
activationConstraint: {
distance: 2,
Expand All @@ -77,6 +84,9 @@ export function SortableTabs(props: Props) {
const { isOver } = useMouse(divRef);

const itemWidth = useMemo(() => {
if (tabWidth) {
return tabWidth;
}
if (divRef.current == null) {
lastRef.current = null;
return undefined;
Expand Down
1 change: 1 addition & 0 deletions src/packages/frontend/project/page/home-page/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function HomePageButton({ project_id, active, width }) {
fontSize: "24px",
color: active ? COLORS.ANTD_LINK_BLUE : COLORS.FILE_ICON,
transitionDuration: "0s",
background: "#fafafa",
}}
onClick={() => {
// Showing homepage in flyout only mode, otherwise the files as usual
Expand Down
64 changes: 52 additions & 12 deletions src/packages/frontend/projects/projects-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import type { TabsProps } from "antd";
import { Avatar, Popover, Tabs, Tooltip } from "antd";

import {
redux,
useActions,
Expand All @@ -31,6 +30,9 @@ import { CSSProperties, useMemo, useState } from "react";
import { useProjectState } from "../project/page/project-state-hook";
import { useProjectHasInternetAccess } from "../project/settings/has-internet-access-hook";
import { BuyLicenseForProject } from "../site-licenses/purchase/buy-license-for-project";
import { ProjectTitle } from "@cocalc/frontend/projects/project-title";

const minimal = true;

const PROJECT_NAME_STYLE: CSSProperties = {
whiteSpace: "nowrap",
Expand Down Expand Up @@ -83,10 +85,7 @@ function ProjectTab({ project_id }: ProjectTabProps) {
return (
// Hiding this on very skinny devices isn't necessarily bad, since the exact same information is
// now visible via a big "Connecting..." banner after a few seconds.
<span
style={{ paddingLeft: "15px", marginRight: "-15px" }}
className="hidden-xs"
>
<span style={{ marginRight: "-10px" }} className="hidden-xs">
<WebsocketIndicator state={project_websockets?.get(project_id)} />
</span>
);
Expand Down Expand Up @@ -194,13 +193,22 @@ function ProjectTab({ project_id }: ProjectTabProps) {

function renderAvatar() {
const avatar = project?.get("avatar_image_tiny");
if (!avatar) return;
if (!avatar) {
if (!minimal) {
return null;
}
return (
<span style={{ fontSize: "18px", fontWeight: "bold", color: "#666" }}>
{title.slice(0, 1).toUpperCase()}
</span>
);
}
return (
<Avatar
style={{ marginTop: "-2px" }}
style={{ marginTop: "-4px" }}
shape="circle"
icon={<img src={project.get("avatar_image_tiny")} />}
size={20}
size={36}
/>
);
}
Expand All @@ -215,13 +223,23 @@ function ProjectTab({ project_id }: ProjectTabProps) {
}

const body = (
<div onMouseUp={onMouseUp} style={width != null ? { width } : undefined}>
<div
onMouseUp={onMouseUp}
style={{
...(width != null ? { width } : undefined),
}}
>
<div style={nav_style_inner}>{renderWebsocketIndicator()}</div>
<div style={PROJECT_NAME_STYLE} onClick={click_title}>
<div
style={minimal ? undefined : PROJECT_NAME_STYLE}
onClick={click_title}
>
{icon}
{renderNoInternet()}
{renderAvatar()}{" "}
<span style={{ marginLeft: 5, position: "relative" }}>{title}</span>
{!minimal && (
<span style={{ marginLeft: 5, position: "relative" }}>{title}</span>
)}
</div>
</div>
);
Expand Down Expand Up @@ -300,14 +318,19 @@ export function ProjectsNav(props: ProjectsNavProps) {
style={{
overflow: "hidden",
height: `${height}px`,
display: "flex",
flex: 1,
paddingLeft: "15px",
...style,
}}
>
{items.length > 0 && (
<SortableTabs
style={{ width: undefined }}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
items={project_ids}
tabWidth={75}
>
<Tabs
animated={false}
Expand All @@ -317,12 +340,29 @@ export function ProjectsNav(props: ProjectsNavProps) {
onChange={(project_id) => {
actions.set_active_tab(project_id);
}}
type={"editable-card"}
renderTabBar={renderTabBar}
items={items}
type={"editable-card"}
/>
</SortableTabs>
)}
{activeTopTab?.length == 36 && (
<ProjectTitle
noClick
project_id={activeTopTab}
style={{
width: "100%",
fontSize: "14pt",
textOverflow: "ellipsis",
overflow: "hidden",
textAlign: "center",
whiteSpace: "nowrap",
color: "#666",
marginTop: "6px",
marginLeft: "30px",
}}
/>
)}
</div>
);
}
Loading