diff --git a/assets/css/global.css b/assets/css/global.css
index 18b44137cca4..0b8471c001e2 100644
--- a/assets/css/global.css
+++ b/assets/css/global.css
@@ -18,12 +18,6 @@
@apply text-blue-light underline underline-offset-2 dark:text-blue-dark;
}
- .external-link {
- .icon-svg svg {
- @apply text-base ml-1 align-top;
- }
- }
-
.invertible {
@apply dark:hue-rotate-180 dark:invert dark:filter;
}
diff --git a/assets/css/icons.css b/assets/css/icons.css
index d68025ee3272..4a6121f46072 100644
--- a/assets/css/icons.css
+++ b/assets/css/icons.css
@@ -8,4 +8,22 @@
fill: currentColor;
}
}
+
+ .icon-xs {
+ svg {
+ @apply text-base;
+ }
+ }
+
+ .icon-sm {
+ svg {
+ @apply text-lg;
+ }
+ }
+
+ .icon-top {
+ svg {
+ @apply ml-1 align-top;
+ }
+ }
}
diff --git a/assets/js/src/dockerfile-links.js b/assets/js/src/dockerfile-links.js
new file mode 100644
index 000000000000..acb7ecdc7aed
--- /dev/null
+++ b/assets/js/src/dockerfile-links.js
@@ -0,0 +1,33 @@
+const keywords = [
+ "ADD",
+ "ARG",
+ "CMD",
+ "COPY",
+ "ENTRYPOINT",
+ "ENV",
+ "EXPOSE",
+ "FROM",
+ "HEALTHCHECK",
+ "LABEL",
+ // "MAINTAINER",
+ "ONBUILD",
+ "RUN",
+ "SHELL",
+ "STOPSIGNAL",
+ "USER",
+ "VOLUME",
+ "WORKDIR",
+]
+const cmds = Array.from(document.querySelectorAll(".language-dockerfile span.k"))
+ .filter((el) => keywords.some(kwd => el.textContent.includes(kwd)));
+
+for (const cmd of cmds) {
+ const name = cmd.textContent;
+ const a = document.createElement("a")
+ a.classList.add("underline","underline-offset-4","decoration-dashed","cursor-pointer")
+ a.title = `Learn more about the ${name} instruction`
+ a.href = `/reference/dockerfile/#${name.toLowerCase()}`
+ a.innerHTML = cmd.outerHTML
+ cmd.insertAdjacentElement("beforebegin", a)
+ cmd.remove()
+}
diff --git a/assets/js/src/tooltip.js b/assets/js/src/tooltip.js
index acb7ecdc7aed..79db56cf43b4 100644
--- a/assets/js/src/tooltip.js
+++ b/assets/js/src/tooltip.js
@@ -1,33 +1,66 @@
-const keywords = [
- "ADD",
- "ARG",
- "CMD",
- "COPY",
- "ENTRYPOINT",
- "ENV",
- "EXPOSE",
- "FROM",
- "HEALTHCHECK",
- "LABEL",
- // "MAINTAINER",
- "ONBUILD",
- "RUN",
- "SHELL",
- "STOPSIGNAL",
- "USER",
- "VOLUME",
- "WORKDIR",
-]
-const cmds = Array.from(document.querySelectorAll(".language-dockerfile span.k"))
- .filter((el) => keywords.some(kwd => el.textContent.includes(kwd)));
-
-for (const cmd of cmds) {
- const name = cmd.textContent;
- const a = document.createElement("a")
- a.classList.add("underline","underline-offset-4","decoration-dashed","cursor-pointer")
- a.title = `Learn more about the ${name} instruction`
- a.href = `/reference/dockerfile/#${name.toLowerCase()}`
- a.innerHTML = cmd.outerHTML
- cmd.insertAdjacentElement("beforebegin", a)
- cmd.remove()
+import { computePosition, flip, shift, offset, arrow } from "@floating-ui/dom";
+
+/* Regular tooltips (partial) */
+
+const tooltipWrappers = Array.from(
+ document.querySelectorAll("[data-tooltip-wrapper]"),
+);
+
+for (const tooltipWrapper of tooltipWrappers) {
+ const button = tooltipWrapper.firstElementChild;
+ const tooltip = button.nextElementSibling;
+ const arrowElement = tooltip.firstElementChild;
+
+ function update() {
+ computePosition(button, tooltip, {
+ placement: "top",
+ middleware: [
+ offset(6),
+ flip(),
+ shift({ padding: 5 }),
+ arrow({ element: arrowElement }),
+ ],
+ }).then(({ x, y, placement, middlewareData }) => {
+ Object.assign(tooltip.style, {
+ left: `${x}px`,
+ top: `${y}px`,
+ });
+
+ // Accessing the data
+ const { x: arrowX, y: arrowY } = middlewareData.arrow;
+
+ const staticSide = {
+ top: "bottom",
+ right: "left",
+ bottom: "top",
+ left: "right",
+ }[placement.split("-")[0]];
+
+ Object.assign(arrowElement.style, {
+ left: arrowX != null ? `${arrowX}px` : "",
+ top: arrowY != null ? `${arrowY}px` : "",
+ right: "",
+ bottom: "",
+ [staticSide]: "-4px",
+ });
+ });
+ }
+
+ function showTooltip() {
+ tooltip.classList.toggle("hidden");
+ update();
+ }
+
+ function hideTooltip() {
+ tooltip.classList.toggle("hidden");
+ }
+
+ [
+ ["mouseenter", showTooltip],
+ ["mouseleave", hideTooltip],
+ ["focus", showTooltip],
+ ["blur", hideTooltip],
+ ].forEach(([event, listener]) => {
+ button.addEventListener(event, listener);
+ });
}
diff --git a/layouts/_default/_markup/render-link.html b/layouts/_default/_markup/render-link.html
index 9497c6f2d388..d0fb36db1470 100644
--- a/layouts/_default/_markup/render-link.html
+++ b/layouts/_default/_markup/render-link.html
@@ -2,12 +2,12 @@
{{- if (strings.HasPrefix $url "http") -}}
{{/* external link, add icon */}}
{{- .Text | safeHTML -}}
-
+
{{- partial "icon" "open_in_new" -}}
{{- else if (strings.HasPrefix $url "/") -}}
diff --git a/layouts/_default/cli.html b/layouts/_default/cli.html
index 6d12c2c6d40e..fc0b9809e89e 100644
--- a/layouts/_default/cli.html
+++ b/layouts/_default/cli.html
@@ -13,18 +13,39 @@
{{ .Scratch.Set "subheadings" slice }}
{{ partial "breadcrumbs.html" . }}
- {{ if ne .LinkTitle .Title }}
- {{/*
- we use linkTitle for surfacing popular aliases like "docker run"
- if linkTitle is set, use both alias and canonical cmd as title
- */}}
-
- {{ else }}
- {{ end }}
- {{ $data.short | .RenderString (dict "display" "block") }}
+
+
+ {{ with $data.short }}
+
+ | Description |
+ {{ . }}
+ |
+ {{ end }}
+ {{ with $data.usage }}
+
+ | Usage |
+ {{ . }} |
+
+ {{ end }}
+ {{ with $data.aliases }}
+ {{ $aliases := strings.Replace . (fmt.Printf "%s, " page.Title) "" }}
+
+ |
+ Aliases
+ {{ partial "tooltip.html" "An alias is a short or memorable alternative for a longer command." }}
+ |
+
+
+ {{ range (strings.Split $aliases ", ") }}
+ {{ . }}
+ {{ end }}
+
+ |
+
+ {{ end }}
+
+
{{ .Content }}
{{ if $data.deprecated }}
@@ -60,23 +81,6 @@
This command works with the Swarm orchestrator.
{{ end }}
- {{ with $data.usage }}
- {{ $heading := dict "level" 2 "text" "Usage" }}
- {{ partial "heading.html" $heading }}
- {{ $.Scratch.Add "headings" $heading }}
- {{ highlight (strings.Replace . "\t" "") "console" }}
- {{ end }}
- {{ with $data.aliases }}
- {{ $heading := dict "level" 2 "text" "Aliases" }}
- {{ partial "heading.html" $heading }}
- {{ $aliases := strings.Split . ", " }}
- The following commands are equivalent and redirect here:
-
- {{ range $aliases }}
- {{ . }}
- {{ end }}
-
- {{ end }}
{{ with $data.long }}
{{ $heading := dict "level" 2 "text" "Description" }}
{{ partial "heading.html" $heading }}
diff --git a/layouts/partials/github-links.html b/layouts/partials/github-links.html
index d2e8a7e5d062..7755e4952b77 100644
--- a/layouts/partials/github-links.html
+++ b/layouts/partials/github-links.html
@@ -3,9 +3,9 @@
{{ if not (in .Filename "/_vendor/") }}
{{ partial "icon" "edit" }}
- {{ T "editPage" }}
-
+
{{- partial "icon" "open_in_new" -}}
@@ -13,9 +13,9 @@
{{ end }}
{{ partial "icon" "done" }}
- {{ T "requestChanges" }}
-
+
{{- partial "icon" "open_in_new" -}}
diff --git a/layouts/partials/tooltip.html b/layouts/partials/tooltip.html
new file mode 100644
index 000000000000..06fa905ffbb3
--- /dev/null
+++ b/layouts/partials/tooltip.html
@@ -0,0 +1,11 @@
+
+
+ {{ partial "icon" "help" }}
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 3ab08522d2d9..9e33f2957fb4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"dependencies": {
"@alpinejs/collapse": "^3.13.5",
"@docsearch/js": "^3.5.2",
+ "@floating-ui/dom": "^1.6.3",
"@material-symbols/svg-400": "^0.14.6",
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
"@tailwindcss/typography": "^0.5.10",
@@ -244,6 +245,28 @@
}
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
+ "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.1"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz",
+ "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==",
+ "dependencies": {
+ "@floating-ui/core": "^1.0.0",
+ "@floating-ui/utils": "^0.2.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
+ "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
diff --git a/package.json b/package.json
index 58a67a04768e..51341f773ed6 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"dependencies": {
"@alpinejs/collapse": "^3.13.5",
"@docsearch/js": "^3.5.2",
+ "@floating-ui/dom": "^1.6.3",
"@material-symbols/svg-400": "^0.14.6",
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
"@tailwindcss/typography": "^0.5.10",