diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 7f34114067..8e6ac5683c 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -2455,4 +2455,16 @@ public class Functions { public static String generateItemId() { return String.valueOf(Math.floor(Math.random() * 3000)); } + + @Restricted(NoExternalUse.class) + public static String translateModifierKeysForUsersPlatform(String keyboardShortcut) { + StaplerRequest currentRequest = Stapler.getCurrentRequest(); + currentRequest.getWebApp().getDispatchValidator().allowDispatch(currentRequest, Stapler.getCurrentResponse()); + String userAgent = currentRequest.getHeader("User-Agent"); + + List platformsThatUseCommand = List.of("MAC", "IPHONE", "IPAD"); + boolean useCmdKey = platformsThatUseCommand.stream().anyMatch(e -> userAgent.toUpperCase().contains(e)); + + return keyboardShortcut.replace("CMD", useCmdKey ? "⌘" : "CTRL"); + } } diff --git a/core/src/main/resources/lib/layout/keyboard-shortcut.jelly b/core/src/main/resources/lib/layout/keyboard-shortcut.jelly new file mode 100644 index 0000000000..92bbf4a594 --- /dev/null +++ b/core/src/main/resources/lib/layout/keyboard-shortcut.jelly @@ -0,0 +1,56 @@ + + + + + + + Optional prefix to the shortcut + + + Optional suffix to the shortcut + + Displays a keyboard shortcut chip based on the component's body. + CMD/CTRL will automatically be translated to the user's operating system's appropriate variant. + + +
+ + + ${attrs.prefix} + + +
+ + + + +
+ + + ${attrs.suffix} + + +
+
diff --git a/core/src/main/resources/lib/layout/search-bar.jelly b/core/src/main/resources/lib/layout/search-bar.jelly index b86a15fef0..8dbe681fef 100644 --- a/core/src/main/resources/lib/layout/search-bar.jelly +++ b/core/src/main/resources/lib/layout/search-bar.jelly @@ -58,7 +58,12 @@ THE SOFTWARE. spellcheck="false" disabled="${attrs.enabled == false ? true : null}" /> -
+ + + + + +
diff --git a/war/src/main/scss/components/_tooltips.scss b/war/src/main/scss/components/_tooltips.scss index 80a030b8c9..566093bb98 100644 --- a/war/src/main/scss/components/_tooltips.scss +++ b/war/src/main/scss/components/_tooltips.scss @@ -51,3 +51,63 @@ .jenkins-table .healthReportDetails { display: none !important; } + +.jenkins-tooltip__keyboard-shortcut { + display: flex; + align-items: center; + justify-content: center; + gap: 0.6ch; + + &__symbol { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 1.7em; + height: 1.7em; + padding-inline: 0.5ch; + + &::before, + &::after { + content: ""; + position: absolute; + inset: 0; + border-radius: 0.375rem; + border: 0.1rem solid var(--text-color-secondary); + opacity: 0.3; + } + + &::after { + mask-image: linear-gradient( + -45deg, + transparent 40%, + white, + transparent 60% + ); + mask-size: 200% 200%; + mask-position: center; + animation: shortcut-glow-animation 1.25s forwards linear; + } + + svg { + width: 1em; + height: 1em; + } + + @keyframes shortcut-glow-animation { + 0% { + opacity: 0; + mask-position: 100% 100%; + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + mask-position: 0; + } + } + } +}