More UI Tweaks, Testing Variable Fonts for Sidebar/Tabs ()

* MonoFontSize type, add label font, theme vars for sidebar

* fix line-height for tabs

* experiment with variable label font

* lato font, fix open ai fonts, fix cmdinput font
This commit is contained in:
Mike Sawka 2024-02-27 16:26:58 -08:00 committed by GitHub
parent d9ca9394ac
commit 3f83441868
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 195 additions and 115 deletions

BIN
public/fonts/lato-bold.woff Normal file

Binary file not shown.

Binary file not shown.

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
@import "./root.less";
@import "./overrides.less";
html,
body {
@ -153,6 +154,12 @@ svg.icon {
background-color: var(--scrollbar-thumb-hover-color) !important;
}
.no-highlight-scrollbar {
&::-webkit-scrollbar-thumb:hover {
background-color: var(--scrollbar-thumb-color) !important;
}
}
.hide-scrollbar {
&::-webkit-scrollbar {
display: none;

16
src/app/overrides.less Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
:root {
// can put dev overrides for testing here
--label-font-family: "Lato", sans-serif;
--sidebar-font-size: 15px;
--sidebar-font-weight: normal;
--sidebar-highlight-font-weight: bold;
--screentabs-font-size: 15px;
--screentabs-font-weight: normal;
--screentabs-selected-font-weight: bold;
}

View File

@ -16,9 +16,15 @@
--text-s1-font: "Martian Mono", sans-serif;
--markdown-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji";
--label-font-family: "Martian Mono", sans-serif;
// magic
--screentabs-height: 38px;
--markdown-font-size: 14px;
--screentabs-height: 38px; // magic
--screentabs-line-height: 21px; // magic
--screentabs-font-size: 12.5px;
--screentabs-font-weight: 300;
--screentabs-selected-font-weight: 300;
// global colors
--app-accent-color: rgb(88, 193, 66);
@ -139,6 +145,10 @@
--sidebar-settings-color: rgb(255, 255, 255);
--sidebar-separator-color: var(--app-border-color);
--sidebar-highlight-color: rgba(241, 246, 243, 0.08);
--sidebar-font-size: 12.5px;
--sidebar-line-height: 1.5;
--sidebar-font-weight: 300;
--sidebar-highlight-font-weight: 300;
// line colors
--line-sidebar-message-color: rgb(196, 160, 0);

View File

@ -12,6 +12,9 @@
border-radius: var(--app-border-radius) 0 0 var(--app-border-radius);
border-left: 1px solid var(--app-border-color);
border-bottom: 1px solid var(--app-border-color);
font-size: var(--sidebar-font-size);
font-family: var(--label-font-family);
font-weight: var(--sidebar-font-weight);
.title-bar-drag {
-webkit-app-region: drag;
@ -149,6 +152,7 @@
.item {
&.active {
background-color: var(--sidebar-highlight-color);
font-weight: var(--sidebar-highlight-font-weight);
}
.index {
font-size: 10px;

View File

@ -135,6 +135,7 @@
overflow-wrap: anywhere;
border-color: transparent;
border: none;
font-family: var(--termfontfamily);
line-height: var(--termlineheight);
font-size: var(--termfontsize);
border-radius: 4px 4px 0 4px; // 0 is for shelltag

View File

@ -2,7 +2,10 @@
#main .screen-tabs .screen-tab {
border-top: 1px solid transparent;
font-size: 12.5px;
font-size: var(--screentabs-font-size);
line-height: var(--screentabs-line-height);
font-family: var(--label-font-family);
font-weight: var(--screentabs-font-weight);
&:not(:hover) .status-indicator {
.status-indicator-visible;
@ -81,7 +84,8 @@
}
}
.screen-tabs-container {
// #main for selectivity
#main .screen-tabs-container {
display: flex;
position: relative;
overflow: hidden;
@ -159,6 +163,7 @@
&.is-active {
border-top: none;
opacity: 1;
font-weight: var(--screentabs-selected-font-weight);
}
&.is-archived {

View File

@ -185,7 +185,11 @@ class ScreenTabs extends React.Component<
let activeScreenId = this.getActiveScreenId();
const sidebarCollapsed = GlobalModel.mainSidebarModel.getCollapsed();
return (
<div className={cn("screen-tabs-container", { "sidebar-collapsed": sidebarCollapsed })}>
<div
className={cn("screen-tabs-container", {
"sidebar-collapsed": sidebarCollapsed,
})}
>
<If condition={sidebarCollapsed}>
<div key="logo-button" className="logo-button-container">
<div className="logo-button" onClick={this.openSidebar}>
@ -194,7 +198,10 @@ class ScreenTabs extends React.Component<
</div>
</If>
{/* Inner container ensures that hovering over the scrollbar doesn't trigger the hover effect on the tabs. This prevents weird flickering of the icons when the mouse is moved over the scrollbar. */}
<div key="container-inner" className="screen-tabs-container-inner hideScrollbarUntillHover">
<div
key="container-inner"
className="screen-tabs-container-inner no-highlight-scrollbar hideScrollbarUntillHover"
>
<Reorder.Group
className="screen-tabs"
ref={this.tabsRef}

View File

@ -7,8 +7,8 @@ import { createRoot } from "react-dom/client";
import { sprintf } from "sprintf-js";
import { App } from "@/app/app";
import * as DOMPurify from "dompurify";
import { loadFonts } from "./util/util";
import * as textmeasure from "./util/textmeasure";
import { loadFonts } from "@/util/fontutil";
import * as textmeasure from "@/util/textmeasure";
import { getApi } from "@/models";
// @ts-ignore

View File

@ -12,8 +12,8 @@ import {
genMergeSimpleData,
isModKeyPress,
isBlank,
loadFonts,
} from "@/util/util";
import { loadFonts } from "@/util/fontutil";
import { WSControl } from "./ws";
import { cmdStatusIsRunning } from "@/app/line/lineutil";
import * as appconst from "@/app/appconst";

View File

@ -3,6 +3,7 @@
display: flex;
flex-direction: row;
justify-content: flex-start;
font-weight: normal;
.openai-role {
color: var(--prompt-bright-green);
@ -16,8 +17,10 @@
}
.openai-content-user {
white-space: pre;
color: var(--app-text-color);
font-family: var(--markdown-font);
font-size: var(--markdown-font-size);
font-weight: normal;
}
.openai-content-assistant {

View File

@ -844,6 +844,13 @@ declare global {
getContainerType(): LineContainerStrs;
};
type MonoFontSize = {
height: number;
width: number;
fontSize: number;
pad: number;
};
type KeyModsType = {
meta?: boolean;
ctrl?: boolean;

118
src/util/fontutil.ts Normal file
View File

@ -0,0 +1,118 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
let isJetBrainsMonoLoaded = false;
let isLatoFontLoaded = false;
let isHackFontLoaded = false;
let isBaseFontsLoaded = false;
function addToFontFaceSet(fontFaceSet: FontFaceSet, fontFace: FontFace) {
// any cast to work around typing issue
(fontFaceSet as any).add(fontFace);
}
function loadJetBrainsMonoFont() {
if (isJetBrainsMonoLoaded) {
return;
}
isJetBrainsMonoLoaded = true;
const jbmFontNormal = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-regular.woff2')", {
style: "normal",
weight: "400",
});
const jbmFont200 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-200.woff2')", {
style: "normal",
weight: "200",
});
const jbmFont700 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-700.woff2')", {
style: "normal",
weight: "700",
});
addToFontFaceSet(document.fonts, jbmFontNormal);
addToFontFaceSet(document.fonts, jbmFont200);
addToFontFaceSet(document.fonts, jbmFont700);
jbmFontNormal.load();
jbmFont200.load();
jbmFont700.load();
}
function loadLatoFont() {
if (isLatoFontLoaded) {
return;
}
isLatoFontLoaded = true;
const latoFont = new FontFace("Lato", "url('public/fonts/lato-regular.woff')", {
style: "normal",
weight: "400",
});
const latoFontBold = new FontFace("Lato", "url('public/fonts/lato-bold.woff')", {
style: "normal",
weight: "700",
});
addToFontFaceSet(document.fonts, latoFont);
addToFontFaceSet(document.fonts, latoFontBold);
latoFont.load();
latoFontBold.load();
}
function loadHackFont() {
if (isHackFontLoaded) {
return;
}
isHackFontLoaded = true;
let hackRegular = new FontFace("Hack", "url('public/fonts/hack-regular.woff2')", {
style: "normal",
weight: "400",
});
let hackBold = new FontFace("Hack", "url('public/fonts/hack-bold.woff2')", {
style: "normal",
weight: "700",
});
let hackItalic = new FontFace("Hack", "url('public/fonts/hack-italic.woff2')", {
style: "italic",
weight: "400",
});
let hackBoldItalic = new FontFace("Hack", "url('public/fonts/hack-bolditalic.woff2')", {
style: "italic",
weight: "700",
});
addToFontFaceSet(document.fonts, hackRegular);
addToFontFaceSet(document.fonts, hackBold);
addToFontFaceSet(document.fonts, hackItalic);
addToFontFaceSet(document.fonts, hackBoldItalic);
hackRegular.load();
hackBold.load();
hackItalic.load();
hackBoldItalic.load();
}
function loadBaseFonts() {
if (isBaseFontsLoaded) {
return;
}
isBaseFontsLoaded = true;
let faFont = new FontFace("FontAwesome", "url(public/fonts/fontawesome-webfont-4.7.woff2)", {
style: "normal",
weight: "normal",
});
let mmFont = new FontFace("Martian Mono", "url(public/fonts/MartianMono-VariableFont_wdth,wght.ttf)", {
style: "normal",
weight: "normal",
});
addToFontFaceSet(document.fonts, faFont);
addToFontFaceSet(document.fonts, mmFont);
faFont.load();
mmFont.load();
}
function loadFonts(termFont: string) {
loadBaseFonts();
loadLatoFont();
loadJetBrainsMonoFont();
if (termFont == "Hack") {
loadHackFont();
}
document.documentElement.style.setProperty("--termfontfamily", '"' + termFont + '"');
}
export { loadFonts };

View File

@ -7,7 +7,7 @@ import { MagicLayout } from "@/app/magiclayout";
const MinTermCols = 10;
const MaxTermCols = 1024;
let MonoFontSizes: { height: number; width: number }[] = [];
let MonoFontSizes: MonoFontSize[] = [];
// MonoFontSizes[8] = {height: 11, width: 4.797};
// MonoFontSizes[9] = {height: 12, width: 5.398};
@ -19,7 +19,7 @@ let MonoFontSizes: { height: number; width: number }[] = [];
// MonoFontSizes[15] = {height: 20, width: 9};
// MonoFontSizes[16] = {height: 22, width: 9.594};
function getMonoFontSize(fontSize: number): { height: number; width: number } {
function getMonoFontSize(fontSize: number): MonoFontSize {
if (MonoFontSizes[fontSize] != null) {
return MonoFontSizes[fontSize];
}
@ -34,12 +34,9 @@ function clearMonoFontCache(): void {
MonoFontSizes = [];
}
function measureText(
text: string,
textOpts?: { pre?: boolean; mono?: boolean; fontSize?: number | string }
): { height: number; width: number } {
function measureText(text: string, textOpts: { pre?: boolean; mono?: boolean; fontSize: number }): MonoFontSize {
if (textOpts == null) {
textOpts = {};
throw new Error("invalid textOpts passed to measureText (null)");
}
let textElem = document.createElement("span");
if (textOpts.pre) {
@ -61,9 +58,10 @@ function measureText(
throw new Error("cannot measure text, no #measure div");
}
measureDiv.replaceChildren(textElem);
let height = textElem.offsetHeight;
let height = Math.ceil(textElem.offsetHeight);
let width = textElem.offsetWidth;
return { width: width, height: Math.ceil(height) };
let pad = Math.floor(height / 2);
return { width, height, pad, fontSize: textOpts.fontSize };
}
function windowWidthToCols(width: number, fontSize: number): number {

View File

@ -242,101 +242,6 @@ function incObs(inum: mobx.IObservableValue<number>) {
})();
}
function addToFontFaceSet(fontFaceSet: FontFaceSet, fontFace: FontFace) {
// any cast to work around typing issue
(fontFaceSet as any).add(fontFace);
}
let isJetBrainsMonoLoaded = false;
function loadJetBrainsMonoFont() {
if (isJetBrainsMonoLoaded) {
return;
}
isJetBrainsMonoLoaded = true;
let jbmFontNormal = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-regular.woff2')", {
style: "normal",
weight: "400",
});
const jbmFont200 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-200.woff2')", {
style: "normal",
weight: "200",
});
const jbmFont700 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-700.woff2')", {
style: "normal",
weight: "700",
});
addToFontFaceSet(document.fonts, jbmFontNormal);
addToFontFaceSet(document.fonts, jbmFont200);
addToFontFaceSet(document.fonts, jbmFont700);
jbmFontNormal.load();
jbmFont200.load();
jbmFont700.load();
}
let isHackFontLoaded = false;
function loadHackFont() {
if (isHackFontLoaded) {
return;
}
isHackFontLoaded = true;
let hackRegular = new FontFace("Hack", "url('public/fonts/hack-regular.woff2')", {
style: "normal",
weight: "400",
});
let hackBold = new FontFace("Hack", "url('public/fonts/hack-bold.woff2')", {
style: "normal",
weight: "700",
});
let hackItalic = new FontFace("Hack", "url('public/fonts/hack-italic.woff2')", {
style: "italic",
weight: "400",
});
let hackBoldItalic = new FontFace("Hack", "url('public/fonts/hack-bolditalic.woff2')", {
style: "italic",
weight: "700",
});
addToFontFaceSet(document.fonts, hackRegular);
addToFontFaceSet(document.fonts, hackBold);
addToFontFaceSet(document.fonts, hackItalic);
addToFontFaceSet(document.fonts, hackBoldItalic);
hackRegular.load();
hackBold.load();
hackItalic.load();
hackBoldItalic.load();
}
let isBaseFontsLoaded = false;
function loadBaseFonts() {
if (isBaseFontsLoaded) {
return;
}
isBaseFontsLoaded = true;
let faFont = new FontFace("FontAwesome", "url(public/fonts/fontawesome-webfont-4.7.woff2)", {
style: "normal",
weight: "normal",
});
let mmFont = new FontFace("Martian Mono", "url(public/fonts/MartianMono-VariableFont_wdth,wght.ttf)", {
style: "normal",
weight: "normal",
});
addToFontFaceSet(document.fonts, faFont);
addToFontFaceSet(document.fonts, mmFont);
faFont.load();
mmFont.load();
}
function loadFonts(termFont: string) {
loadBaseFonts();
loadJetBrainsMonoFont();
if (termFont == "Hack") {
loadHackFont();
}
document.documentElement.style.setProperty("--termfontfamily", '"' + termFont + '"');
}
const DOW_STRS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
function getTodayStr(): string {
@ -470,7 +375,6 @@ export {
isModKeyPress,
incObs,
isBlank,
loadFonts,
getTodayStr,
getYesterdayStr,
getDateStr,