From 0f5ec2581f44b98581ecb5c958544ed6b2f6b0e2 Mon Sep 17 00:00:00 2001 From: Oliver Salzburg Date: Fri, 15 Nov 2024 23:02:13 +0100 Subject: [PATCH] feat(ui): Beta 9 Polish Now uses CSS Modules to style components. --- @types/module.css.d.ts | 4 + packages/kitten-analysts/package.json | 1 + packages/kitten-engineers/package.json | 1 + packages/kitten-scientists/package.json | 1 + .../kitten-scientists/source/i18n/en-US.json | 3 + .../source/ui/ResetBonfireSettingsUi.ts | 61 ++- .../source/ui/ResetUpgradesSettingsUi.ts | 3 +- .../source/ui/TradeSettingsUi.ts | 43 ++ .../source/ui/UpgradeSettingsUi.ts | 3 +- .../source/ui/UserInterface.module.css | 67 +++ .../source/ui/UserInterface.ts | 381 +----------------- .../source/ui/components/Button.module.css | 41 ++ .../source/ui/components/Button.ts | 29 +- .../source/ui/components/ButtonListItem.ts | 3 +- .../ui/components/CollapsiblePanel.module.css | 10 + .../source/ui/components/CollapsiblePanel.ts | 7 +- .../source/ui/components/Delimiter.module.css | 5 + .../source/ui/components/Delimiter.ts | 3 +- .../source/ui/components/Dialog.ts | 3 +- .../source/ui/components/ExplainerListItem.ts | 3 +- .../components/ExplainerLiteItem.module.css | 13 + .../source/ui/components/Fieldset.module.css | 5 + .../source/ui/components/Fieldset.ts | 9 +- .../ui/components/HeaderListItem.module.css | 11 + .../source/ui/components/HeaderListItem.ts | 3 +- .../ui/components/IconButton.module.css | 18 + .../source/ui/components/IconButton.ts | 7 +- .../ui/components/LabelListItem.module.css | 17 + .../source/ui/components/LabelListItem.ts | 13 +- .../source/ui/components/LimitedButton.ts | 13 +- .../source/ui/components/ListItem.module.css | 22 + .../source/ui/components/ListItem.ts | 3 +- .../source/ui/components/RadioItem.ts | 9 +- .../ui/components/SettingLimitedListItem.ts | 6 +- .../components/SettingLimitedMaxListItem.ts | 5 +- .../SettingLimitedMaxTriggerListItem.ts | 1 + .../ui/components/SettingListItem.module.css | 11 + .../source/ui/components/SettingListItem.ts | 5 +- .../components/SettingMaxTriggerListItem.ts | 1 + .../ui/components/SettingTriggerListItem.ts | 1 + .../ui/components/SettingsList.module.css | 16 + .../source/ui/components/SettingsList.ts | 7 +- .../ui/components/TextButton.module.css | 12 + .../source/ui/components/TextButton.ts | 3 +- .../ui/components/ToolbarListItem.module.css | 8 + .../source/ui/components/ToolbarListItem.ts | 3 +- .../source/ui/components/UiComponent.ts | 3 + .../components/buttons-icon/ConsumeButton.ts | 3 +- .../buttons-icon/ExpandoButton.module.css | 14 + .../components/buttons-icon/ExpandoButton.ts | 15 +- .../components/buttons-icon/PaddingButton.ts | 3 +- .../buttons-icon/StockButton.module.css | 4 + .../ui/components/buttons-icon/StockButton.ts | 7 +- .../components/buttons-icon/TriggerButton.ts | 18 +- .../buttons-text/BuyButton.module.css | 5 + .../ui/components/buttons-text/BuyButton.ts | 3 +- .../buttons-text/MaxButton.module.css | 4 + .../ui/components/buttons-text/MaxButton.ts | 11 +- .../buttons-text/SellButton.module.css | 5 + .../ui/components/buttons-text/SellButton.ts | 3 +- .../kitten-scientists/vite.config.inject.js | 2 + .../vite.config.userscript.js | 24 +- tsconfig.base.json | 1 + tsconfig.json | 1 + yarn.lock | 12 + 65 files changed, 568 insertions(+), 464 deletions(-) create mode 100644 @types/module.css.d.ts create mode 100644 packages/kitten-scientists/source/ui/UserInterface.module.css create mode 100644 packages/kitten-scientists/source/ui/components/Button.module.css create mode 100644 packages/kitten-scientists/source/ui/components/CollapsiblePanel.module.css create mode 100644 packages/kitten-scientists/source/ui/components/Delimiter.module.css create mode 100644 packages/kitten-scientists/source/ui/components/ExplainerLiteItem.module.css create mode 100644 packages/kitten-scientists/source/ui/components/Fieldset.module.css create mode 100644 packages/kitten-scientists/source/ui/components/HeaderListItem.module.css create mode 100644 packages/kitten-scientists/source/ui/components/IconButton.module.css create mode 100644 packages/kitten-scientists/source/ui/components/LabelListItem.module.css create mode 100644 packages/kitten-scientists/source/ui/components/ListItem.module.css create mode 100644 packages/kitten-scientists/source/ui/components/SettingListItem.module.css create mode 100644 packages/kitten-scientists/source/ui/components/SettingsList.module.css create mode 100644 packages/kitten-scientists/source/ui/components/TextButton.module.css create mode 100644 packages/kitten-scientists/source/ui/components/ToolbarListItem.module.css create mode 100644 packages/kitten-scientists/source/ui/components/buttons-icon/ExpandoButton.module.css create mode 100644 packages/kitten-scientists/source/ui/components/buttons-icon/StockButton.module.css create mode 100644 packages/kitten-scientists/source/ui/components/buttons-text/BuyButton.module.css create mode 100644 packages/kitten-scientists/source/ui/components/buttons-text/MaxButton.module.css create mode 100644 packages/kitten-scientists/source/ui/components/buttons-text/SellButton.module.css diff --git a/@types/module.css.d.ts b/@types/module.css.d.ts new file mode 100644 index 000000000..e46074ae8 --- /dev/null +++ b/@types/module.css.d.ts @@ -0,0 +1,4 @@ +declare module "*.module.css" { + const styles: Record; + export = styles; +} diff --git a/packages/kitten-analysts/package.json b/packages/kitten-analysts/package.json index c50d2eafb..02f81379c 100644 --- a/packages/kitten-analysts/package.json +++ b/packages/kitten-analysts/package.json @@ -55,6 +55,7 @@ "esbuild": "0.24.0", "typescript": "5.6.3", "vite": "5.4.11", + "vite-plugin-css-injected-by-js": "3.5.2", "vite-plugin-userscript": "0.1.3" }, "keywords": [ diff --git a/packages/kitten-engineers/package.json b/packages/kitten-engineers/package.json index 69d087cf8..3d4f382e8 100644 --- a/packages/kitten-engineers/package.json +++ b/packages/kitten-engineers/package.json @@ -39,6 +39,7 @@ "devDependencies": { "typescript": "5.6.3", "vite": "5.4.11", + "vite-plugin-css-injected-by-js": "3.5.2", "vite-plugin-userscript": "0.1.3" }, "keywords": [ diff --git a/packages/kitten-scientists/package.json b/packages/kitten-scientists/package.json index 3ec0c12a1..79019b258 100644 --- a/packages/kitten-scientists/package.json +++ b/packages/kitten-scientists/package.json @@ -46,6 +46,7 @@ "@types/web": "0.0.179", "typescript": "5.6.3", "vite": "5.4.11", + "vite-plugin-css-injected-by-js": "3.5.2", "vite-plugin-userscript": "0.1.3" }, "keywords": [ diff --git a/packages/kitten-scientists/source/i18n/en-US.json b/packages/kitten-scientists/source/i18n/en-US.json index 3c4303e42..86a30f782 100644 --- a/packages/kitten-scientists/source/i18n/en-US.json +++ b/packages/kitten-scientists/source/i18n/en-US.json @@ -245,7 +245,10 @@ "ui.trigger.build.inherited": "inherited from section", "ui.trigger.build.prompt": "Trigger for {0} (Current: {1})", "ui.trigger.build.promptExplainer": "If you submit an empty value, or a negative value, the section trigger is used instead. If you submit an invalid value, it will be treated as if you hit Cancel.", + "ui.trigger.prompt.absolute": "Enter the new trigger value as an absolute value between 0.0 and Infinity.", "ui.trigger.prompt.percentage": "Enter the new trigger value as a percentage between 0.0 and 100.0.", + "ui.trigger.reset.inactive": "inactive", + "ui.trigger.reset.promptExplainer": "If you submit a negative value, the item will be disabled. If you submit an empty value, or an invalid value, it will be treated as if you hit Cancel.", "ui.trigger.section.inactive": "∞ (nothing is built automatically)", "ui.trigger.section.prompt": "Trigger for section {0} (Current: {1})", "ui.trigger.section.promptExplainer": "If you submit an empty value, or a negative value, the section trigger will be set to infinity (∞), which disables all builds, unless they have their own trigger set.\nIf you submit an invalid value, it will be treated as if you hit Cancel.", diff --git a/packages/kitten-scientists/source/ui/ResetBonfireSettingsUi.ts b/packages/kitten-scientists/source/ui/ResetBonfireSettingsUi.ts index 7e73db5b3..42b9b809d 100644 --- a/packages/kitten-scientists/source/ui/ResetBonfireSettingsUi.ts +++ b/packages/kitten-scientists/source/ui/ResetBonfireSettingsUi.ts @@ -1,9 +1,12 @@ import { isNil } from "@oliversalzburg/js-utils/data/nil.js"; +import { redirectErrorsToConsole } from "@oliversalzburg/js-utils/errors/console.js"; import { KittenScientists } from "../KittenScientists.js"; import { Icons } from "../images/Icons.js"; import { ResetBonfireSettings } from "../settings/ResetBonfireSettings.js"; import { SettingTrigger } from "../settings/Settings.js"; import { StagedBuilding } from "../types/index.js"; +import stylesDelimiter from "./components/Delimiter.module.css"; +import { Dialog } from "./components/Dialog.js"; import { HeaderListItem } from "./components/HeaderListItem.js"; import { IconSettingsPanel } from "./components/IconSettingsPanel.js"; import { SettingTriggerListItem } from "./components/SettingTriggerListItem.js"; @@ -32,10 +35,16 @@ export class ResetBonfireSettingsUi extends IconSettingsPanel item.baseBuilding === building, )?.building as StagedBuilding; this._buildings.push( - this._getResetOption(host, this.setting.buildings[building], meta.stages[0].label), + this._getResetOption( + host, + this.setting.buildings[building], + label, + meta.stages[0].label, + ), this._getResetOption( host, this.setting.buildings[name], + label, meta.stages[1].label, false, true, @@ -43,14 +52,14 @@ export class ResetBonfireSettingsUi extends IconSettingsPanel { host.engine.imessage("status.reset.check.enable", [i18nName]); @@ -74,7 +84,50 @@ export class ResetBonfireSettingsUi extends IconSettingsPanel { host.engine.imessage("status.reset.check.disable", [i18nName]); }, + onRefresh: () => { + element.triggerButton.inactive = option.trigger === -1; + }, + onRefreshTrigger: () => { + element.triggerButton.element[0].title = host.engine.i18n("ui.trigger", [ + option.trigger < 0 + ? host.engine.i18n("ui.trigger.reset.inactive", [sectionLabel]) + : option.trigger.toString(), + ]); + }, + onSetTrigger: () => { + Dialog.prompt( + host, + host.engine.i18n("ui.trigger.prompt.absolute"), + host.engine.i18n("ui.trigger.build.prompt", [ + i18nName, + option.trigger !== -1 + ? option.trigger.toString() + : host.engine.i18n("ui.trigger.reset.inactive"), + ]), + option.trigger !== -1 ? option.trigger.toString() : "", + host.engine.i18n("ui.trigger.reset.promptExplainer"), + ) + .then(value => { + if (value === undefined) { + return; + } + + if (value === "" || value.startsWith("-")) { + option.trigger = -1; + option.enabled = false; + return; + } + + option.enabled = true; + option.trigger = Number(value); + }) + .then(() => { + element.refreshUi(); + }) + .catch(redirectErrorsToConsole(console)); + }, upgradeIndicator, }); + return element; } } diff --git a/packages/kitten-scientists/source/ui/ResetUpgradesSettingsUi.ts b/packages/kitten-scientists/source/ui/ResetUpgradesSettingsUi.ts index ece75b523..c3402f6e1 100644 --- a/packages/kitten-scientists/source/ui/ResetUpgradesSettingsUi.ts +++ b/packages/kitten-scientists/source/ui/ResetUpgradesSettingsUi.ts @@ -4,6 +4,7 @@ import { KittenScientists } from "../KittenScientists.js"; import { Icons } from "../images/Icons.js"; import { ResetUpgradeSettings } from "../settings/ResetUpgradeSettings.js"; import { Setting, SettingOptions } from "../settings/Settings.js"; +import stylesDelimiter from "./components/Delimiter.module.css"; import { IconSettingsPanel } from "./components/IconSettingsPanel.js"; import { SettingListItem } from "./components/SettingListItem.js"; import { SettingsList } from "./components/SettingsList.js"; @@ -41,7 +42,7 @@ export class ResetUpgradesSettingsUi extends IconSettingsPanel { @@ -27,6 +30,46 @@ export class TradeSettingsUi extends SettingsPanel { onUnCheck: () => { host.engine.imessage("status.auto.disable", [label]); }, + onRefresh: item => { + (item as SettingTriggerListItem).triggerButton.inactive = settings.trigger < 0; + }, + onRefreshTrigger: item => { + item.triggerButton.element[0].title = host.engine.i18n("ui.trigger", [ + settings.trigger < 0 + ? host.engine.i18n("ui.trigger.section.inactive") + : `${UiComponent.renderPercentage(settings.trigger)}%`, + ]); + }, + onSetTrigger: () => { + Dialog.prompt( + host, + host.engine.i18n("ui.trigger.prompt.percentage"), + host.engine.i18n("ui.trigger.section.prompt", [ + label, + settings.trigger !== -1 + ? `${UiComponent.renderPercentage(settings.trigger)}%` + : host.engine.i18n("ui.infinity"), + ]), + settings.trigger !== -1 ? UiComponent.renderPercentage(settings.trigger) : "", + host.engine.i18n("ui.trigger.section.promptExplainer"), + ) + .then(value => { + if (value === undefined) { + return; + } + + if (value === "" || value.startsWith("-")) { + settings.trigger = -1; + return; + } + + settings.trigger = UiComponent.parsePercentage(value); + }) + .then(() => { + this.refreshUi(); + }) + .catch(redirectErrorsToConsole(console)); + }, }), ); diff --git a/packages/kitten-scientists/source/ui/UpgradeSettingsUi.ts b/packages/kitten-scientists/source/ui/UpgradeSettingsUi.ts index d722002a5..5a0b72a6e 100644 --- a/packages/kitten-scientists/source/ui/UpgradeSettingsUi.ts +++ b/packages/kitten-scientists/source/ui/UpgradeSettingsUi.ts @@ -6,6 +6,7 @@ import { SettingOptions } from "../settings/Settings.js"; import { UpgradeSettings } from "../settings/UpgradeSettings.js"; import { PaddingButton } from "./components/buttons-icon/PaddingButton.js"; import { PanelOptions } from "./components/CollapsiblePanel.js"; +import stylesDelimiter from "./components/Delimiter.module.css"; import { Dialog } from "./components/Dialog.js"; import { SettingsList } from "./components/SettingsList.js"; import { SettingsPanel } from "./components/SettingsPanel.js"; @@ -87,7 +88,7 @@ export class UpgradeSettingsUi extends SettingsPanel { ? upgrades.sort((a, b) => a.label.localeCompare(b.label)) : upgrades) { if (!isNil(lastElement) && localeSupportsSortMethod && lastLabel[0] !== upgrade.label[0]) { - lastElement.element.addClass("ks-delimiter"); + lastElement.element.addClass(stylesDelimiter.delimiter); } const option = this.setting.upgrades[upgrade.name]; diff --git a/packages/kitten-scientists/source/ui/UserInterface.module.css b/packages/kitten-scientists/source/ui/UserInterface.module.css new file mode 100644 index 000000000..bec031ae8 --- /dev/null +++ b/packages/kitten-scientists/source/ui/UserInterface.module.css @@ -0,0 +1,67 @@ +#ksColumn { + min-width: 250px; + max-width: 440px; + vertical-align: top; + padding-left: 8px; + top: 20px; + position: relative; + overflow-y: auto; +} +.spacer { + display: block; + margin-bottom: 100px; +} +.ui { + margin: 5px 0 10px 0; + padding-right: 10px; + font-size: 14px; +} +.ui ul { + list-style: none; + margin: 0; + padding: 0; +} +.ui ul:after { + clear: both; + content: " "; + display: block; + height: 0; +} + +.showActivity { + cursor: pointer; + display: inline-block; + vertical-align: middle; +} + +/* Dialogs */ +.dialog.ks-dialog { + display: flex; + flex-direction: column; + height: fit-content !important; + box-shadow: none; +} +.dialog.ks-dialog .close { + position: absolute; + top: 10px; + right: 15px; +} + +/* Rules needed to enable stock warning. */ + +.ui #toggle-list-resources .stockWarn *, +.ui #toggle-reset-list-resources .stockWarn * { + color: #dd1e00; +} + +/* Ensure the right column gets a scrollbar, when our content extends it too far down. */ +#game #rightColumn { + overflow-y: auto; +} + +#game .res-row .res-cell.ks-stock-above { + color: green; +} +#game .res-row .res-cell.ks-stock-below { + color: red; +} diff --git a/packages/kitten-scientists/source/ui/UserInterface.ts b/packages/kitten-scientists/source/ui/UserInterface.ts index 304a5f59d..8c3350629 100644 --- a/packages/kitten-scientists/source/ui/UserInterface.ts +++ b/packages/kitten-scientists/source/ui/UserInterface.ts @@ -1,4 +1,3 @@ -import { isNil, mustExist } from "@oliversalzburg/js-utils/data/nil.js"; import { KittenScientists } from "../KittenScientists.js"; import { Icons } from "../images/Icons.js"; import { cwarn } from "../tools/Log.js"; @@ -14,6 +13,7 @@ import { StateManagementUi } from "./StateManagementUi.js"; import { TimeControlSettingsUi } from "./TimeControlSettingsUi.js"; import { TimeSettingsUi } from "./TimeSettingsUi.js"; import { TradeSettingsUi } from "./TradeSettingsUi.js"; +import styles from "./UserInterface.module.css"; import { VillageSettingsUi } from "./VillageSettingsUi.js"; import { WorkshopSettingsUi } from "./WorkshopSettingsUi.js"; import { UiComponent } from "./components/UiComponent.js"; @@ -60,9 +60,9 @@ export class UserInterface extends UiComponent { new InternalsUi(host, engine.settings), ]; - this._installCss(); + //this._installCss(); - const ks = $("
", { id: "ks" }).addClass("ks-ui"); + const ks = $("
").addClass(styles.ui); const optionsListElement = $("
    "); optionsListElement.append(this._engineUi.element); @@ -103,7 +103,7 @@ export class UserInterface extends UiComponent { this.showActivity = $("", { html: ``, title: host.engine.i18n("summary.show"), - }).addClass("ks-show-activity"); + }).addClass(styles.showActivity); this.showActivity.on("click", () => { host.engine.displayActivitySummary(); @@ -114,7 +114,7 @@ export class UserInterface extends UiComponent { // Add Kitten Scientists above the game log. if (engine.settings.ksColumn.enabled) { $("#rightColumn").after( - '
    ', + `
    `, ); } else { $("#ksColumn").remove(); @@ -146,375 +146,4 @@ export class UserInterface extends UiComponent { section.refreshUi(); } } - - private _installCss(): void { - // Basic layout for our own list-based options menus. - this._addRule( - `#ksColumn { - min-width: 250px; - max-width: 440px; - vertical-align: top; - padding-left: 8px; - top: 20px; - position: relative; - overflow-y: auto; - }`, - ); - this._addRule( - `.ksSpacer { - display: block; - margin-bottom: 100px; - }`, - ); - this._addRule( - `#ks { - margin: 5px 0 10px 0; - padding-right: 10px; - font-size: 14px; - }`, - ); - this._addRule(".ks-ui ul { list-style: none; margin: 0; padding: 0; }"); - this._addRule('.ks-ui ul:after { clear: both; content: " "; display: block; height: 0; }'); - this._addRule( - `.ks-ui .ks-checkbox { - margin: 1px 5px 2px 2px; - }`, - ); - this._addRule( - `.ks-ui .ks-fieldset { - border-bottom: none; - border-right: none; - border-top: none; - }`, - ); - - // List Item Generic - this._addRule( - `.ks-head { - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100%; - - border-bottom: 1px solid transparent; - transition: .3s; - }`, - ); - this._addRule( - `.ks-head .ks-label { - align-items: flex-start; - display: flex; - flex: 1; - white-space: nowrap; - }`, - ); - this._addRule( - `.ks-head .ks-fill-space { - flex: *; - }`, - ); - this._addRule( - `.ks-head > .ks-button { - flex: 1; - margin-right: 8px; - }`, - ); - this._addRule( - `.ks-head > .ks-text-button { - flex: 1; - margin-right: 8px; - }`, - ); - this._addRule( - `.ks-panel-content { - border-left: 1px dashed grey; - padding-left: 16px; - margin-left: 8px; - margin-top: 5px; - }`, - ); - this._addRule( - `.ks-ui ul li.ks-expanded { - margin-bottom: 10px; - }`, - ); - // Hover guides - this._addRule( - `.ks-ui ul .ks-setting { - border-bottom: 1px solid transparent; - }`, - ); - this._addRule( - `.ks-ui ul .ks-setting:not(.ks-expanded):hover { - border-bottom: 1px solid rgba(185, 185, 185, 0.5); - }`, - ); - - // Setting: Label - this._addRule( - `.ks-label { - display: inline-block; - flex: 1; - min-width: 120px; - opacity: 0.8; - }`, - ); - this._addRule( - `.ks-label:hover { - opacity: 1; - }`, - ); - // Setting: +/- Expando Toggle - this._addRule( - `.ks-expando-button:not(.expanded) .up { - display: none; - }`, - ); - this._addRule( - `.ks-expando-button.expanded .down { - display: none; - }`, - ); - // Setting: Toolbar - this._addRule( - `.ks-ui ul li.ks-toolbar { - padding: 0 0 2px 0; - margin: 0 0 3px 0; - }`, - ); - this._addRule( - `.ks-ui .ks-toolbar > * { - margin: 0 3px 0 0; - }`, - ); - // Setting: Button - this._addRule( - `.ks-button { - border: 1px solid rgba(255, 255, 255, 0.2); - cursor: pointer; - display: inline-block; - padding: 0 2px; - transition: border .3s; - opacity: 0.8; - }`, - ); - this._addRule( - `.ks-button.large { - padding: 5px 10px; - }`, - ); - this._addRule( - `.ks-button.ks-consume-button { - border: 1px solid transparent; - }`, - ); - this._addRule( - `.ks-button.ks-stock-button { - border: 1px solid transparent; - }`, - ); - this._addRule( - `.ks-button:hover { - border: 1px solid rgba(255, 255, 255, 1); - opacity: 1; - }`, - ); - this._addRule( - `.ks-button .ks-button-icon { - margin: 0 2px 0 0; - vertical-align: sub; - }`, - ); - // Setting: Icon Button - this._addRule( - `.ks-icon-button { - cursor: pointer; - display: block; - padding-right: 3px; - line-height: 0; - opacity: 0.8; - transition: .3s; - }`, - ); - this._addRule( - `.ks-icon-button.ks-inactive { - opacity: 0.2; - }`, - ); - this._addRule( - `.ks-icon-button:hover { - opacity: 1; - }`, - ); - this._addRule( - `.ks-icon-button.ks-inactive:hover { - opacity: 0.4; - }`, - ); - this._addRule( - `.ks-icon-label { - display: inline-block; - margin-right: 4px; - margin-left: 2px; - vertical-align: middle; - }`, - ); - // Setting: Text Button - this._addRule( - `.ks-text-button { - display: inline-block; - white-space: nowrap; - opacity: 0.8; - - cursor: pointer; - user-select: none; - }`, - ); - this._addRule( - `.ks-text-button:hover { - opacity: 1; - }`, - ); - - // Setting: Header - this._addRule( - `.ks-header { - display: block; - margin-bottom: 3px; - min-width: 100px; - - border-bottom: 1px dashed rgba(255, 255, 255, 0.1); - - font-weight: bold; - user-select: none; - }`, - ); - // Setting: Explainer - this._addRule( - `.ks-explainer { - color: #888; - display: inline-block; - min-width: 100px; - user-select: none; - padding: 4px; - user-select: none; - white-space: break-spaces; - }`, - ); - this._addRule( - `.ks-explainer p { - margin: 0; - }`, - ); - - // Setting: List - this._addRule( - // This compensates the floating tools below the list. - `.ks-list-container { - margin-bottom: 4px; - }`, - ); - this._addRule( - `.ks-list.ks-items-list { - user-select: none; - }`, - ); - this._addRule( - `.ks-list ~ .ks-list-tools { - border-top: 1px dotted grey; - margin-left: 0px; - margin-top: 2px; - }`, - ); - this._addRule( - `.ks-list ~ .ks-list-tools .ks-icon-button { - display: inline-block; - }`, - ); - this._addRule( - `.ks-max-button { - padding-right: 5px; - padding-top: 2px; - }`, - ); - // The stock buttons should layout similarly to ks-label. - this._addRule( - `.ks-stock-button { - display: inline-block; - }`, - ); - // blackcoin buy/sell threshold buttons - this._addRule( - `.ks-buy-button { - display: inline-block; - padding-right: 10px; - min-width: 86px; - }`, - ); - this._addRule( - `.ks-sell-button { - display: inline-block; - padding-right: 10px; - min-width: 86px; - }`, - ); - - // Style settings that act as UI delimiters. - this._addRule( - `.ks-delimiter { - clear: left; - margin-bottom: 10px; - }`, - ); - - // Dialogs - this._addRule( - `.dialog.ks-dialog { - display: flex; - flex-direction: column; - height: fit-content !important; - box-shadow: none; - }`, - ); - this._addRule( - `.dialog.ks-dialog .close { - position: absolute; - top: 10px; - right: 15px; - }`, - ); - - // Rules needed to enable stock warning. - this._addRule(` - .ks-ui #toggle-list-resources .stockWarn *, - .ks-ui #toggle-reset-list-resources .stockWarn * { - color: #DD1E00; - }`); - - this._addRule( - `#game .ks-show-activity { - cursor: pointer; - display: inline-block; - vertical-align: middle; - }`, - ); - - // Ensure the right column gets a scrollbar, when our content extends it too far down. - this._addRule("#game #rightColumn { overflow-y: auto }"); - - this._addRule("#game .res-row .res-cell.ks-stock-above { color: green; }"); - this._addRule("#game .res-row .res-cell.ks-stock-below { color: red; }"); - } - - private _addRule(rule: string) { - const styleSheetId = "kitten-scientists-styles"; - let styleSheet = document.getElementById(styleSheetId) as HTMLStyleElement; - if (isNil(styleSheet)) { - styleSheet = document.createElement("style"); - styleSheet.id = styleSheetId; - document.head.appendChild(styleSheet); - } - const sheet = mustExist(styleSheet.sheet); - sheet.insertRule(rule); - } } diff --git a/packages/kitten-scientists/source/ui/components/Button.module.css b/packages/kitten-scientists/source/ui/components/Button.module.css new file mode 100644 index 000000000..0e0965f74 --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/Button.module.css @@ -0,0 +1,41 @@ +/* Setting: Button */ +.button { + cursor: pointer; + display: inline-block; + transition: 0.3s; + opacity: 0.8; + + &:hover { + opacity: 1; + } + + &.inactive { + opacity: 0.2; + + &:hover { + opacity: 0.4; + } + } + + .buttonIcon { + margin: 0 2px 0 0; + vertical-align: sub; + } +} +.button.bordered { + border: 1px solid rgba(255, 255, 255, 0.2); + padding: 0 2px; + + &:hover { + border: 1px solid rgba(255, 255, 255, 1); + } +} +.button.large { + padding: 5px 10px; +} +.button.consumeButton { + border: 1px solid transparent; +} +.button.stockButton { + border: 1px solid transparent; +} diff --git a/packages/kitten-scientists/source/ui/components/Button.ts b/packages/kitten-scientists/source/ui/components/Button.ts index f8b45feb0..c00059009 100644 --- a/packages/kitten-scientists/source/ui/components/Button.ts +++ b/packages/kitten-scientists/source/ui/components/Button.ts @@ -1,8 +1,11 @@ import { KittenScientists } from "../../KittenScientists.js"; +import styles from "./Button.module.css"; import { IconButtonOptions } from "./IconButton.js"; import { UiComponent } from "./UiComponent.js"; export type ButtonOptions = IconButtonOptions & { + readonly border: boolean; + readonly alignment: "left" | "right"; readonly title: string; }; @@ -10,6 +13,8 @@ export type ButtonOptions = IconButtonOptions & { * A button that has a label and can optionally have an SVG icon. */ export class Button extends UiComponent { + declare readonly _options: Partial; + protected readonly _iconElement: JQuery | undefined; readonly element: JQuery; readOnly: boolean; @@ -31,13 +36,21 @@ export class Button extends UiComponent { ) { super(host, { ...options, children: [], classes: [] }); - this.element = $("
    ", { title: options?.title }).addClass("ks-button").text(label); + this.element = $("
    ", { title: options?.title }).addClass(styles.button).text(label); + + if (options?.border !== false) { + this.element.addClass(styles.bordered); + } if (pathData !== null) { this._iconElement = $( - ``, + ``, ); - this.element.prepend(this._iconElement); + if (options?.alignment === "right") { + this.element.append(this._iconElement); + } else { + this.element.prepend(this._iconElement); + } } options?.classes?.forEach(className => this.element.addClass(className)); @@ -58,7 +71,11 @@ export class Button extends UiComponent { updateLabel(label: string) { this.element.text(label); if (this._iconElement !== undefined) { - this.element.prepend(this._iconElement); + if (this._options.alignment === "right") { + this.element.append(this._iconElement); + } else { + this.element.prepend(this._iconElement); + } } } updateTitle(title: string) { @@ -83,9 +100,9 @@ export class Button extends UiComponent { } if (this.inactive) { - this.element.addClass("ks-inactive"); + this.element.addClass(styles.inactive); } else { - this.element.removeClass("ks-inactive"); + this.element.removeClass(styles.inactive); } } } diff --git a/packages/kitten-scientists/source/ui/components/ButtonListItem.ts b/packages/kitten-scientists/source/ui/components/ButtonListItem.ts index ee28ecd6e..56945f038 100644 --- a/packages/kitten-scientists/source/ui/components/ButtonListItem.ts +++ b/packages/kitten-scientists/source/ui/components/ButtonListItem.ts @@ -1,5 +1,6 @@ import { KittenScientists } from "../../KittenScientists.js"; import { ListItem, ListItemOptions } from "./ListItem.js"; +import stylesListItem from "./ListItem.module.css"; import { TextButton } from "./TextButton.js"; export class ButtonListItem extends ListItem { @@ -10,7 +11,7 @@ export class ButtonListItem extends ListItem { this.button = button; - this.element.addClass("ks-head"); + this.element.addClass(stylesListItem.head); this.element.append(button.element); this.addChildren(options?.children); diff --git a/packages/kitten-scientists/source/ui/components/CollapsiblePanel.module.css b/packages/kitten-scientists/source/ui/components/CollapsiblePanel.module.css new file mode 100644 index 000000000..ffb54d224 --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/CollapsiblePanel.module.css @@ -0,0 +1,10 @@ +.panelContent { + border-left: 1px dashed grey; + padding-left: 16px; + margin-left: 8px; + margin-top: 5px; +} + +.expanded { + margin-bottom: 10px; +} diff --git a/packages/kitten-scientists/source/ui/components/CollapsiblePanel.ts b/packages/kitten-scientists/source/ui/components/CollapsiblePanel.ts index 1ce6b8be8..70fd65349 100644 --- a/packages/kitten-scientists/source/ui/components/CollapsiblePanel.ts +++ b/packages/kitten-scientists/source/ui/components/CollapsiblePanel.ts @@ -1,6 +1,7 @@ import { is } from "@oliversalzburg/js-utils/data/nil.js"; import { KittenScientists } from "../../KittenScientists.js"; import { ExpandoButton } from "./buttons-icon/ExpandoButton.js"; +import styles from "./CollapsiblePanel.module.css"; import { Container } from "./Container.js"; import { LabelListItem } from "./LabelListItem.js"; import { UiComponent, UiComponentOptions } from "./UiComponent.js"; @@ -44,7 +45,7 @@ export class CollapsiblePanel< super(host, options); this.container = new Container(host); - this.container.element.addClass("ks-panel-content"); + this.container.element.addClass(styles.panelContent); this.children.add(this.container); this._head = head; @@ -95,13 +96,13 @@ export class CollapsiblePanel< // Reflect expanded state on expando. this._expando.setExpanded(); // Reflect expanded state for CSS. - this._head.element.addClass("ks-expanded"); + this._head.element.addClass(styles.expanded); // This is NOT a DOM event! It can only be caught by listening on this panel directly. this.dispatchEvent(new CustomEvent("panelShown")); } else { this.container.element.hide(); this._expando.setCollapsed(); - this._head.element.removeClass("ks-expanded"); + this._head.element.removeClass(styles.expanded); this.dispatchEvent(new CustomEvent("panelHidden")); } } diff --git a/packages/kitten-scientists/source/ui/components/Delimiter.module.css b/packages/kitten-scientists/source/ui/components/Delimiter.module.css new file mode 100644 index 000000000..045d62087 --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/Delimiter.module.css @@ -0,0 +1,5 @@ +/* Style settings that act as UI delimiters. */ +.delimiter { + clear: left; + margin-bottom: 10px; +} diff --git a/packages/kitten-scientists/source/ui/components/Delimiter.ts b/packages/kitten-scientists/source/ui/components/Delimiter.ts index a57d9244e..3137ff4fa 100644 --- a/packages/kitten-scientists/source/ui/components/Delimiter.ts +++ b/packages/kitten-scientists/source/ui/components/Delimiter.ts @@ -1,4 +1,5 @@ import { KittenScientists } from "../../KittenScientists.js"; +import styles from "./Delimiter.module.css"; import { UiComponent } from "./UiComponent.js"; export class Delimiter extends UiComponent { @@ -14,7 +15,7 @@ export class Delimiter extends UiComponent { constructor(host: KittenScientists) { super(host, {}); - const element = $("
    ").addClass("ks-delimiter"); + const element = $("
    ").addClass(styles.delimiter); this.element = element; } } diff --git a/packages/kitten-scientists/source/ui/components/Dialog.ts b/packages/kitten-scientists/source/ui/components/Dialog.ts index 27daeea04..8d72cfbb0 100644 --- a/packages/kitten-scientists/source/ui/components/Dialog.ts +++ b/packages/kitten-scientists/source/ui/components/Dialog.ts @@ -3,6 +3,7 @@ import { KittenScientists } from "../../KittenScientists.js"; import { Button } from "./Button.js"; import { Container } from "./Container.js"; import { Delimiter } from "./Delimiter.js"; +import stylesExplainer from "./ExplainerLiteItem.module.css"; import { HeaderListItem } from "./HeaderListItem.js"; import { Input } from "./Input.js"; import { Paragraph } from "./Paragraph.js"; @@ -130,7 +131,7 @@ export class Dialog extends UiComponent { ? [ new Container(host, { children: [new Paragraph(host, explainer)], - classes: ["ks-explainer"], + classes: [stylesExplainer.explainer], }), ] : [], diff --git a/packages/kitten-scientists/source/ui/components/ExplainerListItem.ts b/packages/kitten-scientists/source/ui/components/ExplainerListItem.ts index 03d5b353b..6f3d666b4 100644 --- a/packages/kitten-scientists/source/ui/components/ExplainerListItem.ts +++ b/packages/kitten-scientists/source/ui/components/ExplainerListItem.ts @@ -1,5 +1,6 @@ import { TranslatedString } from "../../Engine.js"; import { KittenScientists } from "../../KittenScientists.js"; +import styles from "./ExplainerLiteItem.module.css"; import { UiComponent, UiComponentOptions } from "./UiComponent.js"; export class ExplainerListItem extends UiComponent { @@ -20,7 +21,7 @@ export class ExplainerListItem extends ) { super(host); - const element = $("
  • ", { text: host.engine.i18n(key) }).addClass("ks-explainer"); + const element = $("
  • ", { text: host.engine.i18n(key) }).addClass(styles.explainer); this.element = element; this.addChildren(options?.children); diff --git a/packages/kitten-scientists/source/ui/components/ExplainerLiteItem.module.css b/packages/kitten-scientists/source/ui/components/ExplainerLiteItem.module.css new file mode 100644 index 000000000..700ccc938 --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/ExplainerLiteItem.module.css @@ -0,0 +1,13 @@ +/* Setting: Explainer */ +explainer { + color: #888; + display: inline-block; + min-width: 100px; + user-select: none; + padding: 4px; + user-select: none; + white-space: break-spaces; +} +explainer p { + margin: 0; +} diff --git a/packages/kitten-scientists/source/ui/components/Fieldset.module.css b/packages/kitten-scientists/source/ui/components/Fieldset.module.css new file mode 100644 index 000000000..0884b4c5a --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/Fieldset.module.css @@ -0,0 +1,5 @@ +.fieldset { + border-bottom: none; + border-right: none; + border-top: none; +} diff --git a/packages/kitten-scientists/source/ui/components/Fieldset.ts b/packages/kitten-scientists/source/ui/components/Fieldset.ts index cd8c4584c..ebb8fe979 100644 --- a/packages/kitten-scientists/source/ui/components/Fieldset.ts +++ b/packages/kitten-scientists/source/ui/components/Fieldset.ts @@ -1,4 +1,7 @@ import { KittenScientists } from "../../KittenScientists.js"; +import stylesDelimiter from "./Delimiter.module.css"; +import styles from "./Fieldset.module.css"; +import stylesLabel from "./LabelListItem.module.css"; import { UiComponent, UiComponentOptions } from "./UiComponent.js"; export type FieldsetOptions = UiComponentOptions & { @@ -18,11 +21,11 @@ export class Fieldset extends UiComponent { constructor(host: KittenScientists, label: string, options?: Partial) { super(host, options); - const element = $("
    ").addClass("ks-fieldset"); + const element = $("
    ").addClass(styles.fieldset); if (options?.delimiter) { - element.addClass("ks-delimiter"); + element.addClass(stylesDelimiter.delimiter); } - const legend = $("").text(label).addClass("ks-label"); + const legend = $("").text(label).addClass(stylesLabel.label); element.append(legend); this.element = element; diff --git a/packages/kitten-scientists/source/ui/components/HeaderListItem.module.css b/packages/kitten-scientists/source/ui/components/HeaderListItem.module.css new file mode 100644 index 000000000..6b02e5690 --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/HeaderListItem.module.css @@ -0,0 +1,11 @@ +/* Setting: Header */ +.header { + display: block; + margin-bottom: 3px; + min-width: 100px; + + border-bottom: 1px dashed rgba(255, 255, 255, 0.1); + + font-weight: bold; + user-select: none; +} diff --git a/packages/kitten-scientists/source/ui/components/HeaderListItem.ts b/packages/kitten-scientists/source/ui/components/HeaderListItem.ts index 375a69f5b..80a74a24e 100644 --- a/packages/kitten-scientists/source/ui/components/HeaderListItem.ts +++ b/packages/kitten-scientists/source/ui/components/HeaderListItem.ts @@ -1,4 +1,5 @@ import { KittenScientists } from "../../KittenScientists.js"; +import styles from "./HeaderListItem.module.css"; import { ListItem } from "./ListItem.js"; import { UiComponent, UiComponentOptions } from "./UiComponent.js"; @@ -19,7 +20,7 @@ export class HeaderListItem extends UiComponent implements ListItem { constructor(host: KittenScientists, text: string, options?: Partial) { super(host, options); - const element = $("
  • ", { text }).addClass("ks-header"); + const element = $("
  • ", { text }).addClass(styles.header); this.element = element; this.addChildren(options?.children); diff --git a/packages/kitten-scientists/source/ui/components/IconButton.module.css b/packages/kitten-scientists/source/ui/components/IconButton.module.css new file mode 100644 index 000000000..2d24a5cb1 --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/IconButton.module.css @@ -0,0 +1,18 @@ +/* Setting: Icon Button */ +.iconButton { + cursor: pointer; + display: block; + padding-right: 3px; + line-height: 0; + opacity: 0.8; + transition: 0.3s; +} +.iconButton.inactive { + opacity: 0.2; +} +.iconButton:hover { + opacity: 1; +} +.iconButton.inactive:hover { + opacity: 0.4; +} diff --git a/packages/kitten-scientists/source/ui/components/IconButton.ts b/packages/kitten-scientists/source/ui/components/IconButton.ts index 8909a5b15..c4d79c7db 100644 --- a/packages/kitten-scientists/source/ui/components/IconButton.ts +++ b/packages/kitten-scientists/source/ui/components/IconButton.ts @@ -1,4 +1,5 @@ import { KittenScientists } from "../../KittenScientists.js"; +import styles from "./IconButton.module.css"; import { UiComponent, UiComponentOptions } from "./UiComponent.js"; export type IconButtonOptions = UiComponentOptions & { @@ -33,7 +34,7 @@ export class IconButton extends UiComponent { const element = $("
    ", { html: ``, title, - }).addClass("ks-icon-button"); + }).addClass(styles.iconButton); this.element = element; this.addChildren(options?.children); @@ -63,9 +64,9 @@ export class IconButton extends UiComponent { } if (this.inactive) { - this.element.addClass("ks-inactive"); + this.element.addClass(styles.inactive); } else { - this.element.removeClass("ks-inactive"); + this.element.removeClass(styles.inactive); } } } diff --git a/packages/kitten-scientists/source/ui/components/LabelListItem.module.css b/packages/kitten-scientists/source/ui/components/LabelListItem.module.css new file mode 100644 index 000000000..71f573862 --- /dev/null +++ b/packages/kitten-scientists/source/ui/components/LabelListItem.module.css @@ -0,0 +1,17 @@ +/* Setting: Label */ +.label { + display: inline-block; + flex: 1; + min-width: 120px; + opacity: 0.8; +} +.label:hover { + opacity: 1; +} + +.iconLabel { + display: inline-block; + margin-right: 4px; + margin-left: 2px; + vertical-align: middle; +} diff --git a/packages/kitten-scientists/source/ui/components/LabelListItem.ts b/packages/kitten-scientists/source/ui/components/LabelListItem.ts index 1fe6f04b5..ecc48a530 100644 --- a/packages/kitten-scientists/source/ui/components/LabelListItem.ts +++ b/packages/kitten-scientists/source/ui/components/LabelListItem.ts @@ -1,6 +1,8 @@ import { KittenScientists } from "../../KittenScientists.js"; import { Container } from "./Container.js"; +import styles from "./LabelListItem.module.css"; import { ListItem, ListItemOptions } from "./ListItem.js"; +import stylesListItem from "./ListItem.module.css"; export type LabelListItemOptions = ListItemOptions & { /** @@ -30,26 +32,23 @@ export class LabelListItem extends ListItem { super(host, options); this.head = new Container(host); - this.head.element.addClass("ks-head"); + this.head.element.addClass(stylesListItem.head); this.addChild(this.head); this.elementLabel = $("
  • "); if (options?.delimiter === true) { - element.addClass("ks-delimiter"); + element.addClass(stylesDelimiter.delimiter); } this.element = element; diff --git a/packages/kitten-scientists/source/ui/components/RadioItem.ts b/packages/kitten-scientists/source/ui/components/RadioItem.ts index f530ebf6b..b1b1fb97b 100644 --- a/packages/kitten-scientists/source/ui/components/RadioItem.ts +++ b/packages/kitten-scientists/source/ui/components/RadioItem.ts @@ -1,6 +1,9 @@ import { isNil } from "@oliversalzburg/js-utils/data/nil.js"; import { KittenScientists } from "../../KittenScientists.js"; import { SettingOptions } from "../../settings/Settings.js"; +import stylesDelimiter from "./Delimiter.module.css"; +import stylesLabel from "./LabelListItem.module.css"; +import stylesSettingListItem from "./SettingListItem.module.css"; import { UiComponent, UiComponentOptions } from "./UiComponent.js"; export type RadioItemOptions = UiComponentOptions & { @@ -54,15 +57,15 @@ export class RadioItem extends super(host, options); const element = $(`
    `); - element.addClass("ks-setting"); + element.addClass(stylesSettingListItem.setting); if (options?.delimiter === true) { - element.addClass("ks-delimiter"); + element.addClass(stylesDelimiter.delimiter); } const elementLabel = $("