diff --git a/core/src/main/resources/hudson/cli/CLIAction/example.jelly b/core/src/main/resources/hudson/cli/CLIAction/example.jelly index 5a4c4cef320f..06bc43f57f98 100644 --- a/core/src/main/resources/hudson/cli/CLIAction/example.jelly +++ b/core/src/main/resources/hudson/cli/CLIAction/example.jelly @@ -24,16 +24,6 @@ THE SOFTWARE. - - - -
java -jar jenkins-cli.jar -s ${h.inferHudsonURL(request)} -webSocket ${commandArgs}
+
java -jar jenkins-cli.jar -s ${h.inferHudsonURL(request)} -webSocket ${commandArgs}
diff --git a/core/src/main/resources/hudson/cli/CLIAction/index.jelly b/core/src/main/resources/hudson/cli/CLIAction/index.jelly index 29067da07fad..954d66a6cdf8 100644 --- a/core/src/main/resources/hudson/cli/CLIAction/index.jelly +++ b/core/src/main/resources/hudson/cli/CLIAction/index.jelly @@ -34,7 +34,7 @@ THE SOFTWARE. -

+

${%blurb(rootURL)}

diff --git a/core/src/main/resources/lib/hudson/logRecords.jelly b/core/src/main/resources/lib/hudson/logRecords.jelly index ec5c47119dce..fbb610782b63 100644 --- a/core/src/main/resources/lib/hudson/logRecords.jelly +++ b/core/src/main/resources/lib/hudson/logRecords.jelly @@ -31,10 +31,12 @@ THE SOFTWARE. - +
+
-
+ +
diff --git a/war/src/main/js/widgets/config/tabbar.less b/war/src/main/js/widgets/config/tabbar.less index 3b6824abd045..dd9df35bcd65 100644 --- a/war/src/main/js/widgets/config/tabbar.less +++ b/war/src/main/js/widgets/config/tabbar.less @@ -169,15 +169,6 @@ span.highlight { background-color: #ffff00; } - - // CodeMirror - .CodeMirror { - background: var(--brightest-bg-color); - } - - .CodeMirror-scroll { - border: 1px solid var(--input-border) !important; - } } } } diff --git a/war/src/main/less/abstracts/theme.less b/war/src/main/less/abstracts/theme.less index be86e3ee03f7..9f95aa5a9f61 100644 --- a/war/src/main/less/abstracts/theme.less +++ b/war/src/main/less/abstracts/theme.less @@ -1,6 +1,7 @@ :root { // Font related properties --font-family-sans: -apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Noto Sans", oxygen, ubuntu, cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + --font-family-mono: ui-monospace, SFMono-Regular, SF Mono, JetBrainsMono, Consolas, monospace; --font-size-base: 1rem; // 16px --font-size-sm: 0.875rem; // 14px --font-size-xs: 0.75rem; // 12px @@ -280,9 +281,13 @@ --form-input-border-radius: 6px; --form-input-glow: 0 0 0 10px transparent; --form-input-glow--focus: 0 0 0 5px var(--focus-input-glow); + --pre-background: rgba(0, 0, 0, 0.05); + --pre-color: var(--text-color); + --selection-color: rgba(2, 76, 182, 0.3); // Animations --standard-transition: 0.2s ease; + --elastic-transition: 0.3s cubic-bezier(0, 0.68, 0.5, 1.5); // Pop out menus --menu-text-color: black; diff --git a/war/src/main/less/base-styles-v2.less b/war/src/main/less/base-styles-v2.less index 71b735a4e9d9..7d291f46d170 100644 --- a/war/src/main/less/base-styles-v2.less +++ b/war/src/main/less/base-styles-v2.less @@ -26,12 +26,20 @@ html { @import './base/visibility-utils'; @import './base/yui-compatibility'; +@import './form/checkbox'; +@import './form/codemirror'; +@import './form/input'; +@import './form/layout'; +@import './form/radio'; +@import './form/reorderable-list'; +@import './form/search'; +@import './form/select'; +@import './form/toggle-switch'; + @import './modules/app-bar'; @import './modules/badges'; @import './modules/buttons'; @import './modules/content-blocks'; -@import './modules/draggable-card'; -@import './modules/form'; @import './modules/icon-size'; @import './modules/icons'; @import './modules/manage-jenkins'; diff --git a/war/src/main/less/base/style.less b/war/src/main/less/base/style.less index 59099898d164..b08cd97bc0d4 100644 --- a/war/src/main/less/base/style.less +++ b/war/src/main/less/base/style.less @@ -58,6 +58,10 @@ dt { font-weight: bold; } +::selection { + background: var(--selection-color); +} + .fixed-width { font-family: monospace; } @@ -219,13 +223,21 @@ td.tab { } pre { - white-space: pre-wrap; /* css-3 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - margin: 0; -} - -pre a { + white-space: pre-wrap; + word-wrap: break-word; + margin: 0 0 var(--section-padding); + padding: 0.8rem 1rem; + border-radius: 10px; + background-color: var(--pre-background); + color: var(--pre-color) !important; + font-family: var(--font-family-mono) !important; + font-weight: 600 !important; + line-height: 1.66 !important; + + a { + font-weight: inherit; word-wrap: break-word; + } } pre.console { @@ -718,6 +730,7 @@ table.parameters > tbody:hover { table { border-radius: 0; min-width: 450px; + margin-bottom: 0; box-sizing: content-box; padding-bottom: 2px; @@ -1063,7 +1076,7 @@ table.fingerprint-in-build td { position: relative; padding-left: 32px; transition: var(--standard-transition); - margin-top: 0.66rem; + margin-top: calc(var(--section-padding) / 3); &::after { content: ""; @@ -1320,6 +1333,26 @@ table.progress-bar.red td.progress-bar-done { /* ========================= logRecords.jelly ================== */ +.logrecord-container { + border-radius: 10px; + overflow: hidden; + + pre { + padding-top: 0; + padding-bottom: 0.1rem; + margin-bottom: 0; + border-radius: 0; + + &:first-of-type { + padding-top: 0.8rem; + } + + &:last-of-type { + padding-bottom: 0.8rem; + } + } +} + .logrecord-metadata { font-size: var(--font-size-xs); } diff --git a/war/src/main/less/base/typography.less b/war/src/main/less/base/typography.less index 93330482290b..b62b0c2713e8 100644 --- a/war/src/main/less/base/typography.less +++ b/war/src/main/less/base/typography.less @@ -51,45 +51,45 @@ h6, line-height: var(--line-height-heading); font-weight: bold; display: block; - margin-top: 0.5rem; - margin-bottom: 0.5rem; + margin-top: 0; + margin-bottom: var(--section-padding); } h1, .h1 { - font-size: 2rem; + font-size: 1.6rem; } h2, .h2 { - font-size: 1.75rem; + font-size: 1.4rem; } h3, .h3 { - font-size: 1.5rem; + font-size: 1.2rem; } h4, .h4 { - font-size: 1.25rem; + font-size: 1rem; } h5, .h5 { - font-size: 1rem; + font-size: 0.8rem; } h6, .h6 { - font-size: 0.875rem; + font-size: 0.6rem; } .jenkins-description { color: var(--text-color-secondary); line-height: 1.66; margin-top: 0; - margin-bottom: 2rem; + margin-bottom: var(--section-padding); } .jenkins-label { diff --git a/war/src/main/less/form/checkbox.less b/war/src/main/less/form/checkbox.less new file mode 100644 index 000000000000..d7ae98b74634 --- /dev/null +++ b/war/src/main/less/form/checkbox.less @@ -0,0 +1,143 @@ +.jenkins-checkbox-help-wrapper { + display: flex; + align-items: center; + justify-content: flex-start; +} + +.jenkins-checkbox + a.jenkins-help-button { + vertical-align: top; +} + +.jenkins-checkbox { + position: relative; + display: inline-flex; +} + +.jenkins-checkbox input { + position: absolute; + + width: 1px; + height: 1px; + + // If margin is set to a negative value it can cause text to be announced in + // the wrong order in VoiceOver for OSX + margin: 0; + padding: 0; + + overflow: hidden; + clip: rect(0 0 0 0); + clip-path: inset(50%); + + &:checked { + & + label { + &:active, + &:focus { + &::before { + box-shadow: 0 0 0 5px var(--focus-input-glow), inset 0 0 0 12px var(--focus-input-border); + } + } + } + + & + label { + &::before { + box-shadow: 0 0 0 10px transparent, inset 0 0 0 12px var(--focus-input-border); + } + + &::after { + transform: scale(1); + } + } + } + + &:disabled { + & + label { + cursor: not-allowed; + + &::before { + opacity: 0.35 !important; + box-shadow: 0 0 0 10px transparent, inset 0 0 0 2px var(--input-border) !important; + } + } + + &:checked { + & + label { + &::before { + box-shadow: 0 0 0 10px transparent, inset 0 0 0 12px var(--focus-input-border) !important; + } + + &::after { + transform: scale(1) !important; + } + } + } + } +} + +.jenkins-checkbox label { + position: relative; + display: inline-flex; + align-items: flex-start; + justify-content: flex-start; + margin: 0; + cursor: pointer; + line-height: 22px; + font-weight: var(--form-label-font-weight); + + &::before { + content: ""; + display: inline-block; + position: relative; + min-width: 22px; + min-height: 22px; + border-radius: 6px; + transition: var(--standard-transition); + margin-right: 11px; + box-shadow: 0 0 0 10px transparent, inset 0 0 0 2px var(--input-border); + } + + &::after { + content: ""; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + left: 0; + width: 22px; + height: 22px; + background: var(--background); + mask-image: url("data:image/svg+xml;charset=UTF-8,%3c?xml version='1.0' encoding='UTF-8'?%3e%3csvg width='384px' height='320px' viewBox='0 0 384 320' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3ePath%3c/title%3e%3cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3e%3cpath d='M327.917546,10.9278525 C339.555371,-2.37251966 359.771775,-3.72027991 373.072147,7.91754577 C386.239516,19.4389932 387.692129,39.368305 376.427694,52.671077 L376.082454,53.0721475 L152.082454,309.072147 C140.014868,322.863675 118.889432,323.700972 105.767743,311.015951 L105.372583,310.627417 L9.372583,214.627417 C-3.12419433,202.13064 -3.12419433,181.86936 9.372583,169.372583 C21.7443926,157.000773 41.7261905,156.877055 54.2501999,169.001429 L54.627417,169.372583 L126.441,241.186 L327.917546,10.9278525 Z' id='Path' fill='%23FF0000' fill-rule='nonzero'%3e%3c/path%3e%3c/g%3e%3c/svg%3e"); + mask-size: 10px 10px; + mask-repeat: no-repeat; + mask-position: center; + transition: var(--elastic-transition); + transform: scale(0); + } + + &:empty { + &::before { + margin-right: 0; + } + } + + &:hover { + &::before { + box-shadow: 0 0 0 10px transparent, inset 0 0 0 5px var(--input-border-hover); + } + } + + &:active, + &:focus { + &::before { + box-shadow: 0 0 0 5px var(--focus-input-glow), inset 0 0 0 5px var(--focus-input-border); + } + } +} + +.jenkins-checkbox__description { + margin-top: 0.3rem; + margin-left: 34px; + margin-bottom: 1rem; + color: var(--text-color-secondary); + line-height: 1.66; +} diff --git a/war/src/main/less/form/codemirror.less b/war/src/main/less/form/codemirror.less new file mode 100644 index 000000000000..265544c96265 --- /dev/null +++ b/war/src/main/less/form/codemirror.less @@ -0,0 +1,43 @@ +.CodeMirror-scroll { + // CodeMirror text boxes may be resized both horizontally and vertically to ensure + // users have enough space to write scripts + resize: both; + border: none !important; +} + +.CodeMirror { + display: block; + background: var(--input-color); + border: 2px solid var(--input-border); + border-radius: var(--form-input-border-radius); + width: 100%; + box-shadow: var(--form-input-glow); + transition: var(--standard-transition); + cursor: text; + margin-bottom: var(--section-padding); + + &:hover { + border-color: var(--input-border-hover); + } + + &:active, + &:focus-within { + outline: none; + border-color: var(--focus-input-border); + box-shadow: var(--form-input-glow--focus); + } + + textarea { + background: transparent; + border: none; + outline: none; + } + + .cm-variable { + color: var(--text-color) !important; + } + + .CodeMirror-selected { + background-color: var(--selection-color) !important; + } +} diff --git a/war/src/main/less/form/input.less b/war/src/main/less/form/input.less new file mode 100644 index 000000000000..e67a71671e6b --- /dev/null +++ b/war/src/main/less/form/input.less @@ -0,0 +1,22 @@ +.jenkins-input { + display: block; + background: var(--input-color); + border: 2px solid var(--input-border); + padding: var(--form-input-padding); + border-radius: var(--form-input-border-radius); + width: 100%; + box-shadow: var(--form-input-glow); + // Set height transition to 0s as vertical resizing has a delay/lag otherwise + transition: all var(--standard-transition), height 0s; + + &:hover { + border-color: var(--input-border-hover); + } + + &:active, + &:focus { + outline: none; + border-color: var(--focus-input-border); + box-shadow: var(--form-input-glow--focus); + } +} diff --git a/war/src/main/less/form/layout.less b/war/src/main/less/form/layout.less new file mode 100644 index 000000000000..0cdebc519859 --- /dev/null +++ b/war/src/main/less/form/layout.less @@ -0,0 +1,140 @@ +.jenkins-form { + max-width: var(--form-item-max-width); +} + +.jenkins-fieldset { + border: none; + margin: 0; + padding: 0; + + .jenkins-form-item:last-of-type { + margin-bottom: 0; + } +} + +.jenkins-form-item { + max-width: var(--form-item-max-width); + margin-bottom: var(--section-padding); + + // Workaround for float:right button controls + // (eg Global Credentials' Verify Configuration button being hidden by the floating submit bar) + &::after { + content: " "; /* Older browser do not support empty content */ + visibility: hidden; + display: block; + height: 0; + clear: both; + } + + &--tight + .jenkins-form-item--tight { + margin-top: -0.9rem; + } + + &--small { + max-width: var(--form-item-max-width--small); + } + + &--medium { + max-width: var(--form-item-max-width--medium); + } +} + +.jenkins-form-label { + display: flex; + align-items: center; + font-weight: var(--form-label-font-weight); + margin-top: 0; + margin-bottom: 0.75rem; + padding-inline-start: 0; + padding-inline-end: 0; +} + +.jenkins-form-description { + display: block; + // Tweaked margin so that it appears visually centred when placed next to `.jenkins-form-label` + margin: -0.2rem 0 0.8rem 0; + color: var(--text-color-secondary); + line-height: 1.66; +} + +.jenkins-quote { + position: relative; + display: flex; + line-height: 38px; + + &::before { + content: ""; + position: relative; + width: 2px; + background: var(--input-border); + margin-right: 1rem; + border-radius: 2px; + } + + &--monospace { + font-family: monospace; + } +} + +.jenkins-help-button { + position: relative; + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + margin-left: 1ch; + display: inline-flex; + justify-content: center; + align-items: center; + line-height: 20px; + color: var(--text-color)!important; + border-radius: 100%; + + &::before { + content: "?"; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: var(--text-color); + opacity: 0.1; + border-radius: inherit; + transition: var(--standard-transition); + } + + &::after { + content: ""; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + border: 1px solid rgba(125, 125, 125, 0.35); + box-shadow: var(--form-input-glow); + border-radius: inherit; + opacity: 0.1; + transition: var(--standard-transition); + } + + &:hover { + text-decoration: none; + + &::before { + opacity: 0.2; + } + } + + &:active, &:focus { + outline: none; + text-decoration: none; + + &::before { + opacity: 0.3; + } + + &::after { + box-shadow: 0 0 0 5px var(--text-color); + } + } +} diff --git a/war/src/main/less/form/radio.less b/war/src/main/less/form/radio.less new file mode 100644 index 000000000000..25602daa1bec --- /dev/null +++ b/war/src/main/less/form/radio.less @@ -0,0 +1,123 @@ +.jenkins-radio-help-wrapper { + display: flex; + align-items: center; + justify-content: flex-start; +} + +.jenkins-radio { + margin-top: 3px; + + &:not(:last-of-type) { + margin-bottom: calc(var(--section-padding) / 3); + } + + &__input { + position: absolute; + opacity: 0; + + &:hover { + & + label { + &::before { + box-shadow: 0 0 0 10px transparent, inset 0 0 0 5px var(--input-border-hover); + } + } + } + + &:focus, + &:active { + & + label { + &::before { + transition: box-shadow var(--elastic-transition); + box-shadow: 0 0 0 5px var(--focus-input-glow), inset 0 0 0 8px var(--focus-input-border); + } + } + } + + &:checked { + & + label { + &::before { + box-shadow: 0 0 0 10px transparent, inset 0 0 0 8px var(--focus-input-border); + } + } + } + + &:disabled { + & + label { + cursor: not-allowed; + + &::before { + opacity: 0.35; + } + } + } + } + + &__label { + position: relative; + display: inline-block; + margin-bottom: 0; + padding: 0 0 5px 32px; + cursor: pointer; + font-weight: var(--form-label-font-weight); + // remove 300ms pause on mobile + touch-action: manipulation; + + &::before { + content: ""; + box-sizing: border-box; + position: absolute; + top: 0; + left: 0; + + width: 22px; + height: 22px; + + border-radius: 50%; + background: transparent; + box-shadow: 0 0 0 10px transparent, inset 0 0 0 2px var(--input-border); + + transition: box-shadow var(--standard-transition); + } + } + + &__description { + margin: 0 0 0 32px; + color: var(--text-color-secondary); + line-height: 1.66; + } + + &__children { + position: relative; + margin-top: 0; + opacity: 0; + padding-left: 32px; + transition: var(--standard-transition); + visibility: hidden; + max-height: 0; + + &::after { + content: ""; + position: absolute; + top: 0; + left: 10px; + bottom: 0; + width: 2px; + background: var(--input-border); + border-radius: 2px; + transition: var(--standard-transition); + } + + &:focus-within { + &::after { + background: var(--focus-input-border); + } + } + } + + &__input:checked + &__label + &__children { + visibility: visible; + margin-top: 10px; + opacity: 1; + max-height: none; + } +} diff --git a/war/src/main/less/modules/draggable-card.less b/war/src/main/less/form/reorderable-list.less similarity index 100% rename from war/src/main/less/modules/draggable-card.less rename to war/src/main/less/form/reorderable-list.less diff --git a/war/src/main/less/form/search.less b/war/src/main/less/form/search.less new file mode 100644 index 000000000000..4ee208fb52f1 --- /dev/null +++ b/war/src/main/less/form/search.less @@ -0,0 +1,112 @@ +.jenkins-search { + position: relative; + max-width: 420px; + + &__input { + appearance: none; + display: block; + background: var(--input-color); + border: 2px solid var(--input-border); + border-radius: var(--form-input-border-radius); + width: 100%; + margin: 0; + padding: 0 4px 0 29px; + line-height: 30px; + box-shadow: var(--form-input-glow); + transition: var(--standard-transition); + + // Safari adds unwanted padding - let's remove it + &::-webkit-search-decoration { + -webkit-appearance: none; + } + + // By default the clear text button doesn't change the cursor on hover - lets turn it into a pointer + &::-webkit-search-cancel-button:hover { + cursor: pointer; + } + + &:hover { + border-color: var(--input-border-hover); + } + + &:active, + &:focus { + outline: none; + border-color: var(--focus-input-border); + box-shadow: var(--form-input-glow--focus); + } + } + + &__icon { + position: absolute; + top: 9px; + left: 9px; + width: 16px; + height: 16px; + fill: var(--input-border-hover); + transition: var(--standard-transition); + } + + &::before { + content: ""; + position: absolute; + top: 17px; + left: 17px; + width: 0; + height: 0; + color: inherit; + border: 2px solid currentColor; + border-radius: 100%; + opacity: 0; + transition: var(--standard-transition); + } + + &::after { + content: ""; + position: absolute; + top: 17px; + left: 17px; + width: 0; + height: 0; + color: inherit; + border: 2px solid currentColor; + border-radius: 100%; + clip-path: inset(0 0 50% 50%); + opacity: 0; + transition: var(--standard-transition); + animation: loading-spinner 1s infinite linear; + + @media (prefers-reduced-motion) { + animation-duration: 2s; + } + } + + &--loading { + .jenkins-search__icon { + opacity: 0; + transform: scale(0); + } + + &::before { + opacity: 0.2; + top: 9px; + left: 9px; + width: 16px; + height: 16px; + } + + &::after { + opacity: 1; + top: 9px; + left: 9px; + width: 16px; + height: 16px; + } + } + + &:focus-within { + .jenkins-search__icon { + fill: var(--focus-input-border); + } + } +} diff --git a/war/src/main/less/form/select.less b/war/src/main/less/form/select.less new file mode 100644 index 000000000000..acdedfc17728 --- /dev/null +++ b/war/src/main/less/form/select.less @@ -0,0 +1,66 @@ +.jenkins-select { + position: relative; + width: 100%; + + &::after { + content: ""; + position: absolute; + top: 0; + right: 13px; + bottom: 0; + width: 12px; + background-color: currentColor; + mask-image: url("data:image/svg+xml;charset=UTF-8,%3c?xml version='1.0' encoding='UTF-8'?%3e%3csvg width='336px' height='192px' viewBox='0 0 336 192' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3ePath%3c/title%3e%3cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3e%3cg id='arrow' transform='translate(0.000000, 0.000000)' fill='%23FF0000' fill-rule='nonzero'%3e%3cpath d='M7.02943725,7.02943725 C16.3053957,-2.24652118 31.2852799,-2.34214962 40.6788451,6.74255194 L40.9705627,7.02943725 L168,134.059 L295.029437,7.02943725 C304.305396,-2.24652118 319.28528,-2.34214962 328.678845,6.74255194 L328.970563,7.02943725 C338.246521,16.3053957 338.34215,31.2852799 329.257448,40.6788451 L328.970563,40.9705627 L184.970563,184.970563 C175.694604,194.246521 160.71472,194.34215 151.321155,185.257448 L151.029437,184.970563 L7.02943725,40.9705627 C-2.34314575,31.5979797 -2.34314575,16.4020203 7.02943725,7.02943725 Z' id='Path'%3e%3c/path%3e%3c/g%3e%3c/g%3e%3c/svg%3e"); + mask-size: contain; + mask-repeat: no-repeat; + mask-position: center; + pointer-events: none; + } + + &__input { + appearance: none; + display: block; + border: 2px solid var(--input-border); + padding: 8px; + width: 100% !important; // TODO remove important after https://github.com/jenkinsci/credentials-plugin/pull/255 + max-width: 100% !important; // TODO remove important after https://github.com/jenkinsci/credentials-plugin/pull/255 + border-radius: 6px; + box-shadow: 0 0 0 10px transparent; + transition: var(--standard-transition); + min-height: 38px; + + &:hover { + border-color: var(--input-border-hover); + } + + &:active, + &:focus { + outline: none; + border-color: var(--focus-input-border); + box-shadow: 0 0 0 5px var(--focus-input-glow); + } + + &:disabled { + pointer-events: none; + } + } +} + +.jenkins-multi-select { + position: relative; + width: 100%; + border: 2px solid var(--input-border); + border-radius: var(--form-input-border-radius); + box-shadow: 0 0 0 10px transparent; + transition: var(--standard-transition); + outline: none; + + &:focus { + border-color: var(--focus-input-border); + box-shadow: 0 0 0 5px var(--focus-input-glow); + } + + &:disabled { + pointer-events: none; + } +} diff --git a/war/src/main/less/form/toggle-switch.less b/war/src/main/less/form/toggle-switch.less new file mode 100644 index 000000000000..8a1390cffe13 --- /dev/null +++ b/war/src/main/less/form/toggle-switch.less @@ -0,0 +1,156 @@ +.jenkins-toggle-switch { + position: relative; + display: inline-block; + + &--invert-label { + input { + &:checked { + & + label { + &::after { + left: unset !important; + right: 5px !important; + } + } + } + } + + label { + flex-direction: row-reverse; + + &::before { + margin-left: 1rem; + margin-right: 0 !important; + } + + &::after { + left: unset !important; + right: 25px; + } + + &:active, + &:focus { + &::after { + right: 20px !important; + } + } + + .jenkins-toggle-switch__label__enabled-title, + .jenkins-toggle-switch__label__disabled-title { + left: unset !important; + right: calc(50px + 1rem) !important; + } + } + } +} + +.jenkins-toggle-switch input { + position: absolute; + + width: 1px; + height: 1px; + + // If margin is set to a negative value it can cause text to be announced in + // the wrong order in VoiceOver for OSX + margin: 0; + padding: 0; + + overflow: hidden; + clip: rect(0 0 0 0); + clip-path: inset(50%); + + &:checked + label::before { + background-color: var(--focus-input-border); + } + + &:checked { + & + label { + &::after { + left: 25px; + mask-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg width='66px' height='66px' viewBox='0 0 66 66' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cpath d='M66,0 L66,66 L0,66 L0,0 L66,0 Z M37.7154094,29.2061836 C37.3690459,28.9031155 36.8425777,28.9382134 36.5395097,29.2845769 L36.5395097,29.2845769 L31.2924962,35.2799905 L29.4225874,33.410737 L29.3440813,33.3414133 C29.0171724,33.0872262 28.5444804,33.1103341 28.2440774,33.410737 C27.9186409,33.7361736 27.9186409,34.2638104 28.2440774,34.589247 L28.2440774,34.589247 L30.7440745,37.0892441 L30.8202748,37.15679 C31.1634387,37.4256962 31.6657159,37.3856111 31.9604761,37.0487424 L31.9604761,37.0487424 L37.7938027,30.3820833 L37.8577508,30.2991398 C38.0896293,29.9560466 38.0351295,29.4859387 37.7154094,29.2061836 Z' fill='%23000000'%3E%3C/path%3E%3C/g%3E%3C/svg%3E"); + } + + &:active, + &:focus { + &::after { + left: 20px; + width: 25px; + } + } + } + } + + &:disabled { + & + label { + cursor: not-allowed; + } + } +} + +.jenkins-toggle-switch label { + position: relative; + display: flex; + align-items: flex-start; + justify-content: flex-start; + margin: 0; + cursor: pointer; + line-height: 30px; + font-weight: var(--form-label-font-weight); + + &::before { + display: inline-block; + content: ""; + position: relative; + min-width: 50px; + min-height: 30px; + background: var(--input-border); + border-radius: 19px; + transition: var(--standard-transition); + margin-right: 1rem; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 0 0 10px transparent; + } + + &::after { + content: ""; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 5px; + left: 5px; + width: 20px; + height: 20px; + background: var(--background); + mask-size: 60px 60px; + mask-position: center; + border-radius: 100px; + transition: var(--standard-transition); + box-shadow: -1px 0 0 rgba(0, 0, 0, 0.1); + } + + &:hover::before { + background-color: var(--input-border-hover); + } + + &:active, + &:focus { + &::before { + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 0 0 5px var(--focus-input-glow); + } + &::after { + left: 5px; + width: 25px; + } + } + + .jenkins-toggle-switch__label__enabled-title { + opacity: 0; + } + + .jenkins-toggle-switch__label__enabled-title, + .jenkins-toggle-switch__label__disabled-title { + position: absolute; + left: calc(50px + 1rem); + transition: 0.55s cubic-bezier(0, 0.68, 0.5, 1.25); + transform-style: preserve-3d; + } +} diff --git a/war/src/main/less/modules/app-bar.less b/war/src/main/less/modules/app-bar.less index 3469d31e25d1..401585c0a2cd 100644 --- a/war/src/main/less/modules/app-bar.less +++ b/war/src/main/less/modules/app-bar.less @@ -2,7 +2,7 @@ display: flex; align-items: center; justify-content: space-between; - margin-bottom: 2rem; + margin-bottom: var(--section-padding); .jenkins-app-bar__content { display: flex; @@ -16,7 +16,7 @@ display: flex; align-items: center; justify-content: center; - margin-left: 2rem; + margin-left: var(--section-padding); min-height: 36px; .jenkins-search { @@ -25,13 +25,13 @@ } &--border { - margin-bottom: 2rem; - padding-bottom: 2rem; + margin-bottom: var(--section-padding); + padding-bottom: var(--section-padding); border-bottom: 2px solid var(--panel-border-color); } h1 { margin: 0; - font-size: 1.7rem; + font-size: 1.6rem; } } diff --git a/war/src/main/less/modules/form.less b/war/src/main/less/modules/form.less deleted file mode 100644 index 694ff7159d4a..000000000000 --- a/war/src/main/less/modules/form.less +++ /dev/null @@ -1,798 +0,0 @@ -.jenkins-form { - max-width: var(--form-item-max-width); -} - -.jenkins-form-item { - max-width: var(--form-item-max-width); - margin-bottom: var(--section-padding); - - // Workaround for float:right button controls - // (eg Global Credentials' Verify Configuration button being hidden by the floating submit bar) - &::after { - content: " "; /* Older browser do not support empty content */ - visibility: hidden; - display: block; - height: 0; - clear: both; - } - - &--tight + .jenkins-form-item--tight { - margin-top: -0.9rem; - } - - &--small { - max-width: var(--form-item-max-width--small); - } - - &--medium { - max-width: var(--form-item-max-width--medium); - } -} - -.jenkins-fieldset { - border: none; - margin: 0; - padding: 0; - - .jenkins-form-item:last-of-type { - margin-bottom: 0; - } -} - -.jenkins-form-label { - display: flex; - align-items: center; - font-weight: var(--form-label-font-weight); - margin-top: 0; - margin-bottom: 0.75rem; - padding-inline-start: 0; - padding-inline-end: 0; -} - -.jenkins-form-description { - display: block; - // Tweaked margin so that it appears visually centred when placed next to `.jenkins-form-label` - margin: -0.2rem 0 0.8rem 0; - color: var(--text-color-secondary); - line-height: 1.66; -} - -.jenkins-quote { - position: relative; - display: flex; - line-height: 38px; - - &::before { - content: ""; - position: relative; - width: 2px; - background: var(--input-border); - margin-right: 1rem; - border-radius: 2px; - } - - &--monospace { - font-family: monospace; - } -} - -.jenkins-input { - display: block; - background: var(--input-color); - border: 2px solid var(--input-border); - padding: var(--form-input-padding); - border-radius: var(--form-input-border-radius); - width: 100%; - box-shadow: var(--form-input-glow); - transition: var(--standard-transition); - - &:hover { - border-color: var(--input-border-hover); - } - - &:active, - &:focus { - outline: none; - border-color: var(--focus-input-border); - box-shadow: var(--form-input-glow--focus); - } -} - -.jenkins-search { - position: relative; - max-width: 420px; - - &__input { - appearance: none; - display: block; - background: var(--input-color); - border: 2px solid var(--input-border); - border-radius: var(--form-input-border-radius); - width: 100%; - margin: 0; - padding: 0 4px 0 29px; - line-height: 30px; - box-shadow: var(--form-input-glow); - transition: var(--standard-transition); - - // Safari adds unwanted padding - let's remove it - &::-webkit-search-decoration { - -webkit-appearance: none; - } - - // By default the clear text button doesn't change the cursor on hover - lets turn it into a pointer - &::-webkit-search-cancel-button:hover { - cursor: pointer; - } - - &:hover { - border-color: var(--input-border-hover); - } - - &:active, - &:focus { - outline: none; - border-color: var(--focus-input-border); - box-shadow: var(--form-input-glow--focus); - } - } - - &__icon { - position: absolute; - top: 9px; - left: 9px; - width: 16px; - height: 16px; - fill: var(--input-border-hover); - transition: var(--standard-transition); - } - - &::before { - content: ""; - position: absolute; - top: 17px; - left: 17px; - width: 0; - height: 0; - color: inherit; - border: 2px solid currentColor; - border-radius: 100%; - opacity: 0; - transition: var(--standard-transition); - } - - &::after { - content: ""; - position: absolute; - top: 17px; - left: 17px; - width: 0; - height: 0; - color: inherit; - border: 2px solid currentColor; - border-radius: 100%; - clip-path: inset(0 0 50% 50%); - opacity: 0; - transition: var(--standard-transition); - animation: loading-spinner 1s infinite linear; - - @media (prefers-reduced-motion) { - animation-duration: 2s; - } - } - - &--loading { - .jenkins-search__icon { - opacity: 0; - transform: scale(0); - } - - &::before { - opacity: 0.2; - top: 9px; - left: 9px; - width: 16px; - height: 16px; - } - - &::after { - opacity: 1; - top: 9px; - left: 9px; - width: 16px; - height: 16px; - } - } - - &:focus-within { - .jenkins-search__icon { - fill: var(--focus-input-border); - } - } -} - -@keyframes loading-spinner { - to { - transform: rotate(360deg); - } -} - -.jenkins-select { - position: relative; - width: 100%; - - &::after { - content: ""; - position: absolute; - top: 0; - right: 13px; - bottom: 0; - width: 12px; - background-color: currentColor; - mask-image: url("data:image/svg+xml;charset=UTF-8,%3c?xml version='1.0' encoding='UTF-8'?%3e%3csvg width='336px' height='192px' viewBox='0 0 336 192' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3ePath%3c/title%3e%3cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3e%3cg id='arrow' transform='translate(0.000000, 0.000000)' fill='%23FF0000' fill-rule='nonzero'%3e%3cpath d='M7.02943725,7.02943725 C16.3053957,-2.24652118 31.2852799,-2.34214962 40.6788451,6.74255194 L40.9705627,7.02943725 L168,134.059 L295.029437,7.02943725 C304.305396,-2.24652118 319.28528,-2.34214962 328.678845,6.74255194 L328.970563,7.02943725 C338.246521,16.3053957 338.34215,31.2852799 329.257448,40.6788451 L328.970563,40.9705627 L184.970563,184.970563 C175.694604,194.246521 160.71472,194.34215 151.321155,185.257448 L151.029437,184.970563 L7.02943725,40.9705627 C-2.34314575,31.5979797 -2.34314575,16.4020203 7.02943725,7.02943725 Z' id='Path'%3e%3c/path%3e%3c/g%3e%3c/g%3e%3c/svg%3e"); - mask-size: contain; - mask-repeat: no-repeat; - mask-position: center; - pointer-events: none; - } - - &__input { - appearance: none; - display: block; - border: 2px solid var(--input-border); - padding: 8px; - width: 100% !important; // TODO remove important after https://github.com/jenkinsci/credentials-plugin/pull/255 - max-width: 100% !important; // TODO remove important after https://github.com/jenkinsci/credentials-plugin/pull/255 - border-radius: 6px; - box-shadow: 0 0 0 10px transparent; - transition: var(--standard-transition); - min-height: 38px; - - &:hover { - border-color: var(--input-border-hover); - } - - &:active, - &:focus { - outline: none; - border-color: var(--focus-input-border); - box-shadow: 0 0 0 5px var(--focus-input-glow); - } - - &:disabled { - pointer-events: none; - } - } -} - -.jenkins-multi-select { - position: relative; - width: 100%; - border: 2px solid var(--input-border); - border-radius: var(--form-input-border-radius); - box-shadow: 0 0 0 10px transparent; - transition: var(--standard-transition); - outline: none; - - &:focus { - border-color: var(--focus-input-border); - box-shadow: 0 0 0 5px var(--focus-input-glow); - } - - &:disabled { - pointer-events: none; - } -} - -.jenkins-radio-help-wrapper { - display: flex; - align-items: center; - justify-content: flex-start; -} - -.jenkins-radio { - margin-top: 3px; - - &:not(:last-of-type) { - margin-bottom: calc(var(--section-padding) / 2); - } - - &__input { - position: absolute; - opacity: 0; - } - - &__label { - position: relative; - display: inline-block; - margin-bottom: 0; - padding: 0 0 5px 32px; - cursor: pointer; - font-weight: var(--form-label-font-weight); - // remove 300ms pause on mobile - touch-action: manipulation; - - &::before { - content: ""; - box-sizing: border-box; - position: absolute; - top: 0; - left: 0; - - width: 22px; - height: 22px; - - border: 2px solid var(--input-border); - border-radius: 50%; - background: transparent; - box-shadow: var(--form-input-glow); - - transition: var(--standard-transition); - } - - &:hover::before { - border-width: 5px; - border-color: var(--input-border-hover); - } - } - - &__input:focus + &__label:before, &__input:active + &__label:before { - border-width: 8px; - border-color: var(--focus-input-border); - box-shadow: var(--form-input-glow--focus); - } - - &__input:checked + &__label:before { - border-width: 8px; - border-color: var(--focus-input-border); - } - - &__description { - margin: 0 0 0 32px; - color: var(--text-color-secondary); - line-height: 1.66; - } - - &__children { - position: relative; - margin-top: 0; - opacity: 0; - padding-left: 32px; - transition: var(--standard-transition); - visibility: hidden; - max-height: 0; - - &::after { - content: ""; - position: absolute; - top: 0; - left: 10px; - bottom: 0; - width: 2px; - background: var(--input-border); - border-radius: 2px; - transition: var(--standard-transition); - } - - &:focus-within { - &::after { - background: var(--focus-input-border); - } - } - } - - &__input:checked + &__label + &__children { - visibility: visible; - margin-top: 10px; - opacity: 1; - max-height: none; - } -} - -// Align help buttons correctly with checkboxes - -.jenkins-checkbox-help-wrapper { - display: flex; - align-items: center; - justify-content: flex-start; -} - -.jenkins-checkbox + a.jenkins-help-button { - vertical-align: top; -} - -.jenkins-checkbox { - position: relative; - display: inline-flex; -} - -.jenkins-checkbox input { - position: absolute; - - width: 1px; - height: 1px; - - // If margin is set to a negative value it can cause text to be announced in - // the wrong order in VoiceOver for OSX - margin: 0; - padding: 0; - - overflow: hidden; - clip: rect(0 0 0 0); - clip-path: inset(50%); - - &:checked { - & + label { - &:active, - &:focus { - &::before { - box-shadow: 0 0 0 5px var(--focus-input-glow), inset 0 0 0 12px var(--focus-input-border); - } - } - } - - & + label { - &::before { - box-shadow: 0 0 0 10px transparent, inset 0 0 0 12px var(--focus-input-border); - } - - &::after { - transform: scale(1); - } - } - } - - &:disabled { - & + label { - cursor: not-allowed; - - &::before { - opacity: 0.35 !important; - box-shadow: 0 0 0 10px transparent, inset 0 0 0 2px var(--input-border) !important; - } - } - - &:checked { - & + label { - &::before { - box-shadow: 0 0 0 10px transparent, inset 0 0 0 12px var(--focus-input-border) !important; - } - - &::after { - transform: scale(1) !important; - } - } - } - } -} - -.jenkins-checkbox label { - position: relative; - display: inline-flex; - align-items: flex-start; - justify-content: flex-start; - margin: 0; - cursor: pointer; - line-height: 22px; - font-weight: var(--form-label-font-weight); - - &::before { - content: ""; - display: inline-block; - position: relative; - min-width: 22px; - min-height: 22px; - border-radius: 6px; - transition: var(--standard-transition); - margin-right: 11px; - box-shadow: 0 0 0 10px transparent, inset 0 0 0 2px var(--input-border); - } - - &::after { - content: ""; - display: flex; - align-items: center; - justify-content: center; - position: absolute; - top: 0; - left: 0; - width: 22px; - height: 22px; - background: var(--background); - mask-image: url("data:image/svg+xml;charset=UTF-8,%3c?xml version='1.0' encoding='UTF-8'?%3e%3csvg width='384px' height='320px' viewBox='0 0 384 320' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3ePath%3c/title%3e%3cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3e%3cpath d='M327.917546,10.9278525 C339.555371,-2.37251966 359.771775,-3.72027991 373.072147,7.91754577 C386.239516,19.4389932 387.692129,39.368305 376.427694,52.671077 L376.082454,53.0721475 L152.082454,309.072147 C140.014868,322.863675 118.889432,323.700972 105.767743,311.015951 L105.372583,310.627417 L9.372583,214.627417 C-3.12419433,202.13064 -3.12419433,181.86936 9.372583,169.372583 C21.7443926,157.000773 41.7261905,156.877055 54.2501999,169.001429 L54.627417,169.372583 L126.441,241.186 L327.917546,10.9278525 Z' id='Path' fill='%23FF0000' fill-rule='nonzero'%3e%3c/path%3e%3c/g%3e%3c/svg%3e"); - mask-size: 10px 10px; - mask-repeat: no-repeat; - mask-position: center; - transition: 0.3s cubic-bezier(0, 0.68, 0.5, 1.5); - transform: scale(0); - } - - &:empty { - &::before { - margin-right: 0; - } - } - - &:hover { - &::before { - box-shadow: 0 0 0 10px transparent, inset 0 0 0 5px var(--input-border-hover); - } - } - - &:active, - &:focus { - &::before { - box-shadow: 0 0 0 5px var(--focus-input-glow), inset 0 0 0 5px var(--focus-input-border); - } - } -} - -.jenkins-checkbox__description { - margin-top: 0.3rem; - margin-left: 34px; - margin-bottom: 1rem; - color: var(--text-color-secondary); - line-height: 1.66; -} - -.jenkins-toggle-switch { - position: relative; - display: inline-block; -} - -.jenkins-toggle-switch input { - position: absolute; - - width: 1px; - height: 1px; - - // If margin is set to a negative value it can cause text to be announced in - // the wrong order in VoiceOver for OSX - margin: 0; - padding: 0; - - overflow: hidden; - clip: rect(0 0 0 0); - clip-path: inset(50%); - - &:checked + label:before { - background-color: var(--focus-input-border); - } - - &:checked + label:after { - left: 25px; - color: var(--focus-input-border); - transform: rotate(0deg); - } - - &:active + label:before, &:focus + label:before { - box-shadow: 0 0 0 5px var(--focus-input-glow); - } -} - -.jenkins-toggle-switch label { - position: relative; - display: flex; - align-items: flex-start; - justify-content: flex-start; - margin: 0; - cursor: pointer; - line-height: 30px; - font-weight: bold; - - &::before { - display: inline-block; - content: ""; - position: relative; - min-width: 50px; - min-height: 30px; - background: var(--input-border); - border-radius: 19px; - transition: 0.2s ease; - margin-right: 15px; - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 0 0 10px transparent; - } - - &::after { - content: "✓"; - display: flex; - align-items: center; - justify-content: center; - position: absolute; - top: 5px; - left: 5px; - width: 20px; - height: 20px; - background: var(--background); - border-radius: 19px; - color: transparent; - transition: 0.2s ease; - transform: rotate(-90deg); - font-size: 12px; - font-weight: bold; - padding-top: 2px; - box-shadow: -1px 0 0 rgba(0, 0, 0, 0.1); - } - - &:hover::before { - background-color: var(--input-border-hover); - } - - &:active, &:focus { - &::before { - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 0 0 5px var(--focus-input-glow); - } - } -} - -.jenkins-help-button { - position: relative; - width: 20px; - height: 20px; - min-width: 20px; - min-height: 20px; - margin-left: 1ch; - display: inline-flex; - justify-content: center; - align-items: center; - line-height: 20px; - color: var(--text-color)!important; - border-radius: 100%; - - &::before { - content: ""; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: var(--text-color); - opacity: 0.1; - border-radius: inherit; - transition: var(--standard-transition); - } - - &::after { - content: ""; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - border: 1px solid rgba(125, 125, 125, 0.35); - box-shadow: var(--form-input-glow); - border-radius: inherit; - opacity: 0.1; - transition: var(--standard-transition); - } - - &:hover { - text-decoration: none; - - &::before { - opacity: 0.2; - } - } - - &:active, &:focus { - outline: none; - text-decoration: none; - - &::before { - opacity: 0.3; - } - - &::after { - box-shadow: 0 0 0 5px var(--text-color); - } - } -} - -.jenkins-toggle-switch { - position: relative; - display: inline-block; -} - -.jenkins-toggle-switch input { - position: absolute; - - width: 1px; - height: 1px; - - // If margin is set to a negative value it can cause text to be announced in - // the wrong order in VoiceOver for OSX - margin: 0; - padding: 0; - - overflow: hidden; - clip: rect(0 0 0 0); - clip-path: inset(50%); - - &:disabled { - & + label { - cursor: default; - - &::before { - opacity: 0.25 !important; - background-color: var(--input-border) !important; - box-shadow: none !important; - } - - &::after { - opacity: 0.5 !important; - } - } - } - - &:checked + label::before { - background-color: var(--focus-input-border); - } - - &:checked + label::after { - left: 25px; - color: var(--focus-input-border); - transform: rotate(0deg); - } - - &:active + label::before, &:focus + label::before { - box-shadow: 0 0 0 5px var(--focus-input-glow); - } -} - -.jenkins-toggle-switch label { - position: relative; - display: flex; - align-items: flex-start; - justify-content: flex-start; - margin: 0; - cursor: pointer; - line-height: 30px; - font-weight: bold; - - &::before { - display: inline-block; - content: ""; - position: relative; - min-width: 50px; - min-height: 30px; - background: var(--input-border); - border-radius: 19px; - transition: 0.2s ease; - margin-right: 15px; - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 0 0 10px transparent; - } - - &::after { - content: "✓"; - display: flex; - align-items: center; - justify-content: center; - position: absolute; - top: 5px; - left: 5px; - width: 20px; - height: 20px; - background: var(--background); - border-radius: 19px; - color: transparent; - transition: 0.2s ease; - transform: rotate(-90deg); - font-size: 12px; - padding-top: 2px; - box-shadow: -1px 0 0 rgba(0, 0, 0, 0.1); - } - - &:hover::before { - background-color: var(--input-border-hover); - } - - &:active, &:focus { - &::before { - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 0 0 5px var(--focus-input-glow); - } - } -} - -.CodeMirror-scroll { - resize: both; -} diff --git a/war/src/main/less/modules/table.less b/war/src/main/less/modules/table.less index 1a6762c4979c..9804595a3ab2 100644 --- a/war/src/main/less/modules/table.less +++ b/war/src/main/less/modules/table.less @@ -7,6 +7,7 @@ border: 5px solid var(--table-background); border-bottom-width: 3px; border-spacing: 0 2px; + margin-bottom: var(--section-padding); * { -webkit-border-horizontal-spacing: 0; diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 59e64024ef84..e2f0cb86c17a 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -1113,7 +1113,6 @@ function rowvgStartEachRow(recursive,f) { } } }).getWrapperElement(); - w.setAttribute("style","border:1px solid black; margin-top: 1em; margin-bottom: 1em") })(); });