feat(editor): the dark scheme everywhere — the surface, documentation, mode buttons, program windows
The surface turns dark with light labels and cables and a faint light outline round Java's icons; documentation rectangles become a tint of their colour and texts are drawn towards light; the mode buttons use Java's pictures freed from their grey ground (tools/dark-pictures/make.py); native controls follow color-scheme; the desktop's program windows paint through Java-look tokens whose light values are Java's own. The exported image and the report keep Java's colours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 950 B |
Binary file not shown.
|
After Width: | Height: | Size: 973 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -36,7 +36,7 @@ import { bounds, cablePath, deviceBox, ICONS, iconOf, JAVA_LABEL_FONT, type Devi
|
||||
import { fitted, middle, shifted, spread, toScreen, toSurface, zoomedAt, zoomIn, zoomOut, type Point, type Size, type Viewport } from './viewport.js';
|
||||
import { ZoomBar } from './ZoomBar.js';
|
||||
import { gripPlace, handlePlace, HANDLES, menuPlace, NO_EDGE, shownHandles, TARGET, type Edges } from './handles.js';
|
||||
import { EDGE_BAND, edgesAt, FOCUS_BAND, FOCUS_BORDER, fontFamily, holdFrame, rectangleBorder, rectangleFill, TEXT_BORDER, textColor, type Frame } from './documentationPaint.js';
|
||||
import { darkRectangleBorder, darkRectangleFill, darkTextColor, EDGE_BAND, edgesAt, FOCUS_BAND, FOCUS_BORDER, fontFamily, holdFrame, rectangleBorder, rectangleFill, textColor, type Frame } from './documentationPaint.js';
|
||||
|
||||
/** How far a pointer moves before a press becomes a drag. */
|
||||
export const DRAG_THRESHOLD = 4;
|
||||
@@ -152,6 +152,8 @@ function Documentation({ item, documenting, focused }: { readonly item: Document
|
||||
fill={rectangleFill(item.color, documenting)}
|
||||
stroke={focused ? 'none' : rectangleBorder(item.color)}
|
||||
strokeWidth={1}
|
||||
// The dark scheme's paint (sheet.css takes it): Java's is for a white surface.
|
||||
style={{ '--doc-fill-dark': darkRectangleFill(item.color, documenting), '--doc-stroke-dark': focused ? 'none' : darkRectangleBorder(item.color) } as CSSProperties}
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
@@ -166,14 +168,15 @@ function Documentation({ item, documenting, focused }: { readonly item: Document
|
||||
style={{
|
||||
boxSizing: 'border-box',
|
||||
padding: 1,
|
||||
color: textColor(item.color),
|
||||
// The words' colour, in the dark scheme drawn towards light (sheet.css).
|
||||
...({ '--doc-ink': textColor(item.color), '--doc-ink-dark': darkTextColor(item.color) } as CSSProperties),
|
||||
font: `${item.italic ? 'italic ' : ''}${item.bold ? 'bold ' : ''}${item.size}px ${fontFamily(item.font)}`,
|
||||
whiteSpace: 'pre-wrap',
|
||||
overflowWrap: 'break-word',
|
||||
overflow: 'hidden',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
border: documenting && !focused ? `1px solid ${TEXT_BORDER}` : undefined,
|
||||
border: documenting && !focused ? '1px solid var(--doc-text-border)' : undefined,
|
||||
visibility: focused ? 'hidden' : undefined,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -40,6 +40,24 @@ export function textColor(color: Color): string {
|
||||
return `rgba(${byte(color.red)}, ${byte(color.green)}, ${byte(color.blue)}, ${color.alpha})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The editor's dark scheme (not Java's — it has none; the exported image and
|
||||
* the report keep Java's paint): a rectangle's colour as a tint of the dark
|
||||
* surface, stronger while documenting, its border the colour itself, faded.
|
||||
*/
|
||||
export function darkRectangleFill(color: Color, documenting: boolean): string {
|
||||
return `rgba(${byte(color.red)}, ${byte(color.green)}, ${byte(color.blue)}, ${documenting ? 0.28 : 0.2})`;
|
||||
}
|
||||
|
||||
export function darkRectangleBorder(color: Color): string {
|
||||
return `rgba(${byte(color.red)}, ${byte(color.green)}, ${byte(color.blue)}, 0.7)`;
|
||||
}
|
||||
|
||||
/** A text's colour on the dark surface: drawn towards the light text colour, so that Java's black reads as light and a red as a light red. */
|
||||
export function darkTextColor(color: Color): string {
|
||||
return `color-mix(in oklab, ${textColor(color)} 15%, var(--canvas-label))`;
|
||||
}
|
||||
|
||||
/** Java's logical font names as the browser has them; any other a font of that name, else sans-serif. */
|
||||
export function fontFamily(name: string): string {
|
||||
switch (name.toLowerCase()) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useEffect, useRef } from 'react';
|
||||
import type * as Y from 'yjs';
|
||||
import { replaceText, type DocumentationView } from '@mdg-filius/doc';
|
||||
import type { ScreenFrame } from '../canvas/Canvas.js';
|
||||
import { fontFamily, textColor } from '../canvas/documentationPaint.js';
|
||||
import { darkTextColor, fontFamily, textColor } from '../canvas/documentationPaint.js';
|
||||
import { followText } from '../desktop/textBinding.js';
|
||||
import { useTranslate } from '../i18n/i18n.js';
|
||||
|
||||
@@ -37,6 +37,7 @@ export function DocumentationText({ item, frame, text, origin, onDone, onRemove
|
||||
ref={area}
|
||||
aria-label={t('docu.text')}
|
||||
data-doc-text={item.id}
|
||||
className="doc-text-field"
|
||||
spellCheck={false}
|
||||
onInput={(event) => {
|
||||
const next = event.currentTarget.value;
|
||||
@@ -67,7 +68,8 @@ export function DocumentationText({ item, frame, text, origin, onDone, onRemove
|
||||
resize: 'none',
|
||||
overflow: 'hidden',
|
||||
background: 'transparent',
|
||||
color: textColor(item.color),
|
||||
// The words' colour as the drawn text has it, in the dark scheme too (sheet.css).
|
||||
...({ '--doc-ink': textColor(item.color), '--doc-ink-dark': darkTextColor(item.color) } as React.CSSProperties),
|
||||
font: `${item.italic ? 'italic ' : ''}${item.bold ? 'bold ' : ''}${item.size}px ${fontFamily(item.font)}`,
|
||||
lineHeight: 'normal',
|
||||
whiteSpace: 'pre-wrap',
|
||||
|
||||
@@ -167,9 +167,9 @@
|
||||
.desktop-network {
|
||||
margin: 0;
|
||||
padding: 8px 12px;
|
||||
border: 2px inset #c0c0c0;
|
||||
background: #eeeeee;
|
||||
color: #000000;
|
||||
border: 2px inset var(--java-grid);
|
||||
background: var(--java-panel);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -187,8 +187,8 @@
|
||||
|
||||
.desktop-network dd {
|
||||
padding: 2px 6px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #b0b0b0;
|
||||
background: var(--java-field);
|
||||
border: 1px solid var(--java-line);
|
||||
font-variant-numeric: tabular-nums;
|
||||
user-select: text;
|
||||
}
|
||||
@@ -199,14 +199,14 @@
|
||||
align-items: stretch;
|
||||
height: 44px;
|
||||
flex: none;
|
||||
background: rgb(180 180 180);
|
||||
background: var(--java-taskbar);
|
||||
}
|
||||
|
||||
.desktop-home,
|
||||
.desktop-network-icon {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #000000;
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -228,7 +228,7 @@
|
||||
inset: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #ffffff;
|
||||
background: var(--java-field);
|
||||
}
|
||||
|
||||
.program-titlebar {
|
||||
@@ -343,8 +343,8 @@
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
background: #eeeeee;
|
||||
color: #000000;
|
||||
background: var(--java-panel);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -371,8 +371,8 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
background: #ffffff;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: var(--java-field);
|
||||
border: 1px solid var(--java-border);
|
||||
}
|
||||
|
||||
.installation-list li {
|
||||
@@ -385,11 +385,11 @@
|
||||
}
|
||||
|
||||
.installation-list li[aria-selected='true'] {
|
||||
background: rgb(184 207 229);
|
||||
background: var(--java-selected);
|
||||
}
|
||||
|
||||
.installation-list li:focus-visible {
|
||||
outline: 2px solid rgb(99 130 191);
|
||||
outline: 2px solid var(--java-focus);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
@@ -404,10 +404,10 @@
|
||||
.installation-apply {
|
||||
min-width: 44px;
|
||||
min-height: 44px;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
border-radius: 6px;
|
||||
background: #f8f8f8;
|
||||
color: #000000;
|
||||
background: var(--java-button);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -425,7 +425,7 @@
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #eeeeee;
|
||||
background: var(--java-panel);
|
||||
font: 13px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -441,9 +441,9 @@
|
||||
min-width: 0;
|
||||
min-height: 36px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
color: var(--java-text);
|
||||
font: 16px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -452,10 +452,10 @@
|
||||
min-width: 44px;
|
||||
min-height: 36px;
|
||||
padding: 0 14px;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
border-radius: 6px;
|
||||
background: #f8f8f8;
|
||||
color: #000000;
|
||||
background: var(--java-button);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -466,7 +466,7 @@
|
||||
margin: 0 5px 5px;
|
||||
display: flex;
|
||||
background: #ffffff;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
}
|
||||
|
||||
.browser-page iframe {
|
||||
@@ -496,8 +496,8 @@
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
padding: 5px 10px 10px;
|
||||
background: #eeeeee;
|
||||
color: #000000;
|
||||
background: var(--java-panel);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -533,20 +533,20 @@
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
background: #ffffff;
|
||||
background: var(--java-field);
|
||||
}
|
||||
|
||||
.web-server-hosts th {
|
||||
padding: 4px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #e4e4e4;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-head);
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.web-server-hosts td {
|
||||
padding: 0;
|
||||
border: 1px solid #c0c0c0;
|
||||
border: 1px solid var(--java-grid);
|
||||
}
|
||||
|
||||
.web-server-hosts td input {
|
||||
@@ -556,7 +556,7 @@
|
||||
padding: 0 5px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #000000;
|
||||
color: var(--java-text);
|
||||
font: 16px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -566,8 +566,8 @@
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
padding: 4px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
font: 12px ui-monospace, Menlo, Consolas, monospace;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
@@ -588,8 +588,8 @@
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
padding: 5px;
|
||||
background: #eeeeee;
|
||||
color: #000000;
|
||||
background: var(--java-panel);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -612,10 +612,10 @@
|
||||
min-width: 44px;
|
||||
min-height: 40px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
border-radius: 6px;
|
||||
background: #f8f8f8;
|
||||
color: #000000;
|
||||
background: var(--java-button);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -642,23 +642,23 @@
|
||||
min-width: 0;
|
||||
min-height: 32px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
color: var(--java-text);
|
||||
font: 16px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
.mail-client [aria-invalid='true'],
|
||||
.mail-server [aria-invalid='true'] {
|
||||
border-color: #ff0000;
|
||||
color: #ff0000;
|
||||
border-color: var(--java-invalid);
|
||||
color: var(--java-invalid);
|
||||
}
|
||||
|
||||
.mail-tabs {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
flex: none;
|
||||
border-bottom: 1px solid #a0a0a0;
|
||||
border-bottom: 1px solid var(--java-border);
|
||||
}
|
||||
|
||||
.mail-tabs button {
|
||||
@@ -667,17 +667,17 @@
|
||||
gap: 6px;
|
||||
min-height: 40px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
border-bottom: none;
|
||||
border-radius: 6px 6px 0 0;
|
||||
background: #e0e0e0;
|
||||
color: #000000;
|
||||
background: var(--java-tab);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mail-tabs button[aria-selected='true'] {
|
||||
background: #ffffff;
|
||||
background: var(--java-field);
|
||||
}
|
||||
|
||||
.mail-list,
|
||||
@@ -685,8 +685,8 @@
|
||||
flex: 1;
|
||||
min-height: 80px;
|
||||
overflow: auto;
|
||||
background: #ffffff;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: var(--java-field);
|
||||
border: 1px solid var(--java-border);
|
||||
}
|
||||
|
||||
.mail-accounts {
|
||||
@@ -711,8 +711,8 @@
|
||||
.mail-list th,
|
||||
.mail-accounts th {
|
||||
padding: 4px 6px;
|
||||
border-bottom: 1px solid #a0a0a0;
|
||||
background: #e4e4e4;
|
||||
border-bottom: 1px solid var(--java-border);
|
||||
background: var(--java-head);
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
}
|
||||
@@ -729,7 +729,7 @@
|
||||
|
||||
.mail-list tr[aria-selected='true'] td,
|
||||
.mail-accounts tr[aria-selected='true'] td {
|
||||
background: rgb(184 207 229);
|
||||
background: var(--java-selected);
|
||||
}
|
||||
|
||||
.mail-preview {
|
||||
@@ -737,8 +737,8 @@
|
||||
min-height: 80px;
|
||||
overflow: auto;
|
||||
padding: 4px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
}
|
||||
|
||||
.mail-preview pre,
|
||||
@@ -763,8 +763,8 @@
|
||||
min-height: 80px;
|
||||
overflow: auto;
|
||||
padding: 4px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
}
|
||||
|
||||
.mail-form {
|
||||
@@ -805,7 +805,7 @@
|
||||
gap: 6px;
|
||||
overflow: auto;
|
||||
padding: 0 8px 8px;
|
||||
background: #eeeeee;
|
||||
background: var(--java-panel);
|
||||
}
|
||||
|
||||
.mail-dialog h4 {
|
||||
@@ -821,7 +821,7 @@
|
||||
flex: 1;
|
||||
min-height: 120px;
|
||||
padding: 4px;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
font: 16px ui-monospace, Menlo, Consolas, monospace;
|
||||
}
|
||||
|
||||
@@ -833,9 +833,9 @@
|
||||
transform: translateX(-50%);
|
||||
width: min(90%, 380px);
|
||||
padding: 12px;
|
||||
border: 1px solid #808080;
|
||||
border: 1px solid var(--java-border-strong);
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
background: var(--java-field);
|
||||
box-shadow: 0 4px 16px rgb(0 0 0 / 30%);
|
||||
}
|
||||
|
||||
@@ -858,7 +858,7 @@
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
padding: 5px;
|
||||
background: #eeeeee;
|
||||
background: var(--java-panel);
|
||||
}
|
||||
|
||||
.text-editor-bar {
|
||||
@@ -874,17 +874,17 @@
|
||||
min-width: 44px;
|
||||
min-height: 40px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
border-radius: 6px;
|
||||
background: #f8f8f8;
|
||||
color: #000000;
|
||||
background: var(--java-button);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.text-editor-bar button:disabled,
|
||||
.file-dialog-folder button:disabled {
|
||||
color: #a0a0a0;
|
||||
color: var(--java-disabled);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@@ -893,9 +893,9 @@
|
||||
min-height: 0;
|
||||
resize: none;
|
||||
padding: 4px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
color: var(--java-text);
|
||||
font: 16px 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
@@ -919,8 +919,8 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@@ -933,14 +933,14 @@
|
||||
padding: 0 6px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #000000;
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-dialog-entries button[aria-pressed='true'] {
|
||||
background: #b8cfe5;
|
||||
background: var(--java-selected);
|
||||
}
|
||||
|
||||
/* The file explorer (GUIApplicationFileExplorerWindow): the menu's actions
|
||||
@@ -954,7 +954,7 @@
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
padding: 5px;
|
||||
background: #eeeeee;
|
||||
background: var(--java-panel);
|
||||
}
|
||||
|
||||
.file-explorer-bar {
|
||||
@@ -968,16 +968,16 @@
|
||||
min-width: 44px;
|
||||
min-height: 40px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #a0a0a0;
|
||||
border: 1px solid var(--java-border);
|
||||
border-radius: 6px;
|
||||
background: #f8f8f8;
|
||||
color: #000000;
|
||||
background: var(--java-button);
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-explorer-bar button:disabled {
|
||||
color: #a0a0a0;
|
||||
color: var(--java-disabled);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@@ -995,8 +995,8 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@@ -1010,7 +1010,7 @@
|
||||
padding: 0 6px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #000000;
|
||||
color: var(--java-text);
|
||||
font: 13px Dialog, sans-serif;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
@@ -1019,7 +1019,7 @@
|
||||
.file-explorer-tree button[aria-current='true'],
|
||||
.file-explorer-tree button[aria-pressed='true'],
|
||||
.file-explorer-entries button[aria-pressed='true'] {
|
||||
background: #b8cfe5;
|
||||
background: var(--java-selected);
|
||||
}
|
||||
|
||||
@media (max-width: 639px) {
|
||||
@@ -1048,7 +1048,7 @@
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
padding: 5px;
|
||||
background: #eeeeee;
|
||||
background: var(--java-panel);
|
||||
}
|
||||
|
||||
.image-viewer-picture {
|
||||
@@ -1071,9 +1071,9 @@
|
||||
.simple-client textarea {
|
||||
min-height: 32px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
color: var(--java-text);
|
||||
font: 16px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -1083,13 +1083,13 @@
|
||||
|
||||
.echo-server [aria-invalid='true'],
|
||||
.simple-client [aria-invalid='true'] {
|
||||
border-color: #ff0000;
|
||||
color: #ff0000;
|
||||
border-color: var(--java-invalid);
|
||||
color: var(--java-invalid);
|
||||
}
|
||||
|
||||
.echo-server input:read-only,
|
||||
.simple-client input:read-only {
|
||||
background: #eeeeee;
|
||||
background: var(--java-panel);
|
||||
}
|
||||
|
||||
.simple-client-field,
|
||||
@@ -1134,15 +1134,15 @@
|
||||
.dns-server input:not([type='checkbox']) {
|
||||
min-height: 32px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
color: var(--java-text);
|
||||
font: 16px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
.dns-server [aria-invalid='true'] {
|
||||
border-color: #ff0000;
|
||||
color: #ff0000;
|
||||
border-color: var(--java-invalid);
|
||||
color: var(--java-invalid);
|
||||
}
|
||||
|
||||
.dns-server-notice {
|
||||
@@ -1152,19 +1152,19 @@
|
||||
.dns-server-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: #ffffff;
|
||||
background: var(--java-field);
|
||||
}
|
||||
|
||||
.dns-server-table th {
|
||||
padding: 4px 6px;
|
||||
border-bottom: 1px solid #a0a0a0;
|
||||
border-bottom: 1px solid var(--java-border);
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.dns-server-table td {
|
||||
padding: 2px;
|
||||
border-bottom: 1px solid #dddddd;
|
||||
border-bottom: 1px solid var(--java-rule);
|
||||
}
|
||||
|
||||
.dns-server-table td input {
|
||||
@@ -1175,7 +1175,7 @@
|
||||
|
||||
.dns-server-table tr[aria-selected='true'] td,
|
||||
.dns-server-table tr[aria-selected='true'] input {
|
||||
background: #b8cfe5;
|
||||
background: var(--java-selected);
|
||||
}
|
||||
|
||||
/* A computer's firewall (GUIApplicationFirewallWindow): two tabs, the boxes,
|
||||
@@ -1215,9 +1215,9 @@
|
||||
.personal-firewall select {
|
||||
min-height: 32px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
color: var(--java-text);
|
||||
font: 16px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
@@ -1226,8 +1226,8 @@
|
||||
}
|
||||
|
||||
.personal-firewall [aria-invalid='true'] {
|
||||
border-color: #ff0000;
|
||||
color: #ff0000;
|
||||
border-color: var(--java-invalid);
|
||||
color: var(--java-invalid);
|
||||
}
|
||||
|
||||
.personal-firewall-table td {
|
||||
@@ -1269,15 +1269,15 @@
|
||||
.gnutella input {
|
||||
min-height: 32px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #a0a0a0;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
border: 1px solid var(--java-border);
|
||||
background: var(--java-field);
|
||||
color: var(--java-text);
|
||||
font: 16px Dialog, sans-serif;
|
||||
}
|
||||
|
||||
.gnutella [aria-invalid='true'] {
|
||||
border-color: #ff0000;
|
||||
color: #ff1414;
|
||||
border-color: var(--java-invalid);
|
||||
color: var(--java-invalid-text);
|
||||
}
|
||||
|
||||
.gnutella-table td {
|
||||
|
||||
@@ -50,6 +50,30 @@
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Documentation on the surface: a text's words in their colour; in the dark
|
||||
* scheme a rectangle as a tint and the words drawn towards light
|
||||
* (documentationPaint.ts) — Java paints for a white surface. Java's icons get
|
||||
* a faint light outline there, or its black switches and routers would sink
|
||||
* into the dark. */
|
||||
.doc-text,
|
||||
.doc-text-field {
|
||||
color: var(--doc-ink);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .doc-text,
|
||||
:root[data-theme='dark'] .doc-text-field {
|
||||
color: var(--doc-ink-dark);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .doc-rectangle {
|
||||
fill: var(--doc-fill-dark);
|
||||
stroke: var(--doc-stroke-dark);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .filius-canvas .devices image {
|
||||
filter: drop-shadow(0 0 1px rgb(255 255 255 / 55%));
|
||||
}
|
||||
|
||||
/* A focused documentation item's handles (Canvas): a finger's target of
|
||||
* 44 px around a dot in Java's focus blue, over the field a text is typed
|
||||
* into; a text's grip a round button above its corner. */
|
||||
@@ -117,6 +141,26 @@
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* The mode buttons' pictures (ModeBar): Java's in the light scheme; in the
|
||||
* dark one freed from their grey ground, the button marking the mode that is on. */
|
||||
.mode-picture {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mode-picture[data-scheme='dark'],
|
||||
:root[data-theme='dark'] .mode-picture[data-scheme='light'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .mode-picture[data-scheme='dark'] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .mode-button[aria-pressed='true'] {
|
||||
border-color: var(--accent) !important;
|
||||
background: var(--accent-soft) !important;
|
||||
}
|
||||
|
||||
/* A word beside the mode buttons: that this person only reads. */
|
||||
.editor-note {
|
||||
display: flex;
|
||||
|
||||
@@ -11,8 +11,28 @@ import design from '../assets/modes/entwurfsmodus.png';
|
||||
import designOn from '../assets/modes/entwurfsmodus_aktiv.png';
|
||||
import documentation from '../assets/modes/dokumodus.png';
|
||||
import documentationOn from '../assets/modes/dokumodus_aktiv.png';
|
||||
import simulationDark from '../assets/modes/aktionsmodus_dunkel.png';
|
||||
import simulationOnDark from '../assets/modes/aktionsmodus_aktiv_dunkel.png';
|
||||
import designDark from '../assets/modes/entwurfsmodus_dunkel.png';
|
||||
import designOnDark from '../assets/modes/entwurfsmodus_aktiv_dunkel.png';
|
||||
import documentationDark from '../assets/modes/dokumodus_dunkel.png';
|
||||
import documentationOnDark from '../assets/modes/dokumodus_aktiv_dunkel.png';
|
||||
import { useTranslate } from '../i18n/i18n.js';
|
||||
|
||||
/**
|
||||
* A mode's picture: Java's (a grey button's gradient, light blue when on),
|
||||
* and for the dark scheme the same freed from its ground, the button showing
|
||||
* whether it is on (sheet.css: .mode-picture).
|
||||
*/
|
||||
function ModePicture({ light, dark }: { readonly light: string; readonly dark: string }) {
|
||||
return (
|
||||
<>
|
||||
<img className="mode-picture" data-scheme="light" src={light} alt="" width={50} height={50} />
|
||||
<img className="mode-picture" data-scheme="dark" src={dark} alt="" width={50} height={50} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const modeButton: CSSProperties = {
|
||||
width: 52,
|
||||
height: 52,
|
||||
@@ -46,6 +66,7 @@ export function ModeBar({
|
||||
<button
|
||||
type="button"
|
||||
name="documentationMode"
|
||||
className="mode-button"
|
||||
style={modeButton}
|
||||
aria-pressed={mode === 'documentation'}
|
||||
aria-label={t('mode.documentation')}
|
||||
@@ -53,13 +74,13 @@ export function ModeBar({
|
||||
disabled={!canRun && mode === 'simulation'}
|
||||
onClick={() => onMode('documentation')}
|
||||
>
|
||||
<img src={mode === 'documentation' ? documentationOn : documentation} alt="" width={50} height={50} />
|
||||
<ModePicture light={mode === 'documentation' ? documentationOn : documentation} dark={mode === 'documentation' ? documentationOnDark : documentationDark} />
|
||||
</button>
|
||||
<button type="button" name="designMode" style={modeButton} aria-pressed={mode === 'design'} aria-label={t('mode.design')} title={t('mode.design')} disabled={!canRun && mode === 'simulation'} onClick={() => onMode('design')}>
|
||||
<img src={mode === 'design' ? designOn : design} alt="" width={50} height={50} />
|
||||
<button type="button" name="designMode" className="mode-button" style={modeButton} aria-pressed={mode === 'design'} aria-label={t('mode.design')} title={t('mode.design')} disabled={!canRun && mode === 'simulation'} onClick={() => onMode('design')}>
|
||||
<ModePicture light={mode === 'design' ? designOn : design} dark={mode === 'design' ? designOnDark : designDark} />
|
||||
</button>
|
||||
<button type="button" name="simulationMode" style={modeButton} aria-pressed={mode === 'simulation'} aria-label={t('mode.simulation')} title={t('mode.simulation')} disabled={!canRun} onClick={() => onMode('simulation')}>
|
||||
<img src={mode === 'simulation' ? simulationOn : simulation} alt="" width={50} height={50} />
|
||||
<button type="button" name="simulationMode" className="mode-button" style={modeButton} aria-pressed={mode === 'simulation'} aria-label={t('mode.simulation')} title={t('mode.simulation')} disabled={!canRun} onClick={() => onMode('simulation')}>
|
||||
<ModePicture light={mode === 'simulation' ? simulationOn : simulation} dark={mode === 'simulation' ? simulationOnDark : simulationDark} />
|
||||
</button>
|
||||
{mode === 'simulation' ? (
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '0 8px', minHeight: 52, borderRadius: 8, background: 'var(--surface-raised)', border: '1px solid var(--border-default)' }}>
|
||||
|
||||
@@ -45,6 +45,28 @@
|
||||
--capture-on-layer: #000000;
|
||||
--capture-chosen: #000000;
|
||||
--capture-on-chosen: #ffffff;
|
||||
/* A documentation text's border in the documentation mode (textPanelBorderNormalColor). */
|
||||
--doc-text-border: rgb(179 179 179);
|
||||
/* Java's Swing look in the desktop's program windows (Metal): a panel, a field, its border and text, a button, a
|
||||
* table's head, a chosen row, the focus, a refused entry; the taskbar (GUIDesktopPanel). */
|
||||
--java-panel: #eeeeee;
|
||||
--java-field: #ffffff;
|
||||
--java-text: #000000;
|
||||
--java-border: #a0a0a0;
|
||||
--java-border-strong: #808080;
|
||||
--java-grid: #c0c0c0;
|
||||
--java-line: #b0b0b0;
|
||||
--java-rule: #dddddd;
|
||||
--java-disabled: #a0a0a0;
|
||||
--java-button: #f8f8f8;
|
||||
--java-head: #e4e4e4;
|
||||
--java-tab: #e0e0e0;
|
||||
--java-selected: #b8cfe5;
|
||||
--java-focus: rgb(99 130 191);
|
||||
--java-invalid: #ff0000;
|
||||
--java-invalid-text: #ff1414;
|
||||
--java-taskbar: rgb(180 180 180);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] {
|
||||
@@ -70,12 +92,13 @@
|
||||
--danger: #f2695a;
|
||||
--danger-soft: #3a1a17;
|
||||
--danger-on-soft: #ffa79b;
|
||||
/* Java's icons are drawn for a light ground: the surface stays light, a shade darker. */
|
||||
--canvas-bg: #e9ecf1;
|
||||
--canvas-cable: rgb(64 64 64);
|
||||
--canvas-cable-wireless: rgb(150 150 150);
|
||||
--canvas-cable-active: rgb(0 200 50);
|
||||
--canvas-label: #000000;
|
||||
/* The surface dark too, a step above the sheets, so that Java's black switches and routers keep their edge
|
||||
* (each icon gets a faint light outline, sheet.css); labels and cables light. */
|
||||
--canvas-bg: #262b33;
|
||||
--canvas-cable: rgb(150 158 170);
|
||||
--canvas-cable-wireless: rgb(105 113 125);
|
||||
--canvas-cable-active: rgb(40 220 90);
|
||||
--canvas-label: #e6e9ef;
|
||||
--connection-plugged: rgb(0 190 0);
|
||||
--connection-free: rgb(210 40 40);
|
||||
--connection-marked: rgb(235 215 0);
|
||||
@@ -86,6 +109,25 @@
|
||||
--capture-on-layer: #e6e9ef;
|
||||
--capture-chosen: #e6e9ef;
|
||||
--capture-on-chosen: #14171c;
|
||||
--doc-text-border: #4a5361;
|
||||
--java-panel: #20252c;
|
||||
--java-field: #15181d;
|
||||
--java-text: #e6e9ef;
|
||||
--java-border: #4a5361;
|
||||
--java-border-strong: #5c6573;
|
||||
--java-grid: #3a414c;
|
||||
--java-line: #3a414c;
|
||||
--java-rule: #2e343d;
|
||||
--java-disabled: #6b7380;
|
||||
--java-button: #2b3038;
|
||||
--java-head: #2a2f37;
|
||||
--java-tab: #262b33;
|
||||
--java-selected: #2c4a66;
|
||||
--java-focus: #6f9ad6;
|
||||
--java-invalid: #f2695a;
|
||||
--java-invalid-text: #ff8a7d;
|
||||
--java-taskbar: #2a2f37;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
html,
|
||||
|
||||
Reference in New Issue
Block a user