This Confluence user macro lets users add a customizable tile to a page. You can configure the tile's title, subtitle, icon, icon color, and background color theme. An optional external link can be added to the top-right corner, opening in a new tab when clicked.
The tile supports light styling, hover effects, and color filtering for icons using CSS.
More icons can be found at Iconoir.
#*
This user macro renders a single visual tile with customizable icon, title, subtitle, link, and color theme.
*#
#set($title = $parameters["title"])
#set($subtitle = $parameters["subtitle"])
#set($imageUrl = $parameters["imageUrl"])
#set($link = $parameters["link"])
#set($iconColor = $parameters["iconColor"])
#set($tileTheme = $parameters["tileTheme"])
<div id="tiles-container" style="display: flex; gap: 1rem; padding: 10px;"></div>
<script>
const title = "$title" || "Your title";
const subtitle = "$subtitle" || "Your subtitle";
const imgUrl = "$imageUrl" || "https://cdn.jsdelivr.net/npm/iconoir@6/icons/book.svg";
const link = "$link";
const iconColor = "$iconColor";
const tileTheme = "$tileTheme";
const colorFilters = {
blue: "invert(31%) sepia(99%) saturate(3489%) hue-rotate(216deg) brightness(94%) contrast(102%)",
green: "invert(52%) sepia(42%) saturate(723%) hue-rotate(75deg) brightness(92%) contrast(85%)",
red: "invert(25%) sepia(92%) saturate(1818%) hue-rotate(348deg) brightness(89%) contrast(100%)",
yellow: "invert(93%) sepia(89%) saturate(1021%) hue-rotate(360deg) brightness(102%) contrast(104%)",
purple: "invert(20%) sepia(75%) saturate(1383%) hue-rotate(250deg) brightness(90%) contrast(96%)",
orange: "invert(64%) sepia(94%) saturate(1234%) hue-rotate(5deg) brightness(101%) contrast(100%)",
gray: "invert(53%) sepia(0%) saturate(0%) hue-rotate(179deg) brightness(90%) contrast(92%)"
};
const themes = {
sky: {
background: "#E9F2FF",
text: "#0c4a6e",
meta: "#1e3a8a"
},
blush: {
background: "#FFECF8",
text: "#831843",
meta: "#9d174d"
},
mint: {
background: "#DCFFF1",
text: "#064e3b",
meta: "#065f46"
},
gray: {
background: "#091E4208",
text: "#101214",
meta: "#091E427D"
}
};
const theme = themes[tileTheme] || {};
const container = document.getElementById("tiles-container");
const div = document.createElement("div");
div.style.cssText =
"position: relative;" +
"display: flex;" +
"flex-direction: column;" +
"align-items: flex-start;" +
"width: 100vw;" +
"box-sizing: border-box;" +
"padding: 1rem;" +
"border: 1px solid #ccc;" +
"border-radius: 6px;" +
"transition: box-shadow 0.3s ease;" +
"cursor: pointer;" +
"background: " + theme.background + ";";
if (link) {
const icon = document.createElement("div");
icon.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
viewBox="0 0 24 24" fill="none" stroke="#666" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
<polyline points="15 3 21 3 21 9" />
<line x1="10" y1="14" x2="21" y2="3" />
</svg>
`;
icon.style.cssText =
"position: absolute;" +
"top: 0.5rem;" +
"right: 0.5rem;" +
"opacity: 0;" +
"transition: opacity 0.2s, transform 0.2s, stroke 0.2s;" +
"cursor: pointer;";
icon.title = "Open in a new tab";
icon.onclick = () => {
window.open(link, "_blank");
setTimeout(() => {
div.style.boxShadow = "none";
icon.style.opacity = "0";
icon.querySelector("svg").style.stroke = "#666";
}, 50);
};
div.addEventListener("mouseenter", () => {
div.style.boxShadow = "0 8px 24px rgba(0, 0, 0, 0.2)";
icon.style.opacity = "1";
});
div.addEventListener("mouseleave", () => {
div.style.boxShadow = "none";
icon.style.opacity = "0";
});
icon.addEventListener("mouseenter", () => {
const svg = icon.querySelector("svg");
svg.style.stroke = "#1d4ed8";
svg.style.transform = "scale(1.1)";
});
icon.addEventListener("mouseleave", () => {
const svg = icon.querySelector("svg");
svg.style.stroke = "#666";
svg.style.transform = "scale(1)";
});
div.appendChild(icon);
}
const img = document.createElement("img");
img.src = imgUrl;
img.alt = title;
img.style.cssText = "width: 40px; height: 40px; object-fit: contain; margin-bottom: 0.5rem;";
if (colorFilters[iconColor]) {
img.style.filter = colorFilters[iconColor];
}
const titleDiv = document.createElement("div");
titleDiv.textContent = title;
titleDiv.style.cssText = "font-weight: bold;" + "margin-bottom: 1.5rem;" + "color: " + theme.text + ";";
const subtitleDiv = document.createElement("div");
subtitleDiv.textContent = subtitle;
subtitleDiv.style.cssText = "font-size: 0.85rem;" + "color: " + theme.meta + ";";
div.appendChild(img);
div.appendChild(titleDiv);
div.appendChild(subtitleDiv);
container.appendChild(div);
</script>Show confetti bursts and a motivational message upon saving an edited page
Hide specific content from users in a particular Confluence group
Create dropdown menus in Confluence Cloud with predefined option sets, multiselect support, and permission-based access controls
Retrieve and display all page content properties in an AUI sortable table
Embed a typo-tolerant search bar directly into Confluence pages to find, highlight, and jump to specific content
Show filtered issues and their relations
Display the creation date of the current Confluence page
Add a configurable floating panel to a Confluence page
Embed external content such as web pages, forms, slides and charts as iframe in Confluence pages, write custom HTML, and use CSS and Javascript for better looks and features
Get the latest cryptocurrency exchange rates for major coins