diff --git a/apps/portals/my-pages/src/components/Header/Header.css.ts b/apps/portals/my-pages/src/components/Header/Header.css.ts
index 847e4716b855..bc620e2873b1 100644
--- a/apps/portals/my-pages/src/components/Header/Header.css.ts
+++ b/apps/portals/my-pages/src/components/Header/Header.css.ts
@@ -7,7 +7,7 @@ import {
import { theme, themeUtils } from '@island.is/island-ui/theme'
export const header = style({
- position: 'relative',
+ position: 'fixed',
zIndex: zIndex.header,
display: 'flex',
alignItems: 'center',
@@ -18,7 +18,6 @@ export const header = style({
'@media': {
[`screen and (min-width: ${theme.breakpoints.lg}px)`]: {
height: SERVICE_PORTAL_HEADER_HEIGHT_LG,
- position: 'fixed',
},
},
transition: 'all 250ms ease-in-out',
diff --git a/apps/portals/my-pages/src/components/Layout/Layout.css.ts b/apps/portals/my-pages/src/components/Layout/Layout.css.ts
index 026b46939360..d44c413fe927 100644
--- a/apps/portals/my-pages/src/components/Layout/Layout.css.ts
+++ b/apps/portals/my-pages/src/components/Layout/Layout.css.ts
@@ -21,12 +21,6 @@ export const lock = style({
export const btn = style({})
-export const mobileNav = style({
- position: 'sticky',
- top: 0,
- zIndex: 99,
-})
-
globalStyle(`${btn} > span`, {
boxShadow: 'none',
})
diff --git a/apps/portals/my-pages/src/components/Layout/NarrowLayout.tsx b/apps/portals/my-pages/src/components/Layout/NarrowLayout.tsx
index 3c102bb5df89..27c139af7ec7 100644
--- a/apps/portals/my-pages/src/components/Layout/NarrowLayout.tsx
+++ b/apps/portals/my-pages/src/components/Layout/NarrowLayout.tsx
@@ -1,12 +1,16 @@
import { ReactNode } from 'react'
-import { Box, NavigationItem, Icon } from '@island.is/island-ui/core'
+import {
+ Box,
+ Navigation,
+ NavigationItem,
+ Icon,
+} from '@island.is/island-ui/core'
import ContentBreadcrumbs from '../../components/ContentBreadcrumbs/ContentBreadcrumbs'
import {
m,
ServicePortalNavigationItem,
ModuleAlertBannerSection,
GoBack,
- Navigation,
} from '@island.is/portals/my-pages/core'
import { useLocale } from '@island.is/localization'
import { useWindowSize } from 'react-use'
@@ -97,10 +101,11 @@ export const NarrowLayout = ({
)
}}
asSpan
- baseId="service-portal-navigation"
+ baseId={'service-portal-navigation'}
title={formatMessage(activeParent?.name ?? m.tableOfContents)}
items={subNavItems ?? []}
expand
+ expandOnActivation
titleIcon={activeParent?.icon}
/>
@@ -117,7 +122,7 @@ export const NarrowLayout = ({
>
{isMobile && subNavItems && subNavItems.length > 0 && (
-
+
{
return item?.href ? (
@@ -127,7 +132,7 @@ export const NarrowLayout = ({
)
}}
asSpan
- baseId="service-portal-mobile-navigation"
+ baseId={'service-portal-mobile-navigation'}
title={
activeParent?.name
? formatMessage(activeParent?.name)
diff --git a/libs/portals/my-pages/core/src/components/Navigation/Navigation.css.ts b/libs/portals/my-pages/core/src/components/Navigation/Navigation.css.ts
deleted file mode 100644
index e4f08cac0b62..000000000000
--- a/libs/portals/my-pages/core/src/components/Navigation/Navigation.css.ts
+++ /dev/null
@@ -1,215 +0,0 @@
-import { style, styleVariants, keyframes } from '@vanilla-extract/css'
-import { theme } from '@island.is/island-ui/theme'
-
-export const divider = style({
- width: '100%',
- height: 1,
-})
-
-export const largerClickableArea = style({
- ':after': {
- position: 'absolute',
- display: 'inline-block',
- cursor: 'pointer',
- left: 0,
- right: 0,
- bottom: 0,
- top: 0,
- content: '""',
- margin: -10,
- },
-})
-
-export const root = style({
- transition: 'background-color 150ms',
-})
-
-export const ul = style({
- borderLeftWidth: 1,
- borderLeftStyle: 'solid',
- borderLeftColor: theme.color.transparent,
-})
-
-export const colorScheme = styleVariants({
- blue: {},
- purple: {},
- darkBlue: {},
-})
-
-export const text = style({
- position: 'relative',
-})
-
-export const textNarrower = style({
- width: 'calc(100% - 34px)',
-})
-
-export const link = style({
- position: 'relative',
- ':hover': {
- textDecoration: 'none',
- cursor: 'pointer',
- },
-})
-
-export const level = styleVariants({
- 1: {
- padding: 0,
- },
- 2: {
- marginTop: theme.spacing[1],
- marginBottom: theme.spacing[1],
- marginLeft: theme.spacing[3],
- marginRight: theme.spacing[3],
- },
-})
-
-export const menuBtn = style({
- width: '100%',
- cursor: 'pointer',
- outline: 'none',
- borderRadius: 8,
- padding: `${theme.spacing['p2']}px ${theme.spacing[2]}px`,
- transition: 'box-shadow .25s, color .25s, background-color .25s',
- ':focus-visible': {
- boxShadow: `0 0 0 3px ${theme.color.blue400}`,
- },
-})
-
-export const listItem = style({
- position: 'relative',
-})
-
-const translate = 'translateX(-50%) translateY(-50%)'
-
-export const icon = style({
- position: 'absolute',
- left: '50%',
- top: '50%',
- opacity: 1,
- transform: `${translate} rotateZ(0deg)`,
- transition: 'opacity 150ms ease, transform 300ms ease',
-})
-
-export const iconRemoveHidden = style({
- opacity: 0,
- transform: `${translate} rotateZ(-90deg)`,
-})
-
-export const iconRemoveVisible = style({
- opacity: 1,
- transform: `${translate} rotateZ(0deg)`,
-})
-
-export const iconAddHidden = style({
- opacity: 0,
- transform: `${translate} rotateZ(0deg)`,
-})
-
-export const iconAddVisible = style({
- opacity: 1,
- transform: `${translate} rotateZ(-0deg)`,
-})
-
-export const rotated = style({
- transition: 'transform 300ms ease',
-})
-
-export const accordionIcon = style({
- position: 'absolute',
- display: 'inline-block',
- lineHeight: 0,
- justifyContent: 'center',
- alignItems: 'center',
- borderRadius: '50%',
- top: 10,
- right: 0,
- width: 24,
- height: 24,
- outline: 0,
-})
-
-export const dropdownIcon = style({
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- height: 40,
- width: 40,
- borderRadius: '50%',
-})
-
-export const menuShadow = styleVariants({
- blue: {
- boxShadow: ' 0px 4px 30px rgba(0, 97, 255, 0.25)',
- },
- purple: {
- boxShadow: ' 0px 4px 30px rgba(106, 46, 160, 0.25)',
- },
- darkBlue: {
- boxShadow: ' 0px 4px 30px rgba(0, 0, 60, 0.25)',
- },
-})
-
-export const transition = style({
- opacity: 0,
- transition: 'opacity 150ms ease-in-out',
- selectors: {
- '&[data-enter]': {
- opacity: 1,
- },
- },
-})
-const stretchKeyframe = keyframes({
- '0%': {
- transform: 'scaleX(0)',
- },
- '100%': {
- transform: 'scaleX(1)',
- },
-})
-export const menuDialog = style({
- '::before': {
- content: '',
- position: 'absolute',
- top: 0,
- bottom: -1,
- zIndex: -1,
- left: `-${theme.spacing[2]}px`,
- right: `-${theme.spacing[2]}px`,
- background: theme.color.blue100,
- borderBottom: `1px solid ${theme.color.blue200}`,
- animation: `${stretchKeyframe} 0.35s ease-in-out`,
- },
-})
-
-export const mobileNav = style({
- zIndex: 1500,
- opacity: 1,
- backgroundColor: theme.color.blue100,
- height: '100%',
-})
-
-export const shakeKeyframe = keyframes({
- from: {
- transform: 'translateX(0)',
- },
- '25%': {
- transform: 'translateX(-1px)',
- },
- '45%': {
- transform: 'translateX(1px)',
- },
- '55%': {
- transform: 'translateX(-1px)',
- },
- '75%': {
- transform: 'translateX(1px)',
- },
- to: {
- transform: 'translateX(0)',
- },
-})
-
-export const shake = style({
- animation: `${shakeKeyframe} 0.5s`,
-})
diff --git a/libs/portals/my-pages/core/src/components/Navigation/Navigation.tsx b/libs/portals/my-pages/core/src/components/Navigation/Navigation.tsx
deleted file mode 100644
index d5e33451c180..000000000000
--- a/libs/portals/my-pages/core/src/components/Navigation/Navigation.tsx
+++ /dev/null
@@ -1,698 +0,0 @@
-import React, {
- FC,
- useState,
- useEffect,
- ReactNode,
- createContext,
- ReactElement,
- useRef,
-} from 'react'
-import cn from 'classnames'
-import AnimateHeight from 'react-animate-height'
-import { useMenuState, Menu, MenuButton, MenuStateReturn } from 'reakit/Menu'
-import { theme, Colors } from '@island.is/island-ui/theme'
-import {
- Text,
- Box,
- BoxProps,
- FocusableBox,
- Icon,
- IconProps,
- ModalBase,
- VisuallyHidden,
-} from '@island.is/island-ui/core'
-
-import * as styles from './Navigation.css'
-
-type NavigationContextProps = {
- baseId: string
- activeAccordions: Array
- toggleAccordion: (id: string) => void
-}
-
-export const NavigationContext = createContext({
- baseId: '',
- activeAccordions: [],
- toggleAccordion: () => null,
-})
-
-export type NavigationColorAttributes =
- | 'color'
- | 'dividerColor'
- | 'backgroundColor'
- | 'activeColor'
-
-const colorSchemeColors: Record<
- keyof typeof styles.colorScheme,
- Record
-> = {
- blue: {
- color: 'blue600' as Colors,
- dividerColor: 'blue200' as Colors,
- backgroundColor: 'blue100' as Colors,
- activeColor: 'blue400' as Colors,
- },
- darkBlue: {
- color: 'white' as Colors,
- dividerColor: 'blue600' as Colors,
- backgroundColor: 'blue400' as Colors,
- activeColor: 'white' as Colors,
- },
- purple: {
- color: 'purple600' as Colors,
- dividerColor: 'purple200' as Colors,
- backgroundColor: 'purple100' as Colors,
- activeColor: 'purple400' as Colors,
- },
-}
-
-export interface NavigationItem {
- title: string
- href?: string
- active?: boolean
- accordion?: boolean
- items?: NavigationItem[]
- typename?: string
- slug?: string[]
-}
-interface MobileNavigationDialogProps {
- Title: ReactNode
- colorScheme: keyof typeof styles.colorScheme
- items: NavigationItem[]
- renderLink: NavigationTreeProps['renderLink']
- asSpan?: NavigationTreeProps['asSpan']
- isVisible: boolean
- onClick: () => void
- menuState: MenuStateReturn
- mobileNavigationButtonCloseLabel?: string
-}
-
-interface NavigationTreeProps {
- items: NavigationItem[]
- level?: Level
- colorScheme?: keyof typeof styles.colorScheme
- expand?: boolean
- renderLink?: (link: ReactElement, item?: NavigationItem) => ReactNode
- menuState: MenuStateReturn
- linkOnClick?: () => void
- id?: string
- labelId?: string
- asSpan?: boolean
-}
-
-export interface NavigationProps {
- title: string
- titleIcon?: Pick
- label?: string
- activeItemTitle?: string
- colorScheme?: keyof typeof styles.colorScheme
- /**
- * Keep all child menu items expanded
- */
- expand?: boolean
- /**
- * Only a single acccordion can be expanded at a time
- */
- singleAccordion?: boolean
- isMenuDialog?: boolean
- titleLink?: Pick
- items: NavigationItem[]
- baseId: string
- /**
- * Render function for all links, useful for wrapping framework specific routing links
- */
- renderLink?: NavigationTreeProps['renderLink']
- /**
- * Wrap the link in a instead of a for passing in framework specific routing links
- */
- asSpan?: NavigationTreeProps['asSpan']
- titleProps?: NavigationItem
- mobileNavigationButtonOpenLabel?: string
- mobileNavigationButtonCloseLabel?: string
-}
-
-// The sidebar nav is not designed to show more than 2 levels.
-type Level = keyof typeof styles.level
-
-const MAX_LEVELS = 2
-
-const basePadding = {
- paddingY: 1,
- paddingX: 3,
-} as Pick
-
-const defaultLinkRender: NavigationTreeProps['renderLink'] = (link) => link
-
-const toggleId = (arr: Array = [], id: string, single = false) =>
- arr.includes(id) ? arr.filter((i) => i !== id) : [...(single ? [] : arr), id]
-
-export const Navigation: FC> = ({
- title = 'Efnisyfirlit',
- titleLink,
- titleIcon,
- activeItemTitle,
- label,
- colorScheme = 'blue',
- expand,
- singleAccordion = false,
- renderLink = defaultLinkRender,
- isMenuDialog = false,
- items,
- titleProps,
- baseId,
- asSpan,
- mobileNavigationButtonOpenLabel = 'Open',
- mobileNavigationButtonCloseLabel = 'Close',
-}) => {
- const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
-
- const [activeAccordions, setActiveAccordions] = useState>(
- () => {
- const initialActivePathIndex = items?.findIndex(
- (item) => item.active && item.accordion,
- )
-
- if (initialActivePathIndex > 0) {
- //first level only
- return [
- `1-${items?.findIndex(
- (item) =>
- item.active &&
- item.accordion &&
- item.items?.some((child) => child.active),
- )}`,
- ]
- }
-
- return []
- },
- )
-
- const color = colorSchemeColors[colorScheme]['color']
- const activeColor = colorSchemeColors[colorScheme]['activeColor']
- const backgroundColor = colorSchemeColors[colorScheme]['backgroundColor']
- const dividerColor = colorSchemeColors[colorScheme]['dividerColor']
-
- const menu = useMenuState({
- animated: true,
- baseId,
- visible: false,
- })
-
- useEffect(() => {
- setMobileMenuOpen(menu.visible)
- }, [menu.visible])
-
- const titleLinkProps = titleLink
- ? {
- href: titleLink.href,
- }
- : null
-
- const toggleAccordion = (id: string) => {
- setActiveAccordions(toggleId(activeAccordions, id, singleAccordion))
- }
-
- const Title: MobileNavigationDialogProps['Title'] = titleLinkProps ? (
- renderLink(
-
- {({ isFocused, isHovered }) => {
- const textColor =
- titleLink?.active || isFocused || isHovered ? activeColor : color
-
- return (
- <>
-
- {title}
-
-
- {title}
-
- >
- )
- }}
- ,
- titleProps,
- )
- ) : (
-
-
- {titleIcon && (
-
-
-
- )}
-
- {title}
-
-
-
- )
- const [isScrolled, setIsScrolled] = useState(false)
-
- useEffect(() => {
- const handleScroll = () => {
- const element = document.getElementById('menuDialog-mobile-test')
- if (element) {
- const rect = element.getBoundingClientRect()
-
- setIsScrolled(rect.top === 0)
- }
- }
-
- window.addEventListener('scroll', handleScroll)
- return () => {
- window.removeEventListener('scroll', handleScroll)
- }
- }, [baseId, isScrolled])
-
- return (
-
- {isMenuDialog ? (
-
- ) : (
-
- {Title}
-
-
-
-
-
- )}
-
- )
-}
-
-const MobileNavigationDialog = ({
- Title,
- colorScheme,
- items,
- renderLink,
- onClick,
- menuState,
- asSpan,
- mobileNavigationButtonCloseLabel,
-}: MobileNavigationDialogProps) => {
- return (
-
-
-
- {Title}
-
-
-
- {mobileNavigationButtonCloseLabel}
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-interface MobileButtonProps {
- title: string
- titleIcon?: Pick
- colorScheme: keyof typeof styles.colorScheme
- mobileNavigationButtonOpenLabel?: string
-}
-
-const MobileButton = ({
- title,
- colorScheme,
- titleIcon,
- mobileNavigationButtonOpenLabel,
-}: MobileButtonProps) => {
- const [isShaking, setIsShaking] = useState(false)
- const time = 15000 // 15 seconds
- const idleTimerRef = useRef(null)
-
- useEffect(() => {
- const handleIdle = () => {
- setIsShaking(true)
- setTimeout(() => setIsShaking(false), 1000) // Stop shaking after 1 second
- }
-
- const resetTimer = () => {
- if (idleTimerRef.current) {
- clearTimeout(idleTimerRef.current)
- }
- idleTimerRef.current = setTimeout(handleIdle, time)
- }
-
- resetTimer() // Initialize the timer
-
- window.addEventListener('mousemove', resetTimer)
- window.addEventListener('keydown', resetTimer)
-
- return () => {
- if (idleTimerRef.current) {
- clearTimeout(idleTimerRef.current)
- }
- window.removeEventListener('mousemove', resetTimer)
- window.removeEventListener('keydown', resetTimer)
- }
- }, [])
-
- return (
-
-
- {titleIcon && (
-
-
-
- )}
-
- {title}
-
-
-
-
-
- {mobileNavigationButtonOpenLabel}
-
-
-
-
- )
-}
-
-export const NavigationTree: FC<
- React.PropsWithChildren
-> = ({
- items,
- level = 1,
- colorScheme = 'blue',
- expand = false,
- renderLink = defaultLinkRender,
- menuState,
- linkOnClick,
- id = '',
- labelId = '',
- asSpan,
-}: NavigationTreeProps) => {
- return (
-
- {({ baseId, activeAccordions, toggleAccordion }) => (
- 1
- ? theme.color[colorSchemeColors[colorScheme]['dividerColor']]
- : undefined,
- }}
- >
- {items.map((item, index) => {
- const { title, href, items = [], active, accordion } = item
- const nextLevel: Level = (level + 1) as Level
- const isChildren = level > 1
- const showNextLevel =
- (active || expand) &&
- items.length &&
- nextLevel <= MAX_LEVELS &&
- !accordion
- const isAccordion = !!(
- items.length &&
- nextLevel <= MAX_LEVELS &&
- accordion
- )
- const accordionId = `${level}-${index}`
- const activeAccordion = activeAccordions.includes(accordionId)
- const labelId = `${baseId}-title-${accordionId}`
- const ariaId = `${baseId}-tree-${accordionId}`
-
- const nextLevelTree = (
-
- )
-
- const parentItem = (
- {
- if (linkOnClick && !isAccordion) {
- linkOnClick()
- }
- if (isAccordion) {
- toggleAccordion(accordionId)
- }
- }}
- >
- {({ isFocused, isHovered }) => {
- const textColor =
- active || isFocused || isHovered
- ? colorSchemeColors[colorScheme]['activeColor']
- : colorSchemeColors[colorScheme]['color']
-
- return (
-
-
- {title}
-
-
- )
- }}
-
- )
- return (
-
- {/*Note: Need to review usage (e.g. PortalNavigation) if we change the rendered element to something other than FocusableBox.*/}
- {isAccordion ? parentItem : renderLink(parentItem, item)}
- {isAccordion && (
- {
- toggleAccordion(accordionId)
- }}
- //background={colorSchemeColors[colorScheme]['dividerColor']}
- marginRight={2}
- aria-expanded={activeAccordion}
- aria-controls={ariaId}
- className={cn(
- styles.accordionIcon,
- styles.largerClickableArea,
- )}
- >
-
-
-
- )}
- {isAccordion && (
-
- {nextLevelTree}
-
- )}
- {!!showNextLevel && nextLevelTree}
-
- )
- })}
-
- )}
-
- )
-}
diff --git a/libs/portals/my-pages/core/src/index.ts b/libs/portals/my-pages/core/src/index.ts
index 2742a48abd88..f107e2eea54e 100644
--- a/libs/portals/my-pages/core/src/index.ts
+++ b/libs/portals/my-pages/core/src/index.ts
@@ -48,7 +48,6 @@ export * from './components/StackOrTableBlock/StackOrTableBlock'
export * from './components/IntroWrapper/IntroWrapper'
export * from './components/InstitutionPanel/InstitutionPanel'
export * from './components/MobileTable/MobileTable'
-export * from './components/Navigation/Navigation'
export * from './utils/utils'
export * from './utils/amountFormat'
export * from './utils/numberFormat'