From c1a87d72995abf1e595c92dc61a009b0484f763d Mon Sep 17 00:00:00 2001 From: CHOMPStation2StaffMirrorBot <94713762+CHOMPStation2StaffMirrorBot@users.noreply.github.com> Date: Sat, 26 Oct 2024 16:23:55 -0700 Subject: [PATCH] [MIRROR] Statpanel styles (#9325) Co-authored-by: ShadowLarkens --- html/statbrowser.css | 328 ++++++++---------- html/statbrowser.html | 8 +- html/statbrowser.js | 43 ++- .../tgui-panel/settings/SettingsPanel.tsx | 2 + .../tgui-panel/settings/SettingsStatPanel.tsx | 84 +++++ .../packages/tgui-panel/settings/constants.ts | 4 + .../tgui-panel/settings/middleware.ts | 38 +- tgui/packages/tgui-panel/settings/reducer.ts | 3 + 8 files changed, 312 insertions(+), 198 deletions(-) create mode 100644 tgui/packages/tgui-panel/settings/SettingsStatPanel.tsx diff --git a/html/statbrowser.css b/html/statbrowser.css index 0e20233b47..d8c0f92b62 100644 --- a/html/statbrowser.css +++ b/html/statbrowser.css @@ -1,150 +1,147 @@ body { font-family: Verdana, Geneva, Tahoma, sans-serif; - font-size: 12px !important; + font-size: 12px; margin: 0 !important; padding: 0 !important; - overflow-x: hidden; - overflow-y: scroll; -} - -body.dark { - background-color: #131313; - color: #b2c4dd; - scrollbar-base-color: #1c1c1c; - scrollbar-face-color: #3b3b3b; - scrollbar-3dlight-color: #252525; - scrollbar-highlight-color: #252525; - scrollbar-track-color: #1c1c1c; - scrollbar-arrow-color: #929292; - scrollbar-shadow-color: #3b3b3b; -} - -#menu { - background-color: #F0F0F0; - position: fixed; - width: 100%; - z-index: 100; -} - -.dark #menu { - background-color: #202020; -} - -#statcontent { - padding: 7px 7px 7px 7px; + overflow: hidden; } a { - color: black; - text-decoration: none -} - -.dark a { - color: #b2c4dd; -} - -a:hover, -.dark a:hover { - text-decoration: underline; -} - -ul { - list-style-type: none; - margin: 0; - padding: 0; - background-color: #333; -} - -li { - float: left; -} - -li a { - display: block; - color: white; - text-align: center; - padding: 14px 16px; + color: #003399; text-decoration: none; } -li a:hover:not(.active) { - background-color: #111; +a:hover { + color: #007fff; } -.button-container { - display: inline-flex; +h3 { + margin: 0 -0.5em 0.5em; + padding: 1em 0.66em 0.5em; + border-bottom: 0.1667em solid; +} + + +img { + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; +} + +.stat-container { + display: flex; + flex-direction: column; + height: 100vh; +} + +#menu { + display: flex; + overflow-x: auto; + overflow-y: hidden; + padding: 0.25em 0.25em 0; + background-color: #ffffff; +} + +.menu-wrap { flex-wrap: wrap-reverse; - flex-direction: row; - align-items: flex-start; - overflow-x: hidden; - white-space: pre-wrap; - padding: 0 4px; +} + +#menu.tabs-classic { + padding: 0.15em; +} + +#menu.tabs-classic .button { + min-width: 2em; + margin: 0.1em; + padding: 0.25em 0.4em; + border: 0; + border-radius: 0.25em; +} + +#menu.tabs-classic .button.active { + background-color: #0668b8; + color: white; } .button { - background-color: #dfdfdf; - border: 1px solid #cecece; - border-bottom-width: 2px; - color: rgba(0, 0, 0, 0.7); - padding: 6px 4px 4px; - text-align: center; - text-decoration: none; - font-size: 12px; - margin: 0; + display: inline-table; cursor: pointer; - transition-duration: 100ms; - order: 3; - min-width: 40px; -} - -.dark button { - background-color: #222222; - border-color: #343434; - color: rgba(255, 255, 255, 0.5); + user-select: none; + -ms-user-select: none; /* Remove after Byond 516 */ + text-align: center; + font-size: 1em; + min-width: 2.9em; + padding: 0.5em 0.5em 0.4em; + background-color: transparent; + color: rgba(0, 0, 0, 0.5); + border: 0; + border-bottom: 0.1667em solid transparent; + border-radius: 0.25em 0.25em 0 0; } .button:hover { background-color: #ececec; - transition-duration: 0; } -.dark button:hover { - background-color: #2e2e2e; -} - -.button:active, .button.active { - background-color: #ffffff; + cursor: default; + background-color: #dfdfdf; color: black; - border-top-color: #cecece; - border-left-color: #cecece; - border-right-color: #cecece; - border-bottom-color: #ffffff; + border-bottom-color: #000000; } -.dark .button:active, -.dark .button.active { - background-color: #444444; - color: white; - border-top-color: #343434; - border-left-color: #343434; - border-right-color: #343434; - border-bottom-color: #ffffff; +#under-menu { + height: 0.5em; + background-color: #eeeeee; +} + +#statcontent { + flex: 1; + padding: 0.75em 0.5em; + overflow-y: scroll; + overflow-x: hidden; } .grid-container { - margin: -2px; - margin-right: -15px; + margin: -0.25em; } .grid-item { + display: inline-flex; position: relative; - display: inline-block; + user-select: none; + -ms-user-select: none; /* Remove after Byond 516 */ width: 100%; - box-sizing: border-box; - overflow: visible; - padding: 3px 2px; + max-height: 1.85em; text-decoration: none; + background-color: transparent; + color: black; +} + +.grid-item:hover, +.grid-item:active { + color: #003399; + z-index: 1; +} + +.grid-item-text { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + pointer-events: none; + width: 100%; + padding: 0.33em 0.5em; + border-radius: 0.25em; +} + +.grid-item:hover .grid-item-text { + overflow: visible; + white-space: normal; + background-color: #ececec; +} + +.grid-item:active .grid-item-text { + background-color: #dfdfdf; } @media only screen and (min-width: 300px) { @@ -171,91 +168,72 @@ li a:hover:not(.active) { } } -.grid-item:hover { - z-index: 1; +.status-info { + margin: 0 0.33em 0.25em; } -.grid-item:hover .grid-item-text { - width: auto; - text-decoration: underline; +.interview_panel_stats, +.interview_panel_controls { + margin-bottom: 1em; } -.grid-item-text { - display: inline-block; - width: 100%; - background-color: #ffffff; - margin: 0 -6px; - padding: 0 6px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - pointer-events: none; +/* Dark theme colors */ +body.dark { + background-color: #131313; + color: #b2c4dd; + scrollbar-base-color: #1c1c1c; + scrollbar-face-color: #3b3b3b; + scrollbar-3dlight-color: #252525; + scrollbar-highlight-color: #252525; + scrollbar-track-color: #1c1c1c; + scrollbar-arrow-color: #929292; + scrollbar-shadow-color: #3b3b3b; } -.dark .grid-item-text { +.dark a { + color: #6699ff; +} + +.dark a:hover, +.dark .grid-item:hover, +.dark .grid-item:active { + color: #80bfff; +} + +.dark #menu { background-color: #131313; } -.link { - display: inline; - background: none; - border: none; - padding: 7px 14px; - color: black; - text-decoration: none; - cursor: pointer; - font-size: 13px; - margin: 2px 2px; +.dark #menu.tabs-classic .button.active { + background-color: #20b142; } -.linkelem { - display: inline; - background: none; - border: none; - padding: 0px 14px; - color: black; - text-decoration: none; - cursor: pointer; - font-size: 13px; - margin: 2px 2px; +.dark .button { + color: rgba(255, 255, 255, 0.5); } -.elemcontainer { - border-collapse: separate; - border-spacing: 0 5px; - display: flex; +.dark .button:hover { + background-color: #252525; } -.elem { - background: none; - border: none; - padding: 0px 14px; - font-size: 13px; - margin: 2px 2px; +.dark .button.active { + background-color: #313131; + color: #d4dfec; + border-bottom-color: #d4dfec; } -.dark .link { - color: #abc6ec; +.dark #under-menu { + background-color: #202020; } -.dark .linkelem { - color: #abc6ec; +.dark .grid-item{ + color: #b2c4dd; } -.link:hover { - text-decoration: underline; +.dark .grid-item:hover .grid-item-text { + background-color: #252525; } -.linkelem:hover { - text-decoration: underline; -} - -img { - -ms-interpolation-mode: nearest-neighbor; - image-rendering: pixelated; -} - -.interview_panel_controls, -.interview_panel_stats { - margin-bottom: 10px; +.dark .grid-item:active .grid-item-text { + background-color: #313131; } diff --git a/html/statbrowser.html b/html/statbrowser.html index 1aea8811d5..ffd7425bd2 100644 --- a/html/statbrowser.html +++ b/html/statbrowser.html @@ -1,3 +1,5 @@ - -
-
+
+ +
+
+
diff --git a/html/statbrowser.js b/html/statbrowser.js index 2572d121ef..7f49fd2486 100644 --- a/html/statbrowser.js +++ b/html/statbrowser.js @@ -33,7 +33,6 @@ var turfname = ""; var imageRetryDelay = 500; var imageRetryLimit = 50; var menu = document.getElementById('menu'); -var under_menu = document.getElementById('under_menu'); var statcontentdiv = document.getElementById('statcontent'); var storedimages = []; var split_admin_tabs = false; @@ -59,26 +58,25 @@ function createStatusTab(name) { if (!verb_tabs.includes(name) && !permanent_tabs.includes(name)) { return; } - var B = document.createElement("BUTTON"); - B.onclick = function () { + var button = document.createElement("DIV"); + button.onclick = function () { tab_change(name); this.blur(); }; - B.id = name; - B.textContent = name; - B.className = "button"; + button.id = name; + button.textContent = name; + button.className = "button"; //ORDERING ALPHABETICALLY - B.style.order = name.charCodeAt(0); + button.style.order = name.charCodeAt(0); if (name == "Status" || name == "MC") { - B.style.order = name == "Status" ? 1 : 2; + button.style.order = name == "Status" ? 1 : 2; } if (name == "Tickets") { - B.style.order = 3; + button.style.order = 3; } //END ORDERING - menu.appendChild(B); + menu.appendChild(button); SendTabToByond(name); - under_menu.style.height = menu.clientHeight + 'px'; } function removeStatusTab(name) { @@ -92,7 +90,6 @@ function removeStatusTab(name) { } menu.removeChild(document.getElementById(name)); TakeTabFromByond(name); - under_menu.style.height = menu.clientHeight + 'px'; } function sortVerbs() { @@ -108,10 +105,6 @@ function sortVerbs() { }) } -window.onresize = function () { - under_menu.style.height = menu.clientHeight + 'px'; -} - function addPermanentTab(name) { if (!permanent_tabs.includes(name)) { permanent_tabs.push(name); @@ -383,6 +376,7 @@ function draw_status() { } else { var div = document.createElement("div"); div.textContent = status_tab_parts[i]; + div.className = "status-info"; document.getElementById("statcontent").appendChild(div); } } @@ -777,6 +771,23 @@ function set_theme(which) { } } +function set_font_size(size) { + document.body.style.setProperty('font-size', size); +} + +function set_tabs_style(style) { + if (style == "default") { + menu.classList.add('menu-wrap'); + menu.classList.remove('tabs-classic'); + } else if (style == "classic") { + menu.classList.add('menu-wrap'); + menu.classList.add('tabs-classic'); + } else if (style == "scrollable") { + menu.classList.remove('menu-wrap'); + menu.classList.remove('tabs-classic'); + } +} + function set_style_sheet(sheet) { if (document.getElementById("goonStyle")) { var currentSheet = document.getElementById("goonStyle"); diff --git a/tgui/packages/tgui-panel/settings/SettingsPanel.tsx b/tgui/packages/tgui-panel/settings/SettingsPanel.tsx index e017d83c12..a141b09e93 100644 --- a/tgui/packages/tgui-panel/settings/SettingsPanel.tsx +++ b/tgui/packages/tgui-panel/settings/SettingsPanel.tsx @@ -11,6 +11,7 @@ import { ChatPageSettings } from '../chat'; import { changeSettingsTab } from './actions'; import { SETTINGS_TABS } from './constants'; import { selectActiveTab } from './selectors'; +import { SettingsStatPanel } from './SettingsStatPanel'; import { AdminSettings } from './SettingTabs/AdminSettings'; import { ExportTab } from './SettingTabs/ExportTab'; import { MessageLimits } from './SettingTabs/MessageLimits'; @@ -49,6 +50,7 @@ export const SettingsPanel = (props) => { {activeTab === 'export' && } {activeTab === 'chatPage' && } {activeTab === 'textHighlight' && } + {activeTab === 'statPanel' && } {activeTab === 'adminSettings' && } diff --git a/tgui/packages/tgui-panel/settings/SettingsStatPanel.tsx b/tgui/packages/tgui-panel/settings/SettingsStatPanel.tsx new file mode 100644 index 0000000000..68ca14131c --- /dev/null +++ b/tgui/packages/tgui-panel/settings/SettingsStatPanel.tsx @@ -0,0 +1,84 @@ +import { toFixed } from 'common/math'; +import { capitalize } from 'common/string'; +import { useDispatch, useSelector } from 'tgui/backend'; +import { + Button, + LabeledList, + NoticeBox, + Section, + Slider, + Stack, +} from 'tgui/components'; + +import { updateSettings } from './actions'; +import { selectSettings } from './selectors'; + +const TabsViews = ['default', 'classic', 'scrollable']; +const LinkedToChat = () => ( + Unlink Stat Panel from chat! +); + +export function SettingsStatPanel(props) { + const { statLinked, statFontSize, statTabsStyle } = + useSelector(selectSettings); + const dispatch = useDispatch(); + + return ( +
+ + + + + {TabsViews.map((view) => ( + + ))} + + + + {statLinked ? ( + + ) : ( + toFixed(value)} + onChange={(e, value) => + dispatch(updateSettings({ statFontSize: value })) + } + /> + )} + + + + + + + + + +
+ ); +} diff --git a/tgui/packages/tgui-panel/settings/constants.ts b/tgui/packages/tgui-panel/settings/constants.ts index 8be68f3d2c..8bb3222a1b 100644 --- a/tgui/packages/tgui-panel/settings/constants.ts +++ b/tgui/packages/tgui-panel/settings/constants.ts @@ -29,6 +29,10 @@ export const SETTINGS_TABS = [ id: 'chatPage', name: 'Chat Tabs', }, + { + id: 'statPanel', + name: 'Stat Panel', + }, ]; export const FONTS_DISABLED = 'Default'; diff --git a/tgui/packages/tgui-panel/settings/middleware.ts b/tgui/packages/tgui-panel/settings/middleware.ts index fc09fe5d2c..078b9a7874 100644 --- a/tgui/packages/tgui-panel/settings/middleware.ts +++ b/tgui/packages/tgui-panel/settings/middleware.ts @@ -13,11 +13,12 @@ import { removeHighlightSetting, updateHighlightSetting, updateSettings, - updateToggle, } from './actions'; import { FONTS_DISABLED } from './constants'; import { selectSettings } from './selectors'; +let statFontTimer: NodeJS.Timeout; +let statTabsTimer: NodeJS.Timeout; let overrideRule: HTMLStyleElement; let overrideFontFamily: string | undefined; let overrideFontSize: string; @@ -45,14 +46,37 @@ function updateGlobalOverrideRule() { document.body.style.setProperty('font-size', overrideFontSize); } -function setGlobalFontSize(fontSize: string) { +function setGlobalFontSize( + fontSize: string, + statFontSize: string, + statLinked: boolean, +) { overrideFontSize = `${fontSize}px`; + + // Used solution from theme.ts + clearInterval(statFontTimer); + Byond.command( + `.output statbrowser:set_font_size ${statLinked ? fontSize : statFontSize}px`, + ); + statFontTimer = setTimeout(() => { + Byond.command( + `.output statbrowser:set_font_size ${statLinked ? fontSize : statFontSize}px`, + ); + }, 1500); } function setGlobalFontFamily(fontFamily: string) { overrideFontFamily = fontFamily === FONTS_DISABLED ? undefined : fontFamily; } +function setStatTabsStyle(style: string) { + clearInterval(statTabsTimer); + Byond.command(`.output statbrowser:set_tabs_style ${style}`); + statTabsTimer = setTimeout(() => { + Byond.command(`.output statbrowser:set_tabs_style ${style}`); + }, 1500); +} + export function settingsMiddleware(store) { let initialized = false; @@ -66,7 +90,6 @@ export function settingsMiddleware(store) { }); } if ( - type !== updateToggle.type && type !== updateSettings.type && type !== loadSettings.type && type !== addHighlightSetting.type && @@ -87,8 +110,15 @@ export function settingsMiddleware(store) { const settings = selectSettings(store.getState()); + // Update stat panel settings + setStatTabsStyle(settings.statTabsStyle); + // Update global UI font size - setGlobalFontSize(settings.fontSize); + setGlobalFontSize( + settings.fontSize, + settings.statFontSize, + settings.statLinked, + ); setGlobalFontFamily(settings.fontFamily); updateGlobalOverrideRule(); diff --git a/tgui/packages/tgui-panel/settings/reducer.ts b/tgui/packages/tgui-panel/settings/reducer.ts index a4f6d3c56a..2fd2e0b94d 100644 --- a/tgui/packages/tgui-panel/settings/reducer.ts +++ b/tgui/packages/tgui-panel/settings/reducer.ts @@ -62,6 +62,9 @@ const initialState = { hideImportantInAdminTab: false, interleave: false, interleaveColor: '#909090', + statLinked: true, + statFontSize: 12, + statTabsStyle: 'default', } as const; export function settingsReducer(