From 273b976cabd25ce04f71f140794f2948d1d2fe7e Mon Sep 17 00:00:00 2001 From: George Gevoian Date: Thu, 21 Sep 2023 12:57:58 -0400 Subject: [PATCH] (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 --- app/client/aclui/ACLMemoEditor.ts | 6 +- app/client/aclui/ACLSelect.ts | 4 +- app/client/aclui/PermissionsWidget.ts | 6 +- app/client/components/AceEditor.css | 10 + app/client/components/ActionLog.css | 33 +- app/client/components/ActionLog.ts | 14 +- app/client/components/ColumnTransform.ts | 2 + app/client/components/DetailView.css | 19 +- app/client/components/DetailView.js | 32 +- app/client/components/GridView.css | 12 +- app/client/components/Preferences.css | 44 -- app/client/components/RawDataPage.ts | 2 +- app/client/components/RefSelect.ts | 19 +- app/client/components/SelectionSummary.ts | 4 +- app/client/components/TypeConversion.ts | 12 +- app/client/components/ViewConfigTab.js | 11 +- app/client/components/ViewLayout.css | 5 +- app/client/components/ViewLayout.ts | 2 +- app/client/components/buildViewSectionDom.ts | 8 +- app/client/components/modals.ts | 3 +- app/client/components/viewCommon.css | 5 +- app/client/lib/ACUserManager.ts | 8 +- app/client/lib/TokenField.ts | 8 +- app/client/lib/koForm.css | 5 +- app/client/models/AppModel.ts | 15 +- app/client/ui/AccountPage.ts | 17 +- app/client/ui/AccountPageCss.ts | 7 - app/client/ui/ColumnFilterMenu.ts | 5 - app/client/ui/DescriptionConfig.ts | 1 + app/client/ui/FieldConfig.ts | 7 +- app/client/ui/FloatingPopup.ts | 2 +- app/client/ui/LoginPagesCss.ts | 10 +- app/client/ui/Pages.ts | 5 +- app/client/ui/PinnedDocs.ts | 2 +- app/client/ui/RightPanel.ts | 1 - app/client/ui/RightPanelStyles.ts | 1 + app/client/ui/ShareMenu.ts | 7 +- app/client/ui/SupportGristNudge.ts | 7 +- app/client/ui/SupportGristPage.ts | 18 +- app/client/ui/TemplateDocs.ts | 4 +- app/client/ui/ThemeConfig.ts | 23 +- app/client/ui/ViewSectionMenu.ts | 9 +- app/client/ui/shadowScroll.ts | 4 +- app/client/ui2018/ColorSelect.ts | 28 +- app/client/ui2018/buttonSelect.ts | 14 +- app/client/ui2018/buttons.ts | 3 +- app/client/ui2018/checkbox.ts | 4 +- app/client/ui2018/cssVars.ts | 114 +++-- app/client/ui2018/links.ts | 8 +- app/client/ui2018/pages.ts | 2 +- app/client/ui2018/select.ts | 6 +- app/client/widgets/AbstractWidget.js | 10 +- app/client/widgets/AttachmentsEditor.ts | 34 +- app/client/widgets/AttachmentsWidget.ts | 14 +- app/client/widgets/CellStyle.ts | 45 +- app/client/widgets/CheckBox.css | 8 +- app/client/widgets/ChoiceEditor.js | 16 +- app/client/widgets/ChoiceListCell.ts | 12 +- app/client/widgets/ChoiceListEditor.ts | 35 +- app/client/widgets/ChoiceListEntry.ts | 15 +- app/client/widgets/ChoiceTextBox.ts | 10 +- app/client/widgets/ChoiceToken.ts | 24 +- app/client/widgets/DateTimeEditor.css | 8 + app/client/widgets/EditorButtons.ts | 6 +- app/client/widgets/EditorTooltip.ts | 4 +- app/client/widgets/FieldBuilder.css | 14 +- app/client/widgets/FieldBuilder.ts | 26 +- app/client/widgets/HyperLinkTextBox.ts | 6 +- app/client/widgets/NewAbstractWidget.ts | 12 +- app/client/widgets/NumericTextBox.ts | 2 +- app/client/widgets/Reference.ts | 6 +- app/client/widgets/ReferenceEditor.ts | 19 +- app/client/widgets/ReferenceList.ts | 4 +- app/client/widgets/ReferenceListEditor.ts | 6 +- app/client/widgets/Switch.css | 4 +- app/client/widgets/TextEditor.css | 4 + app/client/widgets/Toggle.ts | 3 +- app/common/ThemePrefs-ti.ts | 50 ++- app/common/ThemePrefs.ts | 66 ++- app/common/themes/GristDark.ts | 442 ++++++++++--------- app/common/themes/GristLight.ts | 80 +++- test/nbrowser/CellColor.ts | 8 +- test/nbrowser/ChoiceList.ts | 2 +- test/nbrowser/CustomWidgets.ts | 4 +- test/nbrowser/MultiColumn.ts | 6 +- test/nbrowser/SelectBy.ts | 6 +- test/nbrowser/gristUtils.ts | 21 +- 87 files changed, 979 insertions(+), 651 deletions(-) delete mode 100644 app/client/components/Preferences.css diff --git a/app/client/aclui/ACLMemoEditor.ts b/app/client/aclui/ACLMemoEditor.ts index 0cc9e46e..ecc111f4 100644 --- a/app/client/aclui/ACLMemoEditor.ts +++ b/app/client/aclui/ACLMemoEditor.ts @@ -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}; } `); diff --git a/app/client/aclui/ACLSelect.ts b/app/client/aclui/ACLSelect.ts index e96360d8..ae25985b 100644 --- a/app/client/aclui/ACLSelect.ts +++ b/app/client/aclui/ACLSelect.ts @@ -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; } `); diff --git a/app/client/aclui/PermissionsWidget.ts b/app/client/aclui/PermissionsWidget.ts index b812ac67..0f4e379e 100644 --- a/app/client/aclui/PermissionsWidget.ts +++ b/app/client/aclui/PermissionsWidget.ts @@ -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; diff --git a/app/client/components/AceEditor.css b/app/client/components/AceEditor.css index 4daec6c4..9ae188ab 100644 --- a/app/client/components/AceEditor.css +++ b/app/client/components/AceEditor.css @@ -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; } diff --git a/app/client/components/ActionLog.css b/app/client/components/ActionLog.css index 78006cee..57c8ae9b 100644 --- a/app/client/components/ActionLog.css +++ b/app/client/components/ActionLog.css @@ -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); +} diff --git a/app/client/components/ActionLog.ts b/app/client/components/ActionLog.ts index 3c68fb72..d1f3f9cc 100644 --- a/app/client/components/ActionLog.ts +++ b/app/client/components/ActionLog.ts @@ -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...'), diff --git a/app/client/components/ColumnTransform.ts b/app/client/components/ColumnTransform.ts index aadd9791..127caae2 100644 --- a/app/client/components/ColumnTransform.ts +++ b/app/client/components/ColumnTransform.ts @@ -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', () => { diff --git a/app/client/components/DetailView.css b/app/client/components/DetailView.css index 33cde4ca..45d9cdbe 100644 --- a/app/client/components/DetailView.css +++ b/app/client/components/DetailView.css @@ -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 { diff --git a/app/client/components/DetailView.js b/app/client/components/DetailView.js index 7fcda3a1..98b336cd 100644 --- a/app/client/components/DetailView.js +++ b/app/client/components/DetailView.js @@ -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'), + ), + ), )) ); }; diff --git a/app/client/components/GridView.css b/app/client/components/GridView.css index d44a32e7..c64f92dd 100644 --- a/app/client/components/GridView.css +++ b/app/client/components/GridView.css @@ -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; diff --git a/app/client/components/Preferences.css b/app/client/components/Preferences.css deleted file mode 100644 index 29c75514..00000000 --- a/app/client/components/Preferences.css +++ /dev/null @@ -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%; -} diff --git a/app/client/components/RawDataPage.ts b/app/client/components/RawDataPage.ts index 1f74d6f3..e4e05e43 100644 --- a/app/client/components/RawDataPage.ts +++ b/app/client/components/RawDataPage.ts @@ -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; diff --git a/app/client/components/RefSelect.ts b/app/client/components/RefSelect.ts index a751bd56..dade783a 100644 --- a/app/client/components/RefSelect.ts +++ b/app/client/components/RefSelect.ts @@ -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; +`); diff --git a/app/client/components/SelectionSummary.ts b/app/client/components/SelectionSummary.ts index e4f25c8c..23c37246 100644 --- a/app/client/components/SelectionSummary.ts +++ b/app/client/components/SelectionSummary.ts @@ -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; } diff --git a/app/client/components/TypeConversion.ts b/app/client/components/TypeConversion.ts index cb97fa32..f8181f3f 100644 --- a/app/client/components/TypeConversion.ts +++ b/app/client/components/TypeConversion.ts @@ -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; diff --git a/app/client/components/ViewConfigTab.js b/app/client/components/ViewConfigTab.js index de8057a6..409e05bd 100644 --- a/app/client/components/ViewConfigTab.js +++ b/app/client/components/ViewConfigTab.js @@ -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'), + )), ), ]; }); diff --git a/app/client/components/ViewLayout.css b/app/client/components/ViewLayout.css index 177e0a0d..bd5cc8a9 100644 --- a/app/client/components/ViewLayout.css +++ b/app/client/components/ViewLayout.css @@ -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; } diff --git a/app/client/components/ViewLayout.ts b/app/client/components/ViewLayout.ts index a7340c3e..75b24453 100644 --- a/app/client/components/ViewLayout.ts +++ b/app/client/components/ViewLayout.ts @@ -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; diff --git a/app/client/components/buildViewSectionDom.ts b/app/client/components/buildViewSectionDom.ts index 0715638f..e498e108 100644 --- a/app/client/components/buildViewSectionDom.ts +++ b/app/client/components/buildViewSectionDom.ts @@ -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; diff --git a/app/client/components/modals.ts b/app/client/components/modals.ts index 58b2464e..f95e157c 100644 --- a/app/client/components/modals.ts +++ b/app/client/components/modals.ts @@ -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); } } `); diff --git a/app/client/components/viewCommon.css b/app/client/components/viewCommon.css index dbdd4d96..859ee673 100644 --- a/app/client/components/viewCommon.css +++ b/app/client/components/viewCommon.css @@ -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 { diff --git a/app/client/lib/ACUserManager.ts b/app/client/lib/ACUserManager.ts index 3ce4e318..fb746a56 100644 --- a/app/client/lib/ACUserManager.ts +++ b/app/client/lib/ACUserManager.ts @@ -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; +`); diff --git a/app/client/lib/TokenField.ts b/app/client/lib/TokenField.ts index b9e46cee..f7e7073e 100644 --- a/app/client/lib/TokenField.ts +++ b/app/client/lib/TokenField.ts @@ -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; diff --git a/app/client/lib/koForm.css b/app/client/lib/koForm.css index c85b00f5..92f84175 100644 --- a/app/client/lib/koForm.css +++ b/app/client/lib/koForm.css @@ -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; } diff --git a/app/client/models/AppModel.ts b/app/client/models/AppModel.ts index 0cceeeed..7dfe341e 100644 --- a/app/client/models/AppModel.ts +++ b/app/client/models/AppModel.ts @@ -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); + })); } } diff --git a/app/client/ui/AccountPage.ts b/app/client/ui/AccountPage.ts index 3e7b4809..187ac7c3 100644 --- a/app/client/ui/AccountPage.ts +++ b/app/client/ui/AccountPage.ts @@ -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(this, ''); private _userObs = Observable.create(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}`; + } + } + })); + } } /** diff --git a/app/client/ui/AccountPageCss.ts b/app/client/ui/AccountPageCss.ts index f5147d27..d556b885 100644 --- a/app/client/ui/AccountPageCss.ts +++ b/app/client/ui/AccountPageCss.ts @@ -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}; -`); diff --git a/app/client/ui/ColumnFilterMenu.ts b/app/client/ui/ColumnFilterMenu.ts index 64fbd16b..e59b1707 100644 --- a/app/client/ui/ColumnFilterMenu.ts +++ b/app/client/ui/ColumnFilterMenu.ts @@ -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', }, }), diff --git a/app/client/ui/DescriptionConfig.ts b/app/client/ui/DescriptionConfig.ts index b838a40b..7e592769 100644 --- a/app/client/ui/DescriptionConfig.ts +++ b/app/client/ui/DescriptionConfig.ts @@ -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}; diff --git a/app/client/ui/FieldConfig.ts b/app/client/ui/FieldConfig.ts index 808fa8a9..62f1caec 100644 --- a/app/client/ui/FieldConfig.ts +++ b/app/client/ui/FieldConfig.ts @@ -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}; } `); diff --git a/app/client/ui/FloatingPopup.ts b/app/client/ui/FloatingPopup.ts index b593b1b7..19e0a559 100644 --- a/app/client/ui/FloatingPopup.ts +++ b/app/client/ui/FloatingPopup.ts @@ -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), () => { diff --git a/app/client/ui/LoginPagesCss.ts b/app/client/ui/LoginPagesCss.ts index 7d7e3708..22f44b47 100644 --- a/app/client/ui/LoginPagesCss.ts +++ b/app/client/ui/LoginPagesCss.ts @@ -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}; } `); diff --git a/app/client/ui/Pages.ts b/app/client/ui/Pages.ts index 4a9836ef..3d13fd7a 100644 --- a/app/client/ui/Pages.ts +++ b/app/client/ui/Pages.ts @@ -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; `); diff --git a/app/client/ui/PinnedDocs.ts b/app/client/ui/PinnedDocs.ts index 674f24d1..35d97a7d 100644 --- a/app/client/ui/PinnedDocs.ts +++ b/app/client/ui/PinnedDocs.ts @@ -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; diff --git a/app/client/ui/RightPanel.ts b/app/client/ui/RightPanel.ts index 3574fc31..a4d887c3 100644 --- a/app/client/ui/RightPanel.ts +++ b/app/client/ui/RightPanel.ts @@ -311,7 +311,6 @@ export class RightPanel extends Disposable { ]), cssLabel(t("TRANSFORM")), dom.maybe(fieldBuilder, builder => builder.buildTransformDom()), - dom.maybe(isMultiSelect, () => disabledSection()), testId('panel-transform'), ), this._disableIfReadonly(), diff --git a/app/client/ui/RightPanelStyles.ts b/app/client/ui/RightPanelStyles.ts index 58ed5ac5..fac081e5 100644 --- a/app/client/ui/RightPanelStyles.ts +++ b/app/client/ui/RightPanelStyles.ts @@ -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}; diff --git a/app/client/ui/ShareMenu.ts b/app/client/ui/ShareMenu.ts index ddeae9a2..557d2ea6 100644 --- a/app/client/ui/ShareMenu.ts +++ b/app/client/ui/ShareMenu.ts @@ -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}; } `); diff --git a/app/client/ui/SupportGristNudge.ts b/app/client/ui/SupportGristNudge.ts index bed48c53..77de6c74 100644 --- a/app/client/ui/SupportGristNudge.ts +++ b/app/client/ui/SupportGristNudge.ts @@ -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}; } `); diff --git a/app/client/ui/SupportGristPage.ts b/app/client/ui/SupportGristPage.ts index 25cb9d35..f5a50586 100644 --- a/app/client/ui/SupportGristPage.ts +++ b/app/client/ui/SupportGristPage.ts @@ -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() { diff --git a/app/client/ui/TemplateDocs.ts b/app/client/ui/TemplateDocs.ts index 0aa5bd6c..73928421 100644 --- a/app/client/ui/TemplateDocs.ts +++ b/app/client/ui/TemplateDocs.ts @@ -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', ` diff --git a/app/client/ui/ThemeConfig.ts b/app/client/ui/ThemeConfig.ts index 2501a44d..7b371a62 100644 --- a/app/client/ui/ThemeConfig.ts +++ b/app/client/ui/ThemeConfig.ts @@ -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'), ), diff --git a/app/client/ui/ViewSectionMenu.ts b/app/client/ui/ViewSectionMenu.ts index d8d8b8f2..e7241167 100644 --- a/app/client/ui/ViewSectionMenu.ts +++ b/app/client/ui/ViewSectionMenu.ts @@ -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', ` diff --git a/app/client/ui/shadowScroll.ts b/app/client/ui/shadowScroll.ts index 0fb0cc90..3610cff6 100644 --- a/app/client/ui/shadowScroll.ts +++ b/app/client/ui/shadowScroll.ts @@ -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 diff --git a/app/client/ui2018/ColorSelect.ts b/app/client/ui2018/ColorSelect.ts index 4a73438c..4f9eb6a6 100644 --- a/app/client/ui2018/ColorSelect.ts +++ b/app/client/ui2018/ColorSelect.ts @@ -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, @@ -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}; } diff --git a/app/client/ui2018/buttonSelect.ts b/app/client/ui2018/buttonSelect.ts index 065af49c..b8b82d00 100644 --- a/app/client/ui2018/buttonSelect.ts +++ b/app/client/ui2018/buttonSelect.ts @@ -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', ` diff --git a/app/client/ui2018/buttons.ts b/app/client/ui2018/buttons.ts index 2bb08d9c..efd13456 100644 --- a/app/client/ui2018/buttons.ts +++ b/app/client/ui2018/buttons.ts @@ -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; } `); diff --git a/app/client/ui2018/checkbox.ts b/app/client/ui2018/checkbox.ts index 36e9a6f0..77122084 100644 --- a/app/client/ui2018/checkbox.ts +++ b/app/client/ui2018/checkbox.ts @@ -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; diff --git a/app/client/ui2018/cssVars.ts b/app/client/ui2018/cssVars.ts index affeb047..0e1fcf99 100644 --- a/app/client/ui2018/cssVars.ts +++ b/app/client/ui2018/cssVars.ts @@ -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); diff --git a/app/client/ui2018/links.ts b/app/client/ui2018/links.ts index a6bf74d3..e46bc21c 100644 --- a/app/client/ui2018/links.ts +++ b/app/client/ui2018/links.ts @@ -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}); `); diff --git a/app/client/ui2018/pages.ts b/app/client/ui2018/pages.ts index 52c3931e..c2ec4604 100644 --- a/app/client/ui2018/pages.ts +++ b/app/client/ui2018/pages.ts @@ -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}; diff --git a/app/client/ui2018/select.ts b/app/client/ui2018/select.ts index ea52d1bc..9921fb72 100644 --- a/app/client/ui2018/select.ts +++ b/app/client/ui2018/select.ts @@ -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; } `); diff --git a/app/client/widgets/AbstractWidget.js b/app/client/widgets/AbstractWidget.js index f83e8b67..5a529334 100644 --- a/app/client/widgets/AbstractWidget.js +++ b/app/client/widgets/AbstractWidget.js @@ -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); diff --git a/app/client/widgets/AttachmentsEditor.ts b/app/client/widgets/AttachmentsEditor.ts index 303fbbe0..28d6593e 100644 --- a/app/client/widgets/AttachmentsEditor.ts +++ b/app/client/widgets/AttachmentsEditor.ts @@ -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; diff --git a/app/client/widgets/AttachmentsWidget.ts b/app/client/widgets/AttachmentsWidget.ts index 86183ee1..fd345971 100644 --- a/app/client/widgets/AttachmentsWidget.ts +++ b/app/client/widgets/AttachmentsWidget.ts @@ -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; `); diff --git a/app/client/widgets/CellStyle.ts b/app/client/widgets/CellStyle.ts index e4969fc9..a7192baa 100644 --- a/app/client/widgets/CellStyle.ts +++ b/app/client/widgets/CellStyle.ts @@ -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, diff --git a/app/client/widgets/CheckBox.css b/app/client/widgets/CheckBox.css index 1739ca02..531823df 100644 --- a/app/client/widgets/CheckBox.css +++ b/app/client/widgets/CheckBox.css @@ -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; } diff --git a/app/client/widgets/ChoiceEditor.js b/app/client/widgets/ChoiceEditor.js index 1e7aef72..19ebfcba 100644 --- a/app/client/widgets/ChoiceEditor.js +++ b/app/client/widgets/ChoiceEditor.js @@ -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; diff --git a/app/client/widgets/ChoiceListCell.ts b/app/client/widgets/ChoiceListCell.ts index 6c3bb64e..dd33f47a 100644 --- a/app/client/widgets/ChoiceListCell.ts +++ b/app/client/widgets/ChoiceListCell.ts @@ -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') - ) - ); + ); + }); }), ); } diff --git a/app/client/widgets/ChoiceListEditor.ts b/app/client/widgets/ChoiceListEditor.ts index 753b202d..60329b63 100644 --- a/app/client/widgets/ChoiceListEditor.ts +++ b/app/client/widgets/ChoiceListEditor.ts @@ -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(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().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}; `); diff --git a/app/client/widgets/ChoiceListEntry.ts b/app/client/widgets/ChoiceListEntry.ts index e2613030..9e83197d 100644 --- a/app/client/widgets/ChoiceListEntry.ts +++ b/app/client/widgets/ChoiceListEntry.ts @@ -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; } `); diff --git a/app/client/widgets/ChoiceTextBox.ts b/app/client/widgets/ChoiceTextBox.ts index 558328fc..c4a87ef3 100644 --- a/app/client/widgets/ChoiceTextBox.ts +++ b/app/client/widgets/ChoiceTextBox.ts @@ -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; 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; `); diff --git a/app/client/widgets/ChoiceToken.ts b/app/client/widgets/ChoiceToken.ts index 87813ccb..cb146ffe 100644 --- a/app/client/widgets/ChoiceToken.ts +++ b/app/client/widgets/ChoiceToken.ts @@ -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}; diff --git a/app/client/widgets/DateTimeEditor.css b/app/client/widgets/DateTimeEditor.css index bf86319e..1a660ac1 100644 --- a/app/client/widgets/DateTimeEditor.css +++ b/app/client/widgets/DateTimeEditor.css @@ -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, diff --git a/app/client/widgets/EditorButtons.ts b/app/client/widgets/EditorButtons.ts index 81cdbe51..71f28648 100644 --- a/app/client/widgets/EditorButtons.ts +++ b/app/client/widgets/EditorButtons.ts @@ -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; `); diff --git a/app/client/widgets/EditorTooltip.ts b/app/client/widgets/EditorTooltip.ts index c806f912..b86dd246 100644 --- a/app/client/widgets/EditorTooltip.ts +++ b/app/client/widgets/EditorTooltip.ts @@ -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; diff --git a/app/client/widgets/FieldBuilder.css b/app/client/widgets/FieldBuilder.css index 52f88809..8ad6f597 100644 --- a/app/client/widgets/FieldBuilder.css +++ b/app/client/widgets/FieldBuilder.css @@ -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 { diff --git a/app/client/widgets/FieldBuilder.ts b/app/client/widgets/FieldBuilder.ts index 0b458d94..ab396c22 100644 --- a/app/client/widgets/FieldBuilder.ts +++ b/app/client/widgets/FieldBuilder.ts @@ -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(); }) diff --git a/app/client/widgets/HyperLinkTextBox.ts b/app/client/widgets/HyperLinkTextBox.ts index 20b17b37..501b61f3 100644 --- a/app/client/widgets/HyperLinkTextBox.ts +++ b/app/client/widgets/HyperLinkTextBox.ts @@ -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); diff --git a/app/client/widgets/NewAbstractWidget.ts b/app/client/widgets/NewAbstractWidget.ts index b58b744a..85a8c3fe 100644 --- a/app/client/widgets/NewAbstractWidget.ts +++ b/app/client/widgets/NewAbstractWidget.ts @@ -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; protected textColor: Observable; protected fillColor: Observable; - 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'; } /** diff --git a/app/client/widgets/NumericTextBox.ts b/app/client/widgets/NumericTextBox.ts index 48c7397b..48a3b342 100644 --- a/app/client/widgets/NumericTextBox.ts +++ b/app/client/widgets/NumericTextBox.ts @@ -172,7 +172,7 @@ const cssDecimalsBox = styled('div', ` margin-right: 16px; } &-disabled { - background-color: ${theme.rightPanelToggleButtonDisabledBg}; + opacity: 0.4; pointer-events: none; } `); diff --git a/app/client/widgets/Reference.ts b/app/client/widgets/Reference.ts index e0cef663..f060222e 100644 --- a/app/client/widgets/Reference.ts +++ b/app/client/widgets/Reference.ts @@ -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} } `); diff --git a/app/client/widgets/ReferenceEditor.ts b/app/client/widgets/ReferenceEditor.ts index a6d4f2e7..71ee3254 100644 --- a/app/client/widgets/ReferenceEditor.ts +++ b/app/client/widgets/ReferenceEditor.ts @@ -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; diff --git a/app/client/widgets/ReferenceList.ts b/app/client/widgets/ReferenceList.ts index 5c183f67..90f84456 100644 --- a/app/client/widgets/ReferenceList.ts +++ b/app/client/widgets/ReferenceList.ts @@ -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') diff --git a/app/client/widgets/ReferenceListEditor.ts b/app/client/widgets/ReferenceListEditor.ts index 2fe98377..be6f7426 100644 --- a/app/client/widgets/ReferenceListEditor.ts +++ b/app/client/widgets/ReferenceListEditor.ts @@ -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}; } `); diff --git a/app/client/widgets/Switch.css b/app/client/widgets/Switch.css index 07b0bcc3..5bc086d4 100644 --- a/app/client/widgets/Switch.css +++ b/app/client/widgets/Switch.css @@ -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; } diff --git a/app/client/widgets/TextEditor.css b/app/client/widgets/TextEditor.css index 47bf1bcc..e2fa80ea 100644 --- a/app/client/widgets/TextEditor.css +++ b/app/client/widgets/TextEditor.css @@ -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; diff --git a/app/client/widgets/Toggle.ts b/app/client/widgets/Toggle.ts index e4e3c0d7..24032e56 100644 --- a/app/client/widgets/Toggle.ts +++ b/app/client/widgets/Toggle.ts @@ -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) { diff --git a/app/common/ThemePrefs-ti.ts b/app/common/ThemePrefs-ti.ts index 980eb7f7..b581cacb 100644 --- a/app/common/ThemePrefs-ti.ts +++ b/app/common/ThemePrefs-ti.ts @@ -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 = { diff --git a/app/common/ThemePrefs.ts b/app/common/ThemePrefs.ts index aee78492..b45cc571 100644 --- a/app/common/ThemePrefs.ts +++ b/app/common/ThemePrefs.ts @@ -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; @@ -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', diff --git a/app/common/themes/GristDark.ts b/app/common/themes/GristDark.ts index dccee33b..af36cfd4 100644 --- a/app/common/themes/GristDark.ts +++ b/app/common/themes/GristDark.ts @@ -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', }; diff --git a/app/common/themes/GristLight.ts b/app/common/themes/GristLight.ts index 3a734a19..0e91f918 100644 --- a/app/common/themes/GristLight.ts +++ b/app/common/themes/GristLight.ts @@ -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', }; diff --git a/test/nbrowser/CellColor.ts b/test/nbrowser/CellColor.ts index 4026447e..6ef7ad97 100644 --- a/test/nbrowser/CellColor.ts +++ b/test/nbrowser/CellColor.ts @@ -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); diff --git a/test/nbrowser/ChoiceList.ts b/test/nbrowser/ChoiceList.ts index 6108e2e2..2267e039 100644 --- a/test/nbrowser/ChoiceList.ts +++ b/test/nbrowser/ChoiceList.ts @@ -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(); }); diff --git a/test/nbrowser/CustomWidgets.ts b/test/nbrowser/CustomWidgets.ts index 0deb22bd..c0911405 100644 --- a/test/nbrowser/CustomWidgets.ts +++ b/test/nbrowser/CustomWidgets.ts @@ -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(); diff --git a/test/nbrowser/MultiColumn.ts b/test/nbrowser/MultiColumn.ts index 401c4a26..c1b63092 100644 --- a/test/nbrowser/MultiColumn.ts +++ b/test/nbrowser/MultiColumn.ts @@ -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() { diff --git a/test/nbrowser/SelectBy.ts b/test/nbrowser/SelectBy.ts index d385d10c..8fd90d3b 100644 --- a/test/nbrowser/SelectBy.ts +++ b/test/nbrowser/SelectBy.ts @@ -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); diff --git a/test/nbrowser/gristUtils.ts b/test/nbrowser/gristUtils.ts index 70220941..7f98b836 100644 --- a/test/nbrowser/gristUtils.ts +++ b/test/nbrowser/gristUtils.ts @@ -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