From 36d5cf32a0473cd390497259bf30acf7bc9f104d Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Tue, 3 Jun 2025 18:12:55 +0200 Subject: [PATCH 01/15] wip --- .../docs/DesignCompliantExampleSection.md | 3 + .../ObjectPage/ObjectPage.stories.tsx | 15 +- .../src/webComponents/ShellBar/ShellBar.mdx | 37 +- .../ShellBar/ShellBar.stories.tsx | 140 +- patterns/navigation-layout/.gitignore | 24 + patterns/navigation-layout/README.md | 22 + patterns/navigation-layout/eslint.config.mjs | 25 + patterns/navigation-layout/index.html | 18 + patterns/navigation-layout/package-lock.json | 3604 +++++++++++++++++ patterns/navigation-layout/package.json | 33 + patterns/navigation-layout/public/vite.svg | 1 + patterns/navigation-layout/src/App.tsx | 134 + .../src/ClearAllMessageBox.tsx | 13 + patterns/navigation-layout/src/NLShellBar.tsx | 151 + .../src/NLSideNavigation.tsx | 142 + .../src/NotificationsPopover.tsx | 391 ++ patterns/navigation-layout/src/index.css | 7 + patterns/navigation-layout/src/main.tsx | 14 + patterns/navigation-layout/src/vite-env.d.ts | 1 + patterns/navigation-layout/tsconfig.json | 27 + patterns/navigation-layout/tsconfig.node.json | 10 + patterns/navigation-layout/vite.config.ts | 7 + 22 files changed, 4795 insertions(+), 24 deletions(-) create mode 100644 .storybook/docs/DesignCompliantExampleSection.md create mode 100644 patterns/navigation-layout/.gitignore create mode 100644 patterns/navigation-layout/README.md create mode 100644 patterns/navigation-layout/eslint.config.mjs create mode 100644 patterns/navigation-layout/index.html create mode 100644 patterns/navigation-layout/package-lock.json create mode 100644 patterns/navigation-layout/package.json create mode 100644 patterns/navigation-layout/public/vite.svg create mode 100644 patterns/navigation-layout/src/App.tsx create mode 100644 patterns/navigation-layout/src/ClearAllMessageBox.tsx create mode 100644 patterns/navigation-layout/src/NLShellBar.tsx create mode 100644 patterns/navigation-layout/src/NLSideNavigation.tsx create mode 100644 patterns/navigation-layout/src/NotificationsPopover.tsx create mode 100644 patterns/navigation-layout/src/index.css create mode 100644 patterns/navigation-layout/src/main.tsx create mode 100644 patterns/navigation-layout/src/vite-env.d.ts create mode 100644 patterns/navigation-layout/tsconfig.json create mode 100644 patterns/navigation-layout/tsconfig.node.json create mode 100644 patterns/navigation-layout/vite.config.ts diff --git a/.storybook/docs/DesignCompliantExampleSection.md b/.storybook/docs/DesignCompliantExampleSection.md new file mode 100644 index 00000000000..65fdf1c7961 --- /dev/null +++ b/.storybook/docs/DesignCompliantExampleSection.md @@ -0,0 +1,3 @@ +## Design-Compliant Examples + +These examples demonstrate the implementation of design specifications. They primarily illustrate design concepts and mostly do not provide additional functionality. You can reference them to select the appropriate design patterns. diff --git a/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx b/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx index d1ad5383b28..84ee14ea6f8 100644 --- a/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx +++ b/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx @@ -11,7 +11,7 @@ import fullscreenIcon from '@ui5/webcomponents-icons/dist/full-screen.js'; import sunIcon from '@ui5/webcomponents-icons/dist/general-leave-request.js'; import { useRef } from 'react'; import { Toolbar as LegacyToolbar, ToolbarSpacer as LegacyToolbarSpacer } from '../../../../compat/src/index.js'; -import type { ObjectPageDomRef } from '../../index.js'; +import type { ButtonPropTypes, ObjectPageDomRef } from '../../index.js'; import { Bar, Breadcrumbs, @@ -41,6 +41,16 @@ import { ToolbarButton, } from '../../index.js'; import { ObjectPage } from './index.js'; +import { fn } from '@storybook/test'; + +const accessibilityAttributes = { + objectPageAnchorBar: { + expandButton: { + expanded: undefined, + accessibleName: '', + }, + }, +}; const meta = { title: 'Layouts & Floorplans / ObjectPage', @@ -54,11 +64,14 @@ const meta = { accessibilityAttributes: { table: { category: 'Accessibility props' } }, }, args: { + onToggleHeaderArea: fn(), + headerPinned: true, mode: ObjectPageMode.Default, selectedSectionId: 'goals', imageShapeCircle: true, image: SampleImage, style: { height: '700px', maxHeight: '90vh' }, + accessibilityAttributes, footerArea: ( -
+{DesignExamples} -# More Examples +### All Features -
+A comprehensive ShellBar demonstrating all available features including notifications, search, content items, and profile. + + + +### Embedded Back Navigation + +ShellBar with embedded back navigation button in the start area. + + + +### Trial Example + +ShellBar configured for trial environments with trial tags and remaining days indicator. + + + +### Multiple Productive Instances + +ShellBar setup for multiple productive system instances with region indicators. + + + +### Multiple Non-Productive Instances + +ShellBar setup for multiple non-productive system instances with system and region tags. + + + +## More examples -## Open a Popover on ShellBarItem click +### Open a Popover on ShellBarItem click To open a popover with the `ShellBarItem` you can use the `detail.targetRef` property of the `onClick` event. diff --git a/packages/main/src/webComponents/ShellBar/ShellBar.stories.tsx b/packages/main/src/webComponents/ShellBar/ShellBar.stories.tsx index 0006ca55a96..819ddb9c204 100644 --- a/packages/main/src/webComponents/ShellBar/ShellBar.stories.tsx +++ b/packages/main/src/webComponents/ShellBar/ShellBar.stories.tsx @@ -1,9 +1,17 @@ import image from '@sb/demoImages/Person.png'; import type { Meta, StoryObj } from '@storybook/react'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import searchIcon from '@ui5/webcomponents-icons/dist/search.js'; -import { Avatar, Icon, Input, ListItemStandard, ShellBarItem } from '../index'; -import { ShellBar } from './index'; +import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; +import navBackIcon from '@ui5/webcomponents-icons/dist/nav-back.js'; +import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; +import { FlexBox } from '../../components/FlexBox/index.js'; +import { Button } from '../Button/index.js'; +import { Avatar, ShellBarItem, ShellBarSpacer } from '../index.js'; +import { Label } from '../Label/index.js'; +import { ShellBarSearch } from '../ShellBarSearch/index.js'; +import { Switch } from '../Switch/index.js'; +import { Tag } from '../Tag/index.js'; +import { Text } from '../Text/index.js'; +import { ShellBar } from './index.js'; const meta = { title: 'Layouts & Floorplans / ShellBar', @@ -17,26 +25,18 @@ const meta = { startButton: { control: { disable: true } }, }, args: { + primaryTitle: 'Shell Bar', + notificationsCount: '10', + showNotifications: true, logo: SAP Logo, profile: ( - + person-placeholder ), - menuItems: ( - <> - - - - - ), - searchField: } />, - notificationsCount: '10', - primaryTitle: 'Shell Bar', - secondaryTitle: 'Secondary Title', - showNotifications: true, - showProductSwitch: true, - children: , + startButton: + + + } + >
+ } + onClose={closeQuickCreateDialog} + > + Create new item... + + + ); +} + +NLSideNavigation.displayName = 'NLSideNavigation'; diff --git a/patterns/navigation-layout/src/NotificationsPopover.tsx b/patterns/navigation-layout/src/NotificationsPopover.tsx new file mode 100644 index 00000000000..6d1394d328b --- /dev/null +++ b/patterns/navigation-layout/src/NotificationsPopover.tsx @@ -0,0 +1,391 @@ +import { + Avatar, + Bar, + Button, + Menu, + MenuItem, + MessageStrip, + NotificationListItem, + NotificationListGroupItem, + NotificationList, + ResponsivePopover, + Title, + ResponsivePopoverPropTypes, + ResponsivePopoverDomRef, + NotificationListPropTypes, + NotificationListGroupItemPropTypes, + NotificationListItemDomRef, + IllustratedMessage, + MessageBoxPropTypes, +} from '@ui5/webcomponents-react'; +import { forwardRef, useState } from 'react'; +import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; +import NotificationListItemImportance from '@ui5/webcomponents-fiori/dist/types/NotificationListItemImportance.js'; +import AvatarColorScheme from '@ui5/webcomponents/dist/types/AvatarColorScheme.js'; +import '@ui5/webcomponents-fiori/dist/illustrations/NoNotifications.js'; +import { ClearAllMessageBox } from './ClearAllMessageBox.tsx'; + +interface Notification { + id: string; + titleText: string; + importance?: keyof typeof NotificationListItemImportance | NotificationListItemImportance; + footnotes: string[]; + avatarIcon: string; + avatarColorScheme: keyof typeof AvatarColorScheme | AvatarColorScheme; + avatarShape: 'Circle' | 'Square'; + avatarSize: 'XS' | 'S' | 'M' | 'L'; + menuItems: { text: string }[]; + content: string; +} + +interface NotificationsPopoverProps extends ResponsivePopoverPropTypes { + closeNotificationsPopover: () => void; +} + +export const NotificationsPopover = forwardRef((props, ref) => { + const { open, closeNotificationsPopover } = props; + const [notificationsToday, setTodayNotifications] = useState(initialNotificationsToday); + const [notificationsYesterday, setYesterdayNotifications] = useState(initialNotificationsYesterday); + const [groupLoading, setGroupLoading] = useState(false); + const [showMessageStrip, setShowMessageStrip] = useState(false); + const [clearAllOpen, setClearAllOpen] = useState(false); + const [sortMenuOpen, setSortMenuOpen] = useState(false); + + const handleItemClose: NotificationListPropTypes['onItemClose'] = (e) => { + const { id, group } = e.detail.item.dataset; + if (!id || !group) { + return; + } + + if (group === 'today') { + setTodayNotifications((prev) => prev.filter((item) => item.id !== id)); + } else if (group === 'yesterday') { + setYesterdayNotifications((prev) => prev.filter((item) => item.id !== id)); + } + }; + + const handleLoadMore: NotificationListGroupItemPropTypes['onLoadMore'] = (e) => { + if (e.target == e.currentTarget) { + const itemsToLoad = 10; + const nextItems = Array.from({ length: itemsToLoad }).map((_, index) => { + const newIndex = notificationsToday.length + index + 1; + return { + id: `today-${newIndex}`, + titleText: `Loaded Notification ${newIndex}`, + footnotes: ['Auto', new Date().toLocaleTimeString()], + avatarIcon: crmSalesIcon, + avatarColorScheme: AvatarColorScheme.Accent10, + avatarShape: 'Square' as const, + avatarSize: 'XS' as const, + menuItems: [{ text: 'Unsubscribe' }], + content: `This is dynamically loaded notification #${newIndex}.`, + }; + }); + const focusIndex = e.target.items.length; + setGroupLoading(true); + setTimeout(() => { + setTodayNotifications((prev) => [...prev, ...nextItems]); + setGroupLoading(false); + setTimeout(() => { + e.target.items[focusIndex].focus(); + }, 500); + }, 2000); + } + }; + + const handleClearAllClose: MessageBoxPropTypes['onClose'] = (e) => { + if (e === 'OK') { + setTodayNotifications([]); + setYesterdayNotifications([]); + } + setClearAllOpen(false); + }; + + return ( + <> + { + if (e.target === e.currentTarget) { + closeNotificationsPopover(); + } + }} + header={ +
+ Notifications} + endContent={ + <> + + +
+ } + > + {notificationsToday.length > 0 || notificationsYesterday.length > 0 ? ( + + {notificationsToday.length > 0 && ( + + {notificationsToday.map((item) => ( + + } + footnotes={item.footnotes.map((note) => ( + {note} + ))} + menu={ + + {item.menuItems.map((mi) => ( + + ))} + + } + > + {item.content} + + ))} + + )} + + {notificationsYesterday.length > 0 && ( + + {notificationsYesterday.map((item) => ( + + } + footnotes={item.footnotes.map((note) => ( + {note} + ))} + menu={ + + {item.menuItems.map((mi) => ( + + ))} + + } + > + {item.content} + + ))} + + )} + + ) : ( + + )} +
+ + { + setSortMenuOpen(false); + }} + > + + + + + ); +}); + +NotificationsPopover.displayName = 'NotificationsPopover'; + +const initialNotificationsToday: Notification[] = [ + { + id: 'today-1', + titleText: 'Start Your Day with Your Sales Target!', + footnotes: ['Sales', '11:13'], + avatarIcon: crmSalesIcon, + avatarColorScheme: 'Accent10', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: + 'Good morning! Don’t forget your daily sales target is $2,000, which needs to be fulfilled by the end of the business day. Let’s make it a great sales day!', + }, + { + id: 'today-2', + titleText: 'Upcoming Client Meeting Reminder', + importance: 'Important', + footnotes: ['Sales', '11:05'], + avatarIcon: crmSalesIcon, + avatarColorScheme: 'Accent10', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Open in calendar' }, { text: 'Unsubscribe' }], + content: 'You have a client meeting scheduled at 3 PM today with Acme Corp. Location: Zoom - link in calendar.', + }, + { + id: 'today-3', + titleText: 'Follow-Up Needed for Prospect', + footnotes: ['Sales', '11:00'], + avatarIcon: crmSalesIcon, + avatarColorScheme: 'Accent10', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Follow-up meeting' }, { text: 'Unsubscribe' }], + content: 'Reminder to follow up with John Doe from XYZ Ltd. Discuss the proposal sent last week.', + }, + { + id: 'today-4', + titleText: 'Budget Report Submission Deadline Approaching', + importance: 'Important', + footnotes: ['Accountant', '10:15'], + avatarIcon: expenseReportIcon, + avatarColorScheme: 'Accent1', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: 'Reminder: The deadline to submit this quarter’s budget report is this Friday.', + }, + { + id: 'today-5', + titleText: 'Urgent: Expense Claims Pending Your Approval', + importance: 'Important', + footnotes: ['Notification', '09:30'], + avatarIcon: expenseReportIcon, + avatarColorScheme: 'Accent1', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: 'You have 5 pending expense claims awaiting your approval. Please review them by EOD.', + }, + { + id: 'today-6', + titleText: 'Monthly Reconciliation Process Begins Next Week', + footnotes: ['Accountant', '09:30'], + avatarIcon: expenseReportIcon, + avatarColorScheme: 'Accent1', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: 'Just a heads-up that we will begin the financial reconciliation process for this month next Monday.', + }, +]; + +const initialNotificationsYesterday: Notification[] = [ + { + id: 'yesterday-1', + titleText: 'New Sales Lead Assigned', + footnotes: ['Sales', '1 Day'], + avatarIcon: crmSalesIcon, + avatarColorScheme: 'Accent10', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: 'A new lead, Jane Smith from Innovative Tech, has been assigned to you. Contact details in CRM.', + }, + { + id: 'yesterday-2', + titleText: 'Reminder: Submit Your EOD Sales Report', + footnotes: ['Sales', '1 Day'], + avatarIcon: crmSalesIcon, + avatarColorScheme: 'Accent10', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: 'Please submit your end-of-day sales report through the portal before logging off today.', + }, + { + id: 'yesterday-3', + titleText: 'Tax Filing Deadline Reminder', + footnotes: ['Accountant', '1 Day'], + avatarIcon: expenseReportIcon, + avatarColorScheme: 'Accent1', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: 'Reminder: The tax filing deadline for this quarter is approaching in two weeks.', + }, + { + id: 'yesterday-4', + titleText: 'Invoice Processing Completed', + footnotes: ['Notification', '1 Day'], + avatarIcon: expenseReportIcon, + avatarColorScheme: 'Accent1', + avatarShape: 'Square', + avatarSize: 'XS', + menuItems: [{ text: 'Unsubscribe' }], + content: 'All invoices for this month have been successfully processed and payments scheduled.', + }, +]; diff --git a/patterns/navigation-layout/src/index.css b/patterns/navigation-layout/src/index.css new file mode 100644 index 00000000000..8d32d976ed3 --- /dev/null +++ b/patterns/navigation-layout/src/index.css @@ -0,0 +1,7 @@ +body { + margin: 0; + width: 100vw; + height: 100vh; + background: var(--sapBackgroundColor); + font-family: var(--sapFontFamily); +} diff --git a/patterns/navigation-layout/src/main.tsx b/patterns/navigation-layout/src/main.tsx new file mode 100644 index 00000000000..debe19419d9 --- /dev/null +++ b/patterns/navigation-layout/src/main.tsx @@ -0,0 +1,14 @@ +import '@ui5/webcomponents-react/dist/Assets.js'; +import { ThemeProvider } from '@ui5/webcomponents-react'; +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App.tsx'; +import './index.css'; + +createRoot(document.getElementById('root') as HTMLElement).render( + + + + + , +); diff --git a/patterns/navigation-layout/src/vite-env.d.ts b/patterns/navigation-layout/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/patterns/navigation-layout/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/patterns/navigation-layout/tsconfig.json b/patterns/navigation-layout/tsconfig.json new file mode 100644 index 00000000000..8759648762b --- /dev/null +++ b/patterns/navigation-layout/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "skipLibCheck": true, + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "exclude": ["src/**/*.cy.tsx"], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/patterns/navigation-layout/tsconfig.node.json b/patterns/navigation-layout/tsconfig.node.json new file mode 100644 index 00000000000..b4812afe369 --- /dev/null +++ b/patterns/navigation-layout/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts", "cypress.config.ts"] +} diff --git a/patterns/navigation-layout/vite.config.ts b/patterns/navigation-layout/vite.config.ts new file mode 100644 index 00000000000..627a3196243 --- /dev/null +++ b/patterns/navigation-layout/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); From ec5a3dde47beb613f974ae9dd54a9bf6ec550bed Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Wed, 4 Jun 2025 16:31:48 +0200 Subject: [PATCH 02/15] before cleanup --- .../main/src/components/MessageBox/index.tsx | 1 + patterns/navigation-layout/index.html | 4 +- patterns/navigation-layout/public/avatar.png | Bin 0 -> 108908 bytes .../navigation-layout/public/sap-logo.svg | 1 + patterns/navigation-layout/public/vite.svg | 1 - patterns/navigation-layout/src/App.tsx | 31 ---- patterns/navigation-layout/src/NLShellBar.tsx | 90 +++++----- patterns/navigation-layout/src/NLUserMenu.tsx | 116 +++++++++++++ .../src/UserSettingsDialog/AppearanceItem.tsx | 112 +++++++++++++ .../UserSettingsDialog/LanguageRegionItem.tsx | 129 +++++++++++++++ .../src/UserSettingsDialog/MobileItem.tsx | 127 ++++++++++++++ .../NLUserSettingsDialog.tsx | 82 +++++++++ .../src/UserSettingsDialog/ResetItem.tsx | 138 ++++++++++++++++ .../UserSettingsDialog/UserAccountItem.tsx | 156 ++++++++++++++++++ patterns/navigation-layout/src/index.css | 97 +++++++++++ 15 files changed, 1008 insertions(+), 77 deletions(-) create mode 100644 patterns/navigation-layout/public/avatar.png create mode 100644 patterns/navigation-layout/public/sap-logo.svg delete mode 100644 patterns/navigation-layout/public/vite.svg create mode 100644 patterns/navigation-layout/src/NLUserMenu.tsx create mode 100644 patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx create mode 100644 patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx create mode 100644 patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx create mode 100644 patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx create mode 100644 patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx create mode 100644 patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx diff --git a/packages/main/src/components/MessageBox/index.tsx b/packages/main/src/components/MessageBox/index.tsx index 6a1b58d38de..2856dd49b4a 100644 --- a/packages/main/src/components/MessageBox/index.tsx +++ b/packages/main/src/components/MessageBox/index.tsx @@ -49,6 +49,7 @@ export interface MessageBoxPropTypes * Flag whether the Message Box should be opened or closed */ open?: DialogPropTypes['open']; + // todo: add headerText prop and deprecate `titleText` /** * A custom title for the MessageBox. If not present, it will be derived from the `MessageBox` type. */ diff --git a/patterns/navigation-layout/index.html b/patterns/navigation-layout/index.html index e7846caa3e4..72eaa2f2fd5 100644 --- a/patterns/navigation-layout/index.html +++ b/patterns/navigation-layout/index.html @@ -2,7 +2,7 @@ - + UI5 Web Components React - Navigation Layout Page - +
diff --git a/patterns/navigation-layout/public/avatar.png b/patterns/navigation-layout/public/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..7b33e4a7f17a5c8b1820777e4cdd5123e7240434 GIT binary patch literal 108908 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 z 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 z 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ï`0{bs3GTD@ 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 \ No newline at end of file diff --git a/patterns/navigation-layout/public/vite.svg b/patterns/navigation-layout/public/vite.svg deleted file mode 100644 index e7b8dfb1b2a..00000000000 --- a/patterns/navigation-layout/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/patterns/navigation-layout/src/App.tsx b/patterns/navigation-layout/src/App.tsx index c0016d00636..c090fd74bf6 100644 --- a/patterns/navigation-layout/src/App.tsx +++ b/patterns/navigation-layout/src/App.tsx @@ -90,37 +90,6 @@ function App() { sideContent={} mode={mode} > - - - - - - - - - - - -

{contentTitle}
diff --git a/patterns/navigation-layout/src/NLShellBar.tsx b/patterns/navigation-layout/src/NLShellBar.tsx index b6862cbbf74..2900c3e6461 100644 --- a/patterns/navigation-layout/src/NLShellBar.tsx +++ b/patterns/navigation-layout/src/NLShellBar.tsx @@ -1,50 +1,29 @@ +import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; +import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; +import daIcon from '@ui5/webcomponents-icons/dist/da.js'; +import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; +import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; import { Avatar, Button, NavigationLayoutDomRef, ResponsivePopoverDomRef, + SearchItem, SearchScope, ShellBar, ShellBarItem, ShellBarPropTypes, ShellBarSearch, + ShellBarSearchPropTypes, ShellBarSpacer, Tag, Text, ToggleButton, ToggleButtonPropTypes, + UserMenuDomRef, } from '@ui5/webcomponents-react'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; import { Dispatch, SetStateAction, useRef, useState } from 'react'; -import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; +import { NLUserMenu } from './NLUserMenu.tsx'; import { NotificationsPopover } from './NotificationsPopover.tsx'; interface NLShellBarProps extends ShellBarPropTypes { @@ -54,8 +33,10 @@ interface NLShellBarProps extends ShellBarPropTypes { export function NLShellBar(props: NLShellBarProps) { const { setMode, ...rest } = props; const notificationsPopoverRef = useRef(null); + const userMenuRef = useRef(null); const [assistantBtnPressed, setAssistantBtnPressed] = useState(false); const [notificationsPopoverOpen, setNotificationsPopoverOpen] = useState(false); + const [userMenuOpen, setUserMenuOpen] = useState(false); const handleAssistantClick: ToggleButtonPropTypes['onClick'] = (e) => { setAssistantBtnPressed(e.currentTarget!.pressed); @@ -78,6 +59,13 @@ export function NLShellBar(props: NLShellBarProps) { setNotificationsPopoverOpen(false); }; + const handleProfileClick: ShellBarPropTypes['onProfileClick'] = (e) => { + userMenuRef.current!.opener = e.detail.targetRef; + setUserMenuOpen(true); + }; + + const handleSearchScopeChange: ShellBarSearchPropTypes['onScopeChange'] = (e) => {}; + return ( <> } - logo={ - SAP Logo - } + logo={SAP Logo} content={ <> @@ -123,16 +106,27 @@ export function NLShellBar(props: NLShellBarProps) { /> } searchField={ - - - - + + + + + + } + > + {scopeData.map((item) => ( + + ))} } profile={ - {/*todo person placeholder*/} - User Avatar + User Avatar } > @@ -144,8 +138,18 @@ export function NLShellBar(props: NLShellBarProps) { ref={notificationsPopoverRef} closeNotificationsPopover={closeNotificationsPopover} /> + ); } NLShellBar.displayName = 'NLShellBar'; + +const scopeData = [ + { name: 'Laptop', scope: 'products' }, + { name: 'Leave Requests', scope: 'apps' }, + { name: 'Log work', scope: 'apps' }, + { name: 'Manage Products', scope: 'apps' }, + { name: 'Mobile Phones', scope: 'products' }, + { name: 'Tablet', scope: 'products' }, +]; diff --git a/patterns/navigation-layout/src/NLUserMenu.tsx b/patterns/navigation-layout/src/NLUserMenu.tsx new file mode 100644 index 00000000000..758e08be8b0 --- /dev/null +++ b/patterns/navigation-layout/src/NLUserMenu.tsx @@ -0,0 +1,116 @@ +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; +import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; +import { MessageBox, MessageBoxPropTypes, UserMenuDomRef, UserMenuPropTypes } from '@ui5/webcomponents-react'; +import { UserMenu, UserMenuAccount, UserMenuItem, Text } from '@ui5/webcomponents-react'; +import { Dispatch, forwardRef, SetStateAction, useState } from 'react'; +import { NLUserSettingsDialog } from './UserSettingsDialog/NLUserSettingsDialog.tsx'; + +interface NLUserMenuProps extends Pick { + setOpen: Dispatch>; +} + +export const NLUserMenu = forwardRef((props, ref) => { + const { open, setOpen } = props; + const [accountsLoading, setAccountsLoading] = useState(false); + const [selectedAccount, setSelectedAccount] = useState('0'); + const [messageBoxOpen, setMessageBoxOpen] = useState(false); + const [userSettingsOpen, setUserSettingsOpen] = useState(false); + + const handleChangeAccount: UserMenuPropTypes['onChangeAccount'] = (e) => { + setAccountsLoading(true); + setTimeout(() => { + setSelectedAccount(e.detail.selectedAccount.dataset.key!); + setAccountsLoading(false); + }, 1000); + }; + + const handleSignOutClick: UserMenuPropTypes['onSignOutClick'] = (e) => { + e.preventDefault(); + setMessageBoxOpen(true); + }; + + const handleMessageBoxClose: MessageBoxPropTypes['onClose'] = (e) => { + if (e === 'OK') { + console.log('Signed out!'); + setOpen(false); + } + setMessageBoxOpen(false); + }; + + const handleSettingsClick = () => { + setUserSettingsOpen(true); + }; + + return ( + <> + { + setOpen(false); + }} + onAvatarClick={() => { + console.log('Avatar clicked!'); + }} + onManageAccountClick={() => { + console.log('Manage Account clicked!'); + }} + onEditAccountsClick={() => { + console.log('Edit Account clicked!'); + }} + onChangeAccount={handleChangeAccount} + onSignOutClick={handleSignOutClick} + accounts={ + <> + + + + + } + > + + + + + + + + + Are you sure you want to sign out? + + {/* conditionally rendered as the dialog could have a lot of content*/} + {userSettingsOpen && } + + ); +}); + +NLUserMenu.displayName = 'NLUserMenu'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx new file mode 100644 index 00000000000..335b68b697e --- /dev/null +++ b/patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx @@ -0,0 +1,112 @@ +import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import { + Avatar, + Button, + ListItemStandard, + Popover, + Title, + ToggleButton, + List, + Tag, + Text, + Bar, + Dialog, + Link, + Icon, + Label, + Panel, + ComboBox, + ComboBoxItem, + RadioButton, + CheckBox, + Toast, + ShellBar, + ShellBarItem, + ShellBarSearch, + ShellBarSpacer, + SearchItem, + SearchScope, + Menu, + MenuItem, + MessageStrip, + NotificationList, + NotificationListGroupItem, + NotificationListItem, + IllustratedMessage, + NoNotifications, + UserMenu, + UserMenuAccount, + UserMenuItem, + UserSettingsView, + UserSettingsItem, + UserSettingsDialog, + NavigationLayout, + SideNavigation, + SideNavigationItem, + SideNavigationSubItem, + ButtonPropTypes, + UserSettingsItemPropTypes, +} from '@ui5/webcomponents-react'; +import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; +import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; +import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; +import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; +import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; +import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; +import daIcon from '@ui5/webcomponents-icons/dist/da.js'; +import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; +import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; +import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; +import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; +import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; +import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; +import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; +import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; +import addIcon from '@ui5/webcomponents-icons/dist/add.js'; +import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; +import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; +import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; +import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; +import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; +import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; +import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; +import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; +import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import { useState } from 'react'; + +export function AppearanceItem(props) { + return ( + + + + + SAP Morning Horizon + + SAP Evening Horizon + SAP High Contrast Black (SAP Horizon) + SAP High Contrast White (SAP Horizon) + + + Changes applied. + + + + + + + + + ); +} + +AppearanceItem.displayName = 'AppearanceItem'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx new file mode 100644 index 00000000000..617e7e4af06 --- /dev/null +++ b/patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx @@ -0,0 +1,129 @@ +import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import { + Avatar, + Button, + ListItemStandard, + Popover, + Title, + ToggleButton, + List, + Tag, + Text, + Bar, + Dialog, + Link, + Icon, + Label, + Panel, + ComboBox, + ComboBoxItem, + RadioButton, + CheckBox, + Toast, + ShellBar, + ShellBarItem, + ShellBarSearch, + ShellBarSpacer, + SearchItem, + SearchScope, + Menu, + MenuItem, + MessageStrip, + NotificationList, + NotificationListGroupItem, + NotificationListItem, + IllustratedMessage, + NoNotifications, + UserMenu, + UserMenuAccount, + UserMenuItem, + UserSettingsView, + UserSettingsItem, + UserSettingsDialog, + NavigationLayout, + SideNavigation, + SideNavigationItem, + SideNavigationSubItem, + ButtonPropTypes, + UserSettingsItemPropTypes, +} from '@ui5/webcomponents-react'; +import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; +import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; +import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; +import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; +import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; +import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; +import daIcon from '@ui5/webcomponents-icons/dist/da.js'; +import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; +import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; +import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; +import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; +import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; +import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; +import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; +import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; +import addIcon from '@ui5/webcomponents-icons/dist/add.js'; +import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; +import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; +import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; +import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; +import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; +import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; +import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; +import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; +import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import { useState } from 'react'; + +export function LanguageRegionItem({ loading }: Pick) { + return ( + +
+
+ + + + + + + + +
+
+ + MMM d, y +
+
+ + + +
+
+ + + +
+ + + + + } + >
+ ); +} + +LanguageRegionItem.displayName = 'LanguageRegionItem'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx new file mode 100644 index 00000000000..8d32743f2a3 --- /dev/null +++ b/patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx @@ -0,0 +1,127 @@ +import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import { + Avatar, + Button, + ListItemStandard, + Popover, + Title, + ToggleButton, + List, + Tag, + Text, + Bar, + Dialog, + Link, + Icon, + Label, + Panel, + ComboBox, + ComboBoxItem, + RadioButton, + CheckBox, + Toast, + ShellBar, + ShellBarItem, + ShellBarSearch, + ShellBarSpacer, + SearchItem, + SearchScope, + Menu, + MenuItem, + MessageStrip, + NotificationList, + NotificationListGroupItem, + NotificationListItem, + IllustratedMessage, + NoNotifications, + UserMenu, + UserMenuAccount, + UserMenuItem, + UserSettingsView, + UserSettingsItem, + UserSettingsDialog, + NavigationLayout, + SideNavigation, + SideNavigationItem, + SideNavigationSubItem, + ButtonPropTypes, + UserSettingsItemPropTypes, +} from '@ui5/webcomponents-react'; +import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; +import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; +import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; +import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; +import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; +import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; +import daIcon from '@ui5/webcomponents-icons/dist/da.js'; +import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; +import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; +import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; +import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; +import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; +import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; +import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; +import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; +import addIcon from '@ui5/webcomponents-icons/dist/add.js'; +import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; +import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; +import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; +import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; +import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; +import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; +import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; +import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; +import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import { useState } from 'react'; + +export function MobileItem(props) { + const [selectedView, setSelectedView] = useState('primary'); + const [viewText, setViewText] = useState(''); + + const handleMobileBtnClick: ButtonPropTypes['onClick'] = (e) => { + setSelectedView('secondary'); + setViewText(e.target.innerText); + }; + + const handleSelectionChange: UserSettingsItemPropTypes['onSelectionChange'] = (e) => { + setSelectedView('primary'); + // doesn't work - issue created + // setSelectedView(e.detail.view.dataset.view!); + }; + + return ( + + + + + + + Enable access to your site from the SAP Mobile Start application. + + + Scan the QR Code to install the mobile application + + + + } + /> + ); +} + +MobileItem.displayName = 'MobileItem'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx b/patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx new file mode 100644 index 00000000000..a9d564b3ce8 --- /dev/null +++ b/patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx @@ -0,0 +1,82 @@ +import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; +import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; +import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; +import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; +import { + Avatar, + Button, + ButtonPropTypes, + CheckBox, + ComboBox, + ComboBoxItem, + Icon, + Label, + List, + ListItemStandard, + Panel, + RadioButton, + Text, + Title, + Toast, + UserSettingsDialog, + UserSettingsDialogPropTypes, + UserSettingsItem, + UserSettingsView, +} from '@ui5/webcomponents-react'; +import { Dispatch, SetStateAction, useState } from 'react'; +import { AppearanceItem } from './AppearanceItem.tsx'; +import { LanguageRegionItem } from './LanguageRegionItem.tsx'; +import { MobileItem } from './MobileItem.tsx'; +import { ResetItem } from './ResetItem.tsx'; +import { UserAccountItem } from './UserAccountItem.tsx'; + +interface UserSettingsDialogProps extends Pick { + setOpen: Dispatch>; +} + +export function NLUserSettingsDialog({ open, setOpen }: UserSettingsDialogProps) { + const [languageLoading, setLanguageLoading] = useState(false); + const closeDialog = () => { + setOpen(false); + }; + + const handleSelectionChange: UserSettingsDialogPropTypes['onSelectionChange'] = (e) => { + if (e.detail.item?.text === 'Language & Region') { + setLanguageLoading(true); + setTimeout(() => { + setLanguageLoading(false); + }, 1000); + } + }; + + return ( + } + > + + + + + + + + } + /> + + ); +} + +NLUserSettingsDialog.displayName = 'NLUserSettingsDialog'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx new file mode 100644 index 00000000000..1476918f784 --- /dev/null +++ b/patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx @@ -0,0 +1,138 @@ +import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import { + Avatar, + Button, + ListItemStandard, + Popover, + Title, + ToggleButton, + List, + Tag, + Text, + Bar, + Dialog, + Link, + Icon, + Label, + Panel, + ComboBox, + ComboBoxItem, + RadioButton, + CheckBox, + Toast, + ShellBar, + ShellBarItem, + ShellBarSearch, + ShellBarSpacer, + SearchItem, + SearchScope, + Menu, + MenuItem, + MessageStrip, + NotificationList, + NotificationListGroupItem, + NotificationListItem, + IllustratedMessage, + NoNotifications, + UserMenu, + UserMenuAccount, + UserMenuItem, + UserSettingsView, + UserSettingsItem, + UserSettingsDialog, + NavigationLayout, + SideNavigation, + SideNavigationItem, + SideNavigationSubItem, + ButtonPropTypes, + UserSettingsItemPropTypes, +} from '@ui5/webcomponents-react'; +import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; +import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; +import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; +import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; +import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; +import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; +import daIcon from '@ui5/webcomponents-icons/dist/da.js'; +import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; +import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; +import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; +import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; +import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; +import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; +import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; +import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; +import addIcon from '@ui5/webcomponents-icons/dist/add.js'; +import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; +import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; +import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; +import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; +import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; +import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; +import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; +import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; +import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import { Dispatch, SetStateAction, useState } from 'react'; +import { createPortal } from 'react-dom'; + +interface ResetItemProps { + slot?: string; + setUserSettingsDialogOpen: Dispatch>; +} + +export function ResetItem({ slot, setUserSettingsDialogOpen }: ResetItemProps) { + const [toastOpen, setToastOpen] = useState(false); + const [toastText, setToastText] = useState('Changes reset!'); + + const handleReset: ButtonPropTypes['onClick'] = (e) => { + const target = e.currentTarget; + if (target?.dataset.key === 'resetPersonalization') { + setToastText('Changes reset!'); + } else { + setToastText('All changes reset!'); + } + setToastOpen(true); + setUserSettingsDialogOpen(false); + }; + + return ( + <> + + + + + + + + + {createPortal( + { + setToastOpen(false); + }} + > + {toastText} + , + document.body, + )} + + ); +} + +ResetItem.displayName = 'ResetItem'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx new file mode 100644 index 00000000000..8b8442a67d6 --- /dev/null +++ b/patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx @@ -0,0 +1,156 @@ +import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import { + Avatar, + Button, + ListItemStandard, + Popover, + Title, + ToggleButton, + List, + Tag, + Text, + Bar, + Dialog, + Link, + Icon, + Label, + Panel, + ComboBox, + ComboBoxItem, + RadioButton, + CheckBox, + Toast, + ShellBar, + ShellBarItem, + ShellBarSearch, + ShellBarSpacer, + SearchItem, + SearchScope, + Menu, + MenuItem, + MessageStrip, + NotificationList, + NotificationListGroupItem, + NotificationListItem, + IllustratedMessage, + NoNotifications, + UserMenu, + UserMenuAccount, + UserMenuItem, + UserSettingsView, + UserSettingsItem, + UserSettingsDialog, + NavigationLayout, + SideNavigation, + SideNavigationItem, + SideNavigationSubItem, + ButtonPropTypes, + UserSettingsItemPropTypes, + MessageBox, + MessageBoxPropTypes, +} from '@ui5/webcomponents-react'; +import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; +import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; +import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; +import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; +import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; +import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; +import daIcon from '@ui5/webcomponents-icons/dist/da.js'; +import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; +import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; +import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; +import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; +import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; +import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; +import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; +import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; +import addIcon from '@ui5/webcomponents-icons/dist/add.js'; +import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; +import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; +import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; +import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; +import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; +import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; +import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; +import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; +import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import { useState } from 'react'; +import { createPortal } from 'react-dom'; + +export function UserAccountItem(props) { + const [messageBoxOpen, setMessageBoxOpen] = useState(false); + + const handleMessageBoxClose: MessageBoxPropTypes['onClose'] = (action) => { + if (action === 'OK') { + console.log('Personalization was reset successfully!'); + } + setMessageBoxOpen(false); + }; + + return ( + <> + +
+ + Profile + + + Alain Chevalier + +
+ + Alain Chevalier +
+
+ + alian.chevalier@sap.com +
+
+ + delivery-001.sap.com +
+
+ +
+ + + + Reset your personalization settings for the launchpad (such as theme, language, user activities, and + home page content). + + + + } + /> + {createPortal( + + Clicking on reset will delete your personalization settings for the launchpad (e.g. theme, language, user + activities, and home page content) and for apps using the launchpad personalization features (e.g. filter + settings, table columns). This action is irreversible. Further changes in the dialog will not be applied. Are + you sure you want to proceed with the reset? + , + document.body, + )} + + ); +} + +UserAccountItem.displayName = 'UserAccountItem'; diff --git a/patterns/navigation-layout/src/index.css b/patterns/navigation-layout/src/index.css index 8d32d976ed3..01c5bd6b575 100644 --- a/patterns/navigation-layout/src/index.css +++ b/patterns/navigation-layout/src/index.css @@ -5,3 +5,100 @@ body { background: var(--sapBackgroundColor); font-family: var(--sapFontFamily); } + +.sideNavigation:not([collapsed]):not([is-phone]) { + width: 18rem; +} + +.mainContent { + padding: var(--sapContent_Gap); +} + +.quickCreateDialog::part(footer) { + padding-inline: 0; +} + +/* Notifications */ +.notificationsPopover { + width: 27rem; + max-height: 40rem; +} + +.notificationsPopover::part(header) { + padding: 0; + box-shadow: none; +} + +.notificationsPopover::part(content) { + padding: 0; +} + +.notificationsPopoverHeader { + display: flex; + flex: 1; + flex-direction: column; +} + +.notificationsPopoverList { + height: 100%; +} + +.notificationsPopoverBar, +.notificationsPopoverBar::part(bar) { + box-shadow: none; +} + +.notificationsMessageStrip { + display: none; + margin: 0.5rem; + width: auto; +} +/* End notifications */ + +/* User Settings Dialog */ + +.ua-name { + display: inline; + margin: 0.5rem; +} +.container { + display: flex; + flex-direction: column; + gap: 1rem; + margin: 3rem; +} + +.ua-info-profile { + align-self: center; +} + +.ua-info-item { + display: grid; + grid-template-columns: 50px 1fr; + align-items: center; + gap: 16px; +} + +.ua-panel { + border-top: 2px solid lightgrey; + margin: 1rem; +} + +.save-btn { + position: absolute; + bottom: 1rem; +} + +.lr-item { + display: grid; + grid-template-columns: 150px 1fr; + align-items: center; + gap: 16px; +} + +.lt-time-format { + display: flex; + align-items: center; + margin: 0 1rem 0 1rem; +} +/* End User Settings Dialog */ From 154bfcb5ff4f5f889e1ea3f6f5e5d4dfa613881d Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Wed, 4 Jun 2025 16:38:52 +0200 Subject: [PATCH 03/15] eslint --- patterns/navigation-layout/eslint.config.mjs | 2 +- patterns/navigation-layout/src/App.tsx | 77 +---------------- patterns/navigation-layout/src/NLShellBar.tsx | 19 ++--- .../src/NLSideNavigation.tsx | 44 +++------- patterns/navigation-layout/src/NLUserMenu.tsx | 7 +- .../src/NotificationsPopover.tsx | 31 +++---- .../src/UserSettingsDialog/AppearanceItem.tsx | 80 ++---------------- .../UserSettingsDialog/LanguageRegionItem.tsx | 79 ++---------------- .../src/UserSettingsDialog/MobileItem.tsx | 83 +------------------ .../NLUserSettingsDialog.tsx | 31 +------ .../src/UserSettingsDialog/ResetItem.tsx | 83 +------------------ .../UserSettingsDialog/UserAccountItem.tsx | 82 ++---------------- patterns/navigation-layout/src/index.css | 3 + patterns/navigation-layout/vite.config.ts | 2 +- 14 files changed, 77 insertions(+), 546 deletions(-) diff --git a/patterns/navigation-layout/eslint.config.mjs b/patterns/navigation-layout/eslint.config.mjs index cfd81c9345d..33c02ac29ac 100644 --- a/patterns/navigation-layout/eslint.config.mjs +++ b/patterns/navigation-layout/eslint.config.mjs @@ -1,7 +1,7 @@ import js from '@eslint/js'; -import globals from 'globals'; import reactHooks from 'eslint-plugin-react-hooks'; import reactRefresh from 'eslint-plugin-react-refresh'; +import globals from 'globals'; import tseslint from 'typescript-eslint'; export default tseslint.config( diff --git a/patterns/navigation-layout/src/App.tsx b/patterns/navigation-layout/src/App.tsx index c090fd74bf6..9bf924bc057 100644 --- a/patterns/navigation-layout/src/App.tsx +++ b/patterns/navigation-layout/src/App.tsx @@ -1,80 +1,5 @@ -import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; -import { - Avatar, - Button, - ListItemStandard, - Popover, - Title, - ToggleButton, - List, - Tag, - Text, - Bar, - Dialog, - Link, - Icon, - Label, - Panel, - ComboBox, - ComboBoxItem, - RadioButton, - CheckBox, - Toast, - ShellBar, - ShellBarItem, - ShellBarSearch, - ShellBarSpacer, - SearchItem, - SearchScope, - Menu, - MenuItem, - MessageStrip, - NotificationList, - NotificationListGroupItem, - NotificationListItem, - IllustratedMessage, - NoNotifications, - UserMenu, - UserMenuAccount, - UserMenuItem, - UserSettingsView, - UserSettingsItem, - UserSettingsDialog, - NavigationLayout, - SideNavigation, - SideNavigationItem, - SideNavigationSubItem, -} from '@ui5/webcomponents-react'; import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import { NavigationLayout, Text, Title } from '@ui5/webcomponents-react'; import { useState } from 'react'; import { NLShellBar } from './NLShellBar.tsx'; import { NLSideNavigation } from './NLSideNavigation.tsx'; diff --git a/patterns/navigation-layout/src/NLShellBar.tsx b/patterns/navigation-layout/src/NLShellBar.tsx index 2900c3e6461..9c3a92dfed7 100644 --- a/patterns/navigation-layout/src/NLShellBar.tsx +++ b/patterns/navigation-layout/src/NLShellBar.tsx @@ -3,26 +3,28 @@ import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; import daIcon from '@ui5/webcomponents-icons/dist/da.js'; import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; +import type { + NavigationLayoutDomRef, + ResponsivePopoverDomRef, + ShellBarPropTypes, + ToggleButtonPropTypes, + UserMenuDomRef, +} from '@ui5/webcomponents-react'; import { Avatar, Button, - NavigationLayoutDomRef, - ResponsivePopoverDomRef, SearchItem, SearchScope, ShellBar, ShellBarItem, - ShellBarPropTypes, ShellBarSearch, - ShellBarSearchPropTypes, ShellBarSpacer, Tag, Text, ToggleButton, - ToggleButtonPropTypes, - UserMenuDomRef, } from '@ui5/webcomponents-react'; -import { Dispatch, SetStateAction, useRef, useState } from 'react'; +import type { Dispatch, SetStateAction } from 'react'; +import { useRef, useState } from 'react'; import { NLUserMenu } from './NLUserMenu.tsx'; import { NotificationsPopover } from './NotificationsPopover.tsx'; @@ -64,8 +66,6 @@ export function NLShellBar(props: NLShellBarProps) { setUserMenuOpen(true); }; - const handleSearchScopeChange: ShellBarSearchPropTypes['onScopeChange'] = (e) => {}; - return ( <> diff --git a/patterns/navigation-layout/src/NLSideNavigation.tsx b/patterns/navigation-layout/src/NLSideNavigation.tsx index 99985055de5..cd53939ec3e 100644 --- a/patterns/navigation-layout/src/NLSideNavigation.tsx +++ b/patterns/navigation-layout/src/NLSideNavigation.tsx @@ -1,44 +1,24 @@ +import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; +import addIcon from '@ui5/webcomponents-icons/dist/add.js'; +import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; +import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; +import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; +import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; +import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; +import type { SideNavigationPropTypes } from '@ui5/webcomponents-react'; import { Bar, Button, Dialog, SideNavigation, SideNavigationItem, - SideNavigationPropTypes, SideNavigationSubItem, Text, } from '@ui5/webcomponents-react'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; -import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; -import { Dispatch, SetStateAction, useState } from 'react'; +import type { Dispatch, SetStateAction } from 'react'; +import { useState } from 'react'; interface NLSideNavigationProps extends SideNavigationPropTypes { setContentTitle: Dispatch>; diff --git a/patterns/navigation-layout/src/NLUserMenu.tsx b/patterns/navigation-layout/src/NLUserMenu.tsx index 758e08be8b0..9bc86a66eb7 100644 --- a/patterns/navigation-layout/src/NLUserMenu.tsx +++ b/patterns/navigation-layout/src/NLUserMenu.tsx @@ -1,9 +1,10 @@ import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import { MessageBox, MessageBoxPropTypes, UserMenuDomRef, UserMenuPropTypes } from '@ui5/webcomponents-react'; -import { UserMenu, UserMenuAccount, UserMenuItem, Text } from '@ui5/webcomponents-react'; -import { Dispatch, forwardRef, SetStateAction, useState } from 'react'; +import type { MessageBoxPropTypes, UserMenuDomRef, UserMenuPropTypes } from '@ui5/webcomponents-react'; +import { MessageBox, Text, UserMenu, UserMenuAccount, UserMenuItem } from '@ui5/webcomponents-react'; +import type { Dispatch, SetStateAction } from 'react'; +import { forwardRef, useState } from 'react'; import { NLUserSettingsDialog } from './UserSettingsDialog/NLUserSettingsDialog.tsx'; interface NLUserMenuProps extends Pick { diff --git a/patterns/navigation-layout/src/NotificationsPopover.tsx b/patterns/navigation-layout/src/NotificationsPopover.tsx index 6d1394d328b..d31b72c6605 100644 --- a/patterns/navigation-layout/src/NotificationsPopover.tsx +++ b/patterns/navigation-layout/src/NotificationsPopover.tsx @@ -1,30 +1,31 @@ +import AvatarColorScheme from '@ui5/webcomponents/dist/types/AvatarColorScheme.js'; +import type NotificationListItemImportance from '@ui5/webcomponents-fiori/dist/types/NotificationListItemImportance.js'; +import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; +import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; +import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; +import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; +import type { + MessageBoxPropTypes, + NotificationListGroupItemPropTypes, + NotificationListPropTypes, + ResponsivePopoverDomRef, + ResponsivePopoverPropTypes, +} from '@ui5/webcomponents-react'; import { Avatar, Bar, Button, + IllustratedMessage, Menu, MenuItem, MessageStrip, - NotificationListItem, - NotificationListGroupItem, NotificationList, + NotificationListGroupItem, + NotificationListItem, ResponsivePopover, Title, - ResponsivePopoverPropTypes, - ResponsivePopoverDomRef, - NotificationListPropTypes, - NotificationListGroupItemPropTypes, - NotificationListItemDomRef, - IllustratedMessage, - MessageBoxPropTypes, } from '@ui5/webcomponents-react'; import { forwardRef, useState } from 'react'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import NotificationListItemImportance from '@ui5/webcomponents-fiori/dist/types/NotificationListItemImportance.js'; -import AvatarColorScheme from '@ui5/webcomponents/dist/types/AvatarColorScheme.js'; import '@ui5/webcomponents-fiori/dist/illustrations/NoNotifications.js'; import { ClearAllMessageBox } from './ClearAllMessageBox.tsx'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx index 335b68b697e..0c238601c8b 100644 --- a/patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx +++ b/patterns/navigation-layout/src/UserSettingsDialog/AppearanceItem.tsx @@ -1,85 +1,17 @@ -import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; import { - Avatar, Button, - ListItemStandard, - Popover, - Title, - ToggleButton, - List, - Tag, - Text, - Bar, - Dialog, - Link, - Icon, + CheckBox, Label, + List, + ListItemStandard, Panel, - ComboBox, - ComboBoxItem, - RadioButton, - CheckBox, Toast, - ShellBar, - ShellBarItem, - ShellBarSearch, - ShellBarSpacer, - SearchItem, - SearchScope, - Menu, - MenuItem, - MessageStrip, - NotificationList, - NotificationListGroupItem, - NotificationListItem, - IllustratedMessage, - NoNotifications, - UserMenu, - UserMenuAccount, - UserMenuItem, - UserSettingsView, UserSettingsItem, - UserSettingsDialog, - NavigationLayout, - SideNavigation, - SideNavigationItem, - SideNavigationSubItem, - ButtonPropTypes, - UserSettingsItemPropTypes, + UserSettingsView, } from '@ui5/webcomponents-react'; -import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; -import { useState } from 'react'; -export function AppearanceItem(props) { +export function AppearanceItem() { return ( diff --git a/patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx index 617e7e4af06..75a9047f77f 100644 --- a/patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx +++ b/patterns/navigation-layout/src/UserSettingsDialog/LanguageRegionItem.tsx @@ -1,83 +1,14 @@ -import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import type { UserSettingsItemPropTypes } from '@ui5/webcomponents-react'; import { - Avatar, - Button, - ListItemStandard, - Popover, - Title, - ToggleButton, - List, - Tag, - Text, - Bar, - Dialog, - Link, - Icon, - Label, - Panel, ComboBox, ComboBoxItem, + Label, + Panel, RadioButton, - CheckBox, - Toast, - ShellBar, - ShellBarItem, - ShellBarSearch, - ShellBarSpacer, - SearchItem, - SearchScope, - Menu, - MenuItem, - MessageStrip, - NotificationList, - NotificationListGroupItem, - NotificationListItem, - IllustratedMessage, - NoNotifications, - UserMenu, - UserMenuAccount, - UserMenuItem, - UserSettingsView, + Text, UserSettingsItem, - UserSettingsDialog, - NavigationLayout, - SideNavigation, - SideNavigationItem, - SideNavigationSubItem, - ButtonPropTypes, - UserSettingsItemPropTypes, + UserSettingsView, } from '@ui5/webcomponents-react'; -import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; -import { useState } from 'react'; export function LanguageRegionItem({ loading }: Pick) { return ( diff --git a/patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx index 8d32743f2a3..d8bd13ecf60 100644 --- a/patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx +++ b/patterns/navigation-layout/src/UserSettingsDialog/MobileItem.tsx @@ -1,85 +1,10 @@ -import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; -import { - Avatar, - Button, - ListItemStandard, - Popover, - Title, - ToggleButton, - List, - Tag, - Text, - Bar, - Dialog, - Link, - Icon, - Label, - Panel, - ComboBox, - ComboBoxItem, - RadioButton, - CheckBox, - Toast, - ShellBar, - ShellBarItem, - ShellBarSearch, - ShellBarSpacer, - SearchItem, - SearchScope, - Menu, - MenuItem, - MessageStrip, - NotificationList, - NotificationListGroupItem, - NotificationListItem, - IllustratedMessage, - NoNotifications, - UserMenu, - UserMenuAccount, - UserMenuItem, - UserSettingsView, - UserSettingsItem, - UserSettingsDialog, - NavigationLayout, - SideNavigation, - SideNavigationItem, - SideNavigationSubItem, - ButtonPropTypes, - UserSettingsItemPropTypes, -} from '@ui5/webcomponents-react'; -import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; +import type { ButtonPropTypes, UserSettingsItemPropTypes } from '@ui5/webcomponents-react'; +import { Button, Icon, Text, UserSettingsItem, UserSettingsView } from '@ui5/webcomponents-react'; import { useState } from 'react'; -export function MobileItem(props) { +export function MobileItem() { const [selectedView, setSelectedView] = useState('primary'); const [viewText, setViewText] = useState(''); @@ -88,7 +13,7 @@ export function MobileItem(props) { setViewText(e.target.innerText); }; - const handleSelectionChange: UserSettingsItemPropTypes['onSelectionChange'] = (e) => { + const handleSelectionChange: UserSettingsItemPropTypes['onSelectionChange'] = () => { setSelectedView('primary'); // doesn't work - issue created // setSelectedView(e.detail.view.dataset.view!); diff --git a/patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx b/patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx index a9d564b3ce8..fe44cef0fad 100644 --- a/patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx +++ b/patterns/navigation-layout/src/UserSettingsDialog/NLUserSettingsDialog.tsx @@ -1,31 +1,8 @@ import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import { - Avatar, - Button, - ButtonPropTypes, - CheckBox, - ComboBox, - ComboBoxItem, - Icon, - Label, - List, - ListItemStandard, - Panel, - RadioButton, - Text, - Title, - Toast, - UserSettingsDialog, - UserSettingsDialogPropTypes, - UserSettingsItem, - UserSettingsView, -} from '@ui5/webcomponents-react'; -import { Dispatch, SetStateAction, useState } from 'react'; +import type { UserSettingsDialogPropTypes } from '@ui5/webcomponents-react'; +import { CheckBox, UserSettingsDialog, UserSettingsItem, UserSettingsView } from '@ui5/webcomponents-react'; +import type { Dispatch, SetStateAction } from 'react'; +import { useState } from 'react'; import { AppearanceItem } from './AppearanceItem.tsx'; import { LanguageRegionItem } from './LanguageRegionItem.tsx'; import { MobileItem } from './MobileItem.tsx'; diff --git a/patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx index 1476918f784..e89842e2d97 100644 --- a/patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx +++ b/patterns/navigation-layout/src/UserSettingsDialog/ResetItem.tsx @@ -1,83 +1,8 @@ -import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; -import { - Avatar, - Button, - ListItemStandard, - Popover, - Title, - ToggleButton, - List, - Tag, - Text, - Bar, - Dialog, - Link, - Icon, - Label, - Panel, - ComboBox, - ComboBoxItem, - RadioButton, - CheckBox, - Toast, - ShellBar, - ShellBarItem, - ShellBarSearch, - ShellBarSpacer, - SearchItem, - SearchScope, - Menu, - MenuItem, - MessageStrip, - NotificationList, - NotificationListGroupItem, - NotificationListItem, - IllustratedMessage, - NoNotifications, - UserMenu, - UserMenuAccount, - UserMenuItem, - UserSettingsView, - UserSettingsItem, - UserSettingsDialog, - NavigationLayout, - SideNavigation, - SideNavigationItem, - SideNavigationSubItem, - ButtonPropTypes, - UserSettingsItemPropTypes, -} from '@ui5/webcomponents-react'; -import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; -import { Dispatch, SetStateAction, useState } from 'react'; +import type { ButtonPropTypes } from '@ui5/webcomponents-react'; +import { Button, Toast, UserSettingsItem, UserSettingsView } from '@ui5/webcomponents-react'; +import type { Dispatch, SetStateAction } from 'react'; +import { useState } from 'react'; import { createPortal } from 'react-dom'; interface ResetItemProps { diff --git a/patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx b/patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx index 8b8442a67d6..a2a0ef530e1 100644 --- a/patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx +++ b/patterns/navigation-layout/src/UserSettingsDialog/UserAccountItem.tsx @@ -1,88 +1,20 @@ -import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; +import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; +import type { MessageBoxPropTypes } from '@ui5/webcomponents-react'; import { Avatar, Button, - ListItemStandard, - Popover, - Title, - ToggleButton, - List, - Tag, - Text, - Bar, - Dialog, - Link, - Icon, Label, + MessageBox, Panel, - ComboBox, - ComboBoxItem, - RadioButton, - CheckBox, - Toast, - ShellBar, - ShellBarItem, - ShellBarSearch, - ShellBarSpacer, - SearchItem, - SearchScope, - Menu, - MenuItem, - MessageStrip, - NotificationList, - NotificationListGroupItem, - NotificationListItem, - IllustratedMessage, - NoNotifications, - UserMenu, - UserMenuAccount, - UserMenuItem, - UserSettingsView, + Text, + Title, UserSettingsItem, - UserSettingsDialog, - NavigationLayout, - SideNavigation, - SideNavigationItem, - SideNavigationSubItem, - ButtonPropTypes, - UserSettingsItemPropTypes, - MessageBox, - MessageBoxPropTypes, + UserSettingsView, } from '@ui5/webcomponents-react'; -import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; -import globeIcon from '@ui5/webcomponents-icons/dist/globe.js'; -import collaborateIcon from '@ui5/webcomponents-icons/dist/collaborate.js'; -import officialServiceIcon from '@ui5/webcomponents-icons/dist/official-service.js'; -import privateIcon from '@ui5/webcomponents-icons/dist/private.js'; -import acceleratedIcon from '@ui5/webcomponents-icons/dist/accelerated.js'; -import daIcon from '@ui5/webcomponents-icons/dist/da.js'; -import da2Icon from '@ui5/webcomponents-icons/dist/da-2.js'; -import menu2Icon from '@ui5/webcomponents-icons/dist/menu2.js'; -import settingsIcon from '@ui5/webcomponents-icons/dist/settings.js'; -import sysHelpIcon from '@ui5/webcomponents-icons/dist/sys-help.js'; -import homeIcon from '@ui5/webcomponents-icons/dist/home.js'; -import favoriteListIcon from '@ui5/webcomponents-icons/dist/favorite-list.js'; -import accountIcon from '@ui5/webcomponents-icons/dist/account.js'; -import businessByDesignIcon from '@ui5/webcomponents-icons/dist/business-by-design.js'; -import crmSalesIcon from '@ui5/webcomponents-icons/dist/crm-sales.js'; -import s4hanaIcon from '@ui5/webcomponents-icons/dist/s4hana.js'; -import addIcon from '@ui5/webcomponents-icons/dist/add.js'; -import managerInsightIcon from '@ui5/webcomponents-icons/dist/manager-insight.js'; -import actionSettingsIcon from '@ui5/webcomponents-icons/dist/action-settings.js'; -import sortIcon from '@ui5/webcomponents-icons/dist/sort.js'; -import messageInformationIcon from '@ui5/webcomponents-icons/dist/message-information.js'; -import expenseReportIcon from '@ui5/webcomponents-icons/dist/expense-report.js'; -import userSettingsIcon from '@ui5/webcomponents-icons/dist/user-settings.js'; -import personPlaceholderIcon from '@ui5/webcomponents-icons/dist/person-placeholder.js'; -import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; -import iphoneIcon from '@ui5/webcomponents-icons/dist/iphone.js'; -import qrCodeIcon from '@ui5/webcomponents-icons/dist/qr-code.js'; -import bellIcon from '@ui5/webcomponents-icons/dist/bell.js'; -import resetIcon from '@ui5/webcomponents-icons/dist/reset.js'; import { useState } from 'react'; import { createPortal } from 'react-dom'; -export function UserAccountItem(props) { +export function UserAccountItem() { const [messageBoxOpen, setMessageBoxOpen] = useState(false); const handleMessageBoxClose: MessageBoxPropTypes['onClose'] = (action) => { diff --git a/patterns/navigation-layout/src/index.css b/patterns/navigation-layout/src/index.css index 01c5bd6b575..ccb9c0a483d 100644 --- a/patterns/navigation-layout/src/index.css +++ b/patterns/navigation-layout/src/index.css @@ -53,6 +53,7 @@ body { margin: 0.5rem; width: auto; } + /* End notifications */ /* User Settings Dialog */ @@ -61,6 +62,7 @@ body { display: inline; margin: 0.5rem; } + .container { display: flex; flex-direction: column; @@ -101,4 +103,5 @@ body { align-items: center; margin: 0 1rem 0 1rem; } + /* End User Settings Dialog */ diff --git a/patterns/navigation-layout/vite.config.ts b/patterns/navigation-layout/vite.config.ts index 627a3196243..4e7004ebc6b 100644 --- a/patterns/navigation-layout/vite.config.ts +++ b/patterns/navigation-layout/vite.config.ts @@ -1,5 +1,5 @@ -import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; // https://vitejs.dev/config/ export default defineConfig({ From 2973c2ed69ae4d811c7e7a3e713651cf1b72844b Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Wed, 4 Jun 2025 16:39:47 +0200 Subject: [PATCH 04/15] revert changes in ObjectPage story --- .../components/ObjectPage/ObjectPage.stories.tsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx b/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx index 84ee14ea6f8..d1ad5383b28 100644 --- a/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx +++ b/packages/main/src/components/ObjectPage/ObjectPage.stories.tsx @@ -11,7 +11,7 @@ import fullscreenIcon from '@ui5/webcomponents-icons/dist/full-screen.js'; import sunIcon from '@ui5/webcomponents-icons/dist/general-leave-request.js'; import { useRef } from 'react'; import { Toolbar as LegacyToolbar, ToolbarSpacer as LegacyToolbarSpacer } from '../../../../compat/src/index.js'; -import type { ButtonPropTypes, ObjectPageDomRef } from '../../index.js'; +import type { ObjectPageDomRef } from '../../index.js'; import { Bar, Breadcrumbs, @@ -41,16 +41,6 @@ import { ToolbarButton, } from '../../index.js'; import { ObjectPage } from './index.js'; -import { fn } from '@storybook/test'; - -const accessibilityAttributes = { - objectPageAnchorBar: { - expandButton: { - expanded: undefined, - accessibleName: '', - }, - }, -}; const meta = { title: 'Layouts & Floorplans / ObjectPage', @@ -64,14 +54,11 @@ const meta = { accessibilityAttributes: { table: { category: 'Accessibility props' } }, }, args: { - onToggleHeaderArea: fn(), - headerPinned: true, mode: ObjectPageMode.Default, selectedSectionId: 'goals', imageShapeCircle: true, image: SampleImage, style: { height: '700px', maxHeight: '90vh' }, - accessibilityAttributes, footerArea: ( Date: Wed, 4 Jun 2025 16:42:25 +0200 Subject: [PATCH 05/15] renovate --- .github/renovate.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 22a8b6f8573..36d80b776d5 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -72,21 +72,21 @@ ] }, { - "description": "Example & Template dependencies", + "description": "Example,Template & Pattern dependencies", "extends": ["schedule:weekly"], - "matchFileNames": ["examples/**", "templates/**"], + "matchFileNames": ["examples/**", "templates/**", "patterns/**"], "semanticCommitType": "chore", - "groupName": "all non-major dependencies (examples & templates)", + "groupName": "all non-major dependencies (examples, templates & patterns)", "groupSlug": "examples-all-minor-patch", "matchUpdateTypes": ["minor", "patch"], "matchBaseBranches": ["main"], "matchPackageNames": ["*", "!/^@ui5//"] }, { - "description": "UI5 Web Components (for React) in all examples & templates", - "groupName": "UI5 Web Components React (examples & templates)", + "description": "UI5 Web Components (for React) in all examples, templates & patterns", + "groupName": "UI5 Web Components React (examples, templates & patterns)", "groupSlug": "examples-ui5-webcomponents-react", - "matchFileNames": ["examples/**", "templates/**"], + "matchFileNames": ["examples/**", "templates/**", "patterns/**"], "semanticCommitType": "chore", "matchBaseBranches": ["main"], "matchSourceUrls": [ From d253703972cea8f8611619e115d68a82e5bb9752 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 10:07:54 +0200 Subject: [PATCH 06/15] docs --- .storybook/preview.tsx | 1 + docs/EmbeddedStackBlitz.tsx | 36 ++++++++++++++++++ docs/Patterns.mdx | 11 ++++++ docs/UXCIntegration.tsx | 16 ++++++++ package.json | 1 + patterns/navigation-layout/src/App.tsx | 10 ++++- patterns/navigation-layout/src/NLShellBar.tsx | 6 ++- patterns/navigation-layout/src/NLUserMenu.tsx | 3 +- .../{public => src/assets}/avatar.png | Bin .../{public => src/assets}/sap-logo.svg | 0 patterns/navigation-layout/src/index.css | 3 +- yarn.lock | 8 ++++ 12 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 docs/EmbeddedStackBlitz.tsx create mode 100644 docs/Patterns.mdx create mode 100644 docs/UXCIntegration.tsx rename patterns/navigation-layout/{public => src/assets}/avatar.png (100%) rename patterns/navigation-layout/{public => src/assets}/sap-logo.svg (100%) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 48703f72327..3fd9ca9f5f8 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -144,6 +144,7 @@ const preview: Preview = { 'Knowledge Base', 'Testing with Cypress', ['Setup', 'Commands', 'Queries'], + 'Patterns', 'Charts', ['Docs'], 'Data Display', diff --git a/docs/EmbeddedStackBlitz.tsx b/docs/EmbeddedStackBlitz.tsx new file mode 100644 index 00000000000..6548bba819c --- /dev/null +++ b/docs/EmbeddedStackBlitz.tsx @@ -0,0 +1,36 @@ +import sdk from '@stackblitz/sdk'; +import type { CSSProperties } from 'react'; +import { useEffect, useRef } from 'react'; + +interface EmbeddedStackBlitzProps { + style?: CSSProperties; + projectId: string; +} + +export function EmbeddedStackBlitz({ style, projectId }: EmbeddedStackBlitzProps) { + const containerRef = useRef(null); + + useEffect(() => { + const container = containerRef.current; + if (!container) { + return; + } + sdk.embedProjectId(container, projectId, { + openFile: 'src/App.tsx', + view: 'editor', + height: '90%', + hideDevTools: true, + terminalHeight: 0, + }); + + return () => { + if (container) { + container.innerHTML = ''; + } + }; + }, [projectId]); + + return
; +} + +EmbeddedStackBlitz.displayName = 'EmbeddedStackBlitz'; diff --git a/docs/Patterns.mdx b/docs/Patterns.mdx new file mode 100644 index 00000000000..4415ee52364 --- /dev/null +++ b/docs/Patterns.mdx @@ -0,0 +1,11 @@ +import {Footer} from '@sb/components'; +import {Meta} from '@storybook/blocks'; +import UXCIntegration from "./UXCIntegration.js" + + + +# UXC Integration + + + +
diff --git a/docs/UXCIntegration.tsx b/docs/UXCIntegration.tsx new file mode 100644 index 00000000000..f40728d8677 --- /dev/null +++ b/docs/UXCIntegration.tsx @@ -0,0 +1,16 @@ +import { ThemeProvider } from '@ui5/webcomponents-react'; +import UXCIntegrationApp from '../patterns/navigation-layout/src/App.js'; +import '../patterns/navigation-layout/src/index.css'; +import { EmbeddedStackBlitz } from '@/docs/EmbeddedStackBlitz.js'; + +function UXCIntegration() { + return ( +
+ + } /> + +
+ ); +} + +export default UXCIntegration; diff --git a/package.json b/package.json index eee0000198f..0506a082698 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@eslint/compat": "1.2.9", "@eslint/js": "9.27.0", "@semantic-release/github": "11.0.3", + "@stackblitz/sdk": "^1.11.0", "@testing-library/cypress": "10.0.3", "@types/jscodeshift": "17.3.0", "@types/node": "22.15.21", diff --git a/patterns/navigation-layout/src/App.tsx b/patterns/navigation-layout/src/App.tsx index 9bf924bc057..7b0b59d2086 100644 --- a/patterns/navigation-layout/src/App.tsx +++ b/patterns/navigation-layout/src/App.tsx @@ -1,12 +1,18 @@ import NavigationLayoutMode from '@ui5/webcomponents-fiori/dist/types/NavigationLayoutMode.js'; import { NavigationLayout, Text, Title } from '@ui5/webcomponents-react'; +import type { ReactNode } from 'react'; import { useState } from 'react'; import { NLShellBar } from './NLShellBar.tsx'; import { NLSideNavigation } from './NLSideNavigation.tsx'; -function App() { +interface AppProps { + content?: ReactNode; +} + +function App({ content }: AppProps) { const [mode, setMode] = useState(NavigationLayoutMode.Auto); const [contentTitle, setContentTitle] = useState('Home'); + return ( <> {contentTitle}
- Content... + {content ?? Content...}
diff --git a/patterns/navigation-layout/src/NLShellBar.tsx b/patterns/navigation-layout/src/NLShellBar.tsx index 9c3a92dfed7..92d65504598 100644 --- a/patterns/navigation-layout/src/NLShellBar.tsx +++ b/patterns/navigation-layout/src/NLShellBar.tsx @@ -25,6 +25,8 @@ import { } from '@ui5/webcomponents-react'; import type { Dispatch, SetStateAction } from 'react'; import { useRef, useState } from 'react'; +import avatarPng from './assets/avatar.png'; +import SapLogoSvg from './assets/sap-logo.svg'; import { NLUserMenu } from './NLUserMenu.tsx'; import { NotificationsPopover } from './NotificationsPopover.tsx'; @@ -86,7 +88,7 @@ export function NLShellBar(props: NLShellBarProps) { onClick={handleMenuBtnClick} /> } - logo={SAP Logo} + logo={SAP Logo} content={ <> @@ -125,7 +127,7 @@ export function NLShellBar(props: NLShellBarProps) { } profile={ - User Avatar + User Avatar } > diff --git a/patterns/navigation-layout/src/NLUserMenu.tsx b/patterns/navigation-layout/src/NLUserMenu.tsx index 9bc86a66eb7..83f2ddb596e 100644 --- a/patterns/navigation-layout/src/NLUserMenu.tsx +++ b/patterns/navigation-layout/src/NLUserMenu.tsx @@ -5,6 +5,7 @@ import type { MessageBoxPropTypes, UserMenuDomRef, UserMenuPropTypes } from '@ui import { MessageBox, Text, UserMenu, UserMenuAccount, UserMenuItem } from '@ui5/webcomponents-react'; import type { Dispatch, SetStateAction } from 'react'; import { forwardRef, useState } from 'react'; +import avatarPng from './assets/avatar.png'; import { NLUserSettingsDialog } from './UserSettingsDialog/NLUserSettingsDialog.tsx'; interface NLUserMenuProps extends Pick { @@ -70,7 +71,7 @@ export const NLUserMenu = forwardRef((props, re <> Date: Thu, 5 Jun 2025 10:22:19 +0200 Subject: [PATCH 07/15] update StackBlitz --- docs/EmbeddedStackBlitz.tsx | 12 +++++------- docs/UXCIntegration.tsx | 4 +++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/EmbeddedStackBlitz.tsx b/docs/EmbeddedStackBlitz.tsx index 6548bba819c..d7a714bd45f 100644 --- a/docs/EmbeddedStackBlitz.tsx +++ b/docs/EmbeddedStackBlitz.tsx @@ -1,13 +1,11 @@ import sdk from '@stackblitz/sdk'; -import type { CSSProperties } from 'react'; import { useEffect, useRef } from 'react'; interface EmbeddedStackBlitzProps { - style?: CSSProperties; - projectId: string; + repoPath: string; } -export function EmbeddedStackBlitz({ style, projectId }: EmbeddedStackBlitzProps) { +export function EmbeddedStackBlitz({ repoPath }: EmbeddedStackBlitzProps) { const containerRef = useRef(null); useEffect(() => { @@ -15,7 +13,7 @@ export function EmbeddedStackBlitz({ style, projectId }: EmbeddedStackBlitzProps if (!container) { return; } - sdk.embedProjectId(container, projectId, { + sdk.embedGithubProject(container, repoPath, { openFile: 'src/App.tsx', view: 'editor', height: '90%', @@ -28,9 +26,9 @@ export function EmbeddedStackBlitz({ style, projectId }: EmbeddedStackBlitzProps container.innerHTML = ''; } }; - }, [projectId]); + }, [repoPath]); - return
; + return
; } EmbeddedStackBlitz.displayName = 'EmbeddedStackBlitz'; diff --git a/docs/UXCIntegration.tsx b/docs/UXCIntegration.tsx index f40728d8677..cae76a842d0 100644 --- a/docs/UXCIntegration.tsx +++ b/docs/UXCIntegration.tsx @@ -7,7 +7,9 @@ function UXCIntegration() { return (
- } /> + } + />
); From 3b4be7ca5397277307b6a57b8b65127e188b5fd7 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 10:28:18 +0200 Subject: [PATCH 08/15] Update UXCIntegration.tsx --- docs/UXCIntegration.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/UXCIntegration.tsx b/docs/UXCIntegration.tsx index cae76a842d0..3ab77941520 100644 --- a/docs/UXCIntegration.tsx +++ b/docs/UXCIntegration.tsx @@ -1,4 +1,4 @@ -import { ThemeProvider } from '@ui5/webcomponents-react'; +import { MessageStrip, ThemeProvider } from '@ui5/webcomponents-react'; import UXCIntegrationApp from '../patterns/navigation-layout/src/App.js'; import '../patterns/navigation-layout/src/index.css'; import { EmbeddedStackBlitz } from '@/docs/EmbeddedStackBlitz.js'; @@ -8,7 +8,15 @@ function UXCIntegration() {
} + content={ + <> + + For a full-page view of this pattern, click "Fork on StackBlitz" below to open it in the + standalone StackBlitz editor. + + + + } />
From 79bb5ebfbd4cf369325f88c5b7fa3aef1352fc06 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 11:10:49 +0200 Subject: [PATCH 09/15] Update eslint.config.mjs --- eslint.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/eslint.config.mjs b/eslint.config.mjs index 75226c892f0..d992266ad95 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -30,6 +30,7 @@ const ignorePatterns = { '**/out/**', '**/examples', '**/templates', + '**/patterns/navigation-layout', ], }; From ead9958ceb74db6e3ed747ca3b1967b66a27c7e5 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 11:18:06 +0200 Subject: [PATCH 10/15] ci --- .github/workflows/examples.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 90fb5a0c39c..465b4872164 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -7,10 +7,12 @@ on: paths: - 'examples/**/*' - 'templates/**/*' + - 'patterns/navigation-layout/**/*' pull_request: paths: - 'examples/**/*' - 'templates/**/*' + - 'patterns/navigation-layout/**/*' jobs: examples: @@ -77,3 +79,33 @@ jobs: - name: ESLint run: npm run lint --if-present working-directory: templates/${{ matrix.path }} + + patterns: + runs-on: ubuntu-latest + strategy: + matrix: + path: + - patterns/navigation-layout + fail-fast: false + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4.4.0 + with: + node-version-file: '.nvmrc' + + - name: Install + run: npm ci + working-directory: templates/${{ matrix.path }} + + - name: Build + run: npm run build + working-directory: templates/${{ matrix.path }} + + - name: Test + run: npm run test --if-present + working-directory: templates/${{ matrix.path }} + + - name: ESLint + run: npm run lint --if-present + working-directory: templates/${{ matrix.path }} From f3e028047bfd0e569aa6976276098b45890c39c0 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 11:25:17 +0200 Subject: [PATCH 11/15] Update examples.yml --- .github/workflows/examples.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 465b4872164..4f7789d90e5 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -85,7 +85,7 @@ jobs: strategy: matrix: path: - - patterns/navigation-layout + - navigation-layout fail-fast: false steps: - uses: actions/checkout@v4 @@ -96,16 +96,16 @@ jobs: - name: Install run: npm ci - working-directory: templates/${{ matrix.path }} + working-directory: patterns/${{ matrix.path }} - name: Build run: npm run build - working-directory: templates/${{ matrix.path }} + working-directory: patterns/${{ matrix.path }} - name: Test run: npm run test --if-present - working-directory: templates/${{ matrix.path }} + working-directory: patterns/${{ matrix.path }} - name: ESLint run: npm run lint --if-present - working-directory: templates/${{ matrix.path }} + working-directory: patterns/${{ matrix.path }} From dc4ac558e047f5e8a8d693541c5f7162dc03d865 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 11:28:11 +0200 Subject: [PATCH 12/15] Update NotificationsPopover.tsx --- patterns/navigation-layout/src/NotificationsPopover.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/patterns/navigation-layout/src/NotificationsPopover.tsx b/patterns/navigation-layout/src/NotificationsPopover.tsx index d31b72c6605..26442213359 100644 --- a/patterns/navigation-layout/src/NotificationsPopover.tsx +++ b/patterns/navigation-layout/src/NotificationsPopover.tsx @@ -85,12 +85,14 @@ export const NotificationsPopover = forwardRef { setTodayNotifications((prev) => [...prev, ...nextItems]); setGroupLoading(false); setTimeout(() => { + //@ts-expect-error: `items` are available but private e.target.items[focusIndex].focus(); }, 500); }, 2000); From 9768eb49dd53ab419ce719bcd383c4dfd059ce40 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 11:54:27 +0200 Subject: [PATCH 13/15] Update NotificationsPopover.tsx --- patterns/navigation-layout/src/NotificationsPopover.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patterns/navigation-layout/src/NotificationsPopover.tsx b/patterns/navigation-layout/src/NotificationsPopover.tsx index 26442213359..1b5f8272eb8 100644 --- a/patterns/navigation-layout/src/NotificationsPopover.tsx +++ b/patterns/navigation-layout/src/NotificationsPopover.tsx @@ -85,14 +85,14 @@ export const NotificationsPopover = forwardRef { setTodayNotifications((prev) => [...prev, ...nextItems]); setGroupLoading(false); setTimeout(() => { - //@ts-expect-error: `items` are available but private + //@ts-expect-error: `items` are available e.target.items[focusIndex].focus(); }, 500); }, 2000); From aed9c17c503856e71e5f3147dfc9376faf45f5e5 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 12:27:02 +0200 Subject: [PATCH 14/15] Update NLShellBar.tsx --- patterns/navigation-layout/src/NLShellBar.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/patterns/navigation-layout/src/NLShellBar.tsx b/patterns/navigation-layout/src/NLShellBar.tsx index 92d65504598..37a33c8522a 100644 --- a/patterns/navigation-layout/src/NLShellBar.tsx +++ b/patterns/navigation-layout/src/NLShellBar.tsx @@ -7,6 +7,7 @@ import type { NavigationLayoutDomRef, ResponsivePopoverDomRef, ShellBarPropTypes, + ShellBarSearchPropTypes, ToggleButtonPropTypes, UserMenuDomRef, } from '@ui5/webcomponents-react'; @@ -41,6 +42,7 @@ export function NLShellBar(props: NLShellBarProps) { const [assistantBtnPressed, setAssistantBtnPressed] = useState(false); const [notificationsPopoverOpen, setNotificationsPopoverOpen] = useState(false); const [userMenuOpen, setUserMenuOpen] = useState(false); + const [scopeData, setScopeData] = useState(_scopeData); const handleAssistantClick: ToggleButtonPropTypes['onClick'] = (e) => { setAssistantBtnPressed(e.currentTarget!.pressed); @@ -68,6 +70,11 @@ export function NLShellBar(props: NLShellBarProps) { setUserMenuOpen(true); }; + const handleSearchScopeChange: ShellBarSearchPropTypes['onScopeChange'] = (e) => { + const scopeText = e.detail.scope?.text === 'All' ? '' : e.detail.scope?.text?.toLowerCase(); + setScopeData(_scopeData.filter((item) => !scopeText || item.scope === scopeText)); + }; + return ( <> @@ -146,7 +154,7 @@ export function NLShellBar(props: NLShellBarProps) { NLShellBar.displayName = 'NLShellBar'; -const scopeData = [ +const _scopeData = [ { name: 'Laptop', scope: 'products' }, { name: 'Leave Requests', scope: 'apps' }, { name: 'Log work', scope: 'apps' }, From d22b115a012b502a83f0c663a7640f78ef905ac2 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Thu, 5 Jun 2025 17:06:53 +0200 Subject: [PATCH 15/15] move `stackblitz/sdk` to `dependencies` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0506a082698..8d9e77cf93b 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "create-theming-parameters": "node scripts/generate-theming-parameters.js" }, "dependencies": { + "@stackblitz/sdk": "^1.11.0", "@storybook/addon-a11y": "8.6.14", "@storybook/addon-essentials": "8.6.14", "@storybook/blocks": "8.6.14", @@ -64,7 +65,6 @@ "@eslint/compat": "1.2.9", "@eslint/js": "9.27.0", "@semantic-release/github": "11.0.3", - "@stackblitz/sdk": "^1.11.0", "@testing-library/cypress": "10.0.3", "@types/jscodeshift": "17.3.0", "@types/node": "22.15.21",