RustProxy is an open-source project. Its source code is publicly diff --git a/src/admin/web/style.css b/src/admin/web/style.css index 3f91ce4..c00c054 100644 --- a/src/admin/web/style.css +++ b/src/admin/web/style.css @@ -2924,6 +2924,11 @@ html[data-button-style=compact] body { font-size: 16px } +.window-heading>button[data-i18n="close"] { + margin-inline-start: auto; + flex: 0 0 auto; +} + .window-tools { margin-inline-start: auto; display: flex; @@ -5002,6 +5007,17 @@ dialog .window-heading { white-space: nowrap } +.frontend-protocol-controls { + margin-block-start: 16px; + padding-block-start: 12px; + border-top: 1px solid var(--line); +} + +.frontend-protocol-controls>.small-label { + display: block; + margin-block-end: 10px; +} + .protocol-toggle-row { display: flex; flex-wrap: wrap; diff --git a/tests/modal_frontend_0346.cjs b/tests/modal_frontend_0346.cjs new file mode 100644 index 0000000..eb0ae15 --- /dev/null +++ b/tests/modal_frontend_0346.cjs @@ -0,0 +1,60 @@ +// Run with: node tests/modal_frontend_0346.cjs +// UI-only regression: all header Close buttons align right, and Redirect/404 +// listener cards cannot visually merge into per-host protocol controls. +'use strict'; +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const read = file => fs.readFileSync(path.join(__dirname, '..', file), 'utf8'); +const html = read('src/admin/web/index.html'); +const css = read('src/admin/web/style.css'); +const dialog = id => { + const start = html.indexOf(`id="${id}"`); + assert.ok(start >= 0, `Missing ${id}`); + const close = html.indexOf('', start); + assert.ok(close > start, `Missing dialog end for ${id}`); + return html.slice(start, close); +}; + +const rightAligned = css.match(/\.window-heading\s*>\s*button\[data-i18n="close"\]\s*\{([^}]+)\}/); +assert.ok(rightAligned, 'A shared header Close rule must exist'); +assert.match(rightAligned[1], /margin-inline-start:\s*auto\s*;/); +assert.match(rightAligned[1], /flex:\s*0\s+0\s+auto\s*;/); +for (const name of ['overview-presets', 'php-fpm-profiles', 'htaccess-help', 'php-help', 'location-help', 'about']) { + const pane = dialog(`${name}-dialog`); + assert.match(pane, /class="window-heading"/); + assert.match(pane, new RegExp(`