diff --git a/src/Nav/index.tsx b/src/Nav/index.tsx index bb68dae..f06dfcf 100644 --- a/src/Nav/index.tsx +++ b/src/Nav/index.tsx @@ -5,17 +5,26 @@ import { ITextAppearance, Text } from "@inubekit/text"; import { Stack } from "@inubekit/stack"; import { inube } from "@inubekit/foundations"; -import { StyledNav, StyledFooter, SeparatorLine } from "./styles"; +import { + StyledNav, + StyledFooter, + SeparatorLine, + StyledCollapseContainer, + StyledAnimatedWrapper, + StyledRotatingIcon, +} from "./styles"; import { NavLink } from "../NavLink"; import { ILink, INavNavigation } from "./props"; -import { useContext } from "react"; +import { useContext, useEffect, useState } from "react"; import { ThemeContext } from "styled-components"; +import { Icon } from "@inubekit/icon"; interface INav { navigation: INavNavigation; logoutPath: string; logoutTitle: string; + collapse?: boolean; } interface INavLink { @@ -24,6 +33,11 @@ interface INavLink { const year = new Date().getFullYear(); +const defaultAnimationValues = { + duration: 0.2, + ease: "ease-in-out", +}; + const Links = (props: INavLink) => { const { section } = props; @@ -42,38 +56,106 @@ const Links = (props: INavLink) => { return <>{LinkElements} ; }; -const MultiSections = ({ navigation }: INav) => { - const sections = Object.keys(navigation.sections); +const MultiSections = ({ + navigation, + collapse, +}: { + navigation: INavNavigation; + collapse: boolean; +}) => { + const [expandedSection, setExpandedSection] = useState(null); const theme: typeof inube = useContext(ThemeContext); - const navTitleAppearance = - (theme?.nav?.title?.appearance as ITextAppearance) || - inube.nav.title.appearance; + const navRegularTitleAppearance = + (theme?.nav?.subtitle?.appearance?.regular as ITextAppearance) || + inube.nav.subtitle.appearance.regular; + const navExpandedTitleAppearance = + (theme?.nav?.subtitle?.appearance?.expanded as ITextAppearance) || + inube.nav.subtitle.appearance.expanded; + + useEffect(() => { + if (collapse && Object.keys(navigation.sections).length > 0) { + setExpandedSection( + Object.keys(navigation.sections)[0].toLocaleUpperCase(), + ); + } + }, [collapse, navigation.sections]); + + const toggleSection = (sectionName: string) => { + setExpandedSection((prevSection) => + prevSection === sectionName ? null : sectionName, + ); + }; return ( - {sections.map((section) => ( - - { + const isExpanded = collapse + ? expandedSection === navigation.sections[section].name + : true; + + return ( + - {navigation.sections[section].name} - - - + + collapse && toggleSection(navigation.sections[section].name) + } + $collapse={collapse} + $expanded={isExpanded} + > + + + {navigation.sections[section].name} + + {collapse && ( + + } + /> + )} + + + + + {isExpanded && ( + + + + )} + - - ))} + ); + })} ); }; @@ -91,7 +173,7 @@ const OneSection = ({ navigation }: INav) => { }; const Nav = (props: INav) => { - const { navigation, logoutTitle, logoutPath } = props; + const { navigation, logoutTitle, logoutPath, collapse = false } = props; const theme: typeof inube = useContext(ThemeContext); const navSubtitleAppearance = (theme?.nav?.subtitle?.appearance?.regular as ITextAppearance) || @@ -114,11 +196,7 @@ const Nav = (props: INav) => { {navigation.title} {Object.keys(navigation.sections).length > 1 ? ( - + ) : ( + theme?.nav?.divider?.color || inube.nav.divider.color}; +`; + +const StyledAnimatedWrapper = styled.div` + opacity: 0; + transition: all ${(props) => props.animation.duration}s + ${(props) => props.animation.ease}; + opacity: ${(props) => (props.open ? 1 : 0)}; +`; + +const StyledCollapseContainer = styled.div` + cursor: ${({ $collapse }) => ($collapse ? "pointer" : "default")}; + & > div { + background-color: ${({ theme, $collapse, $expanded }) => + $collapse && $expanded + ? theme?.nav?.subtitle?.background?.expanded || + inube.nav.subtitle.background.expanded + : theme?.nav?.background?.color || inube.nav.background.color}; + } +`; + +const StyledFooter = styled.footer` + width: 100%; +`; const StyledNav = styled.div` width: 248px; @@ -10,17 +42,17 @@ const StyledNav = styled.div` ${({ theme }) => theme?.nav?.divider?.color || inube.nav.divider.color}; `; -const StyledFooter = styled.footer` - width: 100%; -`; - -const SeparatorLine = styled.div` - width: calc(100% - 32px); - margin: 8px 16px; - height: 1px; - padding: 0px; - background-color: ${({ theme }) => - theme?.nav?.divider?.color || inube.nav.divider.color}; +const StyledRotatingIcon = styled(MdKeyboardArrowDown)` + transition: transform 0.2s ease-in-out; + transform: ${({ $expanded }) => + $expanded ? "rotate(180deg)" : "rotate(0deg)"}; `; -export { StyledNav, StyledFooter, SeparatorLine }; +export { + SeparatorLine, + StyledAnimatedWrapper, + StyledCollapseContainer, + StyledFooter, + StyledNav, + StyledRotatingIcon, +};