diff --git a/app/client/ui/HomeLeftPane.ts b/app/client/ui/HomeLeftPane.ts index 054745d390..87962ffc5e 100644 --- a/app/client/ui/HomeLeftPane.ts +++ b/app/client/ui/HomeLeftPane.ts @@ -1,27 +1,36 @@ -import {makeT} from 'app/client/lib/localization'; import {loadUserManager} from 'app/client/lib/imports'; +import {makeT} from 'app/client/lib/localization'; import {urlState} from 'app/client/models/gristUrlState'; import {HomeModel} from 'app/client/models/HomeModel'; import {getWorkspaceInfo, workspaceName} from 'app/client/models/WorkspaceInfo'; -import {getAdminPanelName} from 'app/client/ui/AdminPanelName'; -import * as roles from 'app/common/roles'; import {addNewButton, cssAddNewButton} from 'app/client/ui/AddNewButton'; -import {commonUrls, isFeatureEnabled} from 'app/common/gristUrls'; -import {computed, dom, domComputed, DomElementArg, observable, Observable, styled} from 'grainjs'; -import {newDocMethods} from 'app/client/ui/NewDocMethods'; -import {createHelpTools, cssLeftPanel, cssScrollPane, - cssSectionHeader, cssTools} from 'app/client/ui/LeftPanelCommon'; +import {getAdminPanelName} from 'app/client/ui/AdminPanelName'; +import {createVideoTourToolsButton} from 'app/client/ui/OpenVideoTour'; +import {transientInput} from 'app/client/ui/transientInput'; +import {testId, theme} from 'app/client/ui2018/cssVars'; +import {icon} from 'app/client/ui2018/icons'; import { - cssLinkText, cssMenuTrigger, cssPageEntry, cssPageIcon, cssPageLink, cssSpacer + createHelpTools, + cssHomeTools, + cssLeftPanel, + cssLinkText, + cssMenuTrigger, + cssPageColorIcon, + cssPageEntry, + cssPageIcon, + cssPageLink, + cssScrollPane, + cssSectionHeader, + cssSectionHeaderText } from 'app/client/ui/LeftPanelCommon'; +import {newDocMethods} from 'app/client/ui/NewDocMethods'; import {menu, menuIcon, menuItem, upgradableMenuItem, upgradeText} from 'app/client/ui2018/menus'; -import {testId, theme} from 'app/client/ui2018/cssVars'; import {confirmModal} from 'app/client/ui2018/modals'; -import {createVideoTourToolsButton} from 'app/client/ui/OpenVideoTour'; +import {commonUrls, isFeatureEnabled} from 'app/common/gristUrls'; +import * as roles from 'app/common/roles'; import {getGristConfig} from 'app/common/urlUtils'; -import {icon} from 'app/client/ui2018/icons'; -import {transientInput} from 'app/client/ui/transientInput'; import {Workspace} from 'app/common/UserAPI'; +import {computed, dom, domComputed, DomElementArg, observable, Observable, styled} from 'grainjs'; const t = makeT('HomeLeftPane'); @@ -55,7 +64,7 @@ export function createHomeLeftPane(leftPanelOpen: Observable, home: Hom ), dom.maybe(use => !use(home.singleWorkspace), () => cssSectionHeader( - t("Workspaces"), + cssSectionHeaderText(t("Workspaces")), // Give it a testId, because it's a good element to simulate "click-away" in tests. testId('dm-ws-label') ), @@ -111,7 +120,11 @@ export function createHomeLeftPane(leftPanelOpen: Observable, home: Hom }, testId('dm-ws-name-editor')) ) )), - cssTools( + cssHomeTools( + cssSectionHeader( + cssPageColorIcon('GristLogo'), + cssSectionHeaderText(t("Grist Resources")) + ), cssPageEntry( dom.show(isFeatureEnabled("templates") && Boolean(templateOrg)), cssPageEntry.cls('-selected', (use) => use(home.currentPage) === "templates"), @@ -127,7 +140,6 @@ export function createHomeLeftPane(leftPanelOpen: Observable, home: Hom testId('dm-trash'), ), ), - cssSpacer(), cssPageEntry( dom.show(isFeatureEnabled('tutorials') && Boolean(templateOrg && onboardingTutorialDocId)), cssPageLink(cssPageIcon('Bookmark'), cssLinkText(t("Tutorial")), diff --git a/app/client/ui/LeftPanelCommon.ts b/app/client/ui/LeftPanelCommon.ts index 533fd9e821..c74d1006d0 100644 --- a/app/client/ui/LeftPanelCommon.ts +++ b/app/client/ui/LeftPanelCommon.ts @@ -17,7 +17,7 @@ import {beaconOpenMessage} from 'app/client/lib/helpScout'; import {makeT} from 'app/client/lib/localization'; import {AppModel} from 'app/client/models/AppModel'; import {testId, theme, vars} from 'app/client/ui2018/cssVars'; -import {icon} from 'app/client/ui2018/icons'; +import {colorIcon, icon} from 'app/client/ui2018/icons'; import {commonUrls, isFeatureEnabled} from 'app/common/gristUrls'; import {getGristConfig} from 'app/common/urlUtils'; import {dom, DomContents, Observable, styled} from 'grainjs'; @@ -86,18 +86,34 @@ export const cssTools = styled('div', ` flex: none; margin-top: auto; padding: 16px 0 16px 0; + cursor: default; +`); + + +export const cssHomeTools = styled(cssTools, ` + padding-top: 0px; + border-top: 1px solid ${theme.pagePanelsBorder}; `); + export const cssSectionHeader = styled('div', ` margin: 24px 0 8px 24px; + display: flex; + align-items: center; + .${cssTools.className}-collapsed > & { + visibility: hidden; + } +`); + +export const cssSectionHeaderText = styled('span', ` color: ${theme.lightText}; text-transform: uppercase; font-weight: 500; font-size: ${vars.xsmallFontSize}; letter-spacing: 1px; - .${cssTools.className}-collapsed > & { - visibility: hidden; - } + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; `); export const cssPageEntry = styled('div', ` @@ -160,6 +176,14 @@ export const cssPageIcon = styled(icon, ` } `); +export const cssPageColorIcon = styled(colorIcon, ` + flex: none; + margin-right: var(--page-icon-margin, 8px); + .${cssTools.className}-collapsed & { + margin-right: 0; + } +`); + export const cssSpacer = styled('div', ` height: 18px; `); diff --git a/app/client/ui/Tools.ts b/app/client/ui/Tools.ts index 1ca56d8f26..056f03e6b0 100644 --- a/app/client/ui/Tools.ts +++ b/app/client/ui/Tools.ts @@ -1,13 +1,25 @@ import {ACLUsersPopup} from 'app/client/aclui/ACLUsers'; -import {makeT} from 'app/client/lib/localization'; import {GristDoc} from 'app/client/components/GristDoc'; +import {makeT} from 'app/client/lib/localization'; import {urlState} from 'app/client/models/gristUrlState'; import {getUserOrgPrefObs, markAsSeen} from 'app/client/models/UserPrefs'; import {showExampleCard} from 'app/client/ui/ExampleCard'; import {buildExamples} from 'app/client/ui/ExampleInfo'; -import {createHelpTools, cssLinkText, cssMenuTrigger, cssPageEntry, cssPageEntryMain, cssPageEntrySmall, - cssPageIcon, cssPageLink, cssSectionHeader, cssSpacer, cssSplitPageEntry, - cssTools} from 'app/client/ui/LeftPanelCommon'; +import { + createHelpTools, + cssLinkText, + cssMenuTrigger, + cssPageEntry, + cssPageEntryMain, + cssPageEntrySmall, + cssPageIcon, + cssPageLink, + cssSectionHeader, + cssSectionHeaderText, + cssSpacer, + cssSplitPageEntry, + cssTools +} from 'app/client/ui/LeftPanelCommon'; import {theme} from 'app/client/ui2018/cssVars'; import {icon} from 'app/client/ui2018/icons'; import {confirmModal} from 'app/client/ui2018/modals'; @@ -31,7 +43,7 @@ export function tools(owner: Disposable, gristDoc: GristDoc, leftPanelOpen: Obse updateCanViewAccessRules(); return cssTools( cssTools.cls('-collapsed', (use) => !use(leftPanelOpen)), - cssSectionHeader(t("TOOLS")), + cssSectionHeader(cssSectionHeaderText(t("TOOLS"))), cssPageEntry( cssPageEntry.cls('-selected', (use) => use(gristDoc.activeViewId) === 'acl'), cssPageEntry.cls('-disabled', (use) => !use(canViewAccessRules)), diff --git a/app/client/ui2018/icons.ts b/app/client/ui2018/icons.ts index b088922325..8d8bed79dc 100644 --- a/app/client/ui2018/icons.ts +++ b/app/client/ui2018/icons.ts @@ -68,10 +68,23 @@ const iconStyles = ` background-color: var(--icon-color, var(--grist-theme-text, black)); `; +const iconColorStyles = ` + position: relative; + display: inline-block; + vertical-align: middle; + width: 16px; + height: 16px; + background-repeat: no-repeat; + background-position: center; + background-size: contain; +`; + const cssIconDiv = styled('div', iconStyles); const cssIconSpan = styled('span', iconStyles); +const cssColorIcon = styled('div', iconColorStyles); + export function icon(name: IconName, ...domArgs: DomElementArg[]): HTMLElement { return cssIconDiv( dom.style('-webkit-mask-image', `var(--icon-${name})`), @@ -86,6 +99,13 @@ export function iconSpan(name: IconName, ...domArgs: DomElementArg[]): HTMLEleme ); } +export function colorIcon(name: IconName, ...domArgs: DomElementArg[]): HTMLElement { + return cssColorIcon( + dom.style('background-image', `var(--icon-${name})`), + ...domArgs + ); +} + export const cssIconSpanBackground = styled(cssIconSpan, ` background-color: var(--icon-background, inherit); -webkit-mask: none;