mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Show usage banners in doc menu of free team sites
Summary: Also fixes a minor CSS regression in UserManager where the link to add a team member wasn't shown on a separate row. Test Plan: Browser tests. Reviewers: jarek Reviewed By: jarek Differential Revision: https://phab.getgrist.com/D3444
This commit is contained in:
165
app/client/components/Banner.ts
Normal file
165
app/client/components/Banner.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
import {colors, isNarrowScreenObs} from 'app/client/ui2018/cssVars';
|
||||
import {icon} from 'app/client/ui2018/icons';
|
||||
import {Disposable, dom, DomArg, DomElementArg, makeTestId, Observable, styled} from 'grainjs';
|
||||
|
||||
const testId = makeTestId('test-banner-');
|
||||
|
||||
export interface BannerOptions {
|
||||
/**
|
||||
* Content to display in the banner.
|
||||
*/
|
||||
content: DomArg;
|
||||
|
||||
/**
|
||||
* The banner style.
|
||||
*
|
||||
* Warning banners have a yellow background. Error banners have a red
|
||||
* background.
|
||||
*/
|
||||
style: 'warning' | 'error';
|
||||
|
||||
/**
|
||||
* Optional variant of `content` to display when screen width becomes narrow.
|
||||
*/
|
||||
contentSmall?: DomArg;
|
||||
|
||||
/**
|
||||
* Whether a button to close the banner should be shown.
|
||||
*
|
||||
* If true, `onClose` should also be specified; it will be called when the close
|
||||
* button is clicked.
|
||||
*
|
||||
* Defaults to false.
|
||||
*/
|
||||
showCloseButton?: boolean;
|
||||
|
||||
/**
|
||||
* Whether a button to collapse/expand the banner should be shown on narrow screens.
|
||||
*
|
||||
* Defaults to false.
|
||||
*/
|
||||
showExpandButton?: boolean;
|
||||
|
||||
/**
|
||||
* Function that is called when the banner close button is clicked.
|
||||
*
|
||||
* Should be used to handle disposal of the Banner.
|
||||
*/
|
||||
onClose?(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A customizable banner for displaying at the top of a page.
|
||||
*/
|
||||
export class Banner extends Disposable {
|
||||
private readonly _isExpanded = Observable.create(this, true);
|
||||
|
||||
constructor(private _options: BannerOptions) {
|
||||
super();
|
||||
}
|
||||
|
||||
public buildDom() {
|
||||
return cssBanner(
|
||||
cssBanner.cls(`-${this._options.style}`),
|
||||
this._buildContent(),
|
||||
this._buildButtons(),
|
||||
);
|
||||
}
|
||||
|
||||
private _buildContent() {
|
||||
const {content, contentSmall} = this._options;
|
||||
return dom.domComputed(use => {
|
||||
if (contentSmall === undefined) { return [content]; }
|
||||
|
||||
const isExpanded = use(this._isExpanded);
|
||||
const isNarrowScreen = use(isNarrowScreenObs());
|
||||
return [isNarrowScreen && !isExpanded ? contentSmall : content];
|
||||
});
|
||||
}
|
||||
|
||||
private _buildButtons() {
|
||||
return cssButtons(
|
||||
this._options.showExpandButton ? this._buildExpandButton() : null,
|
||||
this._options.showCloseButton ? this._buildCloseButton() : null,
|
||||
);
|
||||
}
|
||||
|
||||
private _buildCloseButton() {
|
||||
return cssButton('CrossBig',
|
||||
dom.on('click', () => this._options.onClose?.()),
|
||||
testId('close'),
|
||||
);
|
||||
}
|
||||
|
||||
private _buildExpandButton() {
|
||||
return dom.maybe(isNarrowScreenObs(), () => {
|
||||
return cssExpandButton('Dropdown',
|
||||
cssExpandButton.cls('-expanded', this._isExpanded),
|
||||
dom.on('click', () => this._isExpanded.set(!this._isExpanded.get())),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function buildBannerMessage(...domArgs: DomElementArg[]) {
|
||||
return cssBannerMessage(
|
||||
cssIcon('Idea'),
|
||||
cssLightlyBoldedText(domArgs),
|
||||
);
|
||||
}
|
||||
|
||||
const cssBanner = styled('div', `
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
gap: 16px;
|
||||
color: white;
|
||||
|
||||
&-warning {
|
||||
background: #E6A117;
|
||||
}
|
||||
|
||||
&-error {
|
||||
background: ${colors.error};
|
||||
}
|
||||
`);
|
||||
|
||||
const cssButtons = styled('div', `
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
`);
|
||||
|
||||
const cssButton = styled(icon, `
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
background-color: white;
|
||||
`);
|
||||
|
||||
const cssExpandButton = styled(cssButton, `
|
||||
&-expanded {
|
||||
-webkit-mask-image: var(--icon-DropdownUp);
|
||||
}
|
||||
`);
|
||||
|
||||
const cssLightlyBoldedText = styled('div', `
|
||||
font-weight: 500;
|
||||
`);
|
||||
|
||||
const cssIconAndText = styled('div', `
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
`);
|
||||
|
||||
const cssBannerMessage = styled(cssIconAndText, `
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
`);
|
||||
|
||||
const cssIcon = styled(icon, `
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: white;
|
||||
`);
|
||||
Reference in New Issue
Block a user