diff --git a/apps/website/screens/components/application-layout/overview/ApplicationLayoutOverviewPage.tsx b/apps/website/screens/components/application-layout/overview/ApplicationLayoutOverviewPage.tsx
index efb1c5da3..cac27581e 100644
--- a/apps/website/screens/components/application-layout/overview/ApplicationLayoutOverviewPage.tsx
+++ b/apps/website/screens/components/application-layout/overview/ApplicationLayoutOverviewPage.tsx
@@ -248,7 +248,7 @@ const sections = [
multiples of 8px for visual harmony.
- imit 4px adjustments: Reserve finer increments only for edge cases like icon alignment or
+ Imit 4px adjustments: Reserve finer increments only for edge cases like icon alignment or
typography.
diff --git a/apps/website/screens/components/footer/code/FooterCodePage.tsx b/apps/website/screens/components/footer/code/FooterCodePage.tsx
index 943aee208..7bffbaa62 100644
--- a/apps/website/screens/components/footer/code/FooterCodePage.tsx
+++ b/apps/website/screens/components/footer/code/FooterCodePage.tsx
@@ -10,7 +10,7 @@ const bottomLinksTypeString = `{
}[]`;
const logoTypeString = `{
- src: string;
+ src: string | SVG;
alt: string;
}`;
diff --git a/packages/lib/src/footer/Footer.stories.tsx b/packages/lib/src/footer/Footer.stories.tsx
index 73b52fb5a..647058300 100644
--- a/packages/lib/src/footer/Footer.stories.tsx
+++ b/packages/lib/src/footer/Footer.stories.tsx
@@ -7,6 +7,7 @@ import DxcFooter from "./Footer";
import DxcLink from "../link/Link";
import { Meta, StoryObj } from "@storybook/react-vite";
import { userEvent, within } from "storybook/internal/test";
+import { useEffect } from "react";
import DxcParagraph from "../paragraph/Paragraph";
import DxcHeading from "../heading/Heading";
import DxcApplicationLayout from "../layout/ApplicationLayout";
@@ -17,6 +18,15 @@ import DxcButton from "../button/Button";
export default {
title: "Footer",
component: DxcFooter,
+ decorators: [
+ (Story) => {
+ useEffect(() => {
+ document.body.style.padding = "0";
+ }, []);
+
+ return ;
+ },
+ ],
parameters: {
a11y: {
config: {
diff --git a/packages/lib/src/footer/Footer.tsx b/packages/lib/src/footer/Footer.tsx
index 577dfe1c5..2d56ad681 100644
--- a/packages/lib/src/footer/Footer.tsx
+++ b/packages/lib/src/footer/Footer.tsx
@@ -1,4 +1,4 @@
-import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import { isValidElement, useContext, useEffect, useMemo, useRef, useState } from "react";
import styled from "@emotion/styled";
import DxcIcon from "../icon/Icon";
import { Tooltip } from "../tooltip/Tooltip";
@@ -65,6 +65,11 @@ const LogoContainer = styled.span<{ mode?: FooterPropsType["mode"] }>`
justify-content: flex-start;
align-items: center;
`}
+
+ svg {
+ height: ${(props) => (props.mode === "default" ? "var(--height-m)" : "var(--height-xxs)")};
+ width: auto;
+ }
`;
const LogoImg = styled.img<{ mode: FooterPropsType["mode"] }>`
@@ -213,8 +218,10 @@ const DxcFooter = ({
const translatedLabels = useContext(HalstackLanguageContext);
const footerLogo = useMemo(() => {
- if (logo) {
+ if (logo && typeof logo.src === "string") {
return ;
+ } else if (isValidElement(logo?.src)) {
+ return logo.src;
} else {
return mode === "default" ? dxcLogo : dxcSmallLogo;
}
diff --git a/packages/lib/src/footer/types.ts b/packages/lib/src/footer/types.ts
index 2706fa804..857425607 100644
--- a/packages/lib/src/footer/types.ts
+++ b/packages/lib/src/footer/types.ts
@@ -31,7 +31,7 @@ type Logo = {
/**
* Source of the logo image.
*/
- src: string;
+ src: string | SVG;
/**
* Alternative text for the logo image.
*/
diff --git a/packages/lib/src/layout/ApplicationLayout.stories.tsx b/packages/lib/src/layout/ApplicationLayout.stories.tsx
index 4f1fa5b29..9d468b65d 100644
--- a/packages/lib/src/layout/ApplicationLayout.stories.tsx
+++ b/packages/lib/src/layout/ApplicationLayout.stories.tsx
@@ -2,10 +2,20 @@ import { Meta, StoryObj } from "@storybook/react-vite";
import Title from "../../.storybook/components/Title";
import DxcApplicationLayout from "./ApplicationLayout";
import { userEvent, within } from "storybook/internal/test";
+import { useEffect } from "react";
export default {
title: "Application Layout",
component: DxcApplicationLayout,
+ decorators: [
+ (Story) => {
+ useEffect(() => {
+ document.body.style.padding = "0";
+ }, []);
+
+ return ;
+ },
+ ],
} satisfies Meta;
const dxcLogo = (
diff --git a/packages/lib/src/layout/ApplicationLayout.tsx b/packages/lib/src/layout/ApplicationLayout.tsx
index 16b55ab42..1b760aa71 100644
--- a/packages/lib/src/layout/ApplicationLayout.tsx
+++ b/packages/lib/src/layout/ApplicationLayout.tsx
@@ -1,4 +1,4 @@
-import { useMemo, useRef } from "react";
+import React, { useMemo, useRef, useState, useCallback } from "react";
import styled from "@emotion/styled";
import DxcFooter from "../footer/Footer";
import DxcHeader from "../header/Header";
@@ -8,46 +8,42 @@ import { bottomLinks, findChildType, socialLinks, year } from "./utils";
import ApplicationLayoutContext from "./ApplicationLayoutContext";
const ApplicationLayoutContainer = styled.div<{ header?: React.ReactNode }>`
- top: 0;
- left: 0;
display: grid;
- grid-template-rows: ${({ header }) => (header ? "auto 1fr" : "1fr")};
- height: 100vh;
- width: 100vw;
- position: absolute;
- overflow: hidden;
+ grid-template-rows: ${({ header }) => (header ? "auto 1fr auto" : "1fr auto")};
+ min-height: 100vh;
`;
const HeaderContainer = styled.div`
+ position: sticky;
+ top: 0;
width: 100%;
- min-height: var(--height-xxxl);
height: fit-content;
z-index: var(--z-app-layout-header);
`;
const BodyContainer = styled.div<{ hasSidenav?: boolean }>`
+ position: relative;
display: grid;
grid-template-columns: ${({ hasSidenav }) => (hasSidenav ? "auto 1fr" : "1fr")};
grid-template-rows: 1fr;
- overflow: hidden;
+ min-height: 100%;
`;
-const SidenavContainer = styled.div`
+const SidenavContainer = styled.div<{ headerHeight: string }>`
width: fit-content;
height: 100%;
z-index: var(--z-app-layout-sidenav);
position: sticky;
+ top: ${({ headerHeight }) => headerHeight || "0"};
overflow: auto;
+ max-height: ${({ headerHeight }) => `calc(100vh - ${headerHeight || "0"})`};
`;
-const MainContainer = styled.div`
- display: flex;
- flex-grow: 1;
- flex-direction: column;
+const MainContainer = styled.main`
+ position: relative;
+ display: grid;
width: 100%;
height: 100%;
- position: relative;
- overflow: auto;
`;
const FooterContainer = styled.div`
@@ -55,15 +51,21 @@ const FooterContainer = styled.div`
width: 100%;
`;
-const MainContentContainer = styled.main`
- height: 100%;
- display: grid;
- grid-template-rows: 1fr auto;
-`;
-
const Main = ({ children }: AppLayoutMainPropsType): JSX.Element => {children}
;
const DxcApplicationLayout = ({ logo, header, sidenav, footer, children }: ApplicationLayoutPropsType): JSX.Element => {
+ const [headerHeight, setHeaderHeight] = useState("0px");
+
+ const handleHeaderHeight = useCallback(
+ (headerElement: HTMLDivElement | null) => {
+ if (headerElement) {
+ const height = headerElement.offsetHeight;
+ setHeaderHeight(`${height}px`);
+ }
+ },
+ [header]
+ );
+
const contextValue = useMemo(() => {
return {
logo,
@@ -75,24 +77,20 @@ const DxcApplicationLayout = ({ logo, header, sidenav, footer, children }: Appli
return (
- {header && {header}}
+ {header && {header}}
- {sidenav && {sidenav}}
-
-
- {findChildType(children, Main)}
-
- {footer ?? (
-
- )}
-
-
-
+ {sidenav && {sidenav}}
+ {findChildType(children, Main)}
+
+ {footer ?? (
+
+ )}
+
);
diff --git a/packages/lib/src/search-bar/SearchBar.tsx b/packages/lib/src/search-bar/SearchBar.tsx
index a160ee95e..42440567c 100644
--- a/packages/lib/src/search-bar/SearchBar.tsx
+++ b/packages/lib/src/search-bar/SearchBar.tsx
@@ -72,8 +72,8 @@ const DxcSearchBar = ({
const inputRef = useRef(null);
const [innerValue, setInnerValue] = useState("");
- const handleClearActionOnClick = () => {
- setInnerValue("");
+ const handleClearAction = () => {
+ handleSearchChangeValue("");
inputRef.current?.focus();
};
@@ -90,7 +90,7 @@ const DxcSearchBar = ({
case "Escape":
e.preventDefault();
if (innerValue.length > 0) {
- handleClearActionOnClick();
+ handleClearAction();
}
break;
case "Enter":
@@ -123,7 +123,7 @@ const DxcSearchBar = ({
size="xsmall"
shape="circle"
icon="cancel"
- onClick={handleClearActionOnClick}
+ onClick={handleClearAction}
tabIndex={0}
title={!disabled ? translatedLabels.searchBar.clearFieldActionTitle : undefined}
/>
diff --git a/packages/lib/src/sidenav/Sidenav.stories.tsx b/packages/lib/src/sidenav/Sidenav.stories.tsx
index e0a68423d..27adbfa10 100644
--- a/packages/lib/src/sidenav/Sidenav.stories.tsx
+++ b/packages/lib/src/sidenav/Sidenav.stories.tsx
@@ -10,11 +10,20 @@ import DxcAvatar from "../avatar/Avatar";
import { userEvent, within } from "storybook/internal/test";
import disabledRules from "../../test/accessibility/rules/specific/sidenav/disabledRules";
import preview from "../../.storybook/preview";
-import { useState } from "react";
+import { useEffect, useState } from "react";
export default {
title: "Sidenav",
component: DxcSidenav,
+ decorators: [
+ (Story) => {
+ useEffect(() => {
+ document.body.style.padding = "0";
+ }, []);
+
+ return ;
+ },
+ ],
parameters: {
a11y: {
config: {
@@ -34,7 +43,7 @@ const DetailedAvatar = () => {
{
Michael Ramirez