|
1 | | -import React, { useState } from 'react'; |
| 1 | +import React, { useState, useEffect } from 'react'; |
2 | 2 | import clsx from "clsx"; |
3 | 3 | import SAPIcons from "../../icons/index.js"; |
4 | 4 | import SAPTNTIcons from "../../icons-tnt/index.js"; |
5 | 5 | import SAPBSIcons from "../../icons-business-suite/index.js"; |
6 | 6 | import Layout from '@theme/Layout'; |
| 7 | +import "./shared.css"; |
7 | 8 | import "./icons.css"; |
8 | 9 |
|
| 10 | +// Collection metadata |
| 11 | +const COLLECTION_METADATA = { |
| 12 | + "SAP Icons": { |
| 13 | + title: "SAP Icons", |
| 14 | + package: "@ui5/webcomponents-icons", |
| 15 | + packageUrl: "https://www.npmjs.com/package/@ui5/webcomponents-icons" |
| 16 | + }, |
| 17 | + "SAP TNT Icons": { |
| 18 | + title: "SAP TNT Icons", |
| 19 | + package: "@ui5/webcomponents-icons-tnt", |
| 20 | + packageUrl: "https://www.npmjs.com/package/@ui5/webcomponents-icons-tnt" |
| 21 | + }, |
| 22 | + "SAP BSuite Icons": { |
| 23 | + title: "SAP BSuite Icons", |
| 24 | + package: "@ui5/webcomponents-icons-business-suite", |
| 25 | + packageUrl: "https://www.npmjs.com/package/@ui5/webcomponents-icons-business-suite" |
| 26 | + } |
| 27 | +}; |
9 | 28 |
|
10 | 29 | const Select = ({ updateState }) => { |
11 | | - const [ collection, setCollection ] = useState("SAP Icons"); |
| 30 | + const [collection, setCollection] = useState("SAP Icons"); |
12 | 31 |
|
13 | 32 | return <div className="segmented__button"> |
14 | 33 | <div |
15 | | - onClick={() => { |
16 | | - setCollection("SAP Icons") |
17 | | - updateState("SAP Icons"); |
18 | | - }} |
19 | | - className={clsx("segmented__button__item", { 'segmented__button__item--active': collection === "SAP Icons" })} |
| 34 | + onClick={() => { |
| 35 | + setCollection("SAP Icons") |
| 36 | + updateState("SAP Icons"); |
| 37 | + }} |
| 38 | + className={clsx("segmented__button__item", { 'segmented__button__item--active': collection === "SAP Icons" })} |
20 | 39 | >SAP Icons</div> |
21 | 40 | <div |
22 | | - onClick={() => { |
23 | | - setCollection("SAP TNT Icons"); |
24 | | - updateState("SAP TNT Icons"); |
25 | | - }} |
26 | | - className={clsx("segmented__button__item", { 'segmented__button__item--active': collection === "SAP TNT Icons" })} |
| 41 | + onClick={() => { |
| 42 | + setCollection("SAP TNT Icons"); |
| 43 | + updateState("SAP TNT Icons"); |
| 44 | + }} |
| 45 | + className={clsx("segmented__button__item", { 'segmented__button__item--active': collection === "SAP TNT Icons" })} |
27 | 46 | >SAP TNT Icons</div> |
28 | 47 |
|
29 | 48 | <div |
30 | | - onClick={() => { |
31 | | - setCollection("SAP BSuite Icons"); |
32 | | - updateState("SAP BSuite Icons"); |
33 | | - }} |
34 | | - className={clsx("segmented__button__item", { 'segmented__button__item--active': collection === "SAP BSuite Icons" })} |
| 49 | + onClick={() => { |
| 50 | + setCollection("SAP BSuite Icons"); |
| 51 | + updateState("SAP BSuite Icons"); |
| 52 | + }} |
| 53 | + className={clsx("segmented__button__item", { 'segmented__button__item--active': collection === "SAP BSuite Icons" })} |
35 | 54 | >SAP BSuite Icons</div> |
36 | 55 | </div>; |
37 | 56 | }; |
38 | 57 |
|
39 | 58 |
|
40 | | -const Collection = ({ currCollection }) => { |
41 | | - if (currCollection === "SAP TNT Icons") { |
42 | | - return <SAPTNTIcons /> |
43 | | - } else if (currCollection === "SAP BSuite Icons") { |
44 | | - return <SAPBSIcons /> |
45 | | - } |
| 59 | +const Collection = ({ currCollection }) => { |
| 60 | + // if (currCollection === "SAP TNT Icons") { |
| 61 | + // return <SAPTNTIcons /> |
| 62 | + // } else if (currCollection === "SAP BSuite Icons") { |
| 63 | + // return <SAPBSIcons /> |
| 64 | + // } |
46 | 65 |
|
47 | 66 | return <SAPIcons /> |
48 | 67 | }; |
49 | 68 |
|
50 | 69 | export default function Icons() { |
51 | | - const [ collection, setCollection ] = useState("SAP Icons"); |
| 70 | + const [collection, setCollection] = useState("SAP Icons"); |
| 71 | + const [searchQuery, setSearchQuery] = useState(""); |
| 72 | + |
| 73 | + // Client-side search filtering using DOM manipulation |
| 74 | + useEffect(() => { |
| 75 | + if (typeof window === 'undefined') return; |
| 76 | + |
| 77 | + const iconWrappers = document.querySelectorAll('.icon__wrapper'); |
| 78 | + const notFoundElement = document.querySelector('.icon__not__found'); |
| 79 | + let visibleCount = 0; |
| 80 | + |
| 81 | + iconWrappers.forEach(wrapper => { |
| 82 | + const iconName = wrapper.getAttribute('data-icon-name') || ''; |
| 83 | + const matches = iconName.toLowerCase().includes(searchQuery.toLowerCase()); |
| 84 | + |
| 85 | + if (matches) { |
| 86 | + wrapper.classList.remove('hidden'); |
| 87 | + visibleCount++; |
| 88 | + } else { |
| 89 | + wrapper.classList.add('hidden'); |
| 90 | + } |
| 91 | + }); |
| 92 | + |
| 93 | + // Show/hide "not found" message |
| 94 | + if (visibleCount === 0 && searchQuery) { |
| 95 | + notFoundElement?.classList.remove('hidden'); |
| 96 | + } else { |
| 97 | + notFoundElement?.classList.add('hidden'); |
| 98 | + } |
| 99 | + }, [searchQuery, collection]); // Re-run when search or collection changes |
52 | 100 |
|
53 | 101 | return ( |
54 | 102 | <Layout title="UI5 Web Components Icons" description="UI5 Web Components Icons"> |
55 | | - <Select updateState={setCollection}/> |
56 | | - <Collection currCollection={collection}/> |
| 103 | + <div className="icons__container"> |
| 104 | + {/* Header with collection switcher, title, and search */} |
| 105 | + <div className="icons__header"> |
| 106 | + <div className="icons__header__metadata"> |
| 107 | + <h2 className="icons__header__title"> |
| 108 | + {COLLECTION_METADATA[collection].title} |
| 109 | + </h2> |
| 110 | + <a |
| 111 | + href={COLLECTION_METADATA[collection].packageUrl} |
| 112 | + target="_blank" |
| 113 | + rel="noopener noreferrer" |
| 114 | + className="icons__header__package" |
| 115 | + > |
| 116 | + {COLLECTION_METADATA[collection].package} |
| 117 | + </a> |
| 118 | + </div> |
| 119 | + |
| 120 | + <Select updateState={setCollection} /> |
| 121 | + |
| 122 | + <div className='icons__header__separator'></div> |
| 123 | + |
| 124 | + <input |
| 125 | + className="page__search" |
| 126 | + type="search" |
| 127 | + placeholder="Filter icons..." |
| 128 | + aria-label="Filter icons" |
| 129 | + value={searchQuery} |
| 130 | + onChange={(e) => setSearchQuery(e.target.value)} |
| 131 | + /> |
| 132 | + </div> |
| 133 | + |
| 134 | + {/* Icons grid */} |
| 135 | + <Collection currCollection={collection} /> |
| 136 | + </div> |
57 | 137 | </Layout> |
58 | 138 | ); |
59 | 139 | }; |
0 commit comments