mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
ec157dc469
Summary: Adds initial implementation of dark mode. Preferences for dark mode are available on the account settings page. Dark mode is currently a beta feature as there are still some small bugs to squash and a few remaining UI elements to style. Test Plan: Browser tests. Reviewers: jarek Reviewed By: jarek Subscribers: paulfitz, jarek Differential Revision: https://phab.getgrist.com/D3587
140 lines
4.0 KiB
TypeScript
140 lines
4.0 KiB
TypeScript
/**
|
|
* UI 2018 Buttons
|
|
*
|
|
* Four styles are include: basicButton, primaryButton, bigBasicButton, bigPrimaryButton.
|
|
*
|
|
* Buttons support passing in DomElementArgs, which can be used to register click handlers, set
|
|
* the disabled property, and other HTML <button> element behaviors.
|
|
*
|
|
* Examples:
|
|
*
|
|
* `basicButton('Basic button', dom.on('click', () => alert('Basic button')))`
|
|
* `primaryButton('Primary button', dom.prop('disabled', true))`
|
|
*/
|
|
|
|
import { theme, vars } from 'app/client/ui2018/cssVars';
|
|
import { tbind } from 'app/common/tbind';
|
|
import { dom, DomElementArg, styled } from 'grainjs';
|
|
|
|
export const cssButton = styled('button', `
|
|
/* Resets */
|
|
position: relative;
|
|
outline: none;
|
|
border-style: none;
|
|
line-height: normal;
|
|
|
|
/* Vars */
|
|
font-size: ${vars.mediumFontSize};
|
|
letter-spacing: -0.08px;
|
|
padding: 4px 8px;
|
|
|
|
background-color: transparent;
|
|
color: ${theme.controlFg};
|
|
--icon-color: ${theme.controlFg};
|
|
|
|
border: ${vars.controlBorder};
|
|
border-radius: ${vars.controlBorderRadius};
|
|
border-color: ${theme.controlBorder};
|
|
|
|
cursor: pointer;
|
|
|
|
&-large {
|
|
font-weight: 500;
|
|
padding: 10px 24px;
|
|
min-height: 40px;
|
|
}
|
|
|
|
&-primary {
|
|
background-color: ${theme.controlPrimaryBg};
|
|
color: ${theme.controlPrimaryFg};
|
|
--icon-color: ${theme.controlPrimaryFg};
|
|
border-color: ${theme.controlPrimaryBg};
|
|
}
|
|
|
|
&:hover {
|
|
color: ${theme.controlHoverFg};
|
|
--icon-color: ${theme.controlHoverFg};
|
|
border-color: ${theme.controlHoverFg};
|
|
}
|
|
&-primary:hover {
|
|
color: ${theme.controlPrimaryFg};
|
|
--icon-color: ${theme.controlPrimaryFg};
|
|
background-color: ${theme.controlPrimaryHoverBg};
|
|
border-color: ${theme.controlPrimaryHoverBg};
|
|
}
|
|
&:disabled {
|
|
cursor: not-allowed;
|
|
color: ${theme.controlDisabledFg};
|
|
--icon-color: ${theme.controlDisabledFg};
|
|
background-color: ${theme.controlDisabledBg};
|
|
border-color: ${theme.controlDisabledBg};
|
|
}
|
|
|
|
`);
|
|
|
|
interface IButtonProps {
|
|
large?: boolean;
|
|
primary?: boolean;
|
|
link?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Helper to create a button or button-like link with requested properties.
|
|
*/
|
|
function button(props: IButtonProps, ...domArgs: DomElementArg[]) {
|
|
const elem = props.link ? cssButtonLink(dom.cls(cssButton.className)) : cssButton();
|
|
return dom.update(elem,
|
|
cssButton.cls('-large', Boolean(props.large)),
|
|
cssButton.cls('-primary', Boolean(props.primary)),
|
|
...domArgs
|
|
);
|
|
}
|
|
|
|
// Button-creating functions, each taking ...DomElementArg arguments.
|
|
export const basicButton = tbind(button, null, {});
|
|
export const bigBasicButton = tbind(button, null, {large: true});
|
|
export const primaryButton = tbind(button, null, {primary: true});
|
|
export const bigPrimaryButton = tbind(button, null, {large: true, primary: true});
|
|
|
|
// Functions that create button-like <a> links, each taking ...DomElementArg arguments.
|
|
export const basicButtonLink = tbind(button, null, {link: true});
|
|
export const bigBasicButtonLink = tbind(button, null, {link: true, large: true});
|
|
export const primaryButtonLink = tbind(button, null, {link: true, primary: true});
|
|
export const bigPrimaryButtonLink = tbind(button, null, {link: true, large: true, primary: true});
|
|
|
|
// Button that looks like a link (have no background and no border).
|
|
export const textButton = styled(cssButton, `
|
|
border: none;
|
|
padding: 0px;
|
|
background-color: inherit !important;
|
|
&:disabled {
|
|
color: ${theme.controlPrimaryDisabled};
|
|
}
|
|
`);
|
|
|
|
const cssButtonLink = styled('a', `
|
|
display: inline-block;
|
|
&, &:hover, &:focus {
|
|
text-decoration: none;
|
|
}
|
|
`);
|
|
|
|
export const cssButtonGroup = styled('div', `
|
|
display: flex;
|
|
flex-direction: row;
|
|
|
|
& > .${cssButton.className} {
|
|
border-radius: 0;
|
|
}
|
|
|
|
& > .${cssButton.className}:first-child {
|
|
border-top-left-radius: ${vars.controlBorderRadius};
|
|
border-bottom-left-radius: ${vars.controlBorderRadius};
|
|
}
|
|
|
|
& > .${cssButton.className}:last-child {
|
|
border-top-right-radius: ${vars.controlBorderRadius};
|
|
border-bottom-right-radius: ${vars.controlBorderRadius};
|
|
}
|
|
`);
|