diff --git a/layer5.code-workspace b/layer5.code-workspace
new file mode 100644
index 0000000000000..3a04adb55a2ad
--- /dev/null
+++ b/layer5.code-workspace
@@ -0,0 +1,25 @@
+{
+ "folders": [
+ {
+ "path": "."
+ },
+ {
+ "path": "."
+ },
+ {
+ "path": "."
+ },
+ {
+ "path": "."
+ },
+ {
+ "path": "."
+ },
+ {
+ "path": "."
+ },
+ {
+ "path": "."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/onRenderBody.js b/onRenderBody.js
index 139a6b6feffd1..d34c0417123c7 100644
--- a/onRenderBody.js
+++ b/onRenderBody.js
@@ -7,7 +7,7 @@ const themes = { light: lighttheme, dark: darktheme };
const MagicScriptTag = (props) => {
// FIX: Stringify the theme object outside the template literal to prevent syntax errors caused by unescaped quotes inside theme values.
const themeJSON = JSON.stringify(props.theme);
-
+
// Injects CSS variables and theme state strictly before the first paint to prevent FOUC.
const codeToRunOnClient = `
(function() {
@@ -75,6 +75,6 @@ const MagicScriptTag = (props) => {
// FIX: Using setHeadComponents instead of setPreBodyComponents ensures the script runs
// strictly in the
, blocking the first paint until the theme is applied and completely eliminating FOUC.
-export const onRenderBody = ( { setHeadComponents }) => {
+export const onRenderBody = ({ setHeadComponents }) => {
setHeadComponents([]);
-};
\ No newline at end of file
+};
diff --git a/src/sections/Meshery/Meshery-integrations/Integration.style.js b/src/sections/Meshery/Meshery-integrations/Integration.style.js
index 987e47d72eefa..08d11baf7f630 100755
--- a/src/sections/Meshery/Meshery-integrations/Integration.style.js
+++ b/src/sections/Meshery/Meshery-integrations/Integration.style.js
@@ -1,5 +1,4 @@
import styled from "styled-components";
-import Slider from "react-slick";
export const HoneycombGrid = styled.div`
.heading {
@@ -33,27 +32,6 @@ export const HoneycombGrid = styled.div`
justify-content: center;
}
- .items {
- background-color: #d2d8da; //#E7EFF3;
- padding: 0.625rem 1.5625rem;
- border-radius: 0.625rem;
- text-transform: uppercase;
- color: #1e2117;
- font-size: 0.875rem;
- cursor: pointer;
- transition: all 0.1s ease-in-out;
-
- &:hover {
- opacity: 0.8;
- box-shadow: 0px 0px 6px -2px rgb(60, 73, 79);
- }
- }
-
- .selected {
- background-color: ${(props) => props.theme.darkJungleGreenColor};
- color: ${(props) => props.theme.whiteToBlack};
- }
-
ul {
margin: 2.5rem 0 0 0;
padding-left: 50px;
@@ -220,71 +198,188 @@ export const IntegrationCard = styled.div`
// }
`;
-export const IntegrationSlider = styled(Slider)`
- .slick-prev:hover,
- .slick-next:hover {
- box-shadow: none;
- outline: none;
- }
+export const CategoryFilterBar = styled.div`
+ position: relative;
+ margin: 1.5rem 0 2rem;
+ padding: 0 0.5rem;
- .slick-arrow {
- width: 2rem;
- height: 3rem;
- }
+ .category-chips-wrapper {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 0.5rem;
+ padding: 0.25rem 0;
- .slick-list {
- padding-top: 0.2rem;
+ @media screen and (max-width: 768px) {
+ flex-wrap: nowrap;
+ overflow-x: auto;
+ justify-content: flex-start;
+ scroll-behavior: smooth;
+ -webkit-overflow-scrolling: touch;
+ scroll-snap-type: x proximity;
+ gap: 0.625rem;
+ padding: 0.5rem 1.5rem;
+ margin: 0 -1.5rem;
+
+ /* Hide scrollbar but keep functionality */
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ }
}
- .slick-disabled {
+ /* Left overflow fade indicator for mobile scroll */
+ &::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 2.5rem;
pointer-events: none;
- opacity: 0.3;
- }
+ opacity: 0;
+ transition: opacity 0.3s ease;
+ z-index: 2;
- .slick-arrow:before {
- color: ${(props) => props.theme.whiteToBlack};
- font-size: 4rem;
- display: inline-block;
- height: 1rem;
- -webkit-text-size-adjust: none;
- transition: 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
+ @media screen and (max-width: 768px) {
+ opacity: 1;
+ background: linear-gradient(
+ to left,
+ transparent,
+ ${(props) =>
+ props.theme.DarkTheme
+ ? "rgba(18,18,18,0.85)"
+ : "rgba(255,255,255,0.85)"}
+ );
+ }
}
- .slick-arrow:hover:before {
- color: #00b39f;
- }
+ /* Right overflow fade indicator for mobile scroll */
+ &::after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ width: 2.5rem;
+ pointer-events: none;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+ z-index: 2;
- .slick-slide {
- width: auto !important;
- margin: 0 0.5rem;
+ @media screen and (max-width: 768px) {
+ opacity: 1;
+ background: linear-gradient(
+ to right,
+ transparent,
+ ${(props) =>
+ props.theme.DarkTheme
+ ? "rgba(18,18,18,0.85)"
+ : "rgba(255,255,255,0.85)"}
+ );
+ }
}
- .slick-next {
- right: -2.5rem;
- }
+ .category-chip {
+ /* ── Inactive (default) = dark / filled ── */
+ display: inline-flex;
+ align-items: center;
+ gap: 0.375rem;
+ padding: 0.5rem 1.125rem;
+ border-radius: 2rem;
+ font-size: 0.8125rem;
+ font-weight: 600;
+ letter-spacing: 0.025em;
+ text-transform: uppercase;
+ white-space: nowrap;
+ cursor: pointer;
+ user-select: none;
+ border: 1.5px solid transparent;
+ outline: none;
+ scroll-snap-align: start;
- .slick-prev {
- left: -2.5rem;
- }
+ background: ${(props) =>
+ props.theme.DarkTheme
+ ? "rgba(255,255,255,0.08)"
+ : props.theme.darkJungleGreenColor};
+ color: ${(props) =>
+ props.theme.DarkTheme ? "rgba(255,255,255,0.7)" : "#ffffff"};
- .slick-prev:before {
- content: "‹";
- line-height: 0;
- opacity: 1;
- }
+ transition:
+ background 0.25s ease,
+ color 0.25s ease,
+ border-color 0.25s ease,
+ box-shadow 0.25s ease,
+ transform 0.15s ease;
- .slick-track {
- display: flex;
- }
+ &:hover {
+ background: ${(props) =>
+ props.theme.DarkTheme ? "rgba(255,255,255,0.14)" : "#2d3328"};
+ transform: translateY(-1px);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+ }
- .slick-next:before {
- content: "›";
- line-height: 0;
- opacity: 1;
+ &:focus-visible {
+ border-color: ${(props) => props.theme.keppelColor};
+ box-shadow: 0 0 0 3px
+ ${(props) =>
+ props.theme.DarkTheme
+ ? "rgba(0,211,169,0.35)"
+ : "rgba(0,179,159,0.3)"};
+ }
+
+ &:active {
+ transform: scale(0.97);
+ }
+
+ /* ── Active / Selected = light / outlined ── */
+ &.selected {
+ background: ${(props) =>
+ props.theme.DarkTheme ? "rgba(0,211,169,0.15)" : "#f0fdfb"};
+ color: ${(props) =>
+ props.theme.DarkTheme
+ ? props.theme.keppelColor
+ : props.theme.secondaryColor};
+ border-color: ${(props) =>
+ props.theme.DarkTheme
+ ? props.theme.keppelColor
+ : props.theme.secondaryColor};
+ font-weight: 700;
+
+ &:hover {
+ background: ${(props) =>
+ props.theme.DarkTheme ? "rgba(0,211,169,0.22)" : "#e0f9f5"};
+ box-shadow: 0 2px 12px
+ ${(props) =>
+ props.theme.DarkTheme
+ ? "rgba(0,211,169,0.2)"
+ : "rgba(0,179,159,0.18)"};
+ }
+ }
+
+ .chip-count {
+ font-size: 0.6875rem;
+ font-weight: 500;
+ opacity: 0.7;
+ margin-left: 0.125rem;
+ }
+
+ /* Touch-friendly sizing on mobile */
+ @media screen and (max-width: 768px) {
+ padding: 0.5rem 1rem;
+ font-size: 0.75rem;
+ min-height: 2.25rem;
+ }
}
- .slick-prev,
- .slick-next {
- top: 1.5rem;
+ @media (prefers-reduced-motion: reduce) {
+ .category-chip {
+ transition: none;
+ }
+ .category-chips-wrapper {
+ scroll-behavior: auto;
+ }
}
`;
diff --git a/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js b/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js
index 1f41cbe5046f6..cb6ec968d6aa4 100644
--- a/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js
+++ b/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js
@@ -1,6 +1,6 @@
import React, { useState, useEffect, useRef } from "react";
import { Link, useStaticQuery, graphql } from "gatsby";
-import { HoneycombGrid, IntegrationSlider } from "./Integration.style";
+import { HoneycombGrid, CategoryFilterBar } from "./Integration.style";
import useDataList from "../../../utils/usedataList";
import SearchBox from "../../../reusecore/Search";
import EmptyResources from "../../Resources/Resources-error/emptyStateTemplate";
@@ -38,36 +38,6 @@ const IntegrationsGrid = ({ category, count }) => {
}
`);
- const settings = {
- initialSlide: 0,
- variableWidth: true,
- infinite: false,
- slidesToShow: 5.25,
- swipeToSlide: true,
- slidesToScroll: 1,
- // useTransform: false,
-
- responsive: [
- {
- breakpoint: 900,
- settings: {
- initialSlide: 0,
- infinite: false,
- arrows: true,
- slidesToShow: 3,
- },
- },
- {
- breakpoint: 500,
- settings: {
- initialSlide: 0,
- arrows: true,
- infinite: false,
- slidesToShow: 1.5,
- },
- },
- ],
- };
const [searchQuery, setSearchQuery] = useState("");
const { queryResults, searchData } = useDataList(
@@ -162,10 +132,9 @@ const IntegrationsGrid = ({ category, count }) => {
const setFilter = (event) => {
let count = 0;
let tempCategoryList = [...categoryNameList];
- let selectedCategory = event.target.innerHTML.includes("&")
- ? event.target.innerHTML.replace("&", "&")
- : event.target.innerHTML;
- selectedCategory = selectedCategory.split("(")[0].trim();
+ const btn = event.currentTarget;
+ let selectedCategory =
+ btn.getAttribute("data-category") || btn.textContent.split("(")[0].trim();
if (selectedCategory === "All") {
tempCategoryList.forEach((item) => {
@@ -232,21 +201,36 @@ const IntegrationsGrid = ({ category, count }) => {
focusSearch={false}
/>
-
-
- {!hideFilter &&
- categoryNameList.map((item) => {
- return (
-
- {`${item.name} (${item.count})`}
-
- );
- })}
-
+
+ {!hideFilter && (
+
+
+ {categoryNameList.map((item) => {
+ return (
+
+ );
+ })}
+
+
+ )}
{searchQuery.length > 0 && queryResults.length < 1 ? (
diff --git a/src/templates/sistent-component.js b/src/templates/sistent-component.js
index a862992a3da2b..96db535746ef1 100644
--- a/src/templates/sistent-component.js
+++ b/src/templates/sistent-component.js
@@ -9,24 +9,22 @@ import TabButton from "../reusecore/Button";
import { Col, Row } from "../reusecore/Layout";
import CodeBlock from "../components/CodeBlock";
import { SistentThemeProvider, Button } from "@sistent/sistent";
-import { useStyledDarkMode } from "../theme/app/useStyledDarkMode";
import ThemeWrapper from "../sections/Projects/Sistent/theme-wrapper";
-const shortcodes = {
+const shortcodes = {
SistentThemeProvider,
ThemeWrapper,
- Button,
- Col,
- Row,
+ Button,
+ Col,
+ Row,
CodeBlock,
- FaArrowRight
+ FaArrowRight,
};
const SistentComponentTemplate = ({ data, children, pageContext }) => {
const { frontmatter } = data.mdx;
const location = useLocation();
const { componentName, availablePages } = pageContext;
- const { isDark } = useStyledDarkMode();
const baseUrl = `/projects/sistent/components/${componentName}`;
@@ -40,11 +38,11 @@ const SistentComponentTemplate = ({ data, children, pageContext }) => {
-
{displayName}
- {frontmatter.description &&
{frontmatter.description}
}
+
{displayName}
+ {frontmatter.description &&
{frontmatter.description}
}
-
+
{availablePages.includes("overview") && (
{
)}
{availablePages.includes("guidance") && (
navigate(`${baseUrl}/guidance`)}
title="Guidance"
/>
)}
{availablePages.includes("code") && (
navigate(`${baseUrl}/code`)}
title="Code"
/>
)}
-
-
- {children}
-
+
+
{children}
@@ -78,7 +78,7 @@ const SistentComponentTemplate = ({ data, children, pageContext }) => {
};
export const query = graphql`
- query($slug: String!) {
+ query ($slug: String!) {
mdx(fields: { slug: { eq: $slug } }) {
body
frontmatter {
diff --git a/src/theme/app/ThemeManager.js b/src/theme/app/ThemeManager.js
index 819c2881855d5..934d9586ee6cd 100644
--- a/src/theme/app/ThemeManager.js
+++ b/src/theme/app/ThemeManager.js
@@ -26,7 +26,9 @@ export const ThemeManagerContext = createContext(defaultState);
const isBrowser = typeof window !== "undefined";
const systemDarkModeSetting = () =>
- isBrowser && window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
+ isBrowser && window.matchMedia
+ ? window.matchMedia("(prefers-color-scheme: dark)")
+ : null;
const isDarkModeActive = () => {
return !!systemDarkModeSetting()?.matches;
@@ -43,7 +45,7 @@ const applyThemeToDOM = (theme) => {
export const ThemeManagerProvider = (props) => {
const [themeSetting, setThemeSetting] = useState(ThemeSetting.SYSTEM);
const [didLoad, setDidLoad] = useState(false);
-
+
const [isDark, setIsDark] = useState(() => {
if (isBrowser) {
if (window.__theme === ThemeSetting.DARK) return true;
@@ -56,9 +58,12 @@ export const ThemeManagerProvider = (props) => {
if (!isBrowser) return;
const root = window.document.documentElement;
- const initialColorValue = (root.style.getPropertyValue("--initial-color-mode") || "").trim();
- const actualTheme = window.__theme || initialColorValue || ThemeSetting.DARK;
-
+ const initialColorValue = (
+ root.style.getPropertyValue("--initial-color-mode") || ""
+ ).trim();
+ const actualTheme =
+ window.__theme || initialColorValue || ThemeSetting.DARK;
+
// Get stored theme from localStorage
const storedTheme = localStorage.getItem(DarkThemeKey);
@@ -81,7 +86,7 @@ export const ThemeManagerProvider = (props) => {
setDidLoad(true);
}, []);
- // Listen to system color scheme changes only when on SYSTEM mode
+ // Listen to system color scheme changes only when on SYSTEM mode
useEffect(() => {
if (!isBrowser || themeSetting !== ThemeSetting.SYSTEM) return;
@@ -103,11 +108,11 @@ export const ThemeManagerProvider = (props) => {
const newIsDark = !isDark;
const newTheme = newIsDark ? ThemeSetting.DARK : ThemeSetting.LIGHT;
- // Update state
+ // Update state
setIsDark(newIsDark);
setThemeSetting(newTheme);
- // Apply to DOM immediately
+ // Apply to DOM immediately
applyThemeToDOM(newTheme);
// Persist to localStorage
@@ -139,17 +144,17 @@ export const ThemeManagerProvider = (props) => {
return;
}
- // Update state
+ // Update state
setIsDark(newIsDark);
setThemeSetting(setting);
// Apply to DOM immediately
applyThemeToDOM(themeToApply);
- // Persist to localStorage
+ // Persist to localStorage
localStorage.setItem(DarkThemeKey, setting);
},
- [isDark]
+ [isDark],
);
return (