(core) Polish dark mode and remove beta tag

Summary:
Polishes support for dark mode and enables syncing with the OS theme
by default.

Test Plan: Manual.

Reviewers: JakubSerafin

Reviewed By: JakubSerafin

Subscribers: JakubSerafin

Differential Revision: https://phab.getgrist.com/D4041
pull/684/head
George Gevoian 8 months ago
parent d1826987bb
commit 273b976cab

@ -16,7 +16,7 @@ const cssMemoInput = styled('input', `
border-radius: 3px;
border: 1px solid transparent;
cursor: pointer;
color: ${theme.accentText};
color: ${theme.controlFg};
background-color: ${theme.inputBg};
caret-color : ${theme.inputFg};
font: 12px 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
@ -29,7 +29,7 @@ const cssMemoInput = styled('input', `
&:not(&-disabled):focus-within {
outline: none !important;
cursor: text;
box-shadow: inset 0 0 0 1px ${theme.accentBorder};
border-color: ${theme.accentBorder};
box-shadow: inset 0 0 0 1px ${theme.controlFg};
border-color: ${theme.controlFg};
}
`);

@ -1,4 +1,4 @@
import {colors} from 'app/client/ui2018/cssVars';
import {theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {IOption, select} from 'app/client/ui2018/menus';
import {MaybeObsArray, Observable, styled} from 'grainjs';
@ -19,7 +19,7 @@ export const cssSelect = styled(select, `
cursor: pointer;
&:hover, &:focus, &.weasel-popup-open, &-active {
border: 1px solid ${colors.darkGrey};
border: 1px solid ${theme.selectButtonBorder};
box-shadow: none;
}
`);

@ -2,7 +2,7 @@
* Implements a widget showing 3-state boxes for permissions
* (for Allow / Deny / Pass-Through).
*/
import {colors, testId} from 'app/client/ui2018/cssVars';
import {colors, testId, theme} from 'app/client/ui2018/cssVars';
import {cssIconButton, icon} from 'app/client/ui2018/icons';
import {menu, menuIcon, menuItem} from 'app/client/ui2018/menus';
import {PartialPermissionSet, PartialPermissionValue} from 'app/common/ACLPermissions';
@ -155,8 +155,8 @@ const cssBit = styled('div', `
border-radius: 2px;
font-size: 13px;
font-weight: 500;
border: 1px dashed ${colors.darkGrey};
color: ${colors.darkGrey};
border: 1px dashed ${theme.accessRulesTableBodyLightFg};
color: ${theme.accessRulesTableBodyLightFg};
cursor: pointer;
display: flex;

@ -2,6 +2,16 @@
background-color: var(--grist-theme-ace-editor-bg, white);
}
.ace_editor .ace_placeholder {
font-family: Monaco, Menlo, "Ubuntu Mono", Consolas, "Source Code Pro", source-code-pro, monospace;
font-size: 11px;
color: var(--grist-theme-text-light, #929299);
font-style: italic;
white-space: nowrap;
opacity: 1.0;
transform: none;
}
.ace_grist_link_hidden {
display: none;
}

@ -31,7 +31,7 @@
}
.action_desc {
color: var(--grist-theme-document-history-activity-text-light, unset);
color: var(--grist-theme-document-history-activity-text, unset);
}
.action_log_item.undone > .action_info,
@ -68,37 +68,38 @@
text-align: center;
margin-top: 0;
padding-top: 0;
color: var(--grist-theme-document-history-activity-text, #000);
color: var(--grist-theme-document-history-activity-text-light, #333);
}
.action_log_table td {
border-left: 1px solid #888;
border-right: 1px solid #888;
border-bottom: 1px solid #888;
border-top: 1px solid #888;
border: 1px solid var(--grist-theme-document-history-table-border, lightgray);
cursor: pointer;
}
.action_log_table th {
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
color: #888;
border-top: 1px solid var(--grist-theme-document-history-table-border-light, #D9D9D9);
border-left: 1px solid var(--grist-theme-document-history-table-border-light, #D9D9D9);
border-right: 1px solid var(--grist-theme-document-history-table-border-light, #D9D9D9);
color: var(--grist-theme-document-history-table-header-fg, #000);
}
.action_log_table th:first-child {
border: none;
border-bottom: 1px solid #ccc;
border-bottom: 1px solid var(--grist-theme-document-history-table-border-light, #D9D9D9);
}
.action_log_table td:first-child {
border: none;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
color: #888;
border-left: 1px solid var(--grist-theme-document-history-table-border-light, #D9D9D9);
border-bottom: 1px solid var(--grist-theme-document-history-table-border-light, #D9D9D9);
color: var(--grist-theme-document-history-table-header-fg, #000);
cursor: inherit;
}
.action_log_table td:not(:first-child) {
background-color: var(--grist-theme-table-body-bg);
}
.action_log_table td, .action_log_table th {
padding-left: 3px;
padding-right: 3px;
@ -127,3 +128,7 @@
.action_comment {
display: none;
}
.action_info {
color: var(--grist-theme-document-history-activity-text-light, #929299);
}

@ -10,15 +10,15 @@ import * as ko from 'knockout';
import koArray from 'app/client/lib/koArray';
import {KoArray} from 'app/client/lib/koArray';
import * as koDom from 'app/client/lib/koDom';
import * as koForm from 'app/client/lib/koForm';
import {GristDoc} from 'app/client/components/GristDoc';
import {ActionGroup} from 'app/common/ActionGroup';
import {ActionSummary, asTabularDiffs, defunctTableName, getAffectedTables,
LabelDelta} from 'app/common/ActionSummary';
import {CellDelta, TabularDiff} from 'app/common/TabularDiff';
import {DomContents, IDomComponent} from 'grainjs';
import {DomContents, fromKo, IDomComponent} from 'grainjs';
import {makeT} from 'app/client/lib/localization';
import {labeledSquareCheckbox} from 'app/client/ui2018/checkbox';
/**
*
@ -230,10 +230,12 @@ export class ActionLog extends dispose.Disposable implements IDomComponent {
this._loadActionSummaries().catch(() => gristNotify(t("Action Log failed to load")));
return dom('div.action_log',
{tabIndex: '-1'},
dom('div.preference_item',
koForm.checkbox(this._showAllTables,
dom.testId('ActionLog_allTables'),
dom('span.preference_desc', 'All tables'))),
dom('div',
labeledSquareCheckbox(fromKo(this._showAllTables),
t('All tables'),
dom.testId('ActionLog_allTables'),
),
),
dom('div.action_log_load',
koDom.show(() => this._loading()),
'Loading...'),

@ -97,6 +97,8 @@ export class ColumnTransform extends Disposable {
}));
}
return this.editor.buildDom((aceObj: any) => {
aceObj.setOptions({placeholder: 'Enter formula.'});
aceObj.setHighlightActiveLine(false);
this.editor.adjustContentToWidth();
this.editor.attachSaveCommand();
aceObj.on('change', () => {

@ -97,8 +97,25 @@
margin-right: 2px;
}
.detail-buttons {
display: flex;
align-items: center;
gap: 4px;
}
.detail-left, .detail-right, .detail-add-btn {
--icon-color: var(--grist-theme-control-secondary-fg, #929299);
padding: 3px;
border-radius: 4px;
}
.detail-left.disabled, .detail-right.disabled, .detail-add-btn.disabled {
cursor: default !important;
--icon-color: var(--grist-theme-control-secondary-disabled-fg, #D9D9D9);
}
.detail-button:not(.disabled):hover {
cursor: pointer;
background-color: var(--grist-theme-hover, rgba(217,217,217,0.6));
}
.detail-add-grp {

@ -6,6 +6,7 @@ const kd = require('app/client/lib/koDom');
const koDomScrolly = require('app/client/lib/koDomScrolly');
const {renderAllRows} = require('app/client/components/Printing');
const {isNarrowScreen} = require('app/client/ui2018/cssVars');
const {icon} = require('app/client/ui2018/icons');
require('app/client/lib/koUtil'); // Needed for subscribeInit.
@ -381,28 +382,29 @@ DetailView.prototype.buildTitleControls = function() {
kd.text(() => this._isAddRow() ? 'Add record' :
`${this.cursor.rowIndex() + 1} of ${this.getLastDataRowIndex() + 1}`)
),
dom('div.btn-group.btn-group-xs',
dom('div.btn.btn-default.detail-left',
dom('span.glyphicon.glyphicon-chevron-left'),
dom('div.detail-buttons',
dom('div.detail-button.detail-left',
icon('ArrowLeft'),
dom.on('click', () => { this.cursor.rowIndex(this.cursor.rowIndex() - 1); }),
kd.toggleClass('disabled', () => this.cursor.rowIndex() === 0)
kd.toggleClass('disabled', () => this.cursor.rowIndex() === 0),
dom.testId('detailView_detail_left'),
),
dom('div.btn.btn-default.detail-right',
dom('span.glyphicon.glyphicon-chevron-right'),
dom('div.detail-button.detail-right',
icon('ArrowRight'),
dom.on('click', () => { this.cursor.rowIndex(this.cursor.rowIndex() + 1); }),
kd.toggleClass('disabled', () => this.cursor.rowIndex() >= this.viewData.all().length - 1)
)
),
dom('div.btn-group.btn-group-xs.detail-add-grp',
dom('div.btn.btn-default.detail-add-btn',
dom('span.glyphicon.glyphicon-plus'),
kd.toggleClass('disabled', () => this.cursor.rowIndex() >= this.viewData.all().length - 1),
dom.testId('detailView_detail_right'),
),
dom('div.detail-button.detail-add-btn',
icon('Plus'),
dom.on('click', () => {
let addRowIndex = this.viewData.getRowIndex('new');
this.cursor.rowIndex(addRowIndex);
}),
kd.toggleClass('disabled', () => this.viewData.getRowId(this.cursor.rowIndex()) === 'new')
)
)
kd.toggleClass('disabled', () => this.viewData.getRowId(this.cursor.rowIndex()) === 'new'),
dom.testId('detailView_detail_add'),
),
),
))
);
};

@ -71,7 +71,7 @@
width: 4rem; /* Also should match width for .gridview_header_corner, and the overlay elements */
flex: none;
border-bottom: 1px solid var(--grist-theme-table-header-border-dark, var(--grist-color-dark-grey));
border-bottom: 1px solid var(--grist-theme-table-header-border, lightgray);
color: var(--grist-theme-table-header-fg, unset);
background-color: var(--grist-theme-table-header-bg, var(--grist-color-light-grey));
z-index: 20; /* goes over data cells */
@ -102,7 +102,7 @@
* do not want !important, as it interferes with row selection.
*/
.gridview_data_row_num {
background-color: var(--grist-theme-table-header-bg , var(--grist-color-light-grey)) !important;
background-color: var(--grist-color-light-grey) !important;
}
.gridview_header_backdrop_top {
display: none;
@ -111,7 +111,7 @@
display: none;
}
.gridview_data_header {
background-color: var(--grist-theme-table-header-bg, var(--grist-color-light-grey)) !important;
background-color: var(--grist-color-light-grey) !important;
}
.print-widget .gridview_header_backdrop_left, .print-widget .gridview_data_corner_overlay {
display: none;
@ -127,15 +127,15 @@
display: table-header-group;
break-inside: avoid;
position: static;
border-top: 1px solid var(--grist-theme-table-header-border-dark, var(--grist-color-dark-grey));
border-left: 1px solid var(--grist-theme-table-header-border-dark, var(--grist-color-dark-grey));
border-top: 1px solid var(--grist-color-dark-grey);
border-left: 1px solid var(--grist-color-dark-grey);
}
.print-widget .gridview_data_header {
padding-left: 4rem !important;
}
.print-widget .gridview_data_pane .print-all-rows {
display: table-row-group;
border-left: 1px solid var(--grist-theme-table-body-border, var(--grist-color-dark-grey));
border-left: 1px solid var(--grist-color-dark-grey);
}
.print-widget .gridview_data_pane .print-row {
display: table-row;

@ -1,44 +0,0 @@
.preference_mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: rgba(1, 1, 1, 0.3);
}
.preference_window {
position: absolute;
background-color: white;
display: inline-block;
padding: 10px 20px;
width: 60%;
margin: 20%;
box-shadow: 0px 1px 3px 0px rgba(0,0,0,0.8);
}
.preference_title {
color: #546e7a;
text-align: left;
border-bottom: 1px solid rgba(0,0,0,.12);
font-family: 'Roboto', Helvetica, Arial, sans-serif;
width: 100%;
height: 40px;
}
.preference_content {
width: 100%;
font-size: 1.4rem;
}
.preference_desc {
color: var(--grist-theme-document-history-activity-text, unset);
margin-left: 5px;
cursor: pointer;
font-weight: normal;
}
.preference_footer > .kf_elem {
flex: 1 1 100%;
}

@ -152,7 +152,7 @@ const cssSectionWrapper = styled('div', `
border-bottom-right-radius: 0px;
& .viewsection_content {
margin: 0px;
margin-top: 12px;
margin-top: 8px;
}
& .viewsection_title {
padding: 0px 12px;

@ -4,14 +4,13 @@ import * as tableUtil from 'app/client/lib/tableUtil';
import {ColumnRec, DocModel, ViewFieldRec} from 'app/client/models/DocModel';
import {KoSaveableObservable} from 'app/client/models/modelUtil';
import {cssFieldEntry, cssFieldLabel} from 'app/client/ui/VisibleFieldsConfig';
import {colors, testId} from 'app/client/ui2018/cssVars';
import {testId, theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {menuText} from 'app/client/ui2018/menus';
import {menu, menuItem, menuText} from 'app/client/ui2018/menus';
import {FieldBuilder} from 'app/client/widgets/FieldBuilder';
import * as gutil from 'app/common/gutil';
import {Disposable, dom, fromKo, styled} from 'grainjs';
import ko from 'knockout';
import {menu, menuItem} from 'popweasel';
import {makeT} from 'app/client/lib/localization';
const t = makeT('RefSelect');
@ -89,7 +88,7 @@ export class RefSelect extends Disposable {
testId('ref-select'),
dom.forEach(fromKo(this._added.getObservable()), (col) =>
cssFieldEntry(
cssFieldLabel(dom.text(col.label)),
cssColumnLabel(dom.text(col.label)),
cssRemoveIcon('Remove',
dom.on('click', () => this._removeFormulaField(col)),
testId('ref-select-remove'),
@ -233,15 +232,15 @@ const cssEmptyMenuText = styled(menuText, `
const cssAddLink = styled('div', `
display: flex;
cursor: pointer;
color: ${colors.lightGreen};
--icon-color: ${colors.lightGreen};
color: ${theme.controlFg};
--icon-color: ${theme.controlFg};
&:not(:first-child) {
margin-top: 8px;
}
&:hover, &:focus, &:active {
color: ${colors.darkGreen};
--icon-color: ${colors.darkGreen};
color: ${theme.controlHoverFg};
--icon-color: ${theme.controlHoverFg};
}
`);
@ -258,3 +257,7 @@ const cssRemoveIcon = styled(icon, `
display: block;
}
`);
const cssColumnLabel = styled(cssFieldLabel, `
line-height: 16px;
`);

@ -6,7 +6,7 @@ import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {UserError} from 'app/client/models/errors';
import {ALL, RowsChanged, SortedRowSet} from "app/client/models/rowset";
import {showTransientTooltip} from 'app/client/ui/tooltips';
import {colors, isNarrowScreen, isNarrowScreenObs, theme, vars} from 'app/client/ui2018/cssVars';
import {isNarrowScreen, isNarrowScreenObs, theme, vars} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {CellValue} from 'app/common/DocActions';
import {isEmptyList, isListType, isRefListType} from "app/common/gristTypes";
@ -314,7 +314,7 @@ const cssSummaryPart = styled('div', `
left: 0;
bottom: 0;
right: 0;
background-color: ${colors.mediumGrey};
background-color: ${theme.tableCellSummaryBg};
opacity: 0.8;
z-index: -1;
}

@ -160,9 +160,10 @@ export async function prepTransformColInfo(docModel: DocModel, origCol: ColumnRe
// trouble than desired behavior. For many choices, recommend using a Ref to helper table.
const columnData = tableData.getDistinctValues(sourceCol.colId(), 100);
if (columnData) {
columnData.delete("");
columnData.delete(null);
widgetOptions = {...widgetOptions, choices: Array.from(columnData, String)};
const choices = Array.from(columnData, String).filter((choice) => {
return choice !== null && choice.trim() !== '';
});
widgetOptions = {...widgetOptions, choices};
}
}
break;
@ -178,11 +179,12 @@ export async function prepTransformColInfo(docModel: DocModel, origCol: ColumnRe
value = String(decodeObject(value)).trim();
const tags: unknown[] = (value.startsWith('[') && gutil.safeJsonParse(value, null)) || csvDecodeRow(value);
for (const tag of tags) {
choices.add(String(tag).trim());
const choice = String(tag).trim();
if (choice === '') { continue; }
choices.add(choice);
if (choices.size > 100) { break; } // Don't suggest excessively many choices.
}
}
choices.delete("");
widgetOptions = {...widgetOptions, choices: Array.from(choices)};
}
break;

@ -131,13 +131,12 @@ ViewConfigTab.prototype._buildAdvancedSettingsDom = function() {
kd.style('margin-top', '1.5rem')
),
kf.row(kd.hide(isCollapsed),
kf.label('Table ', dom('b', kd.text(table.tableId)), ':')
),
kf.row(kd.hide(isCollapsed),
kf.buttonGroup(kf.button(() => this._makeOnDemand(table),
dom('div', primaryButton(
kd.text(() => table.onDemand() ? t("Unmark On-Demand") : t("Make On-Demand")),
dom.testId('ViewConfig_onDemandBtn')
))
kd.style('margin-top', '1rem'),
dom.on('click', () => this._makeOnDemand(table)),
dom.testId('ViewConfig_onDemandBtn'),
)),
),
];
});

@ -9,14 +9,15 @@
align-items: center;
gap: 8px;
align-self: flex-start;
margin-top: -1px;
}
.viewsection_title {
align-items: center;
flex-shrink: 0;
cursor: default;
height: 24px;
min-height: 24px;
margin-left: -16px; /* to include drag handle that shows up on hover */
margin-bottom: 4px;
white-space: nowrap;
}

@ -456,7 +456,7 @@ const cssLayoutWrapper = styled('div', `
}
&-active .viewsection_content {
margin: 0px;
margin-top: 12px;
margin-top: 8px;
}
&-active .viewsection_title {
padding: 0px 12px;

@ -7,7 +7,7 @@ import {cssIcon} from 'app/client/ui/RightPanelStyles';
import {makeCollapsedLayoutMenu} from 'app/client/ui/ViewLayoutMenu';
import {cssDotsIconWrapper, cssMenu, viewSectionMenu} from 'app/client/ui/ViewSectionMenu';
import {buildWidgetTitle} from 'app/client/ui/WidgetTitle';
import {colors, isNarrowScreenObs, mediaSmall, testId, theme} from 'app/client/ui2018/cssVars';
import {isNarrowScreenObs, mediaSmall, testId, theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {menu} from 'app/client/ui2018/menus';
import {getWidgetTypes} from "app/client/ui/widgetTypesMap";
@ -128,7 +128,6 @@ const cssTestClick = styled(`div`, `
`);
const cssSigmaIcon = styled(icon, `
bottom: 1px;
margin-right: 5px;
background-color: ${theme.lightText}
`);
@ -186,8 +185,7 @@ const cssViewLeafInactive = styled('div', `
// z-index ensure it's above the resizer line, since it's hard to grab otherwise
const cssDragIcon = styled(icon, `
visibility: hidden;
--icon-color: ${colors.slate};
top: -1px;
--icon-color: ${theme.lightText};
z-index: 100;
.viewsection_title:hover &.layout_grabbable {
@ -204,7 +202,7 @@ const cssResizing = styled('div', `
`);
const cssMiniSection = styled('div.mini_section_container', `
--icon-color: ${colors.lightGreen};
--icon-color: ${theme.accentIcon};
display: flex;
align-items: center;
padding-right: 8px;

@ -350,7 +350,8 @@ const cssBehavioralPromptModal = styled('div', `
@media ${mediaXSmall} {
& {
width: 320px;
/* Allocate 32px of space for the left and right margins. */
width: calc(100% - 64px);
}
}
`);

@ -12,6 +12,7 @@
border-style: none;
border-color: var(--grist-theme-table-body-border, var(--grist-color-dark-grey));
border-left-style: solid; /* left border, against rownumbers div, always on */
border-left-color: var(--grist-theme-table-header-border, lightgray);
border-bottom-width: 1px; /* style: none, set by record-hlines*/
/* Record background is white (or theme default) by default.
It gets overridden by the add row, zebra stripes.
@ -203,11 +204,11 @@
text-align: center;
cursor: pointer;
/* Column headers always show vertical gridlines, to make it clear how to resize them */
border-right-color: var(--grist-theme-table-header-border-dark, var(--grist-color-dark-grey));
border-right-color: var(--grist-theme-table-header-border, lightgray);
}
.column_names.record {
border-left-color: var(--grist-theme-table-header-border, var(--grist-color-dark-grey));
border-left-color: var(--grist-theme-table-header-border, lightgray);
}
.column_name.selected > .selection {

@ -3,6 +3,7 @@ import {ACIndex, ACItem, ACResults, buildHighlightedDom, normalizeText} from "ap
import {cssSelectItem} from "app/client/lib/ACSelect";
import {Autocomplete, IAutocompleteOptions} from "app/client/lib/autocomplete";
import {colors, testId, theme} from "app/client/ui2018/cssVars";
import {icon} from "app/client/ui2018/icons";
import {menuCssClass} from "app/client/ui2018/menus";
import {
cssEmailInput,
@ -104,7 +105,7 @@ export function buildACMemberEmail(
const renderSearchItem = (item: ACUserItem, highlightFunc: any): HTMLLIElement => (item?.isNew ? cssSelectItem(
cssMemberListItem(
cssUserImagePlus(
"+",
cssPlusIcon('Plus'),
cssUserImage.cls("-large"),
cssUserImagePlus.cls('-invalid', (use) => !use(enableAdd),
)),
@ -199,3 +200,8 @@ const cssUserImagePlus = styled(cssUserImage, `
color: ${theme.menuItemSelectedBg};
}
`);
const cssPlusIcon = styled(icon, `
width: 20px;
height: 20px;
`);

@ -652,14 +652,14 @@ const cssToken = styled('div', `
position: relative;
flex: none;
border-radius: 3px;
background-color: ${colors.mediumGreyOpaque};
background-color: ${theme.choiceTokenBg};
padding: 4px;
margin: 3px 2px;
user-select: none;
cursor: grab;
&.selected {
background-color: ${colors.darkGrey};
background-color: ${theme.choiceTokenSelectedBg};
}
&.token-dragging {
pointer-events: none;
@ -710,7 +710,7 @@ const cssDragTarget = styled('div', `
&:hover::after {
content: "";
position: absolute;
background-color: ${colors.lightGreen};
background-color: ${theme.controlFg};
width: 2px;
top: 0px;
bottom: 0px;
@ -740,7 +740,7 @@ const cssVerticalDragTarget = styled('div', `
&:hover::after {
content: "";
position: absolute;
background-color: ${colors.lightGreen};
background-color: ${theme.controlFg};
height: 2px;
top: -5px;
bottom: 0px;

@ -335,6 +335,7 @@ div:hover > .kf_tooltip {
color: #606060;
overflow: hidden;
margin-top: 3px;
padding: 1px;
}
@ -362,11 +363,11 @@ div:hover > .kf_tooltip {
}
.kf_spinner_arrow.up {
border-top: none;
border-bottom: 5px solid #606060;
border-bottom: 5px solid var(--grist-theme-numeric-spinner-fg, #606060);
margin: 2px auto;
}
.kf_spinner_arrow.down {
border-top: 5px solid #606060;
border-top: 5px solid var(--grist-theme-numeric-spinner-fg, #606060);
border-bottom: none;
margin: 1px auto 2px auto;
}

@ -26,6 +26,7 @@ import {getGristConfig} from 'app/common/urlUtils';
import {getOrgName, isTemplatesOrg, Organization, OrgError, UserAPI, UserAPIImpl} from 'app/common/UserAPI';
import {getUserPrefObs, getUserPrefsObs, markAsSeen, markAsUnSeen} from 'app/client/models/UserPrefs';
import {bundleChanges, Computed, Disposable, Observable, subscribe} from 'grainjs';
import isEqual from 'lodash/isEqual';
const t = makeT('AppModel');
@ -311,9 +312,7 @@ export class AppModelImpl extends Disposable implements AppModel {
) {
super();
this._applyTheme();
this.autoDispose(this.currentTheme.addListener(() => this._applyTheme()));
this._setTheme();
this._recordSignUpIfIsNewUser();
const state = urlState().state.get();
@ -488,14 +487,16 @@ export class AppModelImpl extends Disposable implements AppModel {
);
}
/**
* Applies a theme based on the user's current theme preferences.
*/
private _applyTheme() {
private _setTheme() {
// Custom CSS is incompatible with custom themes.
if (getGristConfig().enableCustomCss) { return; }
attachCssThemeVars(this.currentTheme.get());
this.autoDispose(this.currentTheme.addListener((newTheme, oldTheme) => {
if (isEqual(newTheme, oldTheme)) { return; }
attachCssThemeVars(newTheme);
}));
}
}

@ -18,7 +18,8 @@ import {getGristConfig} from 'app/common/urlUtils';
import {FullUser} from 'app/common/UserAPI';
import {detectCurrentLang, makeT} from 'app/client/lib/localization';
import {translateLocale} from 'app/client/ui/LanguageMenu';
import {Computed, Disposable, dom, domComputed, makeTestId, Observable, styled} from 'grainjs';
import {getPageTitleSuffix} from 'app/common/gristUrls';
import {Computed, Disposable, dom, domComputed, makeTestId, Observable, styled, subscribe} from 'grainjs';
const testId = makeTestId('test-account-page-');
const t = makeT('AccountPage');
@ -27,6 +28,7 @@ const t = makeT('AccountPage');
* Creates the account page where a user can manage their profile settings.
*/
export class AccountPage extends Disposable {
private readonly _currentPage = Computed.create(this, urlState().state, (_use, s) => s.account);
private _apiKey = Observable.create<string>(this, '');
private _userObs = Observable.create<FullUser|null>(this, null);
private _isEditingName = Observable.create(this, false);
@ -37,6 +39,7 @@ export class AccountPage extends Disposable {
constructor(private _appModel: AppModel) {
super();
this._setPageTitle();
this._fetchAll().catch(reportError);
}
@ -228,6 +231,18 @@ designed to ensure that you're the only person who can access your account, even
testId('username-warning'),
);
}
private _setPageTitle() {
this.autoDispose(subscribe(this._currentPage, (_use, page): string => {
const suffix = getPageTitleSuffix(getGristConfig());
switch (page) {
case undefined:
case 'account': {
return document.title = `Account${suffix}`;
}
}
}));
}
}
/**

@ -100,10 +100,3 @@ export const dataRow = styled('div', `
align-items: baseline;
gap: 2px;
`);
export const betaTag = styled('span', `
text-transform: uppercase;
vertical-align: super;
font-size: ${vars.xsmallFontSize};
color: ${theme.accentText};
`);

@ -354,11 +354,6 @@ export function columnFilterMenu(owner: IDisposableOwner, opts: IFilterMenuOptio
gristDoc.behavioralPromptsManager.attachTip('filterButtons', {
popupOptions: {
attach: null,
modifiers: {
flip: {
behavior: ['right', 'top'],
},
},
placement: 'right',
},
}),

@ -55,6 +55,7 @@ const cssTextArea = styled(textarea, `
border-radius: 3px;
padding: 3px 7px;
min-height: calc(3em * 1.5);
resize: none;
&::placeholder {
color: ${theme.inputPlaceholderFg};

@ -470,18 +470,17 @@ const cssToggleButton = styled(cssIconButton, `
margin-left: 8px;
background-color: ${theme.rightPanelToggleButtonDisabledBg};
box-shadow: inset 0 0 0 1px ${theme.inputBorder};
cursor: pointer;
&-selected, &-selected:hover {
box-shadow: none;
background-color: ${theme.rightPanelToggleButtonEnabledBg};
--icon-color: ${theme.rightPanelToggleButtonEnabledFg};
}
&-selected:hover {
--icon-color: ${theme.rightPanelToggleButtonEnabledHoverFg};
}
&-disabled, &-disabled:hover {
--icon-color: ${theme.rightPanelToggleButtonDisabledFg};
cursor: not-allowed;
background-color: ${theme.rightPanelToggleButtonDisabledBg};
--icon-color: ${theme.iconDisabled};
}
`);

@ -293,7 +293,7 @@ export class FloatingPopup extends Disposable {
const body = cssPopup(
{tabIndex: '-1'},
cssPopup.cls('-auto', this._options.autoHeight ?? false),
dom.style('min-height', `${this._minHeight}px`),
dom.style('min-height', use => use(this._isMinimized) ? 'unset' : `${this._minHeight}px`),
cssPopupHeader(
cssBottomHandle(testId('move-handle')),
dom.maybe(use => !use(this._isMinimized), () => {

@ -1,7 +1,7 @@
import {bigPrimaryButton as gristBigPrimaryButton,
bigPrimaryButtonLink as gristBigPrimaryButtonLink,
textButton as gristTextButton} from 'app/client/ui2018/buttons';
import {colors, mediaXSmall, theme} from 'app/client/ui2018/cssVars';
import {mediaXSmall, theme} from 'app/client/ui2018/cssVars';
import {textInput} from 'app/client/ui/inputs';
import {styled} from 'grainjs';
@ -61,15 +61,15 @@ export const googleButton = styled('button', `
font-weight: 500;
line-height: 16px;
padding: 16px;
color: ${colors.dark};
background-color: ${colors.lightGrey};
border: 1px solid ${colors.darkGrey};
color: ${theme.loginPageGoogleButtonFg};
background-color: ${theme.loginPageGoogleButtonBg};
border: 1px solid ${theme.loginPageGoogleButtonBorder};
border-radius: 4px;
cursor: pointer;
width: 100%;
&:hover {
background-color: ${colors.mediumGrey};
background-color: ${theme.loginPageGoogleButtonBgHover};
}
`);

@ -9,6 +9,7 @@ import {find as findInTree, fromTableData, TreeItemRecord, TreeRecord,
TreeTableData} from 'app/client/models/TreeModel';
import {TreeViewComponent} from 'app/client/ui/TreeViewComponent';
import {cssRadioCheckboxOptions, radioCheckboxOption} from 'app/client/ui2018/checkbox';
import {theme} from 'app/client/ui2018/cssVars';
import {cssLink} from 'app/client/ui2018/links';
import {ISaveModalOptions, saveModal} from 'app/client/ui2018/modals';
import {buildCensoredPage, buildPageDom, PageActions} from 'app/client/ui2018/pages';
@ -175,8 +176,8 @@ const cssWarning = styled('div', `
`);
const cssTableName = styled('div', `
color: black;
background-color: #eee;
color: ${theme.choiceTokenFg};
background-color: ${theme.choiceTokenBg};
padding: 3px 6px;
border-radius: 4px;
`);

@ -263,7 +263,7 @@ const cssPinnedDocDesc = styled(cssPinnedDocTimestamp, `
const cssImage = styled('img', `
position: relative;
background-color: ${colors.light};
background-color: ${colors.dark};
height: 100%;
width: 100%;
object-fit: scale-down;

@ -311,7 +311,6 @@ export class RightPanel extends Disposable {
]),
cssLabel(t("TRANSFORM")),
dom.maybe<FieldBuilder|null>(fieldBuilder, builder => builder.buildTransformDom()),
dom.maybe(isMultiSelect, () => disabledSection()),
testId('panel-transform'),
),
this._disableIfReadonly(),

@ -15,6 +15,7 @@ export const cssLabel = styled('div', `
`);
export const cssHelp = styled('div', `
color: ${theme.lightText};
margin: -8px 16px 12px 16px;
font-style: italic;
font-size: ${vars.xsmallFontSize};

@ -376,12 +376,11 @@ const cssMenuIconLink = styled('a', `
display: block;
flex: none;
padding: 8px 24px;
--icon-color: ${theme.controlFg};
background-color: ${theme.menuBg};
--icon-color: ${theme.menuItemLinkFg};
&:hover {
background-color: ${theme.menuItemLinkselectedBg};
--icon-color: ${theme.menuItemLinkSelectedFg};
background-color: ${theme.hover};
--icon-color: ${theme.controlHoverFg};
}
`);

@ -263,7 +263,8 @@ const cssContributeButtonCloseButton = styled(tokenFieldStyles.cssDeleteButton,
const cssCard = styled('div', `
width: 297px;
padding: 24px;
background: #DCF4EB;
color: ${theme.announcementPopupFg};
background: ${theme.announcementPopupBg};
border-radius: 4px;
align-self: flex-start;
position: sticky;
@ -310,10 +311,10 @@ const cssCloseButton = styled('div', `
padding: 4px;
border-radius: 4px;
cursor: pointer;
--icon-color: ${colors.slate};
--icon-color: ${theme.popupCloseButtonFg};
&:hover {
background-color: ${colors.mediumGreyOpaque};
background-color: ${theme.hover};
}
`);

@ -13,16 +13,17 @@ import {mediaSmall, theme, vars} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {cssLink} from 'app/client/ui2018/links';
import {loadingSpinner} from 'app/client/ui2018/loaders';
import {commonUrls} from 'app/common/gristUrls';
import {commonUrls, getPageTitleSuffix} from 'app/common/gristUrls';
import {TelemetryPrefsWithSources} from 'app/common/InstallAPI';
import {getGristConfig} from 'app/common/urlUtils';
import {Computed, Disposable, dom, makeTestId, Observable, styled} from 'grainjs';
import {Computed, Disposable, dom, makeTestId, Observable, styled, subscribe} from 'grainjs';
const testId = makeTestId('test-support-grist-page-');
const t = makeT('SupportGristPage');
export class SupportGristPage extends Disposable {
private readonly _currentPage = Computed.create(this, urlState().state, (_use, s) => s.supportGrist);
private readonly _model: TelemetryModel = new TelemetryModelImpl(this._appModel);
private readonly _optInToTelemetry = Computed.create(this, this._model.prefs,
(_use, prefs) => {
@ -37,6 +38,7 @@ export class SupportGristPage extends Disposable {
constructor(private _appModel: AppModel) {
super();
this._setPageTitle();
this._model.fetchTelemetryPrefs().catch(reportError);
}
@ -186,6 +188,18 @@ export class SupportGristPage extends Disposable {
testId('sponsorship-section'),
);
}
private _setPageTitle() {
this.autoDispose(subscribe(this._currentPage, (_use, page): string => {
const suffix = getPageTitleSuffix(getGristConfig());
switch (page) {
case undefined:
case 'support-grist': {
return document.title = `Support Grist${suffix}`;
}
}
}));
}
}
function telemetryHelpCenterLink() {

@ -1,5 +1,5 @@
import {docUrl, urlState} from 'app/client/models/gristUrlState';
import {colors} from 'app/client/ui2018/cssVars';
import {theme} from 'app/client/ui2018/cssVars';
import {Document, Workspace} from 'app/common/UserAPI';
import {dom, makeTestId, styled} from 'grainjs';
import {HomeModel, ViewSettings} from 'app/client/models/HomeModel';
@ -63,7 +63,7 @@ const cssDocName = styled(css.docName, `
const cssDocRowDetails = styled('div', `
margin: 0 16px;
line-height: 1.6;
color: ${colors.slate};
color: ${theme.lightText};
`);
const cssTemplateDocs = styled('div', `

@ -2,6 +2,7 @@ import {makeT} from 'app/client/lib/localization';
import {AppModel} from 'app/client/models/AppModel';
import * as css from 'app/client/ui/AccountPageCss';
import {labeledSquareCheckbox} from 'app/client/ui2018/checkbox';
import {prefersDarkModeObs} from 'app/client/ui2018/cssVars';
import {select} from 'app/client/ui2018/menus';
import {ThemeAppearance} from 'app/common/ThemePrefs';
import {Computed, Disposable, dom, makeTestId, styled} from 'grainjs';
@ -12,21 +13,30 @@ const t = makeT('ThemeConfig');
export class ThemeConfig extends Disposable {
private _themePrefs = this._appModel.themePrefs;
private _appearance = Computed.create(this, this._themePrefs, (_use, prefs) => {
return prefs.appearance;
}).onWrite((value) => this._updateAppearance(value));
private _syncWithOS = Computed.create(this, this._themePrefs, (_use, prefs) => {
return prefs.syncWithOS;
}).onWrite((value) => this._updateSyncWithOS(value));
private _appearance = Computed.create(this,
this._themePrefs,
this._syncWithOS,
prefersDarkModeObs(),
(_use, prefs, syncWithOS, prefersDarkMode) => {
if (syncWithOS) {
return prefersDarkMode ? 'dark' : 'light';
} else {
return prefs.appearance;
}
})
.onWrite((value) => this._updateAppearance(value));
constructor(private _appModel: AppModel) {
super();
}
public buildDom() {
return dom('div',
css.subHeader(t("Appearance "), css.betaTag('Beta')),
css.subHeader(t("Appearance ")),
css.dataRow(
cssAppearanceSelect(
select(
@ -35,6 +45,9 @@ export class ThemeConfig extends Disposable {
{value: 'light', label: 'Light'},
{value: 'dark', label: 'Dark'},
],
{
disabled: this._syncWithOS,
},
),
testId('appearance'),
),

@ -263,7 +263,7 @@ const cssFilterMenuWrapper = styled('div', `
border-radius: 3px;
align-items: center;
&-unsaved {
border: 1px solid ${theme.accentBorder};
border: ${theme.controlBorder};
}
& .${cssMenu.className} {
border: none;
@ -364,11 +364,8 @@ const cssSaveTextButton = styled('div', `
cursor: pointer;
font-size: ${vars.mediumFontSize};
padding: 0px 5px;
border-right: 1px solid ${theme.accentBorder};
&-accent {
color: ${theme.accentText};
}
color: ${theme.controlFg};
border-right: ${theme.controlBorder};
`);
const cssRevertIconButton = styled('div', `

@ -1,8 +1,8 @@
import {dom, IDomArgs, Observable, styled} from 'grainjs';
// Shadow css settings for member scroll top and bottom.
const SHADOW_TOP = 'inset 0 4px 6px 0 rgba(217,217,217,0.4)';
const SHADOW_BTM = 'inset 0 -4px 6px 0 rgba(217,217,217,0.4)';
const SHADOW_TOP = 'inset 0 4px 6px 0 var(--grist-theme-scroll-shadow, rgba(217,217,217,0.4))';
const SHADOW_BTM = 'inset 0 -4px 6px 0 var(--grist-theme-scroll-shadow, rgba(217,217,217,0.4))';
/**
* Creates a scroll div used in the UserManager and moveDoc menus to display

@ -274,9 +274,11 @@ interface PickerComponentOptions {
}
class PickerComponent extends Disposable {
private _color = Computed.create(this,
this._model.obs,
(use, val) => (val || this._options.defaultColor).toUpperCase().slice(0, 7));
private _colorHex = Computed.create(this, this._model.obs, (_use, val) =>
val?.toUpperCase().slice(0, 7));
private _colorCss = Computed.create(this, this._colorHex, (_use, color) =>
color || this._options.defaultColor);
constructor(
private _model: PickerModel<string|undefined>,
@ -286,7 +288,7 @@ class PickerComponent extends Disposable {
public buildDom() {
const title = this._options.title;
const colorText = Computed.create(null, use => use(this._color) || this._options.noneText);
const colorText = Computed.create(null, use => use(this._colorHex) || this._options.noneText);
return [
cssHeaderRow(title),
cssControlRow(
@ -294,14 +296,15 @@ class PickerComponent extends Disposable {
dom.update(
cssColorSquare(
cssLightBorder.cls(''),
dom.style('background-color', this._color),
dom.style('background-color', this._colorCss),
cssNoneIcon('Empty',
dom.hide(use => Boolean(use(this._color)) === true)
dom.hide(use => Boolean(use(this._colorCss)))
),
testId(`${title}-color-square`),
),
cssColorInput(
{type: 'color'},
dom.attr('value', this._color),
dom.attr('value', use => use(this._model.obs) ?? ''),
dom.on('input', (ev, elem) => this._setValue(elem.value || undefined)),
testId(`${title}-input`),
),
@ -321,7 +324,7 @@ class PickerComponent extends Disposable {
)
),
cssEmptyBox(
cssEmptyBox.cls('-selected', (use) => !use(this._color)),
cssEmptyBox.cls('-selected', (use) => !use(this._colorCss)),
dom.on('click', () => this._setValue(undefined)),
dom.hide(!this._options.allowsNone),
cssNoneIcon('Empty'),
@ -333,7 +336,7 @@ class PickerComponent extends Disposable {
cssColorSquare(
dom.style('background-color', color),
cssLightBorder.cls('', isLight(index)),
cssColorSquare.cls('-selected', (use) => use(this._color) === color),
cssColorSquare.cls('-selected', (use) => use(this._colorHex) === color),
dom.style('outline-color', isLight(index) ? '' : color),
dom.on('click', () => this._setValue(color)),
testId(`color-${color}`),
@ -381,8 +384,6 @@ class FontComponent extends Disposable {
const cssFontOptions = styled('div', `
display: flex;
gap: 1px;
background: ${theme.colorSelectFontOptionsBorder};
border: 1px solid ${theme.colorSelectFontOptionsBorder};
`);
@ -390,10 +391,13 @@ const cssFontOption = styled('div', `
display: grid;
place-items: center;
flex-grow: 1;
background: ${theme.colorSelectFontOptionBg};
--icon-color: ${theme.colorSelectFontOptionFg};
height: 24px;
cursor: pointer;
&:not(:last-child) {
border-right: 1px solid ${theme.colorSelectFontOptionsBorder};
}
&:hover:not(&-selected) {
background: ${theme.colorSelectFontOptionBgHover};
}

@ -146,6 +146,11 @@ export const cssButtonSelect = styled('div', `
/* Vars */
color: ${theme.text};
flex: 1 1 0;
&-disabled {
opacity: 0.4;
pointer-events: none;
}
`);
const cssSelectorBtn = styled('div', `
@ -187,6 +192,7 @@ const cssSelectorBtn = styled('div', `
}
&:hover:not(&-selected) {
background-color: ${theme.buttonGroupBgHover};
border: 1px solid ${theme.buttonGroupBorderHover};
z-index: 5; /* Update z-index so selected borders take precedent */
}
@ -218,14 +224,6 @@ const cssSelectorBtn = styled('div', `
border: none;
background-color: ${theme.hover};
}
.${cssButtonSelect.className}-disabled > &,
.${cssButtonSelect.className}-disabled > &:hover {
--icon-color: ${theme.rightPanelToggleButtonDisabledFg};
color: ${theme.rightPanelToggleButtonDisabledFg};
background-color: ${theme.rightPanelToggleButtonDisabledBg};
border-color: ${theme.buttonGroupBorder};
pointer-events: none;
}
`);
const cssSelectorLabel = styled('span', `

@ -109,7 +109,8 @@ export const textButton = styled(cssButton, `
text-align: left;
background-color: inherit !important;
&:disabled {
color: ${theme.controlPrimaryDisabled};
color: ${theme.controlPrimaryBg};
opacity: 0.4;
}
`);

@ -199,7 +199,7 @@ export const cssRadioCheckboxOptions = styled('div', `
const cssBlockCheckbox = styled('div', `
display: flex;
padding: 10px 8px;
border: 1px solid ${theme.modalBorder};
border: 1px solid ${theme.controlSecondaryDisabledFg};
border-radius: 3px;
cursor: pointer;
& input::before, & input::after {
@ -207,7 +207,7 @@ const cssBlockCheckbox = styled('div', `
left: unset;
}
&:hover {
border-color: ${theme.accentBorder};
border-color: ${theme.controlFg};
}
&-block {
pointer-events: none;

@ -245,8 +245,6 @@ export const theme = {
'black'),
tooltipCloseButtonHoverBg: new CustomProp('theme-tooltip-close-button-hover-bg', undefined,
'white'),
tooltipPopupHeaderFg: new CustomProp('theme-tooltip-popup-header-fg', undefined, colors.light),
tooltipPopupHeaderBg: new CustomProp('theme-tooltip-popup-header-bg', undefined, colors.lightGreen),
/* Modals */
modalBg: new CustomProp('theme-modal-bg', undefined, 'white'),
@ -290,6 +288,7 @@ export const theme = {
/* Cell Editor */
cellEditorFg: new CustomProp('theme-cell-editor-fg', undefined, colors.dark),
cellEditorPlaceholderFg: new CustomProp('theme-cell-editor-placeholder-fg', undefined, colors.slate),
cellEditorBg: new CustomProp('theme-cell-editor-bg', undefined, colors.light),
/* Cursor */
@ -298,14 +297,12 @@ export const theme = {
cursorReadonly: new CustomProp('theme-cursor-readonly', undefined, colors.slate),
/* Tables */
tableHeaderFg: new CustomProp('theme-table-header-fg', undefined, 'unset'),
tableHeaderSelectedFg: new CustomProp('theme-table-header-selected-fg', undefined, 'unset'),
tableHeaderFg: new CustomProp('theme-table-header-fg', undefined, '#000'),
tableHeaderSelectedFg: new CustomProp('theme-table-header-selected-fg', undefined, '#000'),
tableHeaderBg: new CustomProp('theme-table-header-bg', undefined, colors.lightGrey),
tableHeaderSelectedBg: new CustomProp('theme-table-header-selected-bg', undefined,
colors.mediumGreyOpaque),
tableHeaderBorder: new CustomProp('theme-table-header-border', undefined, 'lightgray'),
tableHeaderBorderDark: new CustomProp('theme-table-header-border-dark', undefined,
colors.darkGrey),
tableBodyBg: new CustomProp('theme-table-body-bg', undefined, 'white'),
tableBodyBorder: new CustomProp('theme-table-body-border', undefined, colors.darkGrey),
tableAddNewBg: new CustomProp('theme-table-add-new-bg', undefined, 'inherit'),
@ -314,6 +311,7 @@ export const theme = {
'#999999'),
tableDragDropIndicator: new CustomProp('theme-table-drag-drop-indicator', undefined, 'gray'),
tableDragDropShadow: new CustomProp('theme-table-drag-drop-shadow', undefined, '#F0F0F0'),
tableCellSummaryBg: new CustomProp('theme-table-cell-summary-bg', undefined, colors.mediumGrey),
/* Cards */
cardCompactWidgetBg: new CustomProp('theme-card-compact-widget-bg', undefined,
@ -339,7 +337,7 @@ export const theme = {
selection: new CustomProp('theme-selection', undefined, colors.selection),
selectionDarker: new CustomProp('theme-selection-darker', undefined, 'rgba(22,179,120,0.25)'),
selectionDarkest: new CustomProp('theme-selection-darkest', undefined, 'rgba(22,179,120,0.35)'),
selectionOpaqueFg: new CustomProp('theme-selection-opaque-fg', undefined, 'unset'),
selectionOpaqueFg: new CustomProp('theme-selection-opaque-fg', undefined, 'black'),
selectionOpaqueBg: new CustomProp('theme-selection-opaque-bg', undefined,
colors.selectionOpaque),
selectionOpaqueDarkBg: new CustomProp('theme-selection-opaque-dark-bg', undefined,
@ -371,6 +369,8 @@ export const theme = {
controlPrimaryFg: new CustomProp('theme-control-primary-fg', undefined, vars.primaryFg),
controlPrimaryBg: new CustomProp('theme-control-primary-bg', undefined, vars.primaryBg),
controlSecondaryFg: new CustomProp('theme-control-secondary-fg', undefined, colors.slate),
controlSecondaryDisabledFg: new CustomProp('theme-control-secondary-disabled-fg',
undefined, colors.darkGrey),
controlHoverFg: new CustomProp('theme-control-hover-fg', undefined, vars.controlFgHover),
controlPrimaryHoverBg: new CustomProp('theme-control-primary-hover-bg', undefined,
vars.primaryBgHover),
@ -380,8 +380,6 @@ export const theme = {
colors.darkGrey),
controlDisabledFg: new CustomProp('theme-control-disabled-fg', undefined, colors.light),
controlDisabledBg: new CustomProp('theme-control-disabled-bg', undefined, colors.slate),
controlPrimaryDisabled: new CustomProp('theme-control-primary-disabled', undefined,
colors.inactiveCursor),
controlBorder: new CustomProp('theme-control-border', undefined, vars.controlBorder),
/* Checkboxes */
@ -464,8 +462,6 @@ export const theme = {
undefined, colors.light),
rightPanelToggleButtonEnabledBg: new CustomProp('theme-right-panel-toggle-button-enabled-bg',
undefined, colors.dark),
rightPanelToggleButtonEnabledHoverFg: new CustomProp(
'theme-right-panel-toggle-button-enabled-hover-fg', undefined, colors.darkGrey),
rightPanelToggleButtonDisabledFg: new CustomProp('theme-right-panel-toggle-button-disabled-fg',
undefined, colors.light),
rightPanelToggleButtonDisabledBg: new CustomProp('theme-right-panel-toggle-button-disabled-bg',
@ -487,9 +483,15 @@ export const theme = {
documentHistorySnapshotBorder: new CustomProp('theme-document-history-snapshot-border',
undefined, colors.mediumGrey),
documentHistoryActivityText: new CustomProp('theme-document-history-activity-text', undefined,
'unset'),
colors.dark),
documentHistoryActivityLightText: new CustomProp('theme-document-history-activity-text-light',
undefined, '#333333'),
documentHistoryTableHeaderFg: new CustomProp('theme-document-history-table-header-fg',
undefined, '#000'),
documentHistoryTableBorder: new CustomProp('theme-document-history-table-border',
undefined, 'lightgray'),
documentHistoryTableBorderLight: new CustomProp('theme-document-history-table-border-light',
undefined, '#D9D9D9'),
/* Accents */
accentIcon: new CustomProp('theme-accent-icon', undefined, colors.lightGreen),
@ -509,6 +511,16 @@ export const theme = {
inputReadonlyBg: new CustomProp('theme-input-readonly-bg', undefined, colors.lightGrey),
inputReadonlyBorder: new CustomProp('theme-input-readonly-border', undefined, colors.mediumGreyOpaque),
/* Choice Tokens */
choiceTokenFg: new CustomProp('theme-choice-token-fg', undefined, '#000000'),
choiceTokenBlankFg: new CustomProp('theme-choice-token-blank-fg', undefined, colors.slate),
choiceTokenBg: new CustomProp('theme-choice-token-bg', undefined, colors.mediumGreyOpaque),
choiceTokenSelectedBg: new CustomProp('theme-choice-token-selected-bg', undefined, colors.darkGrey),
choiceTokenSelectedBorder: new CustomProp('theme-choice-token-selected-border', undefined, colors.lightGreen),
choiceTokenInvalidFg: new CustomProp('theme-choice-token-invalid-fg', undefined, '#000000'),
choiceTokenInvalidBg: new CustomProp('theme-choice-token-invalid-bg', undefined, 'white'),
choiceTokenInvalidBorder: new CustomProp('theme-choice-token-invalid-border', undefined, colors.error),
/* Choice Entry */
choiceEntryBg: new CustomProp('theme-choice-entry-bg', undefined, 'white'),
choiceEntryBorder: new CustomProp('theme-choice-entry-border', undefined, colors.darkGrey),
@ -519,7 +531,6 @@ export const theme = {
selectButtonFg: new CustomProp('theme-select-button-fg', undefined, colors.dark),
selectButtonPlaceholderFg: new CustomProp('theme-select-button-placeholder-fg', undefined,
colors.slate),
selectButtonDisabledFg: new CustomProp('theme-select-button-disabled-fg', undefined, 'grey'),
selectButtonBg: new CustomProp('theme-select-button-bg', undefined, 'white'),
selectButtonBorder: new CustomProp('theme-select-button-border', undefined, colors.darkGrey),
selectButtonBorderInvalid: new CustomProp('theme-select-button-border-invalid', undefined,
@ -529,7 +540,7 @@ export const theme = {
menuText: new CustomProp('theme-menu-text', undefined, colors.slate),
menuLightText: new CustomProp('theme-menu-light-text', undefined, colors.slate),
menuBg: new CustomProp('theme-menu-bg', undefined, 'white'),
menuSubheaderFg: new CustomProp('theme-menu-subheader-fg', undefined, 'unset'),
menuSubheaderFg: new CustomProp('theme-menu-subheader-fg', undefined, colors.dark),
menuBorder: new CustomProp('theme-menu-border', undefined, colors.mediumGreyOpaque),
menuShadow: new CustomProp('theme-menu-shadow', undefined, 'rgba(38, 38, 51, 0.6)'),
@ -540,19 +551,20 @@ export const theme = {
menuItemDisabledFg: new CustomProp('theme-menu-item-disabled-fg', undefined, '#D9D9D9'),
menuItemIconFg: new CustomProp('theme-menu-item-icon-fg', undefined, colors.slate),
menuItemIconSelectedFg: new CustomProp('theme-menu-item-icon-selected-fg', undefined, 'white'),
menuItemLinkFg: new CustomProp('theme-menu-item-link-fg', undefined, colors.lightGreen),
menuItemLinkSelectedFg: new CustomProp('theme-menu-item-link-selected-fg', undefined,
colors.darkGreen),
menuItemLinkselectedBg: new CustomProp('theme-menu-item-link-selected-bg', undefined,
colors.mediumGreyOpaque),
/* Autocomplete */
autocompleteMatchText: new CustomProp('theme-autocomplete-match-text', undefined,
colors.lightGreen),
autocompleteSelectedMatchText: new CustomProp('theme-autocomplete-selected-match-text',
undefined, colors.lighterGreen),
autocompleteChoiceSelectedBg: new CustomProp('theme-autocomplete-item-selected-bg', undefined,
autocompleteItemSelectedBg: new CustomProp('theme-autocomplete-item-selected-bg', undefined,
colors.mediumGreyOpaque),
autocompleteAddNewCircleFg: new CustomProp('theme-autocomplete-add-new-circle-fg', undefined,
colors.light),
autocompleteAddNewCircleBg: new CustomProp('theme-autocomplete-add-new-circle-bg', undefined,
colors.lightGreen),
autocompleteAddNewCircleSelectedBg: new CustomProp(
'theme-autocomplete-add-new-circle-selected-bg', undefined, colors.darkGreen),
/* Search */
searchBorder: new CustomProp('theme-search-border', undefined, 'grey'),
@ -594,7 +606,7 @@ export const theme = {
widgetPickerPrimaryBg: new CustomProp('theme-widget-picker-primary-bg', undefined, 'white'),
widgetPickerSecondaryBg: new CustomProp('theme-widget-picker-secondary-bg', undefined,
colors.lightGrey),
widgetPickerItemFg: new CustomProp('theme-widget-picker-item-fg', undefined, 'unset'),
widgetPickerItemFg: new CustomProp('theme-widget-picker-item-fg', undefined, colors.dark),
widgetPickerItemSelectedBg: new CustomProp('theme-widget-picker-item-selected-bg', undefined,
colors.mediumGrey),
widgetPickerItemDisabledBg: new CustomProp('theme-widget-picker-item-disabled-bg', undefined,
@ -651,7 +663,9 @@ export const theme = {
/* Button Groups */
buttonGroupFg: new CustomProp('theme-button-group-fg', undefined, colors.dark),
buttonGroupLightFg: new CustomProp('theme-button-group-light-fg', undefined, colors.slate),
buttonGroupBg: new CustomProp('theme-button-group-bg', undefined, 'unset'),
buttonGroupBg: new CustomProp('theme-button-group-bg', undefined, 'transparent'),
buttonGroupBgHover: new CustomProp('theme-button-group-bg-hover', undefined,
colors.hover),
buttonGroupIcon: new CustomProp('theme-button-group-icon', undefined, colors.slate),
buttonGroupBorder: new CustomProp('theme-button-group-border', undefined, colors.darkGrey),
buttonGroupBorderHover: new CustomProp('theme-button-group-border-hover', undefined,
@ -670,6 +684,8 @@ export const theme = {
colors.mediumGrey),
accessRulesTableBodyFg: new CustomProp('theme-access-rules-table-body-fg', undefined,
colors.dark),
accessRulesTableBodyLightFg: new CustomProp('theme-access-rules-table-body-light-fg', undefined,
colors.darkGrey),
accessRulesTableBorder: new CustomProp('theme-access-rules-table-border', undefined,
colors.slate),
accessRulesColumnListBorder: new CustomProp('theme-access-rules-column-list-border', undefined,
@ -694,7 +710,7 @@ export const theme = {
undefined, colors.cursor),
/* Cells */
cellFg: new CustomProp('theme-cell-fg', undefined, 'unset'),
cellFg: new CustomProp('theme-cell-fg', undefined, 'black'),
cellBg: new CustomProp('theme-cell-bg', undefined, '#FFFFFF00'),
cellZebraBg: new CustomProp('theme-cell-zebra-bg', undefined, '#F8F8F8'),
@ -772,13 +788,11 @@ export const theme = {
undefined, colors.darkGrey),
colorSelectFontOptionFg: new CustomProp('theme-color-select-font-option-fg',
undefined, colors.dark),
colorSelectFontOptionBg: new CustomProp('theme-color-select-font-option-bg',
undefined, colors.light),
colorSelectFontOptionBgHover: new CustomProp('theme-color-select-font-option-bg-hover',
undefined, colors.lightGrey),
colorSelectFontOptionFgSelected: new CustomProp('theme-color-select-font-option-selected-fg',
colorSelectFontOptionFgSelected: new CustomProp('theme-color-select-font-option-fg-selected',
undefined, colors.light),
colorSelectFontOptionBgSelected: new CustomProp('theme-color-select-font-option-selected-bg',
colorSelectFontOptionBgSelected: new CustomProp('theme-color-select-font-option-bg-selected',
undefined, colors.dark),
colorSelectColorSquareBorder: new CustomProp('theme-color-select-color-square-border',
undefined, '#D9D9D9'),
@ -807,6 +821,14 @@ export const theme = {
loginPageBg: new CustomProp('theme-login-page-bg', undefined, 'white'),
loginPageBackdrop: new CustomProp('theme-login-page-backdrop', undefined, '#F5F8FA'),
loginPageLine: new CustomProp('theme-login-page-line', undefined, colors.lightGrey),
loginPageGoogleButtonFg: new CustomProp('theme-login-page-google-button-fg', undefined,
colors.dark),
loginPageGoogleButtonBg: new CustomProp('theme-login-page-google-button-bg', undefined,
colors.lightGrey),
loginPageGoogleButtonBgHover: new CustomProp('theme-login-page-google-button-bg-hover',
undefined, colors.mediumGrey),
loginPageGoogleButtonBorder: new CustomProp('theme-login-page-google-button-border', undefined,
colors.darkGrey),
/* Formula Assistant */
formulaAssistantHeaderBg: new CustomProp(
@ -815,6 +837,42 @@ export const theme = {
'theme-formula-assistant-border', undefined, colors.darkGrey),
formulaAssistantPreformattedTextBg: new CustomProp(
'theme-formula-assistant-preformatted-text-bg', undefined, colors.lightGrey),
/* Attachments */
attachmentsEditorButtonFg: new CustomProp(
'theme-attachments-editor-button-fg', undefined, colors.darkGreen),
attachmentsEditorButtonHoverFg: new CustomProp(
'theme-attachments-editor-button-hover-fg', undefined, colors.lightGreen),
attachmentsEditorButtonBg: new CustomProp(
'theme-attachments-editor-button-bg', undefined, colors.light),
attachmentsEditorButtonHoverBg: new CustomProp(
'theme-attachments-editor-button-hover-bg', undefined, colors.mediumGreyOpaque),
attachmentsEditorButtonBorder: new CustomProp(
'theme-attachments-editor-button-border', undefined, colors.darkGrey),
attachmentsEditorButtonIcon: new CustomProp(
'theme-attachments-editor-button-icon', undefined, colors.slate),
attachmentsEditorBorder: new CustomProp(
'theme-attachments-editor-border', undefined, colors.mediumGreyOpaque),
attachmentsCellIconFg: new CustomProp(
'theme-attachments-cell-icon-fg', undefined, 'white'),
attachmentsCellIconBg: new CustomProp(
'theme-attachments-cell-icon-bg', undefined, '#D9D9D9'),
attachmentsCellIconHoverBg: new CustomProp(
'theme-attachments-cell-icon-hover-bg', undefined, '#929299'),
/* Announcement Popups */
announcementPopupFg: new CustomProp('theme-announcement-popup-fg', undefined, '#000000'),
announcementPopupBg: new CustomProp('theme-announcement-popup-bg', undefined, '#DCF4EB'),
/* Switches */
switchSliderFg: new CustomProp('theme-switch-slider-fg', undefined, '#ccc'),
switchCircleFg: new CustomProp('theme-switch-circle-fg', undefined, 'white'),
/* Toggle Checkboxes */
toggleCheckboxFg: new CustomProp('theme-toggle-checkbox-fg', undefined, '#606060'),
/* Numeric Spinners */
numericSpinnerFg: new CustomProp('theme-numeric-spinner-fg', undefined, '#606060'),
};
const cssColors = values(colors).map(v => v.decl()).join('\n');
@ -1038,7 +1096,7 @@ function getCssThemeBackgroundProperties(appearance: ThemeAppearance) {
* pollute the document with in-line styles.
*/
function getOrCreateStyleElement(id: string) {
let style = document.head.querySelector(id);
let style = document.head.querySelector(`#${id}`);
if (style) { return style; }
style = document.createElement('style');
style.setAttribute('id', id);

@ -1,6 +1,6 @@
import {findLinks} from 'app/client/lib/textUtils';
import { sameDocumentUrlState, urlState } from 'app/client/models/gristUrlState';
import { colors, hideInPrintView, testId, theme } from 'app/client/ui2018/cssVars';
import { hideInPrintView, testId, theme } from 'app/client/ui2018/cssVars';
import {cssIconBackground, icon} from 'app/client/ui2018/icons';
import { CellValue } from 'app/plugin/GristData';
import { dom, DomArg, IDomArgs, Observable, styled } from 'grainjs';
@ -95,7 +95,7 @@ const cssMaybeWrap = styled('span', `
// A gentle transition effect on hover in, and the same effect on hover out with a little delay.
export const cssHoverIn = (parentClass: string) => styled('span', `
--icon-color: var(--grist-actual-cell-color, ${colors.lightGreen});
--icon-color: var(--grist-actual-cell-color, ${theme.link});
margin: -1px 2px 2px 0;
border-radius: 3px;
transition-property: background-color;
@ -103,7 +103,7 @@ export const cssHoverIn = (parentClass: string) => styled('span', `
transition-duration: 150ms;
transition-delay: 90ms;
.${parentClass}:hover & {
--icon-background: ${colors.lightGreen};
--icon-background: ${theme.link};
--icon-color: white;
transition-duration: 80ms;
transition-delay: 0ms;
@ -113,5 +113,5 @@ export const cssHoverIn = (parentClass: string) => styled('span', `
const cssHoverInText = cssHoverIn(cssMaybeWrap.className);
const linkColor = styled('span', `
color: var(--grist-actual-cell-color, ${colors.lightGreen});;
color: var(--grist-actual-cell-color, ${theme.link});
`);

@ -178,7 +178,7 @@ const cssPageInitial = styled('div', `
&-emoji {
background-color: ${theme.pageInitialsEmojiBg};
box-shadow: 0 0 0 1px var(--grist-theme-left-panel-page-emoji-outline, var(--grist-color-dark-grey));
box-shadow: 0 0 0 1px ${theme.pageInitialsEmojiOutline};
font-size: 15px;
overflow: hidden;
color: ${theme.text};

@ -42,8 +42,8 @@ export const cssSelectBtn = styled('div', `
}
&.disabled, &-disabled {
--icon-color: ${theme.selectButtonDisabledFg};
color: ${theme.selectButtonDisabledFg};
cursor: pointer;
opacity: 0.4;
pointer-events: none;
cursor: default;
}
`);

@ -1,20 +1,20 @@
var dispose = require('../lib/dispose');
const {theme} = require('app/client/ui2018/cssVars');
const {CellStyle} = require('app/client/widgets/CellStyle');
const {dom} = require('grainjs');
/**
* AbstractWidget - The base of the inheritance tree for widgets.
* @param {Function} field - The RowModel for this view field.
* @param {string|undefined} options.defaultTextColor - A hex value to set the default text color
* for the widget. Omit defaults to '#000000'.
* @param {string|undefined} options.defaultTextColor - CSS value of the default
* text color for the widget. Defaults to the current theme's cell fg color.
*
*/
function AbstractWidget(field, opts = {}) {
this.field = field;
this.options = field.widgetOptionsJson;
const {defaultTextColor = '#000000'} = opts;
this.defaultTextColor = defaultTextColor;
this.valueFormatter = this.field.visibleColFormatter;
this.defaultTextColor = opts.defaultTextColor || '#000000';
this.defaultTextColor = opts.defaultTextColor ?? theme.cellFg.toString();
}
dispose.makeDisposable(AbstractWidget);

@ -9,7 +9,7 @@ import {selectFiles, uploadFiles} from 'app/client/lib/uploads';
import {DocData} from 'app/client/models/DocData';
import {MetaTableData} from 'app/client/models/TableData';
import {basicButton, basicButtonLink, cssButtonGroup} from 'app/client/ui2018/buttons';
import {colors, testId, vars} from 'app/client/ui2018/cssVars';
import {testId, theme, vars} from 'app/client/ui2018/cssVars';
import {editableLabel} from 'app/client/ui2018/editableLabel';
import {icon} from 'app/client/ui2018/icons';
import {IModalControl, modal} from 'app/client/ui2018/modals';
@ -315,12 +315,12 @@ const cssCloseButton = styled('div', `
padding: 6px;
border-radius: 32px;
cursor: pointer;
background-color: ${colors.light};
--icon-color: ${colors.lightGreen};
background-color: ${theme.attachmentsEditorButtonBg};
--icon-color: ${theme.attachmentsEditorButtonFg};
&:hover {
background-color: ${colors.mediumGreyOpaque};
--icon-color: ${colors.darkGreen};
background-color: ${theme.attachmentsEditorButtonHoverBg};
--icon-color: ${theme.attachmentsEditorButtonHoverFg};
}
`);
@ -336,10 +336,10 @@ const cssTitle = styled('div', `
overflow: hidden;
&:hover {
outline: 1px solid ${colors.slate};
outline: 1px solid ${theme.lightText};
}
&:focus-within {
outline: 1px solid ${colors.darkGreen};
outline: 1px solid ${theme.controlFg};
}
`);
@ -362,13 +362,14 @@ const cssFileButtons = styled(cssButtonGroup, `
`);
const cssButton = styled(basicButton, `
background-color: ${colors.light};
color: ${theme.attachmentsEditorButtonFg};
background-color: ${theme.attachmentsEditorButtonBg};
font-weight: normal;
padding: 0 16px;
border-top: none;
border-right: none;
border-bottom: none;
border-left: 1px solid ${colors.darkGrey};
border-left: 1px solid ${theme.attachmentsEditorButtonBorder};
display: flex;
align-items: center;
@ -376,13 +377,14 @@ const cssButton = styled(basicButton, `
border: none;
}
&:hover {
background-color: ${colors.mediumGreyOpaque};
border-color: ${colors.darkGrey};
color: ${theme.attachmentsEditorButtonHoverFg};
background-color: ${theme.attachmentsEditorButtonHoverBg};
border-color: ${theme.attachmentsEditorButtonBorder};
}
`);
const cssButtonIcon = styled(icon, `
--icon-color: ${colors.slate};
--icon-color: ${theme.attachmentsEditorButtonIcon};
margin-right: 4px;
`);
@ -397,11 +399,11 @@ const cssNextArrow = styled('div', `
padding: 6px;
border-radius: 32px;
cursor: pointer;
background-color: ${colors.lightGreen};
--icon-color: ${colors.light};
background-color: ${theme.controlPrimaryBg};
--icon-color: ${theme.controlPrimaryFg};
&:hover {
background-color: ${colors.darkGreen};
background-color: ${theme.controlPrimaryHoverBg};
}
&-left {
transform: rotateY(180deg);
@ -453,7 +455,7 @@ const cssDetails = styled('div', `
`);
const cssDragArea = styled(cssContent, `
border: 2px dashed ${colors.mediumGreyOpaque};
border: 2px dashed ${theme.attachmentsEditorBorder};
height: calc(100% - 96px);
margin-top: 64px;
padding: 0px;

@ -3,7 +3,7 @@ import * as commands from 'app/client/components/commands';
import {dragOverClass} from 'app/client/lib/dom';
import {selectFiles, uploadFiles} from 'app/client/lib/uploads';
import {cssRow} from 'app/client/ui/RightPanelStyles';
import {colors, testId, vars} from 'app/client/ui2018/cssVars';
import {colors, testId, theme, vars} from 'app/client/ui2018/cssVars';
import {NewAbstractWidget} from 'app/client/widgets/NewAbstractWidget';
import {encodeQueryParams} from 'app/common/gutil';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
@ -191,16 +191,16 @@ const cssAttachmentIcon = styled('div.glyphicon.glyphicon-paperclip', `
top: 2px;
left: 2px;
padding: 2px;
background-color: #D0D0D0;
color: white;
background-color: ${theme.attachmentsCellIconBg};
color: ${theme.attachmentsCellIconFg};
border-radius: 2px;
border: none;
cursor: pointer;
box-shadow: 0 0 0 1px white;
box-shadow: 0 0 0 1px ${theme.cellEditorBg};
z-index: 1;
&:hover {
background-color: #3290BF;
background-color: ${theme.attachmentsCellIconHoverBg};
}
&-hover {
@ -222,12 +222,12 @@ const cssAttachmentPreview = styled('div', `
justify-content: center;
z-index: 0;
&:hover {
border-color: ${colors.lightGreen};
border-color: ${theme.cursor};
}
`);
const cssSizeLabel = styled('div', `
color: ${colors.slate};
color: ${theme.lightText};
margin-right: 9px;
`);

@ -15,7 +15,7 @@ export class CellStyle extends Disposable {
constructor(
private _field: ViewFieldRec,
private _gristDoc: GristDoc,
private _defaultTextColor: string
private _defaultTextColor: string|undefined
) {
super();
}
@ -51,21 +51,26 @@ export class CellStyle extends Disposable {
});
return colorSelect(
{
textColor: new ColorOption(
{ color: headerTextColor, defaultColor: this._defaultTextColor, noneText: 'default' }
),
fillColor: new ColorOption(
{ color: headerFillColor, allowsNone: true, noneText: 'none' }
),
textColor: new ColorOption({
color: headerTextColor,
defaultColor: theme.tableHeaderFg.toString(),
noneText: 'default',
}),
fillColor: new ColorOption({
color: headerFillColor,
allowsNone: true,
noneText: 'none',
}),
fontBold: headerFontBold,
fontItalic: headerFontItalic,
fontUnderline: headerFontUnderline,
fontStrikethrough: headerFontStrikethrough
}, {
onSave: () => options.save(),
onRevert: () => options.revert(),
placeholder: use => use(hasMixedStyle) ? t('Mixed style') : t('Default header style')
}
},
{
onSave: () => options.save(),
onRevert: () => options.revert(),
placeholder: use => use(hasMixedStyle) ? t('Mixed style') : t('Default header style')
}
);
}),
)];
@ -97,12 +102,16 @@ export class CellStyle extends Disposable {
});
return colorSelect(
{
textColor: new ColorOption(
{ color: textColor, defaultColor: this._defaultTextColor, noneText: 'default'}
),
fillColor: new ColorOption(
{ color: fillColor, allowsNone: true, noneText: 'none'}
),
textColor: new ColorOption({
color: textColor,
defaultColor: this._defaultTextColor,
noneText: 'default',
}),
fillColor: new ColorOption({
color: fillColor,
allowsNone: true,
noneText: 'none',
}),
fontBold: fontBold,
fontItalic: fontItalic,
fontUnderline: fontUnderline,

@ -42,8 +42,8 @@
position: relative;
width: 3px;
height: 12px;
background-color: var(--grist-actual-cell-color, #606060);
border: 1px solid var(--grist-actual-cell-color, #606060);
background-color: var(--grist-actual-cell-color, var(--grist-theme-toggle-checkbox-fg, #606060));
border: 1px solid var(--grist-actual-cell-color, var(--grist-theme-toggle-checkbox-fg, #606060));
left: 3px;
top: -5px;
}
@ -52,7 +52,7 @@
position: relative;
width: 3px;
height: 3px;
background-color: var(--grist-actual-cell-color, #606060);
border: 1px solid var(--grist-actual-cell-color, #606060);
background-color: var(--grist-actual-cell-color, var(--grist-theme-toggle-checkbox-fg, #606060));
border: 1px solid var(--grist-actual-cell-color, var(--grist-theme-toggle-checkbox-fg, #606060));
top: 7px;
}

@ -7,7 +7,7 @@ const {ACIndexImpl, buildHighlightedDom} = require('app/client/lib/ACIndex');
const {ChoiceItem, cssChoiceList, cssMatchText, cssPlusButton,
cssPlusIcon} = require('app/client/widgets/ChoiceListEditor');
const {menuCssClass} = require('app/client/ui2018/menus');
const {testId, colors} = require('app/client/ui2018/cssVars');
const {testId, theme} = require('app/client/ui2018/cssVars');
const {choiceToken, cssChoiceACItem} = require('app/client/widgets/ChoiceToken');
const {dom, styled} = require('grainjs');
const {icon} = require('../ui2018/icons');
@ -34,7 +34,13 @@ _.extend(ChoiceEditor.prototype, TextEditor.prototype);
ChoiceEditor.prototype.getCellValue = function() {
const selectedItem = this.autocomplete && this.autocomplete.getSelectedItem();
return selectedItem ? selectedItem.label : TextEditor.prototype.getCellValue.call(this);
if (selectedItem) {
return selectedItem.label;
} else if (this.textInput.value.trim() === '') {
return null;
} else {
return TextEditor.prototype.getCellValue.call(this);
}
}
ChoiceEditor.prototype.renderACItem = function(item, highlightFunc) {
@ -60,7 +66,7 @@ ChoiceEditor.prototype.attach = function(cellElem) {
// Don't create autocomplete if readonly.
if (this.options.readonly) { return; }
const acItems = this.choices.map(c => new ChoiceItem(c, false));
const acItems = this.choices.map(c => new ChoiceItem(c, false, false));
const acIndex = new ACIndexImpl(acItems);
const acOptions = {
popperOptions: {
@ -100,7 +106,7 @@ ChoiceEditor.prototype.maybeShowAddNew = function(result, text) {
const trimmedText = text.trim();
if (!this.enableAddNew || !trimmedText) { return result; }
const addNewItem = new ChoiceItem(trimmedText, false, true);
const addNewItem = new ChoiceItem(trimmedText, false, false, true);
if (result.items.find((item) => item.cleanText === addNewItem.cleanText)) {
return result;
}
@ -112,7 +118,7 @@ ChoiceEditor.prototype.maybeShowAddNew = function(result, text) {
}
const cssChoiceEditIcon = styled(icon, `
background-color: ${colors.slate};
background-color: ${theme.lightText};
position: absolute;
top: 0;
left: 0;

@ -33,17 +33,19 @@ export class ChoiceListCell extends ChoiceTextBox {
if (!val) { return null; }
// Handle any unexpected values we might get (non-array, or array with non-strings).
const tokens: unknown[] = Array.isArray(val) ? val : [val];
return tokens.map(token =>
choiceToken(
String(token),
return tokens.map(token => {
const isBlank = String(token).trim() === '';
return choiceToken(
isBlank ? '[Blank]' : String(token),
{
...(choiceOptionsByName.get(String(token)) || {}),
invalid: !choiceSet.has(String(token)),
blank: String(token).trim() === '',
},
dom.cls(cssToken.className),
testId('choice-list-cell-token')
)
);
);
});
}),
);
}

@ -21,6 +21,7 @@ export class ChoiceItem implements ACItem, IToken {
constructor(
public label: string,
public isInvalid: boolean, // If set, this token is not one of the valid choices.
public isBlank: boolean, // If set, this token is blank.
public isNew?: boolean, // If set, this is a choice to be added to the config.
) {}
}
@ -50,7 +51,7 @@ export class ChoiceListEditor extends NewBaseEditor {
const choices: string[] = options.field.widgetOptionsJson.peek().choices || [];
this._choiceOptionsByName = options.field.widgetOptionsJson
.peek().choiceOptions || {};
const acItems = choices.map(c => new ChoiceItem(c, false));
const acItems = choices.map(c => new ChoiceItem(c, false, false));
const choiceSet = new Set(choices);
const acIndex = new ACIndexImpl<ChoiceItem>(acItems);
@ -67,21 +68,26 @@ export class ChoiceListEditor extends NewBaseEditor {
// If starting to edit by typing in a string, ignore previous tokens.
const cellValue = decodeObject(options.cellValue);
const startLabels: unknown[] = options.editValue !== undefined || !Array.isArray(cellValue) ? [] : cellValue;
const startTokens = startLabels.map(label => new ChoiceItem(String(label), !choiceSet.has(String(label))));
const startTokens = startLabels.map(label => new ChoiceItem(
String(label),
!choiceSet.has(String(label)),
String(label).trim() === ''
));
this._tokenField = TokenField.ctor<ChoiceItem>().create(this, {
initialValue: startTokens,
renderToken: item => [
item.label,
item.isBlank ? '[Blank]' : item.label,
dom.style('background-color', getRenderFillColor(this._choiceOptionsByName[item.label])),
dom.style('color', getRenderTextColor(this._choiceOptionsByName[item.label])),
dom.cls('font-bold', this._choiceOptionsByName[item.label]?.fontBold ?? false),
dom.cls('font-underline', this._choiceOptionsByName[item.label]?.fontUnderline ?? false),
dom.cls('font-italic', this._choiceOptionsByName[item.label]?.fontItalic ?? false),
dom.cls('font-strikethrough', this._choiceOptionsByName[item.label]?.fontStrikethrough ?? false),
cssChoiceToken.cls('-invalid', item.isInvalid)
cssChoiceToken.cls('-invalid', item.isInvalid),
cssChoiceToken.cls('-blank', item.isBlank),
],
createToken: label => new ChoiceItem(label, !choiceSet.has(label)),
createToken: label => new ChoiceItem(label, !choiceSet.has(label), label.trim() === ''),
acOptions,
openAutocompleteOnFocus: true,
readonly : options.readonly,
@ -222,7 +228,7 @@ export class ChoiceListEditor extends NewBaseEditor {
const trimmedText = text.trim();
if (!this._enableAddNew || !trimmedText) { return result; }
const addNewItem = new ChoiceItem(trimmedText, false, true);
const addNewItem = new ChoiceItem(trimmedText, false, false, true);
if (result.items.find((item) => item.cleanText === addNewItem.cleanText)) {
return result;
}
@ -277,7 +283,7 @@ export const cssToken = styled(tokenFieldStyles.cssToken, `
white-space: pre;
&.selected {
box-shadow: inset 0 0 0 1px ${colors.lightGreen};
box-shadow: inset 0 0 0 1px ${theme.choiceTokenSelectedBorder};
}
`);
@ -341,7 +347,7 @@ export const cssChoiceList = styled('div', `
const cssReadonlyStyle = styled('div', `
padding-left: 16px;
background: white;
background: ${theme.cellEditorBg};
`);
export const cssMatchText = styled('span', `
@ -349,20 +355,21 @@ export const cssMatchText = styled('span', `
`);
export const cssPlusButton = styled('div', `
display: inline-block;
display: flex;
width: 20px;
height: 20px;
border-radius: 20px;
margin-right: 8px;
text-align: center;
background-color: ${colors.lightGreen};
color: ${colors.light};
align-items: center;
justify-content: center;
background-color: ${theme.autocompleteAddNewCircleBg};
color: ${theme.autocompleteAddNewCircleFg};
.selected > & {
background-color: ${colors.darkGreen};
background-color: ${theme.autocompleteAddNewCircleSelectedBg};
}
`);
export const cssPlusIcon = styled(icon, `
background-color: ${colors.light};
background-color: ${theme.autocompleteAddNewCircleFg};
`);

@ -2,7 +2,7 @@ import {IToken, TokenField} from 'app/client/lib/TokenField';
import {cssBlockedCursor} from 'app/client/ui/RightPanelStyles';
import {basicButton, primaryButton} from 'app/client/ui2018/buttons';
import {colorButton, ColorOption} from 'app/client/ui2018/ColorSelect';
import {colors, testId, theme} from 'app/client/ui2018/cssVars';
import {testId, theme} from 'app/client/ui2018/cssVars';
import {editableLabel} from 'app/client/ui2018/editableLabel';
import {icon} from 'app/client/ui2018/icons';
import {ChoiceOptionsByName, IChoiceOptions} from 'app/client/widgets/ChoiceTextBox';
@ -492,7 +492,7 @@ const cssListBoxInactive = styled(cssListBox, `
border: 1px solid ${theme.choiceEntryBorderHover};
}
&-disabled {
opacity: 0.6;
opacity: 0.4;
}
`);
@ -501,8 +501,8 @@ const cssListRow = styled('div', `
margin-top: 4px;
margin-bottom: 4px;
padding: 4px 8px;
color: ${colors.dark};
background-color: ${colors.mediumGreyOpaque};
color: ${theme.choiceTokenFg};
background-color: ${theme.choiceTokenBg};
border-radius: 3px;
text-overflow: ellipsis;
`);
@ -521,7 +521,7 @@ const cssToken = styled(cssListRow, `
cursor: grab;
&.selected {
background-color: ${colors.darkGrey};
background-color: ${theme.choiceTokenSelectedBg};
}
&.token-dragging {
pointer-events: none;
@ -619,8 +619,9 @@ const cssDeleteButton = styled('div', `
`);
const cssDeleteIcon = styled(icon, `
--icon-color: ${colors.slate};
--icon-color: ${theme.text};
opacity: 0.6;
&:hover {
--icon-color: ${colors.dark};
opacity: 1.0;
}
`);

@ -4,10 +4,10 @@ import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {KoSaveableObservable} from 'app/client/models/modelUtil';
import {Style} from 'app/client/models/Styles';
import {cssLabel, cssRow} from 'app/client/ui/RightPanelStyles';
import {colors, testId} from 'app/client/ui2018/cssVars';
import {testId, theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {ChoiceListEntry} from 'app/client/widgets/ChoiceListEntry';
import {choiceToken, DEFAULT_FILL_COLOR, DEFAULT_TEXT_COLOR} from 'app/client/widgets/ChoiceToken';
import {choiceToken, DEFAULT_BACKGROUND_COLOR, DEFAULT_COLOR} from 'app/client/widgets/ChoiceToken';
import {NTextBox} from 'app/client/widgets/NTextBox';
import {Computed, dom, styled} from 'grainjs';
@ -18,11 +18,11 @@ export type ChoiceOptionsByName = Map<string, IChoiceOptions | undefined>;
const t = makeT('ChoiceTextBox');
export function getRenderFillColor(choiceOptions?: IChoiceOptions) {
return choiceOptions?.fillColor ?? DEFAULT_FILL_COLOR;
return choiceOptions?.fillColor ?? DEFAULT_BACKGROUND_COLOR;
}
export function getRenderTextColor(choiceOptions?: IChoiceOptions) {
return choiceOptions?.textColor ?? DEFAULT_TEXT_COLOR;
return choiceOptions?.textColor ?? DEFAULT_COLOR;
}
/**
@ -157,7 +157,7 @@ const cssChoiceText = styled('div', `
`);
const cssChoiceEditIcon = styled(icon, `
background-color: ${colors.slate};
background-color: ${theme.lightText};
display: block;
height: inherit;
`);

@ -1,12 +1,13 @@
import {Style} from 'app/client/models/Styles';
import {colors, theme, vars} from 'app/client/ui2018/cssVars';
import {theme, vars} from 'app/client/ui2018/cssVars';
import {dom, DomContents, DomElementArg, styled} from 'grainjs';
export const DEFAULT_FILL_COLOR = colors.mediumGreyOpaque.value!;
export const DEFAULT_TEXT_COLOR = '#000000';
export const DEFAULT_BACKGROUND_COLOR = theme.choiceTokenBg.toString();
export const DEFAULT_COLOR = theme.choiceTokenFg.toString();
export interface IChoiceTokenOptions extends Style {
invalid?: boolean;
blank?: boolean;
}
/**
@ -29,16 +30,17 @@ export function choiceToken(
...args: DomElementArg[]
): DomContents {
const {fillColor, textColor, fontBold, fontItalic, fontUnderline,
fontStrikethrough, invalid} = options;
fontStrikethrough, invalid, blank} = options;
return cssChoiceToken(
label,
dom.style('background-color', fillColor ?? DEFAULT_FILL_COLOR),
dom.style('color', textColor ?? DEFAULT_TEXT_COLOR),
dom.style('background-color', fillColor ?? DEFAULT_BACKGROUND_COLOR),
dom.style('color', textColor ?? DEFAULT_COLOR),
dom.cls('font-bold', fontBold ?? false),
dom.cls('font-underline', fontUnderline ?? false),
dom.cls('font-italic', fontItalic ?? false),
dom.cls('font-strikethrough', fontStrikethrough ?? false),
invalid ? cssChoiceToken.cls('-invalid') : null,
blank ? cssChoiceToken.cls('-blank') : null,
...args
);
}
@ -52,8 +54,12 @@ export const cssChoiceToken = styled('div', `
white-space: pre;
&-invalid {
background-color: white !important;
box-shadow: inset 0 0 0 1px ${colors.error};
color: ${theme.choiceTokenInvalidFg} !important;
background-color: ${theme.choiceTokenInvalidBg} !important;
box-shadow: inset 0 0 0 1px ${theme.choiceTokenInvalidBorder};
}
&-blank {
color: ${theme.lightText} !important;
}
`);
@ -70,7 +76,7 @@ export const cssChoiceACItem = styled('li', `
cursor: pointer;
&.selected {
background-color: ${theme.autocompleteChoiceSelectedBg};
background-color: ${theme.autocompleteItemSelectedBg};
}
&-with-new {
scroll-margin-bottom: ${ADD_NEW_HEIGHT};

@ -33,6 +33,14 @@
box-shadow: 0 2px 20px 0 var(--grist-theme-menu-shadow, rgba(38, 38, 51, 0.6));
}
.datepicker-dropdown.datepicker-orient-top:after {
border-top: 6px solid var(--grist-theme-menu-bg, #fff);
}
.datepicker-dropdown.datepicker-orient-bottom:after {
border-bottom: 6px solid var(--grist-theme-menu-bg, #fff);
}
.datepicker .prev:hover,
.datepicker .next:hover,
.datepicker .datepicker-switch:hover,

@ -1,5 +1,5 @@
import {isDesktop} from 'app/client/lib/browserInfo';
import {colors} from 'app/client/ui2018/cssVars';
import {colors, theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {IEditorCommandGroup} from 'app/client/widgets/NewBaseEditor';
import {dom, styled} from 'grainjs';
@ -25,7 +25,7 @@ const cssFinishBtn = styled('div', `
padding: 8px;
position: absolute;
top: -8px;
--icon-color: white;
--icon-color: ${theme.controlPrimaryFg};
`);
const cssCancelBtn = styled(cssFinishBtn, `
@ -34,7 +34,7 @@ const cssCancelBtn = styled(cssFinishBtn, `
`);
const cssSaveBtn = styled(cssFinishBtn, `
--icon-background-color: ${colors.lightGreen};
--icon-background-color: ${theme.controlPrimaryBg};
right: -40px;
`);

@ -1,6 +1,6 @@
import {makeT} from 'app/client/lib/localization';
import {ITooltipControl, showTooltip, tooltipCloseButton} from 'app/client/ui/tooltips';
import {colors, testId} from 'app/client/ui2018/cssVars';
import {testId, theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {cssLink} from 'app/client/ui2018/links';
import {dom, styled} from 'grainjs';
@ -29,7 +29,7 @@ export function showTooltipToCreateFormula(editorDom: HTMLElement, convert: () =
const cssConvertTooltip = styled('div', `
display: flex;
align-items: center;
--icon-color: ${colors.lightGreen};
--icon-color: ${theme.controlFg};
& > .${cssLink.className} {
margin-left: 8px;

@ -1,14 +1,14 @@
.transform_editor {
width: 90%;
margin: 5px auto;
border: 1px solid #DDDDDD;
min-height: 28px;
margin: 8px 16px;
padding: 5px 6px;
background-color: var(--grist-theme-ace-editor-bg, white);
border: 1px solid var(--grist-theme-input-border, #D9D9D9);
border-radius: 3px;
}
.transform_menu {
padding: 5px 0;
margin: 5px;
border-top: 1px solid rgba(200, 200, 200, .3);
border-bottom: 1px solid rgba(200, 200, 200, .3);
padding-bottom: 8px;
}
.fieldbuilder_settings {

@ -20,6 +20,7 @@ import { CombinedStyle, Style } from 'app/client/models/Styles';
import { COMMENTS } from 'app/client/models/features';
import { FieldSettingsMenu } from 'app/client/ui/FieldMenus';
import { cssBlockedCursor, cssLabel, cssRow } from 'app/client/ui/RightPanelStyles';
import { textButton } from 'app/client/ui2018/buttons';
import { buttonSelect, cssButtonSelect } from 'app/client/ui2018/buttonSelect';
import { theme } from 'app/client/ui2018/cssVars';
import { IOptionFull, menu, select } from 'app/client/ui2018/menus';
@ -308,6 +309,7 @@ export class FieldBuilder extends Disposable {
grainjsDom.cls('tour-type-selector'),
grainjsDom.cls(cssBlockedCursor.className, use =>
use(this.origColumn.disableModifyBase) ||
use(this._isTransformingFormula) ||
(use(this.field.config.multiselect) && !use(allFormulas))
),
),
@ -415,18 +417,18 @@ export class FieldBuilder extends Disposable {
this.columnTransform.finalize().catch(reportError);
}
}),
kf.row(
15, kf.label(t('Apply Formula to Data')),
3, kf.buttonGroup(
kf.checkButton(transformButton,
dom('span.glyphicon.glyphicon-flash'),
dom.testId("FieldBuilder_editTransform"),
testId('edit-transform'),
kd.toggleClass('disabled', () => this._isTransformingType() || this.origColumn.isFormula() ||
this.origColumn.disableModifyBase())
)
)
),
cssRow(
textButton(t('Apply Formula to Data'),
dom.on('click', () => transformButton(true)),
kd.hide(this._isTransformingFormula),
kd.boolAttr('disabled', () =>
this._isTransformingType() ||
this.origColumn.isFormula() ||
this.origColumn.disableModifyBase() ||
this.field.config.multiselect()),
dom.testId("FieldBuilder_editTransform"),
testId('edit-transform'),
)),
kd.maybe(this._isTransformingFormula, () => {
return this.columnTransform!.buildDom();
})

@ -1,7 +1,7 @@
import { DataRowModel } from 'app/client/models/DataRowModel';
import { ViewFieldRec } from 'app/client/models/entities/ViewFieldRec';
import { constructUrl } from 'app/client/models/gristUrlState';
import { colors, testId } from 'app/client/ui2018/cssVars';
import { testId, theme } from 'app/client/ui2018/cssVars';
import { cssIconBackground, icon } from 'app/client/ui2018/icons';
import { cssHoverIn, gristLink } from 'app/client/ui2018/links';
import { NTextBox } from 'app/client/widgets/NTextBox';
@ -15,7 +15,7 @@ import { Computed, dom, styled } from 'grainjs';
*/
export class HyperLinkTextBox extends NTextBox {
constructor(field: ViewFieldRec) {
super(field, {defaultTextColor: colors.lightGreen.value});
super(field, {defaultTextColor: theme.link.toString()});
}
public buildDom(row: DataRowModel) {
@ -49,7 +49,7 @@ function _formatValue(value: CellValue): string {
}
const cssFieldClip = styled('div.field_clip', `
color: var(--grist-actual-cell-color, ${colors.lightGreen});
color: var(--grist-actual-cell-color, ${theme.link});
`);
const cssHoverOnField = cssHoverIn(cssFieldClip.className);

@ -7,6 +7,7 @@ import {GristDoc} from 'app/client/components/GristDoc';
import {DocData} from 'app/client/models/DocData';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {SaveableObjObservable} from 'app/client/models/modelUtil';
import {theme} from 'app/client/ui2018/cssVars';
import {CellStyle} from 'app/client/widgets/CellStyle';
import {BaseFormatter} from 'app/common/ValueFormatter';
import {
@ -19,7 +20,10 @@ import {
} from 'grainjs';
export interface Options {
// A hex value to set the default widget text color. Default to '#000000' if omitted.
/**
* CSS value of the default widget text color. Defaults to the current theme's
* cell fg color.
*/
defaultTextColor?: string;
}
@ -44,13 +48,13 @@ export abstract class NewAbstractWidget extends Disposable {
protected valueFormatter: Observable<BaseFormatter>;
protected textColor: Observable<string>;
protected fillColor: Observable<string>;
protected readonly defaultTextColor: string;
protected readonly defaultTextColor: string|undefined = this._opts.defaultTextColor
?? theme.cellFg.toString();
constructor(protected field: ViewFieldRec, opts: Options = {}) {
constructor(protected field: ViewFieldRec, private _opts: Options = {}) {
super();
this.options = field.widgetOptionsJson;
this.valueFormatter = fromKo(field.formatter);
this.defaultTextColor = opts?.defaultTextColor || '#000000';
}
/**

@ -172,7 +172,7 @@ const cssDecimalsBox = styled('div', `
margin-right: 16px;
}
&-disabled {
background-color: ${theme.rightPanelToggleButtonDisabledBg};
opacity: 0.4;
pointer-events: none;
}
`);

@ -2,7 +2,7 @@ import {makeT} from 'app/client/lib/localization';
import {DataRowModel} from 'app/client/models/DataRowModel';
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
import {cssLabel, cssRow} from 'app/client/ui/RightPanelStyles';
import {colors, hideInPrintView, testId} from 'app/client/ui2018/cssVars';
import {hideInPrintView, testId, theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {IOptionFull, select} from 'app/client/ui2018/menus';
import {NTextBox} from 'app/client/widgets/NTextBox';
@ -119,12 +119,12 @@ export class Reference extends NTextBox {
const cssRefIcon = styled(icon, `
float: left;
background-color: ${colors.slate};
--icon-color: ${theme.lightText};
margin: -1px 2px 2px 0;
`);
const cssRef = styled('div.field_clip', `
&-blank {
color: ${colors.slate}
color: ${theme.lightText}
}
`);

@ -2,7 +2,7 @@ import { ACResults, buildHighlightedDom, HighlightFunc, normalizeText } from 'ap
import { Autocomplete } from 'app/client/lib/autocomplete';
import { ICellItem } from 'app/client/models/ColumnACIndexes';
import { reportError } from 'app/client/models/errors';
import { colors, testId, theme, vars } from 'app/client/ui2018/cssVars';
import { testId, theme, vars } from 'app/client/ui2018/cssVars';
import { icon } from 'app/client/ui2018/icons';
import { menuCssClass } from 'app/client/ui2018/menus';
import { FieldOptions } from 'app/client/widgets/NewBaseEditor';
@ -181,6 +181,8 @@ const cssRefItem = styled('li', `
scroll-margin-bottom: ${addNewHeight};
}
&-new {
display: flex;
align-items: center;
color: ${theme.lightText};
position: sticky;
bottom: 0px;
@ -195,26 +197,27 @@ const cssRefItem = styled('li', `
`);
export const cssPlusButton = styled('div', `
display: inline-block;
display: flex;
width: 20px;
height: 20px;
border-radius: 20px;
margin-right: 8px;
text-align: center;
background-color: ${colors.lightGreen};
color: ${colors.light};
align-items: center;
justify-content: center;
background-color: ${theme.autocompleteAddNewCircleBg};
color: ${theme.autocompleteAddNewCircleFg};
.selected > & {
background-color: ${colors.darkGreen};
background-color: ${theme.autocompleteAddNewCircleSelectedBg};
}
`);
export const cssPlusIcon = styled(icon, `
background-color: ${colors.light};
background-color: ${theme.autocompleteAddNewCircleFg};
`);
const cssRefEditIcon = styled(icon, `
background-color: ${colors.slate};
background-color: ${theme.lightText};
position: absolute;
top: 0;
left: 0;

@ -1,5 +1,5 @@
import {DataRowModel} from 'app/client/models/DataRowModel';
import {colors, testId} from 'app/client/ui2018/cssVars';
import {testId} from 'app/client/ui2018/cssVars';
import {isList} from 'app/common/gristTypes';
import {dom} from 'grainjs';
import {cssChoiceList, cssToken} from "app/client/widgets/ChoiceListCell";
@ -51,7 +51,7 @@ export class ReferenceList extends Reference {
return choiceToken(
isBlankReference ? '[Blank]' : token,
{
textColor: isBlankReference ? colors.slate.value : undefined
blank: isBlankReference,
},
dom.cls(cssToken.className),
testId('ref-list-cell-token')

@ -298,7 +298,6 @@ const cssTokenField = styled(tokenFieldStyles.cssTokenField, `
padding: 0 3px;
height: min-content;
min-height: 22px;
color: black;
flex-wrap: wrap;
`);
@ -307,13 +306,14 @@ const cssToken = styled(tokenFieldStyles.cssToken, `
margin: 2px;
line-height: 16px;
white-space: pre;
color: ${theme.choiceTokenFg};
&.selected {
box-shadow: inset 0 0 0 1px ${colors.lightGreen};
box-shadow: inset 0 0 0 1px ${theme.choiceTokenSelectedBorder};
}
&-blank {
color: ${colors.slate};
color: ${theme.lightText};
}
`);

@ -12,7 +12,7 @@
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
background-color: var(--grist-theme-switch-slider-fg, #ccc);
border-radius: 17px;
}
@ -28,7 +28,7 @@
width: 13px;
left: 2px;
bottom: 2px;
background-color: white;
background-color: var(--grist-theme-switch-circle-fg, white);
border-radius: 17px;
}

@ -91,6 +91,10 @@
line-height: inherit;
}
.celleditor_text_editor::placeholder {
color: var(--grist-theme-cell-editor-placeholder-fg, unset);
}
.celleditor_content_measure {
position: absolute;
left: 0;

@ -3,6 +3,7 @@ import { DataRowModel } from 'app/client/models/DataRowModel';
import { ViewFieldRec } from 'app/client/models/entities/ViewFieldRec';
import { KoSaveableObservable } from 'app/client/models/modelUtil';
import { NewAbstractWidget, Options } from 'app/client/widgets/NewAbstractWidget';
import { theme } from 'app/client/ui2018/cssVars';
import { dom } from 'grainjs';
/**
@ -28,7 +29,7 @@ abstract class ToggleBase extends NewAbstractWidget {
export class ToggleCheckBox extends ToggleBase {
constructor(field: ViewFieldRec, _options: Options = {}) {
super(field, {defaultTextColor: '#606060'});
super(field, {defaultTextColor: theme.toggleCheckboxFg.toString()});
}
public buildDom(row: DataRowModel) {

@ -77,8 +77,6 @@ export const ThemeColors = t.iface([], {
"tooltip-close-button-fg": "string",
"tooltip-close-button-hover-fg": "string",
"tooltip-close-button-hover-bg": "string",
"tooltip-popup-header-fg": "string",
"tooltip-popup-header-bg": "string",
"modal-bg": "string",
"modal-backdrop": "string",
"modal-border": "string",
@ -102,6 +100,7 @@ export const ThemeColors = t.iface([], {
"hover": "string",
"hover-light": "string",
"cell-editor-fg": "string",
"cell-editor-placeholder-fg": "string",
"cell-editor-bg": "string",
"cursor": "string",
"cursor-inactive": "string",
@ -111,7 +110,6 @@ export const ThemeColors = t.iface([], {
"table-header-bg": "string",
"table-header-selected-bg": "string",
"table-header-border": "string",
"table-header-border-dark": "string",
"table-body-bg": "string",
"table-body-border": "string",
"table-add-new-bg": "string",
@ -119,6 +117,7 @@ export const ThemeColors = t.iface([], {
"table-frozen-columns-border": "string",
"table-drag-drop-indicator": "string",
"table-drag-drop-shadow": "string",
"table-cell-summary-bg": "string",
"card-compact-widget-bg": "string",
"card-compact-record-bg": "string",
"card-blocks-bg": "string",
@ -153,13 +152,13 @@ export const ThemeColors = t.iface([], {
"control-primary-fg": "string",
"control-primary-bg": "string",
"control-secondary-fg": "string",
"control-secondary-disabled-fg": "string",
"control-hover-fg": "string",
"control-primary-hover-bg": "string",
"control-secondary-hover-fg": "string",
"control-secondary-hover-bg": "string",
"control-disabled-fg": "string",
"control-disabled-bg": "string",
"control-primary-disabled": "string",
"control-border": "string",
"checkbox-bg": "string",
"checkbox-disabled-bg": "string",
@ -206,7 +205,6 @@ export const ThemeColors = t.iface([], {
"right-panel-disabled-overlay": "string",
"right-panel-toggle-button-enabled-fg": "string",
"right-panel-toggle-button-enabled-bg": "string",
"right-panel-toggle-button-enabled-hover-fg": "string",
"right-panel-toggle-button-disabled-fg": "string",
"right-panel-toggle-button-disabled-bg": "string",
"right-panel-field-settings-bg": "string",
@ -218,6 +216,9 @@ export const ThemeColors = t.iface([], {
"document-history-snapshot-border": "string",
"document-history-activity-text": "string",
"document-history-activity-text-light": "string",
"document-history-table-header-fg": "string",
"document-history-table-border": "string",
"document-history-table-border-light": "string",
"accent-icon": "string",
"accent-border": "string",
"accent-text": "string",
@ -232,12 +233,19 @@ export const ThemeColors = t.iface([], {
"input-focus": "string",
"input-readonly-bg": "string",
"input-readonly-border": "string",
"choice-token-fg": "string",
"choice-token-blank-fg": "string",
"choice-token-bg": "string",
"choice-token-selected-bg": "string",
"choice-token-selected-border": "string",
"choice-token-invalid-fg": "string",
"choice-token-invalid-bg": "string",
"choice-token-invalid-border": "string",
"choice-entry-bg": "string",
"choice-entry-border": "string",
"choice-entry-border-hover": "string",
"select-button-fg": "string",
"select-button-placeholder-fg": "string",
"select-button-disabled-fg": "string",
"select-button-bg": "string",
"select-button-border": "string",
"select-button-border-invalid": "string",
@ -253,12 +261,12 @@ export const ThemeColors = t.iface([], {
"menu-item-disabled-fg": "string",
"menu-item-icon-fg": "string",
"menu-item-icon-selected-fg": "string",
"menu-item-link-fg": "string",
"menu-item-link-selected-fg": "string",
"menu-item-link-selected-bg": "string",
"autocomplete-match-text": "string",
"autocomplete-selected-match-text": "string",
"autocomplete-item-selected-bg": "string",
"autocomplete-add-new-circle-fg": "string",
"autocomplete-add-new-circle-bg": "string",
"autocomplete-add-new-circle-selected-bg": "string",
"search-border": "string",
"search-prev-next-button-fg": "string",
"search-prev-next-button-bg": "string",
@ -318,6 +326,7 @@ export const ThemeColors = t.iface([], {
"button-group-fg": "string",
"button-group-light-fg": "string",
"button-group-bg": "string",
"button-group-bg-hover": "string",
"button-group-icon": "string",
"button-group-border": "string",
"button-group-border-hover": "string",
@ -328,6 +337,7 @@ export const ThemeColors = t.iface([], {
"access-rules-table-header-fg": "string",
"access-rules-table-header-bg": "string",
"access-rules-table-body-fg": "string",
"access-rules-table-body-light-fg": "string",
"access-rules-table-border": "string",
"access-rules-column-list-border": "string",
"access-rules-column-item-fg": "string",
@ -383,7 +393,6 @@ export const ThemeColors = t.iface([], {
"color-select-shadow": "string",
"color-select-font-options-border": "string",
"color-select-font-option-fg": "string",
"color-select-font-option-bg": "string",
"color-select-font-option-bg-hover": "string",
"color-select-font-option-fg-selected": "string",
"color-select-font-option-bg-selected": "string",
@ -400,9 +409,30 @@ export const ThemeColors = t.iface([], {
"login-page-bg": "string",
"login-page-backdrop": "string",
"login-page-line": "string",
"login-page-google-button-fg": "string",
"login-page-google-button-bg": "string",
"login-page-google-button-bg-hover": "string",
"login-page-google-button-border": "string",
"formula-assistant-header-bg": "string",
"formula-assistant-border": "string",
"formula-assistant-preformatted-text-bg": "string",
"attachments-editor-button-fg": "string",
"attachments-editor-button-hover-fg": "string",
"attachments-editor-button-bg": "string",
"attachments-editor-button-hover-bg": "string",
"attachments-editor-button-border": "string",
"attachments-editor-button-icon": "string",
"attachments-editor-border": "string",
"attachments-cell-icon-fg": "string",
"attachments-cell-icon-bg": "string",
"attachments-cell-icon-hover-bg": "string",
"switch-slider-fg": "string",
"switch-circle-fg": "string",
"announcement-popup-fg": "string",
"announcement-popup-bg": "string",
"scroll-shadow": "string",
"toggle-checkbox-fg": "string",
"numeric-spinner-fg": "string",
});
const exportedTypeSuite: t.ITypeSuite = {

@ -89,8 +89,6 @@ export interface ThemeColors {
'tooltip-close-button-fg': string;
'tooltip-close-button-hover-fg': string;
'tooltip-close-button-hover-bg': string;
'tooltip-popup-header-fg': string;
'tooltip-popup-header-bg': string;
/* Modals */
'modal-bg': string;
@ -128,6 +126,7 @@ export interface ThemeColors {
/* Cell Editor */
'cell-editor-fg': string;
'cell-editor-placeholder-fg': string;
'cell-editor-bg': string;
/* Cursor */
@ -141,7 +140,6 @@ export interface ThemeColors {
'table-header-bg': string;
'table-header-selected-bg': string;
'table-header-border': string;
'table-header-border-dark': string;
'table-body-bg': string;
'table-body-border': string;
'table-add-new-bg': string;
@ -149,6 +147,7 @@ export interface ThemeColors {
'table-frozen-columns-border': string;
'table-drag-drop-indicator': string;
'table-drag-drop-shadow': string;
'table-cell-summary-bg': string;
/* Cards */
'card-compact-widget-bg': string;
@ -197,13 +196,13 @@ export interface ThemeColors {
'control-primary-fg': string;
'control-primary-bg': string;
'control-secondary-fg': string;
'control-secondary-disabled-fg': string;
'control-hover-fg': string;
'control-primary-hover-bg': string;
'control-secondary-hover-fg': string;
'control-secondary-hover-bg': string;
'control-disabled-fg': string;
'control-disabled-bg': string;
'control-primary-disabled': string;
'control-border': string;
/* Checkboxes */
@ -264,7 +263,6 @@ export interface ThemeColors {
'right-panel-disabled-overlay': string;
'right-panel-toggle-button-enabled-fg': string;
'right-panel-toggle-button-enabled-bg': string;
'right-panel-toggle-button-enabled-hover-fg': string;
'right-panel-toggle-button-disabled-fg': string;
'right-panel-toggle-button-disabled-bg': string;
'right-panel-field-settings-bg': string;
@ -278,6 +276,9 @@ export interface ThemeColors {
'document-history-snapshot-border': string;
'document-history-activity-text': string;
'document-history-activity-text-light': string;
'document-history-table-header-fg': string;
'document-history-table-border': string;
'document-history-table-border-light': string;
/* Accents */
'accent-icon': string;
@ -297,6 +298,16 @@ export interface ThemeColors {
'input-readonly-bg': string;
'input-readonly-border': string;
/* Choice Tokens */
'choice-token-fg': string;
'choice-token-blank-fg': string;
'choice-token-bg': string;
'choice-token-selected-bg': string;
'choice-token-selected-border': string;
'choice-token-invalid-fg': string;
'choice-token-invalid-bg': string;
'choice-token-invalid-border': string;
/* Choice Entry */
'choice-entry-bg': string;
'choice-entry-border': string;
@ -305,7 +316,6 @@ export interface ThemeColors {
/* Select Buttons */
'select-button-fg': string;
'select-button-placeholder-fg': string;
'select-button-disabled-fg': string;
'select-button-bg': string;
'select-button-border': string;
'select-button-border-invalid': string;
@ -325,14 +335,14 @@ export interface ThemeColors {
'menu-item-disabled-fg': string;
'menu-item-icon-fg': string;
'menu-item-icon-selected-fg': string;
'menu-item-link-fg': string;
'menu-item-link-selected-fg': string;
'menu-item-link-selected-bg': string;
/* Autocomplete */
'autocomplete-match-text': string;
'autocomplete-selected-match-text': string;
'autocomplete-item-selected-bg': string;
'autocomplete-add-new-circle-fg': string;
'autocomplete-add-new-circle-bg': string;
'autocomplete-add-new-circle-selected-bg': string;
/* Search */
'search-border': string;
@ -416,6 +426,7 @@ export interface ThemeColors {
'button-group-fg': string;
'button-group-light-fg': string;
'button-group-bg': string;
'button-group-bg-hover': string;
'button-group-icon': string;
'button-group-border': string;
'button-group-border-hover': string;
@ -428,6 +439,7 @@ export interface ThemeColors {
'access-rules-table-header-fg': string;
'access-rules-table-header-bg': string;
'access-rules-table-body-fg': string;
'access-rules-table-body-light-fg': string;
'access-rules-table-border': string;
'access-rules-column-list-border': string;
'access-rules-column-item-fg': string;
@ -497,7 +509,6 @@ export interface ThemeColors {
'color-select-shadow': string;
'color-select-font-options-border': string;
'color-select-font-option-fg': string;
'color-select-font-option-bg': string;
'color-select-font-option-bg-hover': string;
'color-select-font-option-fg-selected': string;
'color-select-font-option-bg-selected': string;
@ -518,11 +529,44 @@ export interface ThemeColors {
'login-page-bg': string;
'login-page-backdrop': string;
'login-page-line': string;
'login-page-google-button-fg': string;
'login-page-google-button-bg': string;
'login-page-google-button-bg-hover': string;
'login-page-google-button-border': string;
/* Formula Assistant */
'formula-assistant-header-bg': string;
'formula-assistant-border': string;
'formula-assistant-preformatted-text-bg': string;
/* Attachments */
'attachments-editor-button-fg': string;
'attachments-editor-button-hover-fg': string;
'attachments-editor-button-bg': string;
'attachments-editor-button-hover-bg': string;
'attachments-editor-button-border': string;
'attachments-editor-button-icon': string;
'attachments-editor-border': string;
'attachments-cell-icon-fg': string;
'attachments-cell-icon-bg': string;
'attachments-cell-icon-hover-bg': string;
/* Switches */
'switch-slider-fg': string;
'switch-circle-fg': string;
/* Announcement Popups */
'announcement-popup-fg': string;
'announcement-popup-bg': string;
/* Scroll Shadow */
'scroll-shadow': string;
/* Toggle Checkboxes */
'toggle-checkbox-fg': string;
/* Numeric Spinners */
'numeric-spinner-fg': string;
}
export const ThemePrefsChecker = createCheckers(ThemePrefsTI).ThemePrefs as CheckerT<ThemePrefs>;
@ -532,7 +576,7 @@ export const ThemeNameChecker = createCheckers(ThemePrefsTI).ThemeName as Checke
export function getDefaultThemePrefs(): ThemePrefs {
return {
appearance: 'light',
syncWithOS: false,
syncWithOS: true,
colors: {
light: 'GristLight',
dark: 'GristDark',

@ -3,11 +3,11 @@ import {ThemeColors} from 'app/common/ThemePrefs';
export const GristDark: ThemeColors = {
/* Text */
'text': '#EFEFEF',
'text-light': '#A4A4A4',
'text-light': '#A4A4B1',
'text-dark': '#FFFFFF',
'text-error': '#FF6666',
'text-danger': '#FFA500',
'text-disabled': '#A4A4A4',
'text-disabled': '#A4A4B1',
/* Page */
'page-bg': '#262633',
@ -19,30 +19,30 @@ export const GristDark: ThemeColors = {
'page-panels-right-panel-bg': '#262633',
'page-panels-top-header-bg': '#32323F',
'page-panels-bottom-footer-bg': '#32323F',
'page-panels-border': '#57575F',
'page-panels-border-resizing': '#1DA270',
'page-panels-side-panel-opener-fg': '#A4A4A4',
'page-panels-border': '#60606D',
'page-panels-border-resizing': '#17B378',
'page-panels-side-panel-opener-fg': '#A4A4B1',
'page-panels-side-panel-opener-active-fg': '#FFFFFF',
'page-panels-side-panel-opener-active-bg': '#1DA270',
'page-panels-side-panel-opener-active-bg': '#17B378',
/* Add New */
'add-new-circle-fg': '#FFFFFF',
'add-new-circle-bg': '#157A54',
'add-new-circle-hover-bg': '#0A5438',
'add-new-circle-bg': '#0A5438',
'add-new-circle-hover-bg': '#157A54',
'add-new-circle-small-fg': '#FFFFFF',
'add-new-circle-small-bg': '#1DA270',
'add-new-circle-small-hover-bg': '#157A54',
'add-new-circle-small-bg': '#157A54',
'add-new-circle-small-hover-bg': '#1DA270',
/* Top Bar */
'top-bar-button-primary-fg': '#1DA270',
'top-bar-button-secondary-fg': '#A4A4A4',
'top-bar-button-disabled-fg': '#69697D',
'top-bar-button-primary-fg': '#17B378',
'top-bar-button-secondary-fg': '#A4A4B1',
'top-bar-button-disabled-fg': '#70707D',
'top-bar-button-error-fg': 'FF6666',
/* Notifications */
'notifications-panel-header-bg': '#262633',
'notifications-panel-body-bg': '#32323F',
'notifications-panel-border': '#69697D',
'notifications-panel-border': '#70707D',
/* Toasts */
'toast-text': '#FFFFFF',
@ -64,86 +64,85 @@ export const GristDark: ThemeColors = {
/* Tooltips */
'tooltip-fg': 'white',
'tooltip-bg': 'rgba(0, 0, 0, 0.75)',
'tooltip-icon': '#A4A4A4',
'tooltip-icon': '#A4A4B1',
'tooltip-close-button-fg': 'white',
'tooltip-close-button-hover-fg': 'black',
'tooltip-close-button-hover-bg': 'white',
'tooltip-popup-header-fg': '#EFEFEF',
'tooltip-popup-header-bg': '#1DA270',
/* Modals */
'modal-bg': '#32323F',
'modal-backdrop': 'rgba(0,0,0,0.6)',
'modal-border': '#57575F',
'modal-border-dark': '#69697D',
'modal-border-hover': '#A4A4A4',
'modal-border': '#60606D',
'modal-border-dark': '#70707D',
'modal-border-hover': '#A4A4B1',
'modal-shadow-inner': '#000000',
'modal-shadow-outer': '#000000',
'modal-close-button-fg': '#A4A4A4',
'modal-backdrop-close-button-fg': '#1DA270',
'modal-backdrop-close-button-hover-fg': '#157A54',
'modal-close-button-fg': '#A4A4B1',
'modal-backdrop-close-button-fg': '#17B378',
'modal-backdrop-close-button-hover-fg': '#13D78D',
/* Popups */
'popup-bg': '#32323F',
'popup-shadow-inner': '#000000',
'popup-shadow-outer': '#000000',
'popup-close-button-fg': '#A4A4A4',
'popup-close-button-fg': '#A4A4B1',
/* Prompts */
'prompt-fg': '#A4A4A4',
'prompt-fg': '#A4A4B1',
/* Progress Bars */
'progress-bar-fg': '#1DA270',
'progress-bar-fg': '#17B378',
'progress-bar-error-fg': '#FF6666',
'progress-bar-bg': '#69697D',
'progress-bar-bg': '#70707D',
/* Links */
'link': '#1DA270',
'link-hover': '#1DA270',
'link': '#17B378',
'link-hover': '#17B378',
/* Hover */
'hover': 'rgba(111,111,117,0.6)',
'hover-light': 'rgba(111,111,117,0.4)',
'hover': 'rgba(111,111,125,0.6)',
'hover-light': 'rgba(111,111,125,0.4)',
/* Cell Editor */
'cell-editor-fg': '#FFFFFF',
'cell-editor-placeholder-fg': '#A4A4B1',
'cell-editor-bg': '#32323F',
/* Cursor */
'cursor': '#1DA270',
'cursor-inactive': 'rgba(29,162,112,0.5)',
'cursor-readonly': '#A4A4A4',
'cursor-readonly': '#A4A4B1',
/* Tables */
'table-header-fg': '#EFEFEF',
'table-header-selected-fg': '#EFEFEF',
'table-header-bg': '#262633',
'table-header-selected-bg': '#414358',
'table-header-border': '#57575F',
'table-header-border-dark': '#69697D',
'table-header-border': '#70707D',
'table-body-bg': '#32323F',
'table-body-border': '#69697D',
'table-body-border': '#60606D',
'table-add-new-bg': '#4A4A5D',
'table-scroll-shadow': '#000000',
'table-frozen-columns-border': '#A4A4A4',
'table-drag-drop-indicator': '#A4A4A4',
'table-drag-drop-shadow': 'rgba(111,111,117,0.6)',
'table-frozen-columns-border': '#A4A4B1',
'table-drag-drop-indicator': '#A4A4B1',
'table-drag-drop-shadow': 'rgba(111,111,125,0.6)',
'table-cell-summary-bg': 'rgba(111,111,125,0.6)',
/* Cards */
'card-compact-widget-bg': '#262633',
'card-compact-record-bg': '#32323F',
'card-blocks-bg': '#404150',
'card-form-label': '#A4A4A4',
'card-compact-label': '#A4A4A4',
'card-blocks-label': '#A4A4A4',
'card-form-border': '#69697D',
'card-compact-border': '#69697D',
'card-form-label': '#A4A4B1',
'card-compact-label': '#A4A4B1',
'card-blocks-label': '#A4A4B1',
'card-form-border': '#70707D',
'card-compact-border': '#70707D',
'card-editing-layout-bg': 'rgba(85, 85, 99, 0.2)',
'card-editing-layout-border': '#69697D',
'card-editing-layout-border': '#70707D',
/* Card Lists */
'card-list-form-border': '#57575F',
'card-list-blocks-border': '#57575F',
'card-list-form-border': '#60606D',
'card-list-blocks-border': '#60606D',
/* Selection */
'selection': 'rgba(22,179,120,0.15)',
@ -156,203 +155,214 @@ export const GristDark: ThemeColors = {
/* Widgets */
'widget-bg': '#32323F',
'widget-border': '#57575F',
'widget-active-border': '#1DA270',
'widget-border': '#70707D',
'widget-active-border': '#157A54',
'widget-inactive-stripes-light': '#262633',
'widget-inactive-stripes-dark': '#32323F',
/* Pinned Docs */
'pinned-doc-footer-bg': '#32323F',
'pinned-doc-border': '#57575F',
'pinned-doc-border-hover': '#A4A4A4',
'pinned-doc-editor-bg': '#57575F',
'pinned-doc-border': '#60606D',
'pinned-doc-border-hover': '#A4A4B1',
'pinned-doc-editor-bg': '#60606D',
/* Raw Data */
'raw-data-table-border': '#57575F',
'raw-data-table-border-hover': '#A4A4A4',
'raw-data-table-border': '#60606D',
'raw-data-table-border-hover': '#A4A4B1',
/* Controls */
'control-fg': '#1DA270',
'control-fg': '#17B378',
'control-primary-fg': '#FFFFFF',
'control-primary-bg': '#1DA270',
'control-secondary-fg': '#A4A4A4',
'control-hover-fg': '#157A54',
'control-primary-hover-bg': '#157A54',
'control-primary-bg': '#157A54',
'control-secondary-fg': '#A4A4B1',
'control-secondary-disabled-fg': '#60606D',
'control-hover-fg': '#13D78D',
'control-primary-hover-bg': '#1DA270',
'control-secondary-hover-fg': '#EFEFEF',
'control-secondary-hover-bg': '#57575F',
'control-disabled-fg': '#A4A4A4',
'control-disabled-bg': '#69697D',
'control-primary-disabled': '#5F8C7B',
'control-border': '1px solid #1DA270',
'control-secondary-hover-bg': '#60606D',
'control-disabled-fg': '#A4A4B1',
'control-disabled-bg': '#70707D',
'control-border': '1px solid #17B378',
/* Checkboxes */
'checkbox-bg': '#32323F',
'checkbox-disabled-bg': '#69697D',
'checkbox-border': '#69697D',
'checkbox-border-hover': '#57575F',
'checkbox-disabled-bg': '#70707D',
'checkbox-border': '#70707D',
'checkbox-border-hover': '#A4A4B1',
/* Move Docs */
'move-docs-selected-fg': '#FFFFFF',
'move-docs-selected-bg': '#1DA270',
'move-docs-disabled-bg': '#69697D',
'move-docs-selected-bg': '#157A54',
'move-docs-disabled-bg': '#70707D',
/* Filter Bar */
'filter-bar-button-saved-fg': '#FFFFFF',
'filter-bar-button-saved-bg': '#555563',
'filter-bar-button-saved-hover-bg': '#69697D',
'filter-bar-button-saved-hover-bg': '#70707D',
/* Icons */
'icon-disabled': '#A4A4A4',
'icon-disabled': '#A4A4B1',
'icon-error': '#FFA500',
/* Icon Buttons */
'icon-button-fg': '#FFFFFF',
'icon-button-primary-bg': '#1DA270',
'icon-button-primary-hover-bg': '#157A54',
'icon-button-secondary-bg': '#69697D',
'icon-button-secondary-hover-bg': '#A4A4A4',
'icon-button-primary-bg': '#17B378',
'icon-button-primary-hover-bg': '#13D78D',
'icon-button-secondary-bg': '#70707D',
'icon-button-secondary-hover-bg': '#A4A4B1',
/* Left Panel */
'left-panel-page-hover-bg': 'rgba(111,111,117,0.25)',
'left-panel-active-page-fg': '#EFEFEF',
'left-panel-active-page-bg': '#555563',
'left-panel-disabled-page-fg': '#69697D',
'left-panel-page-options-fg': '#A4A4A4',
'left-panel-active-page-bg': '#646473',
'left-panel-disabled-page-fg': '#70707D',
'left-panel-page-options-fg': '#A4A4B1',
'left-panel-page-options-hover-fg': '#FFFFFF',
'left-panel-page-options-hover-bg': '#69697D',
'left-panel-page-options-selected-hover-bg': '#A4A4A4',
'left-panel-page-options-hover-bg': '#70707D',
'left-panel-page-options-selected-hover-bg': '#A4A4B1',
'left-panel-page-initials-fg': 'white',
'left-panel-page-initials-bg': '#929299',
'left-panel-page-initials-bg': '#8E8EA0',
'left-panel-page-emoji-fg': 'black',
'left-panel-page-emoji-outline': '#69697D',
'left-panel-page-emoji-outline': '#70707D',
/* Right Panel */
'right-panel-tab-fg': '#EFEFEF',
'right-panel-tab-bg': '#262633',
'right-panel-tab-icon': '#A4A4A4',
'right-panel-tab-icon-hover': '#1DA270',
'right-panel-tab-icon': '#A4A4B1',
'right-panel-tab-icon-hover': '#13D78D',
'right-panel-tab-hover-bg': 'rgba(111,111,117,0.6)',
'right-panel-tab-selected-fg': '#FFFFFF',
'right-panel-tab-selected-bg': '#1DA270',
'right-panel-tab-button-hover-bg': '#157A54',
'right-panel-subtab-fg': '#1DA270',
'right-panel-tab-selected-bg': '#157A54',
'right-panel-tab-button-hover-bg': '#0A5438',
'right-panel-subtab-fg': '#17B378',
'right-panel-subtab-selected-fg': '#EFEFEF',
'right-panel-subtab-selected-underline': '#1DA270',
'right-panel-subtab-hover-fg': '#157A54',
'right-panel-subtab-hover-underline': '#1DA270',
'right-panel-subtab-hover-fg': '#13D78D',
'right-panel-subtab-hover-underline': '#13D78D',
'right-panel-disabled-overlay': '#262633',
'right-panel-toggle-button-enabled-fg': '#FFFFFF',
'right-panel-toggle-button-enabled-bg': '#555563',
'right-panel-toggle-button-enabled-hover-fg': '#D9D9D9',
'right-panel-toggle-button-disabled-fg': '#FFFFFF',
'right-panel-toggle-button-disabled-bg': '#333333',
'right-panel-field-settings-bg': '#414358',
'right-panel-field-settings-button-bg': '#57575F',
'right-panel-toggle-button-enabled-bg': '#646473',
'right-panel-toggle-button-disabled-fg': '#646473',
'right-panel-toggle-button-disabled-bg': '#32323F',
'right-panel-field-settings-bg': '#404150',
'right-panel-field-settings-button-bg': '#646473',
/* Document History */
'document-history-snapshot-fg': '#EFEFEF',
'document-history-snapshot-selected-fg': '#EFEFEF',
'document-history-snapshot-bg': '#32323F',
'document-history-snapshot-selected-bg': '#555563',
'document-history-snapshot-border': '#69697D',
'document-history-snapshot-selected-bg': '#646473',
'document-history-snapshot-border': '#70707D',
'document-history-activity-text': '#EFEFEF',
'document-history-activity-text-light': '#A4A4A4',
'document-history-activity-text-light': '#A4A4B1',
'document-history-table-header-fg': '#EFEFEF',
'document-history-table-border': '#70707D',
'document-history-table-border-light': '#60606D',
/* Accents */
'accent-icon': '#1DA270',
'accent-border': '#1DA270',
'accent-text': '#1DA270',
'accent-icon': '#17B378',
'accent-border': '#157A54',
'accent-text': '#17B378',
/* Inputs */
'input-fg': '#EFEFEF',
'input-bg': '#32323F',
'input-disabled-fg': '#A4A4A4',
'input-disabled-fg': '#A4A4B1',
'input-disabled-bg': '#262633',
'input-placeholder-fg': '#A4A4A4',
'input-border': '#69697D',
'input-valid': '#1DA270',
'input-placeholder-fg': '#A4A4B1',
'input-border': '#70707D',
'input-valid': '#17B378',
'input-invalid': '#FF6666',
'input-focus': '#5E9ED6',
'input-readonly-bg': '#262633',
'input-readonly-border': '#69697D',
'input-readonly-border': '#70707D',
/* Choice Tokens */
'choice-token-fg': '#FFFFFF',
'choice-token-blank-fg': '#A4A4B1',
'choice-token-bg': '#70707D',
'choice-token-selected-bg': '#555563',
'choice-token-selected-border': '#17B378',
'choice-token-invalid-fg': '#FFFFFF',
'choice-token-invalid-bg': '#323240',
'choice-token-invalid-border': '#D0021B',
/* Choice Entry */
'choice-entry-bg': '#32323F',
'choice-entry-border': '#69697D',
'choice-entry-border-hover': '#A4A4A4',
'choice-entry-border': '#70707D',
'choice-entry-border-hover': '#A4A4B1',
/* Select Buttons */
'select-button-fg': '#EFEFEF',
'select-button-placeholder-fg': '#A4A4A4',
'select-button-disabled-fg': '#A4A4A4',
'select-button-placeholder-fg': '#A4A4B1',
'select-button-bg': '#32323F',
'select-button-border': '#69697D',
'select-button-border': '#70707D',
'select-button-border-invalid': '#FF6666',
/* Menus */
'menu-text': '#A4A4A4',
'menu-light-text': '#A4A4A4',
'menu-text': '#A4A4B1',
'menu-light-text': '#A4A4B1',
'menu-bg': '#32323F',
'menu-subheader-fg': '#EFEFEF',
'menu-border': '#69697D',
'menu-border': '#70707D',
'menu-shadow': '#000000',
/* Menu Items */
'menu-item-fg': '#FFFFFF',
'menu-item-selected-fg': '#FFFFFF',
'menu-item-selected-bg': '#1DA270',
'menu-item-disabled-fg': '#69697D',
'menu-item-icon-fg': '#A4A4A4',
'menu-item-selected-bg': '#157A54',
'menu-item-disabled-fg': '#70707D',
'menu-item-icon-fg': '#A4A4B1',
'menu-item-icon-selected-fg': '#FFFFFF',
'menu-item-link-fg': '#1DA270',
'menu-item-link-selected-fg': '#157A54',
'menu-item-link-selected-bg': '#484859',
/* Autocomplete */
'autocomplete-match-text': '#1DA270',
'autocomplete-selected-match-text': '#0A5438',
'autocomplete-item-selected-bg': '#69697D',
'autocomplete-match-text': '#17B378',
'autocomplete-selected-match-text': '#13D78D',
'autocomplete-item-selected-bg': '#70707D',
'autocomplete-add-new-circle-fg': '#FFFFFF',
'autocomplete-add-new-circle-bg': '#157A54',
'autocomplete-add-new-circle-selected-bg': '#1DA270',
/* Search */
'search-border': '#69697D',
'search-prev-next-button-fg': '#A4A4A4',
'search-border': '#70707D',
'search-prev-next-button-fg': '#A4A4B1',
'search-prev-next-button-bg': '#24242F',
/* Loading Spinners */
'loader-fg': '#1DA270',
'loader-bg': '#69697D',
'loader-fg': '#17B378',
'loader-bg': '#70707D',
/* Site Switcher */
'site-switcher-active-fg': '#FFFFFF',
'site-switcher-active-bg': '#000000',
/* Doc Menu */
'doc-menu-doc-options-fg': '#69697D',
'doc-menu-doc-options-hover-fg': '#A4A4A4',
'doc-menu-doc-options-hover-bg': '#69697D',
'doc-menu-doc-options-fg': '#70707D',
'doc-menu-doc-options-hover-fg': '#A4A4B1',
'doc-menu-doc-options-hover-bg': '#70707D',
/* Shortcut Keys */
'shortcut-key-fg': '#FFFFFF',
'shortcut-key-primary-fg': '#17B378',
'shortcut-key-secondary-fg': '#A4A4A4',
'shortcut-key-secondary-fg': '#A4A4B1',
'shortcut-key-bg': '#32323F',
'shortcut-key-border': '#A4A4A4',
'shortcut-key-border': '#A4A4B1',
/* Breadcrumbs */
'breadcrumbs-tag-fg': 'white',
'breadcrumbs-tag-bg': '#929299',
'breadcrumbs-tag-fg': '#FFFFFF',
'breadcrumbs-tag-bg': '#70707D',
'breadcrumbs-tag-alert-bg': '#D0021B',
/* Page Widget Picker */
'widget-picker-primary-bg': '#32323F',
'widget-picker-secondary-bg': '#262633',
'widget-picker-item-fg': '#FFFFFF',
'widget-picker-item-selected-bg': 'rgba(111,111,117,0.6)',
'widget-picker-item-disabled-bg': 'rgba(111,111,117,0.6)',
'widget-picker-icon': '#A4A4A4',
'widget-picker-primary-icon': '#1DA270',
'widget-picker-summary-icon': '#1DA270',
'widget-picker-border': 'rgba(111,111,117,0.6)',
'widget-picker-item-selected-bg': 'rgba(111,111,125,0.6)',
'widget-picker-item-disabled-bg': 'rgba(111,111,125,0.6)',
'widget-picker-icon': '#A4A4B1',
'widget-picker-primary-icon': '#17B378',
'widget-picker-summary-icon': '#17B378',
'widget-picker-border': 'rgba(111,111,125,0.6)',
'widget-picker-shadow': '#000000',
/* Code View */
@ -368,10 +378,10 @@ export const GristDark: ThemeColors = {
'code-view-literal': '#9ED682',
/* Importer */
'importer-table-info-border': '#69697D',
'importer-preview-border': '#69697D',
'importer-skipped-table-overlay': 'rgba(111,111,117,0.6)',
'importer-match-icon': '#69697D',
'importer-table-info-border': '#70707D',
'importer-preview-border': '#70707D',
'importer-skipped-table-overlay': 'rgba(111,111,125,0.6)',
'importer-match-icon': '#70707D',
'importer-outside-bg': '#32323F',
'importer-main-content-bg': '#262633',
'importer-active-file-bg': '#16B378',
@ -380,11 +390,11 @@ export const GristDark: ThemeColors = {
'importer-inactive-file-fg': '#FFFFFF',
/* Menu Toggles */
'menu-toggle-fg': '#A4A4A4',
'menu-toggle-hover-fg': '#1DA270',
'menu-toggle-active-fg': '#157A54',
'menu-toggle-fg': '#A4A4B1',
'menu-toggle-hover-fg': '#17B378',
'menu-toggle-active-fg': '#13D78D',
'menu-toggle-bg': '#32323F',
'menu-toggle-border': '#A4A4A4',
'menu-toggle-border': '#A4A4B1',
/* Info Button */
'info-button-fg': '#8F8F8F',
@ -393,31 +403,33 @@ export const GristDark: ThemeColors = {
/* Button Groups */
'button-group-fg': '#EFEFEF',
'button-group-light-fg': '#A4A4A4',
'button-group-bg': 'unset',
'button-group-icon': '#A4A4A4',
'button-group-border': '#69697D',
'button-group-border-hover': '#555563',
'button-group-light-fg': '#A4A4B1',
'button-group-bg': 'transparent',
'button-group-bg-hover': 'rgba(111,111,125,0.25)',
'button-group-icon': '#A4A4B1',
'button-group-border': '#70707D',
'button-group-border-hover': '#646473',
'button-group-selected-fg': '#EFEFEF',
'button-group-light-selected-fg': '#1DA270',
'button-group-selected-bg': '#555563',
'button-group-selected-border': '#555563',
'button-group-light-selected-fg': '#17B378',
'button-group-selected-bg': '#646473',
'button-group-selected-border': '#646473',
/* Access Rules */
'access-rules-table-header-fg': '#EFEFEF',
'access-rules-table-header-bg': '#57575F',
'access-rules-table-body-fg': '#A4A4A4',
'access-rules-table-border': '#A4A4A4',
'access-rules-column-list-border': '#69697D',
'access-rules-table-header-bg': '#60606D',
'access-rules-table-body-fg': '#A4A4B1',
'access-rules-table-body-light-fg': '#70707D',
'access-rules-table-border': '#A4A4B1',
'access-rules-column-list-border': '#70707D',
'access-rules-column-item-fg': '#EFEFEF',
'access-rules-column-item-bg': '#57575F',
'access-rules-column-item-icon-fg': '#A4A4A4',
'access-rules-column-item-bg': '#60606D',
'access-rules-column-item-icon-fg': '#A4A4B1',
'access-rules-column-item-icon-hover-fg': '#EFEFEF',
'access-rules-column-item-icon-hover-bg': '#A4A4A4',
'access-rules-column-item-icon-hover-bg': '#A4A4B1',
'access-rules-formula-editor-bg': '#32323F',
'access-rules-formula-editor-border-hover': '#69697D',
'access-rules-formula-editor-bg-disabled': '#57575F',
'access-rules-formula-editor-focus': '#1DA270',
'access-rules-formula-editor-border-hover': '#70707D',
'access-rules-formula-editor-bg-disabled': '#60606D',
'access-rules-formula-editor-focus': '#17B378',
/* Cells */
'cell-fg': '#FFFFFF',
@ -425,81 +437,113 @@ export const GristDark: ThemeColors = {
'cell-zebra-bg': '#262633',
/* Charts */
'chart-fg': '#A4A4A4',
'chart-fg': '#A4A4B1',
'chart-bg': '#32323F',
'chart-legend-bg': '#32323F80',
'chart-x-axis': '#A4A4A4',
'chart-y-axis': '#A4A4A4',
'chart-legend-bg': 'rgba(50,50,63,0.5)',
'chart-x-axis': '#A4A4B1',
'chart-y-axis': '#A4A4B1',
/* Comments */
'comments-popup-header-bg': '#262633',
'comments-popup-body-bg': '#32323F',
'comments-popup-border': '#69697D',
'comments-user-name-fg': '#DFDFDF',
'comments-popup-border': '#70707D',
'comments-user-name-fg': '#EFEFEF',
'comments-panel-topic-bg': '#32323F',
'comments-panel-topic-border': '#555563',
'comments-panel-resolved-topic-bg': '#262634',
'comments-panel-resolved-topic-bg': '#262633',
/* Date Picker */
'date-picker-selected-fg': '#FFFFFF',
'date-picker-selected-bg': '#7F7F7F',
'date-picker-selected-bg-hover': '#8F8F8F',
'date-picker-selected-bg': '#7A7A8D',
'date-picker-selected-bg-hover': '#8D8D9C',
'date-picker-today-fg': '#FFFFFF',
'date-picker-today-bg': '#1DA270',
'date-picker-today-bg-hover': '#157A54',
'date-picker-range-start-end-bg': '#7F7F7F',
'date-picker-range-start-end-bg-hover': '#8F8F8F',
'date-picker-range-bg': '#57575F',
'date-picker-range-bg-hover': '#7F7F7F',
'date-picker-today-bg': '#157A54',
'date-picker-today-bg-hover': '#1DA270',
'date-picker-range-start-end-bg': '#7A7A8D',
'date-picker-range-start-end-bg-hover': '#8D8D9C',
'date-picker-range-bg': '#60606D',
'date-picker-range-bg-hover': '#7A7A8D',
/* Tutorials */
'tutorials-popup-border': '#69697D',
'tutorials-popup-border': '#70707D',
'tutorials-popup-header-fg': '#FFFFFF',
'tutorials-popup-box-bg': '#57575F',
'tutorials-popup-box-bg': '#60606D',
/* Ace */
'ace-editor-bg': '#32323F',
'ace-autocomplete-primary-fg': '#EFEFEF',
'ace-autocomplete-secondary-fg': '#A4A4A4',
'ace-autocomplete-secondary-fg': '#A4A4B1',
'ace-autocomplete-highlighted-fg': '#FFFFFF',
'ace-autocomplete-bg': '#32323F',
'ace-autocomplete-border': '#69697D',
'ace-autocomplete-border': '#70707D',
'ace-autocomplete-link': '#28BE86',
'ace-autocomplete-link-highlighted': '#45D48B',
'ace-autocomplete-active-line-bg': '#555563',
'ace-autocomplete-line-border-hover': 'rgba(111,111,117,0.3)',
'ace-autocomplete-line-bg-hover': 'rgba(111,111,117,0.3)',
'ace-autocomplete-line-border-hover': 'rgba(111,111,125,0.3)',
'ace-autocomplete-line-bg-hover': 'rgba(111,111,125,0.3)',
/* Color Select */
'color-select-fg': '#EFEFEF',
'color-select-fg': '#A4A4B1',
'color-select-bg': '#32323F',
'color-select-shadow': '#000000',
'color-select-font-options-border': '#69697D',
'color-select-font-options-border': '#555563',
'color-select-font-option-fg': '#EFEFEF',
'color-select-font-option-bg': '#32323F',
'color-select-font-option-bg-hover': '#262633',
'color-select-font-option-bg-hover': 'rgba(111,111,125,0.25)',
'color-select-font-option-fg-selected': '#EFEFEF',
'color-select-font-option-bg-selected': '#555563',
'color-select-color-square-border': '#A4A4A4',
'color-select-font-option-bg-selected': '#646473',
'color-select-color-square-border': '#A4A4B1',
'color-select-color-square-border-empty': '#EFEFEF',
'color-select-input-fg': '#EFEFEF',
'color-select-input-fg': '#A4A4B1',
'color-select-input-bg': '#32323F',
'color-select-input-border': '#69697D',
'color-select-input-border': '#70707D',
/* Highlighted Code */
'highlighted-code-block-bg': '#262633',
'highlighted-code-block-bg-disabled': '#555563',
'highlighted-code-fg': '#A4A4A4',
'highlighted-code-border': '#69697D',
'highlighted-code-bg-disabled': '#555563',
'highlighted-code-fg': '#A4A4B1',
'highlighted-code-border': '#70707D',
'highlighted-code-bg-disabled': '#32323F',
/* Login Page */
'login-page-bg': '#32323F',
'login-page-backdrop': '#404150',
'login-page-line': '#57575F',
'login-page-line': '#60606D',
'login-page-google-button-fg': '#FFFFFF',
'login-page-google-button-bg': '#404150',
'login-page-google-button-bg-hover': '#555563',
'login-page-google-button-border': '#70707D',
/* Formula Assistant */
'formula-assistant-header-bg': '#262633',
'formula-assistant-border': '#69697D',
'formula-assistant-border': '#70707D',
'formula-assistant-preformatted-text-bg': '#262633',
/* Attachments */
'attachments-editor-button-fg': '#17B378',
'attachments-editor-button-hover-fg': '#13D78D',
'attachments-editor-button-bg': '#404150',
'attachments-editor-button-hover-bg': '#555563',
'attachments-editor-button-border': '#70707D',
'attachments-editor-button-icon': '#A4A4B1',
'attachments-editor-border': '#A4A4B1',
'attachments-cell-icon-fg': '#A4A4B1',
'attachments-cell-icon-bg': '#555563',
'attachments-cell-icon-hover-bg': '#70707D',
/* Switches */
'switch-slider-fg': '#70707D',
'switch-circle-fg': '#EFEFEF',
/* Announcement Popups */
'announcement-popup-fg': '#FFFFFF',
'announcement-popup-bg': '#404150',
/* Scroll Shadow */
'scroll-shadow': 'rgba(0,0,0,0.25)',
/* Toggle Checkboxes */
'toggle-checkbox-fg': '#A4A4B1',
/* Numeric Spinners */
'numeric-spinner-fg': '#A4A4B1',
};

@ -68,8 +68,6 @@ export const GristLight: ThemeColors = {
'tooltip-close-button-fg': 'white',
'tooltip-close-button-hover-fg': 'black',
'tooltip-close-button-hover-bg': 'white',
'tooltip-popup-header-fg': 'white',
'tooltip-popup-header-bg': '#16B378',
/* Modals */
'modal-bg': 'white',
@ -107,6 +105,7 @@ export const GristLight: ThemeColors = {
/* Cell Editor */
'cell-editor-fg': '#262633',
'cell-editor-placeholder-fg': '#929299',
'cell-editor-bg': '#FFFFFF',
/* Cursor */
@ -115,12 +114,11 @@ export const GristLight: ThemeColors = {
'cursor-readonly': '#929299',
/* Tables */
'table-header-fg': 'unset',
'table-header-selected-fg': 'unset',
'table-header-fg': '#000',
'table-header-selected-fg': '#000',
'table-header-bg': '#F7F7F7',
'table-header-selected-bg': '#E8E8E8',
'table-header-border': 'lightgray',
'table-header-border-dark': '#D9D9D9',
'table-body-bg': 'white',
'table-body-border': '#D9D9D9',
'table-add-new-bg': 'inherit',
@ -128,6 +126,7 @@ export const GristLight: ThemeColors = {
'table-frozen-columns-border': '#999999',
'table-drag-drop-indicator': 'gray',
'table-drag-drop-shadow': '#F0F0F0',
'table-cell-summary-bg': 'rgba(217,217,217,0.6)',
/* Cards */
'card-compact-widget-bg': 'rgba(217,217,217,0.6)',
@ -176,13 +175,13 @@ export const GristLight: ThemeColors = {
'control-primary-fg': '#FFFFFF',
'control-primary-bg': '#16B378',
'control-secondary-fg': '#929299',
'control-secondary-disabled-fg': '#D9D9D9',
'control-hover-fg': '#009058',
'control-primary-hover-bg': '#009058',
'control-secondary-hover-fg': '#262633',
'control-secondary-hover-bg': '#D9D9D9',
'control-disabled-fg': '#FFFFFF',
'control-disabled-bg': '#929299',
'control-primary-disabled': '#A2E1C9',
'control-border': '1px solid #11B683',
/* Checkboxes */
@ -243,7 +242,6 @@ export const GristLight: ThemeColors = {
'right-panel-disabled-overlay': '#F7F7F7',
'right-panel-toggle-button-enabled-fg': '#FFFFFF',
'right-panel-toggle-button-enabled-bg': '#262633',
'right-panel-toggle-button-enabled-hover-fg': '#D9D9D9',
'right-panel-toggle-button-disabled-fg': '#FFFFFF',
'right-panel-toggle-button-disabled-bg': '#E8E8E8',
'right-panel-field-settings-bg': '#E8E8E8',
@ -255,8 +253,11 @@ export const GristLight: ThemeColors = {
'document-history-snapshot-bg': 'white',
'document-history-snapshot-selected-bg': '#262633',
'document-history-snapshot-border': 'rgba(217,217,217,0.6)',
'document-history-activity-text': '#000000',
'document-history-activity-text-light': '#333333',
'document-history-activity-text': '#262633',
'document-history-activity-text-light': '#929299',
'document-history-table-header-fg': '#000',
'document-history-table-border': 'lightgray',
'document-history-table-border-light': '#D9D9D9',
/* Accents */
'accent-icon': '#16B378',
@ -276,6 +277,16 @@ export const GristLight: ThemeColors = {
'input-readonly-bg': '#F7F7F7',
'input-readonly-border': '#E8E8E8',
/* Choice Tokens */
'choice-token-fg': '#000000',
'choice-token-blank-fg': '#929299',
'choice-token-bg': '#E8E8E8',
'choice-token-selected-bg': '#D9D9D9',
'choice-token-selected-border': '#16B378',
'choice-token-invalid-fg': '#000000',
'choice-token-invalid-bg': 'white',
'choice-token-invalid-border': '#D0021B',
/* Choice Entry */
'choice-entry-bg': 'white',
'choice-entry-border': '#D9D9D9',
@ -284,7 +295,6 @@ export const GristLight: ThemeColors = {
/* Select Buttons */
'select-button-fg': '#262633',
'select-button-placeholder-fg': '#929299',
'select-button-disabled-fg': 'grey',
'select-button-bg': 'white',
'select-button-border': '#D9D9D9',
'select-button-border-invalid': '#D0021B',
@ -293,7 +303,7 @@ export const GristLight: ThemeColors = {
'menu-text': '#929299',
'menu-light-text': '#929299',
'menu-bg': 'white',
'menu-subheader-fg': 'unset',
'menu-subheader-fg': '#262633',
'menu-border': '#E8E8E8',
'menu-shadow': 'rgba(38, 38, 51, 0.6)',
@ -304,14 +314,14 @@ export const GristLight: ThemeColors = {
'menu-item-disabled-fg': '#D9D9D9',
'menu-item-icon-fg': '#929299',
'menu-item-icon-selected-fg': 'white',
'menu-item-link-fg': '#16B378',
'menu-item-link-selected-fg': '#009058',
'menu-item-link-selected-bg': '#E8E8E8',
/* Autocomplete */
'autocomplete-match-text': '#16B378',
'autocomplete-selected-match-text': '#B1FFE2',
'autocomplete-item-selected-bg': '#E8E8E8',
'autocomplete-add-new-circle-fg': '#FFFFFF',
'autocomplete-add-new-circle-bg': '#16B378',
'autocomplete-add-new-circle-selected-bg': '#009058',
/* Search */
'search-border': 'grey',
@ -346,7 +356,7 @@ export const GristLight: ThemeColors = {
/* Page Widget Picker */
'widget-picker-primary-bg': 'white',
'widget-picker-secondary-bg': '#F7F7F7',
'widget-picker-item-fg': 'unset',
'widget-picker-item-fg': '#262633',
'widget-picker-item-selected-bg': 'rgba(217,217,217,0.6)',
'widget-picker-item-disabled-bg': 'rgba(217,217,217,0.6)',
'widget-picker-icon': '#929299',
@ -394,7 +404,8 @@ export const GristLight: ThemeColors = {
/* Button Groups */
'button-group-fg': '#262633',
'button-group-light-fg': '#929299',
'button-group-bg': 'unset',
'button-group-bg': 'transparent',
'button-group-bg-hover': '#D9D9D9',
'button-group-icon': '#929299',
'button-group-border': '#D9D9D9',
'button-group-border-hover': '#BFBFBF',
@ -407,6 +418,7 @@ export const GristLight: ThemeColors = {
'access-rules-table-header-fg': '#262633',
'access-rules-table-header-bg': 'rgba(217,217,217,0.6)',
'access-rules-table-body-fg': '#929299',
'access-rules-table-body-light-fg': '#D9D9D9',
'access-rules-table-border': '#929299',
'access-rules-column-list-border': '#D9D9D9',
'access-rules-column-item-fg': '#262633',
@ -476,8 +488,7 @@ export const GristLight: ThemeColors = {
'color-select-shadow': 'rgba(38,38,51,0.6)',
'color-select-font-options-border': '#D9D9D9',
'color-select-font-option-fg': '#262633',
'color-select-font-option-bg': '#FFFFFF',
'color-select-font-option-bg-hover': '#F7F7F7',
'color-select-font-option-bg-hover': '#D9D9D9',
'color-select-font-option-fg-selected': '#FFFFFF',
'color-select-font-option-bg-selected': '#262633',
'color-select-color-square-border': '#D9D9D9',
@ -497,9 +508,42 @@ export const GristLight: ThemeColors = {
'login-page-bg': 'white',
'login-page-backdrop': '#F5F8FA',
'login-page-line': '#F7F7F7',
'login-page-google-button-fg': '#262633',
'login-page-google-button-bg': '#F7F7F7',
'login-page-google-button-bg-hover': '#E8E8E8',
'login-page-google-button-border': '#D9D9D9',
/* Formula Assistant */
'formula-assistant-header-bg': '#F7F7F7',
'formula-assistant-border': '#D9D9D9',
'formula-assistant-preformatted-text-bg': '#F7F7F7',
/* Attachments */
'attachments-editor-button-fg': '#009058',
'attachments-editor-button-hover-fg': '#16B378',
'attachments-editor-button-bg': '#FFFFFF',
'attachments-editor-button-hover-bg': '#E8E8E8',
'attachments-editor-button-border': '#D9D9D9',
'attachments-editor-button-icon': '#929299',
'attachments-editor-border': '#E8E8E8',
'attachments-cell-icon-fg': 'white',
'attachments-cell-icon-bg': '#D9D9D9',
'attachments-cell-icon-hover-bg': '#929299',
/* Switch */
'switch-slider-fg': '#ccc',
'switch-circle-fg': 'white',
/* Announcement Popups */
'announcement-popup-fg': '#000000',
'announcement-popup-bg': '#DCF4EB',
/* Scroll Shadow */
'scroll-shadow': 'rgba(217,217,217,0.6)',
/* Toggle Checkboxes */
'toggle-checkbox-fg': '#606060',
/* Numeric Spinners */
'numeric-spinner-fg': '#606060',
};

@ -468,7 +468,9 @@ describe('CellColor', function() {
await gu.openCellColorPicker();
// check color preview is correct
assert.equal(await driver.find('.test-text-hex').value(), '#606060');
assert.equal(await driver.find('.test-text-hex').value(), 'default');
assert.equal(await driver.find('.test-text-color-square').getCssValue('background-color'),
'rgba(96, 96, 96, 1)');
// close color picker
await driver.sendKeys(Key.ENTER);
@ -482,7 +484,9 @@ describe('CellColor', function() {
await gu.openCellColorPicker();
// check color preview is correct
assert.equal(await driver.find('.test-text-hex').value(), '#2CB0AF');
assert.equal(await driver.find('.test-text-hex').value(), 'default');
assert.equal(await driver.find('.test-text-color-square').getCssValue('background-color'),
'rgba(44, 176, 175, 1)');
// close picker
await driver.sendKeys(Key.ESCAPE);

@ -441,7 +441,7 @@ describe('ChoiceList', function() {
const convertColumn = stackWrapFunc(async function(typeRe: RegExp) {
await gu.setType(typeRe);
await gu.waitForServer();
await driver.findContent('.type_transform_prompt button', /Apply/).click();
await driver.findContent('.test-type-transform-apply', /Apply/).click();
await gu.waitForServer();
});

@ -278,7 +278,7 @@ describe('CustomWidgets', function () {
assert.equal(await getWidgetColor(), 'rgba(38, 38, 51, 1)');
// Switch the theme to GristDark.
await gu.setGristTheme({appearance: 'dark'});
await gu.setGristTheme({appearance: 'dark', syncWithOS: false});
await driver.navigate().back();
await gu.waitForDocToLoad();
@ -286,7 +286,7 @@ describe('CustomWidgets', function () {
assert.equal(await getWidgetColor(), 'rgba(239, 239, 239, 1)');
// Switch back to GristLight.
await gu.setGristTheme({appearance: 'light'});
await gu.setGristTheme({appearance: 'light', syncWithOS: true});
await driver.navigate().back();
await gu.waitForDocToLoad();

@ -260,13 +260,14 @@ describe('MultiColumn', function() {
assert.isFalse(await deriveDisabled());
assert.isFalse(await labelDisabled());
assert.isFalse(await setTriggerDisabled());
assert.isFalse(await transformSectionDisabled());
assert.isTrue(await transformSectionDisabled());
assert.isFalse(await addConditionDisabled());
assert.isFalse(await columnTypeDisabled());
// Make one column a data column, to disable type selector.
await selectColumns('Test1');
await gu.changeBehavior('Convert column to data');
assert.isFalse(await transformSectionDisabled());
await selectColumns('Test1', 'Test3');
assert.isTrue(await columnTypeDisabled());
@ -1287,8 +1288,7 @@ async function setDataDisabled() {
}
async function transformSectionDisabled() {
const elements = await driver.findAll(".test-panel-transform .test-panel-disabled-section");
return elements.length === 1;
return (await driver.find(".test-fbuilder-edit-transform").getAttribute('disabled')) === 'true';
}
async function addConditionDisabled() {

@ -154,12 +154,12 @@ describe("SelectBy", function() {
assert.equal(await gu.getDetailCell({section, rowNum: 1, col: 'A'}).getText(), '1');
// Check there are nav buttons in the card view.
assert.equal(await section.find('.btn.detail-left').isPresent(), true);
assert.equal(await section.find('.btn.detail-right').isPresent(), true);
assert.equal(await section.find('.detail-button.detail-left').isPresent(), true);
assert.equal(await section.find('.detail-button.detail-right').isPresent(), true);
assert.equal(await section.find('.grist-single-record__menu__count').getText(), '1 OF 1');
// Now add a record to the source table using the card view.
await section.find('.btn.detail-add-btn').click();
await section.find('.detail-button.detail-add-btn').click();
assert.equal(await gu.getDetailCell({section, rowNum: 1, col: 'A'}).getText(), '');
await gu.getDetailCell({section, rowNum: 1, col: 'A'}).click();
await gu.sendKeys('1', Key.ENTER);

@ -3133,16 +3133,27 @@ export async function downloadSectionCsvGridCells(
export async function setGristTheme(options: {
appearance: 'light' | 'dark',
syncWithOS: boolean,
skipOpenSettingsPage?: boolean,
}) {
const {appearance, skipOpenSettingsPage} = options;
const {appearance, syncWithOS, skipOpenSettingsPage} = options;
if (!skipOpenSettingsPage) {
await openProfileSettingsPage();
}
await driver.find('.test-theme-config-appearance .test-select-open').click();
await driver.findContent('.test-select-menu li', appearance === 'light' ? 'Light' : 'Dark')
.click();
await waitForServer();
const syncWithOSCheckbox = await driver.find('.test-theme-config-sync-with-os');
const isSyncWithOSChecked = await syncWithOSCheckbox.getAttribute('checked') === 'true';
if (syncWithOS !== isSyncWithOSChecked) {
await syncWithOSCheckbox.click();
await waitForServer();
}
if (!syncWithOS) {
await driver.find('.test-theme-config-appearance .test-select-open').click();
await driver.findContent('.test-select-menu li', appearance === 'light' ? 'Light' : 'Dark')
.click();
await waitForServer();
}
}
} // end of namespace gristUtils

Loading…
Cancel
Save