From d8a787fec80b5281cba4a99e07698a3ab3abe9c2 Mon Sep 17 00:00:00 2001 From: Mariela Tihova Date: Tue, 5 Aug 2025 16:56:29 +0300 Subject: [PATCH 1/2] New Headers Implementation (#28) --- src/app/data/icons/exit_full_screen.svg | 16 ++ src/app/data/icons/file_download.svg | 9 +- src/app/data/icons/full_screen.svg | 5 + src/app/data/icons/view_more.svg | 5 + src/app/views/home/home-view.scss | 162 +++++-------- src/app/views/home/home-view.tsx | 310 ++++++++++++++++++------ 6 files changed, 333 insertions(+), 174 deletions(-) create mode 100644 src/app/data/icons/exit_full_screen.svg create mode 100644 src/app/data/icons/full_screen.svg create mode 100644 src/app/data/icons/view_more.svg diff --git a/src/app/data/icons/exit_full_screen.svg b/src/app/data/icons/exit_full_screen.svg new file mode 100644 index 0000000..6fc85fa --- /dev/null +++ b/src/app/data/icons/exit_full_screen.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/data/icons/file_download.svg b/src/app/data/icons/file_download.svg index 2bb823e..39005de 100644 --- a/src/app/data/icons/file_download.svg +++ b/src/app/data/icons/file_download.svg @@ -1 +1,8 @@ - \ No newline at end of file + + + + diff --git a/src/app/data/icons/full_screen.svg b/src/app/data/icons/full_screen.svg new file mode 100644 index 0000000..db8e4f7 --- /dev/null +++ b/src/app/data/icons/full_screen.svg @@ -0,0 +1,5 @@ + + + diff --git a/src/app/data/icons/view_more.svg b/src/app/data/icons/view_more.svg new file mode 100644 index 0000000..65c149d --- /dev/null +++ b/src/app/data/icons/view_more.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/app/views/home/home-view.scss b/src/app/views/home/home-view.scss index c3e569e..cc534a9 100644 --- a/src/app/views/home/home-view.scss +++ b/src/app/views/home/home-view.scss @@ -28,15 +28,14 @@ .tab-container { width: 100%; - min-height: 132px; overflow: hidden; flex-shrink: 0; - padding: 16px; display: flex; flex-direction: row; justify-content: space-between; background-color: var(--ig-surface-500); box-sizing: border-box; + & a { text-decoration: none; display: block; @@ -47,29 +46,31 @@ .tab-item-container { width: 100%; - height: 100%; + height: 72px; display: inline-flex; } .tab-item { + align-items: center; height: 100%; display: flex; flex-grow: 1; flex-basis: 0; - flex-direction: column; - justify-content: space-between; + flex-direction: row; + justify-content: center; gap: 8px; padding: 12px; cursor: pointer; user-select: none; - border-bottom: 1px solid var(--ig-gray-300); + color: black; &--selected { border-bottom: 3px solid var(--ig-primary-500); + color: var(--ig-primary-500); } &:hover { - background: hsl(from var(--ig-gray-100) h s l/0.5); + background-color: var(--ig-gray-200); } } @@ -77,118 +78,75 @@ display: flex; flex-direction: row; gap: 8px; - color: var(--ig-gray-900); - font-size: 20px; + font-size: 16px; font-weight: 600; - line-height: 24px; + line-height: 20px; letter-spacing: 0.15px; --ig-size: var(--ig-size-medium); - - &--disabled { - color: var(--ig-gray-700) !important; - } } -.tab-content { +.current-tab-info { display: flex; - flex-direction: column; - gap: 4px; - color: var(--ig-gray-900); - font-size: 14px; - font-weight: 400; - font-family: "aktiv-grotesk", sans-serif; - line-height: 20px; - letter-spacing: 0.25px; - - &--disabled { - color: var(--ig-gray-700) !important; - } -} - -.tab-actions { - display: flex; - flex-direction: row; - align-items: center; justify-content: space-between; - --ig-size: var(--ig-size-small); - --disabled-icon-color: #ffffff; - - igc-icon-button.button--disabled::part(base) { - background-color: var(--ig-gray-600); - color: #ffffff; - &:hover { - background-color: var(--ig-gray-800); - } + gap: 2rem; + width: 100%; + height: 90px; + padding: 20px 24px; + border: 1px solid #D6D6D6; + + .sample-info { + height: 58px; + display: flex; + flex-direction: column; + row-gap: 8px; } - igc-icon-button.button--enabled::part(base) { - background-color: #212121; - color: #ffffff; - &:hover { - background-color: var(--ig-gray-600); - } + .tab-description { + font-weight: 300; + font-size: 12px; + line-height: 100%; + letter-spacing: 0%; } - .learn-text { - text-decoration: none; - color: var(--ig-primary-500); + .sample-actions { + display: flex; + gap: 16px; + align-items: center; + line-height: 100%; font-size: 14px; - font-weight: 700; - font-family: "aktiv-grotesk", sans-serif; - line-height: 20px; - - width: unset; - padding-bottom: 2px; - transition: background-size 350ms; - background: linear-gradient(0deg, var(--bg-color), var(--bg-color)) no-repeat right bottom / 0 var(--bg-h); - --bg-h: 2px; - --bg-color: var(--ig-primary-500); - - &:where(:hover, :focus-visible) { - background-size: 100% var(--bg-h); - background-position-x: left; + + .theme-info { + display: flex; + flex-direction: column; + justify-content: center; + font-weight: 600; + letter-spacing: 0.15px; + height: 40px; + padding-right: 16px; + border-right: 1px solid #D6D6D6; } - &.link--disabled { - color: var(--ig-primary-200); - --bg-color: var(--ig-primary-200); + .action-buttons { + display: flex; + justify-content: space-between; + gap: 16px; + + .custom-button::part(base) { + color: black; + border-color: #D6D6D6; + text-transform: unset; - &:hover { - color: var(--ig-primary-500); - --bg-color: var(--ig-primary-500); + igc-icon::part(icon) { + color: black; + } } } } } -.tooltip { - position: relative; - display: inline-block; - - & .tooltip--text { - visibility: hidden; - background: #85888fe6; - box-shadow: rgba(36, 37, 44, 0.2) 0px 2px 2px 0px; - color: white; - padding: 4px 8px; - font-size: .625rem; - border-radius: 4px; - min-height: 24px; - top: 100%; - left: 50%; - width: 120px; - transform: translateX(-50%) translateY(5px); - text-align: center; - position: absolute; - z-index: 1; - font-family: var(--ig-font-family); - opacity: 0; - transition: opacity 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); - } - &:hover > .tooltip--text { - opacity: 1; - transform: translateX(-50%) translateY(0); - visibility: visible; - transition-delay: 1s; - } -} +:-webkit-full-screen { + width: 100vw; + height: 100vh; + overflow: auto; + background: white; +} \ No newline at end of file diff --git a/src/app/views/home/home-view.tsx b/src/app/views/home/home-view.tsx index 3cf3045..79e7ad7 100644 --- a/src/app/views/home/home-view.tsx +++ b/src/app/views/home/home-view.tsx @@ -1,141 +1,309 @@ -import { useEffect, useState } from 'react'; -import { NavLink, useLocation } from 'react-router-dom'; -import { IgrChip, IgrIcon, IgrIconButton, IgrRipple, registerIcon } from 'igniteui-react'; -import 'igniteui-react-grids/grids/themes/light/material.css'; -import './home-view.scss'; +import { useEffect, useRef, useState } from "react"; +import { NavLink, useLocation } from "react-router-dom"; +import { IgrButton, IgrIcon, registerIcon } from "igniteui-react"; +import "igniteui-react-grids/grids/themes/light/material.css"; +import "./home-view.scss"; -import FILE_DOWNLOAD from '../../data/icons/file_download.svg'; +import FILE_DOWNLOAD from "../../data/icons/file_download.svg"; +import VIEW_MORE from "../../data/icons/view_more.svg"; +import FULL_SCREEN from "../../data/icons/full_screen.svg"; +import EXIT_FULL_SCREEN from "../../data/icons/exit_full_screen.svg"; export interface TabInfo { title: string; - theme: string; content: string; + theme: string; + themeMode: string; moreLink: string; downloadLink: string; } interface TabItemProps { - isActive?: boolean, - tabInfo?: TabInfo, + isActive?: boolean; + tabInfo?: TabInfo; } -export function TabItem({isActive, tabInfo}: TabItemProps) { - - function onLinkClick(event: any) { - window.open(tabInfo?.moreLink, "_blank")?.focus(); - event.preventDefault(); - event.stopPropagation(); - } - - function onDownloadClick(event: any) { - const downloadLink = tabInfo?.downloadLink; - window.open(downloadLink, "_blank")?.focus(); - event.preventDefault(); - event.stopPropagation(); - } +interface TabItemInfoProps { + tabName: string; + tabInfo: Map; + isFullscreen: boolean; + onDownloadClick: (event: MouseEvent, tabName: string) => void; + onViewMoreClick: (event: MouseEvent, tabName: string) => void; + onToggleFullscreen: (event: MouseEvent) => void; +} +export function TabItem({ isActive, tabInfo }: TabItemProps) { return (
-
-
- {tabInfo?.title} - {tabInfo?.theme} +
+
+ {tabInfo?.title.toUpperCase()}
-
- {tabInfo?.content} -
-
- Learn more -
- - - - - Download sample. -
+
+
+ ); +} + +export function TabItemInfo({ + tabName, + tabInfo, + isFullscreen, + onDownloadClick, + onViewMoreClick, + onToggleFullscreen, +}: TabItemInfoProps) { + const info = tabInfo.get(tabName); + + return ( +
+
+
{info?.title}
+
{info?.content}
+
+ +
+
Theme: {info?.theme}
+
Mode: {info?.themeMode}
+ +
+ + onDownloadClick(e.nativeEvent as MouseEvent, tabName) + } + > + + Download + + + + onViewMoreClick(e.nativeEvent as MouseEvent, tabName) + } + > + + View More + + + onToggleFullscreen(e.nativeEvent as MouseEvent)} + > + + {isFullscreen ? "Exit Fullscreen" : "Fullscreen"} +
); -}; +} export default function HomeView() { + const tabs = [ + { key: "inventory" }, + { key: "hr-portal" }, + { key: "finance" }, + { key: "sales" }, + { key: "fleet" }, + ]; const tabInfo = new Map([ [ "inventory", { title: "ERP/ Inventory", - theme: "Material Light", - content: "Tracking and managing quantity, location and details of products in stock.", - moreLink: "https://www.infragistics.com/products/ignite-ui-angular/angular/components/hierarchicalgrid/hierarchical-grid", - downloadLink: "https://www.infragistics.com/resources/sample-applications/erp-inventory-sample-app-react", + theme: "Material", + themeMode: "Light", + content: + "Tracking and managing quantity, location and details of products in stock.", + moreLink: + "https://www.infragistics.com/products/ignite-ui-angular/angular/components/hierarchicalgrid/hierarchical-grid", + downloadLink: + "https://www.infragistics.com/resources/sample-applications/erp-inventory-sample-app-react", }, ], [ "hr-portal", { title: "Org Chart/HR Portal", - theme: "Fluent Light", - content: "Displaying company's hierarchical structure and showing employees data.", - moreLink: "https://www.infragistics.com/products/ignite-ui-angular/angular/components/treegrid/tree-grid", - downloadLink: "https://www.infragistics.com/resources/sample-applications/org-charthr-portal-sample-app-react", + theme: "Fluent", + themeMode: "Light", + content: + "Displaying company's hierarchical structure and showing employees data.", + moreLink: + "https://www.infragistics.com/products/ignite-ui-angular/angular/components/treegrid/tree-grid", + downloadLink: + "https://www.infragistics.com/resources/sample-applications/org-charthr-portal-sample-app-react", }, ], [ "finance", { title: "Financial Portfolio", - theme: "Bootstrap Light", - content: "Asset tracking, profit and loss analysis, featuring interactive dynamic charts.", - moreLink: "https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/grid", - downloadLink: "https://www.infragistics.com/resources/sample-applications/financial-portfolio-sample-app-react", + theme: "Bootstrap", + themeMode: "Light", + content: + "Asset tracking, profit and loss analysis, featuring interactive dynamic charts.", + moreLink: + "https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/grid", + downloadLink: + "https://www.infragistics.com/resources/sample-applications/financial-portfolio-sample-app-react", }, ], [ "sales", { title: "Sales Dashboard", - theme: "Indigo Light", - content: "For trend analysis, KPIs and viewing sales summaries by region, product, etc.", - moreLink: "https://www.infragistics.com/products/ignite-ui-angular/angular/components/pivotGrid/pivot-grid", - downloadLink: "https://www.infragistics.com/resources/sample-applications/sales-grid-sample-app-react", + theme: "Indigo", + themeMode: "Light", + content: + "For trend analysis, KPIs and viewing sales summaries by region, product, etc.", + moreLink: + "https://www.infragistics.com/products/ignite-ui-angular/angular/components/pivotGrid/pivot-grid", + downloadLink: + "https://www.infragistics.com/resources/sample-applications/sales-grid-sample-app-react", }, ], [ "fleet", { title: "Fleet Management", - theme: "Material Dark", - content: "A master-detail grid for managing vehicle acquisition, operations, and maintenance.", - moreLink: "https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/master-detail", - downloadLink: "https://www.infragistics.com/resources/sample-applications/fleet-management-sample-app-react", + theme: "Material", + themeMode: "Dark", + content: + "A master-detail grid for managing vehicle acquisition, operations, and maintenance.", + moreLink: + "https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/master-detail", + downloadLink: + "https://www.infragistics.com/resources/sample-applications/fleet-management-sample-app-react", }, ], ]); const location = useLocation(); const [gridView, setGridView] = useState("inventory"); + const [isFullscreen, setIsFullscreen] = useState(false); + const fullscreenRef = useRef(null); useEffect(() => { registerIcon("file_download", FILE_DOWNLOAD, "custom"); + registerIcon("view_more", VIEW_MORE, "custom"); + registerIcon("full_screen", FULL_SCREEN, "custom"); + registerIcon("exit_full_screen", EXIT_FULL_SCREEN, "custom"); }, []); useEffect(() => { setGridView(location.pathname.replace("/home/", "")); }, [location]); + useEffect(() => { + if (typeof window === "undefined" || typeof document === "undefined") + return; + + const onFullscreenChange = () => { + setIsFullscreen(!!document.fullscreenElement); + }; + + const onResize = () => { + const isF11 = + window.innerWidth === screen.width && + window.innerHeight === screen.height; + + setIsFullscreen((prev) => { + if (prev !== isF11) return isF11; + return prev; + }); + }; + + document.addEventListener("fullscreenchange", onFullscreenChange); + window.addEventListener("resize", onResize); + + return () => { + document.removeEventListener("fullscreenchange", onFullscreenChange); + window.removeEventListener("resize", onResize); + }; + }, []); + + const onDownloadClick = (event: MouseEvent, tabName: string) => { + event.preventDefault(); + event.stopPropagation(); + + if (typeof window === "undefined") return; + + const downloadLink = tabInfo.get(tabName)?.downloadLink; + if (downloadLink) { + window.open(downloadLink, "_blank")?.focus(); + } + }; + + const onViewMoreClick = (event: MouseEvent, tabName: string) => { + event.preventDefault(); + event.stopPropagation(); + + if (typeof window === "undefined") return; + + const moreLink = tabInfo.get(tabName)?.moreLink; + if (moreLink) { + window.open(moreLink, "_blank")?.focus(); + } + }; + + const onToggleFullscreen = async () => { + if (typeof document === "undefined") return; + + if (!document.fullscreenElement) { + await fullscreenRef.current?.requestFullscreen?.(); + } else { + await document.exitFullscreen?.(); + } + }; + return ( -
-
- {['inventory', 'hr-portal', 'finance', 'sales', 'fleet'].map(tabName => - - {({ isActive }) => ( - - )} - - )} -
+
+ {!isFullscreen && ( +
+ {tabs.map(({ key }) => ( + + {({ isActive }) => ( + + )} + + ))} +
+ )} + + +
-