Files
factorio-clusterio/packages/web_ui/src/style.css
T
BastiaanandClaude Opus 5.5 b474573633 Show timestamps in the web UI log console (#1137)
Add a LogEntry type for log entries sent over links and returned by
log queries. It names the fields every entry has (level, message,
timestamp) and leaves the rest as unknown.

The console now prefixes each line with the entry's time in the
browser's local time zone, which makes it possible to tell when an
error happened after the fact.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 19:57:16 +00:00

406 lines
7.2 KiB
CSS

body {
margin: 0;
}
[data-theme="compact"] p, p {
margin: 0;
}
.row-links{
cursor: pointer;
}
/* Make a table link-cell's link fill the cell width, so the whole column
width is clickable and right-click "open in new tab"-able, not just the
text. Uses display:block rather than an overlay so sibling content (e.g.
the restart-required icon) stays interactive. */
.table-link-cell a {
display: block;
}
.login-container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.site-layout-content {
background: #141414;
padding: 24px;
margin: 0;
flex-grow: 0;
}
.site-layout {
overflow-x: clip;
}
.site-layout-content-container {
min-width: 100%;
}
.site-breadcrumb {
margin: 16px 0;
}
@media (min-width: 576px) {
.site-layout-content-container {
padding: 0 24px 24px;
}
}
@media (min-width: 768px) {
.site-layout {
overflow-x: initial;
}
.site-layout-content-container {
min-width: initial;
}
}
/* Top bar hosting the menu toggle and branding, sticky above the content. */
.site-layout-header {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
gap: 16px;
padding-inline: 16px;
background: #001529;
}
/* Keep the sidebar fixed in place (below the header) while content scrolls. */
.site-layout-sider {
position: sticky;
top: 64px;
height: calc(100vh - 64px);
align-self: flex-start;
}
/* Snap the sider open/closed instead of animating its width — the width
transition reflowed the content area and caused styling glitches. */
.ant-layout-sider.site-layout-sider {
transition: none;
}
.page-header {
padding: 0 0 16px;
}
.site-layout-content > h2:first-child {
margin-top: 0;
}
.section-header, .page-header {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.section-header {
margin-top: 16px;
margin-bottom: 8px;
}
.section-header-title, .page-header-title {
flex: auto;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.section-header-title {
font-weight: bold;
font-size: 16px;
line-height: 1.5715;
}
.page-header-title {
margin: 4px 0;
}
.section-header-extra, .page-header-extra {
margin-left: auto;
}
.error-traceback code {
display: block;
margin: 0;
background: #000;
border-color: #252525;
white-space: pre-wrap;
}
.save-list-dragger .ant-upload.ant-upload-drag {
border: none;
background: none;
height: auto;
cursor: inherit;
}
.save-list-dragger .ant-upload.ant-upload-btn {
padding: 0;
}
.save-list-table .ant-table-pagination.ant-pagination {
margin-bottom: 0;
}
.rcon-result code {
display: block;
background: #000;
border-color: #252525;
max-height: 200px;
overflow-y: auto;
white-space: pre-wrap;
animation: rcon-highlight 1s ease-out forwards;
}
@keyframes rcon-highlight {
0% { outline: 3px solid #1668dc; }
100% { outline: 3px solid transparent; }
}
/* see https://blog.eqrion.net/pin-to-bottom/ for how scroll anchors works */
.instance-console code * {
overflow-anchor: none;
}
.instance-console code .scroll-anchor {
overflow-anchor: auto;
height: 1px;
}
/* Scroll headroom above the output so short output sits at the bottom; it is
scroll content, not box padding, so it does not block dragging smaller. */
.instance-console code .console-spacer {
height: 100%;
}
.instance-console code {
display: block;
margin: 0;
background: #000;
border-color: #252525;
/* Drag-resizable (the native handle needs the scroll overflow); height is set
imperatively in LogConsole, border-box keeps padding out of offsetHeight. */
box-sizing: border-box;
height: 300px;
min-height: 100px;
resize: vertical;
overflow-y: scroll;
white-space: pre-wrap;
}
.instance-console .log-time {
color: #808080;
}
.instance-console .factorio-time {
color: #afaf1f;
}
.instance-console .factorio-filename {
color: #808080;
}
.instance-console .factorio-script {
font-weight: bold;
color: #49c33c;
}
.instance-console .factorio-verbose {
font-weight: bold;
color: #888888;
}
.instance-console .factorio-info {
font-weight: bold;
color: #4646ea;
}
.instance-console .factorio-warning {
font-weight: bold;
color: #afaf1f;
}
.instance-console .factorio-error {
font-weight: bold;
color: #ad3939;
}
.instance-console .factorio-action {
color: #afaf1f;
}
.log-verbose {
font-weight: bold;
color: #888888;
}
.log-info {
font-weight: bold;
color: #4646ea;
}
.log-audit {
font-weight: bold;
color: #49c33c;
}
.log-warn {
font-weight: bold;
color: #afaf1f;
}
.log-error {
font-weight: bold;
color: #ad3939;
}
.log-server {
font-weight: bold;
}
.log-fatal {
font-weight: bold;
background-color: #ad3939;
color: #000;
}
.config-container, .config-container .ant-tree {
background-color: #111111;
}
.config-container .ant-form-item {
margin: 0;
}
.config-container .filter-node .ant-tree-node-content-wrapper {
background: #2a1912;
}
.json-input {
font-family: monospace;
}
.factorio-icon {
display: inline-block;
vertical-align: middle;
background-repeat: no-repeat;
}
/* data-mod-pack might not be present, but we need the specificity to win over it if it is */
.factorio-icon:is([data-mod-pack],*)[data-unknown="true"] {
background: url("./images/unknown-item.png");
height: 32px;
width: 32px;
}
.code > code {
display: block;
}
/*
* Render codeblock with options for syntax highlighting
* https://user-images.githubusercontent.com/6792749/152066701-21420461-710b-4fae-a80a-89ef90a0b18f.png
*/
.codeblock {
background-color: black;
padding: 8px;
padding-right: 5em;
margin-bottom: 1em;
min-height: 2.5em;
line-height: 18px;
font-family: Courier;
position: relative;
}
.codeblock .highlight {
color: yellow;
}
.codeblock .copy-button {
position: absolute;
top: 8px;
right: 8px;
}
.ant-descriptions-bordered.borderless > .ant-descriptions-view {
border: none;
}
div.ant-table tr.no-expanded-padding > td,
div.ant-table.ant-table-small .ant-table-tbody > tr.no-expanded-padding > td {
padding: 0;
}
.ant-form-item.changed,
input.ant-input.changed,
textarea.ant-input.changed,
tr.ant-table-row.changed > td {
background: #2a1912;
}
.ant-table-tbody > tr.ant-table-row.changed:hover > td,
.ant-table-tbody > tr.changed > td.ant-table-cell-row-hover
tr.ant-table-row.deleted > td {
background: #3a2922;
}
tr.ant-table-row.deleted {
color: rgba(255, 255, 255, 0.45);
background: #340c08;
text-decoration: line-through;
}
.ant-table-tbody > tr.ant-table-row.deleted:hover > td,
.ant-table-tbody > tr.deleted > td.ant-table-cell-row-hover
tr.ant-table-row.deleted {
background: #441c18;
}
.sticky-notice {
position: sticky;
inset: auto auto 24px auto;
background: #1f1f1f;
padding: 24px;
width: auto;
margin: 16px auto 0;
box-shadow:
0 6px 16px 0 rgba(0, 0, 0, 0.08),
0 3px 6px -4px rgba(0, 0, 0, 0.12),
0 9px 28px 8px rgba(0, 0, 0, 0.05);
border-radius: 8px;
max-width: 384px;
}
/**
* Tri-state segmented control:
* represents include, exclude, or no filter
*/
.seg-yes {
color: #389e0d;
}
.seg-no {
color: #cf1322;
}
.ant-segmented-item-selected.seg-yes {
background-color: #389e0d !important;
color: white !important;
}
.ant-segmented-item-selected.seg-no {
background-color: #cf1322 !important;
color: white !important;
}
.seg-yes:hover {
background-color: #306317;
}
.seg-no:hover {
background-color: #7a2e2f;
}