diff --git a/package-lock.json b/package-lock.json index f1c482ceaca8234eff23840c1b5a0c2c910934d9..350f3d140371e135192ba8b978bfea60090dfc5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@itcenteratunihelsinki/huds-lib", - "version": "0.0.22", + "version": "0.0.88", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -404,27 +404,6 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, - "@fullhuman/postcss-purgecss": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.2.0.tgz", - "integrity": "sha512-q4zYAn8L9olA5uneaLhxkHRBoug9dnAqytbdX9R5dbzSORobhYr1yGR2JN3Q1UMd5RB0apm1NvJekHaymal/BQ==", - "requires": { - "postcss": "7.0.28", - "purgecss": "^2.2.0" - }, - "dependencies": { - "postcss": { - "version": "7.0.28", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.28.tgz", - "integrity": "sha512-YU6nVhyWIsVtlNlnAj1fHTsUKW5qxm3KEgzq2Jj6KTEFOTK8QWR12eIDvrlWhiSTK8WIBFTBhOJV4DY6dUuEbw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - } - } - }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1375,7 +1354,8 @@ "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true }, "@types/graceful-fs": { "version": "4.1.3", @@ -1514,7 +1494,8 @@ "acorn": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", - "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==" + "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", + "dev": true }, "acorn-globals": { "version": "6.0.0", @@ -1526,20 +1507,11 @@ "acorn-walk": "^7.1.1" } }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, "acorn-walk": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", - "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==" + "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", + "dev": true }, "agent-base": { "version": "5.1.1", @@ -1984,9 +1956,9 @@ } }, "bl": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz", - "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "requires": { "buffer": "^5.5.0", @@ -2086,11 +2058,6 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -2118,11 +2085,6 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" - }, "camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", @@ -2140,9 +2102,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001077", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001077.tgz", - "integrity": "sha512-AEzsGvjBJL0lby/87W96PyEvwN0GsYvk5LHsglLg9tW37K4BqvAvoSCdWIE13OZQ8afupqZ73+oL/1LkedN8hA==" + "version": "1.0.30001196", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001196.tgz", + "integrity": "sha512-CPvObjD3ovWrNBaXlAIGWmg2gQQuJ5YhuciUOjPRox6hIQttu8O+b51dx6VIpIY9ESd2d0Vac1RKpICdG4rGUg==" }, "capture-exit": { "version": "2.0.0", @@ -2256,15 +2218,6 @@ "object-visit": "^1.0.0" } }, - "color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", - "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -2278,15 +2231,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2295,11 +2239,6 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, "compare-versions": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", @@ -2407,16 +2346,6 @@ "which": "^1.2.9" } }, - "css-unit-converter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", - "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==" - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" - }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -2556,11 +2485,6 @@ } } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2577,16 +2501,6 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, - "detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - } - }, "diff-sequences": { "version": "25.2.6", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", @@ -3087,16 +3001,6 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3535,11 +3439,6 @@ "repeating": "^2.0.0" } }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -6436,14 +6335,6 @@ "minimist": "^1.2.5" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -6525,9 +6416,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.merge": { "version": "4.6.2", @@ -6541,11 +6432,6 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, - "lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" - }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -6777,14 +6663,6 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-emoji": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", - "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", - "requires": { - "lodash.toarray": "^4.4.0" - } - }, "node-gyp": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", @@ -6960,11 +6838,6 @@ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" }, - "normalize.css": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz", - "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==" - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -7353,42 +7226,6 @@ "supports-color": "^6.1.0" } }, - "postcss-functions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-functions/-/postcss-functions-3.0.0.tgz", - "integrity": "sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4=", - "requires": { - "glob": "^7.1.2", - "object-assign": "^4.1.1", - "postcss": "^6.0.9", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "postcss-import": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", @@ -7407,34 +7244,6 @@ } } }, - "postcss-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.3.tgz", - "integrity": "sha512-zS59pAk3deu6dVHyrGqmC3oDXBdNdajk4k1RyxeVXCrcEDBUBHoIhE4QTsmhxgzXxsaqFDAkUZfmMa5f/N/79w==", - "requires": { - "camelcase-css": "^2.0.1", - "postcss": "^7.0.18" - } - }, - "postcss-nested": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-4.2.1.tgz", - "integrity": "sha512-AMayXX8tS0HCp4O4lolp4ygj9wBn32DJWXvG6gCv+ZvJrEa00GUxJcJEEzMh87BIe6FrWdYkpR2cuyqHKrxmXw==", - "requires": { - "postcss": "^7.0.21", - "postcss-selector-parser": "^6.0.2" - } - }, - "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, "postcss-value-parser": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", @@ -7497,11 +7306,6 @@ } } }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" - }, "pretty-quick": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-2.0.1.tgz", @@ -7736,29 +7540,6 @@ } } }, - "purgecss": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-2.2.1.tgz", - "integrity": "sha512-wngRSLW1dpNr8kr3TL9nTJMyTFI5BiRiaUUEys5M1CA4zEHLF25fRHoshEeDqmhstaNTOddmpYM34zRrUtEGbQ==", - "requires": { - "commander": "^5.0.0", - "glob": "^7.0.0", - "postcss": "7.0.28", - "postcss-selector-parser": "^6.0.2" - }, - "dependencies": { - "postcss": { - "version": "7.0.28", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.28.tgz", - "integrity": "sha512-YU6nVhyWIsVtlNlnAj1fHTsUKW5qxm3KEgzq2Jj6KTEFOTK8QWR12eIDvrlWhiSTK8WIBFTBhOJV4DY6dUuEbw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - } - } - }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", @@ -7856,22 +7637,6 @@ "strip-indent": "^1.0.1" } }, - "reduce-css-calc": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.7.tgz", - "integrity": "sha512-fDnlZ+AybAS3C7Q9xDq5y8A2z+lT63zLbynew/lur/IR24OQF5x98tfNwf79mzEdfywZ0a2wpM860FhFfMxZlA==", - "requires": { - "css-unit-converter": "^1.1.1", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" - } - } - }, "regenerator-runtime": { "version": "0.13.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", @@ -8303,21 +8068,6 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - } - } - }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -8736,78 +8486,6 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "tailwindcss": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.4.6.tgz", - "integrity": "sha512-qV0qInUq1FWih39Bc5CWECdgObSzRrbjGD4ke4kAPSIq6WXrPhv0wwOcUWJgJ66ltT9j+XnSRYikG8WNRU/fTQ==", - "requires": { - "@fullhuman/postcss-purgecss": "^2.1.2", - "autoprefixer": "^9.4.5", - "browserslist": "^4.12.0", - "bytes": "^3.0.0", - "chalk": "^4.0.0", - "color": "^3.1.2", - "detective": "^5.2.0", - "fs-extra": "^8.0.0", - "lodash": "^4.17.15", - "node-emoji": "^1.8.1", - "normalize.css": "^8.0.1", - "postcss": "^7.0.11", - "postcss-functions": "^3.0.0", - "postcss-js": "^2.0.0", - "postcss-nested": "^4.1.1", - "postcss-selector-parser": "^6.0.0", - "pretty-hrtime": "^1.0.3", - "reduce-css-calc": "^2.1.6", - "resolve": "^1.14.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "tar": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", @@ -9053,16 +8731,6 @@ "set-value": "^2.0.1" } }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -9340,11 +9008,6 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/src/components.d.ts b/src/components.d.ts index 348faa9a18b058f0c8871ba488f7f86771264e24..c1fb418b0c11f016ca372d236867adac8e8ab0ac 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -53,6 +53,7 @@ import {CtaLinkValue} from './components/hy-link-list/hy-link-list'; import {AdditionalInfo, RelatedLink} from './components/hy-list-item/hy-list-item'; import {MenuLanguage} from './components/navigation/menu-language/menu-language'; import {ComponentLabels} from './components/site-header/site-header'; +import {DonateLink, MainMenu} from './components/navigation/hy-menu-main-group/hy-menu-main-group'; import {ProcessFlowBoxValue} from './components/process/process'; import {ShortcutLinkValue} from './components/hy-shortcuts/hy-shortcuts'; import {DesktopLinks as DesktopLinks1} from './components/site-header/site-header'; @@ -541,6 +542,7 @@ export namespace Components { dataMenuDonate: string; dataMenuLanguage: string; isDemo: boolean; + isGroup: boolean; labelFrontPage: string; logoLabel: string; logoUrl: string; @@ -594,6 +596,7 @@ export namespace Components { } interface HyMenuLanguage { dataMenuLanguage: MenuLanguage[] | string; + isGroup: boolean; isMobile: boolean; labels?: ComponentLabels[] | string; } @@ -624,6 +627,16 @@ export namespace Components { menuType: MenuType; triggerItem: string; } + interface HyMenuMainGroup { + dataMainMenu: MainMenu[] | string; + donate: DonateLink[]; + isMobile: boolean; + logoLabel?: string; + logoUrl?: string; + menuLabel: string; + siteLabel?: string; + siteUrl?: string; + } interface HyMenuMobileBreadcrumb { bid: string; isFirst: boolean; @@ -769,20 +782,25 @@ export namespace Components { } interface HySiteHeader { dataDesktopLinks: DesktopLinks[] | string; + dataMainMenuLinks: DesktopLinks[] | string; dataMenuDonate: string; dataMenuLanguage: string; dataSearchTools: DesktopLinks[] | string; dataSiteHeaderLabels: string; dataSiteSearchLabels: string; + isGroup: boolean; logoLabel?: string; logoUrl?: string; menuLabel: string; menuLabelClose?: string; menuLabelOpen?: string; menuType: MenuType; + siteLabel?: string; + siteUrl?: string; } interface HySiteLogo { color: ColorVariant; + isGroup: boolean; label?: string; size: SiteLogoSize; type: FooterVariant; @@ -792,6 +810,7 @@ export namespace Components { color: ColorVariant; dataSearchSpecialTools: string; isAlternative: boolean; + isGroup: boolean; labels?: ComponentLabels[] | string; searchLabels: string; searchTools: string; @@ -1193,6 +1212,11 @@ declare global { prototype: HTMLHyMenuLevelContainerElement; new (): HTMLHyMenuLevelContainerElement; }; + interface HTMLHyMenuMainGroupElement extends Components.HyMenuMainGroup, HTMLStencilElement {} + var HTMLHyMenuMainGroupElement: { + prototype: HTMLHyMenuMainGroupElement; + new (): HTMLHyMenuMainGroupElement; + }; interface HTMLHyMenuMobileBreadcrumbElement extends Components.HyMenuMobileBreadcrumb, HTMLStencilElement {} var HTMLHyMenuMobileBreadcrumbElement: { prototype: HTMLHyMenuMobileBreadcrumbElement; @@ -1381,6 +1405,7 @@ declare global { 'hy-menu-language': HTMLHyMenuLanguageElement; 'hy-menu-language-item': HTMLHyMenuLanguageItemElement; 'hy-menu-level-container': HTMLHyMenuLevelContainerElement; + 'hy-menu-main-group': HTMLHyMenuMainGroupElement; 'hy-menu-mobile-breadcrumb': HTMLHyMenuMobileBreadcrumbElement; 'hy-menu-sidebar': HTMLHyMenuSidebarElement; 'hy-pager': HTMLHyPagerElement; @@ -1894,6 +1919,7 @@ declare namespace LocalJSX { dataMenuDonate?: string; dataMenuLanguage?: string; isDemo?: boolean; + isGroup?: boolean; labelFrontPage?: string; logoLabel?: string; logoUrl?: string; @@ -1956,6 +1982,7 @@ declare namespace LocalJSX { } interface HyMenuLanguage { dataMenuLanguage?: MenuLanguage[] | string; + isGroup?: boolean; isMobile?: boolean; labels?: ComponentLabels[] | string; onMenuLanguageToggled?: (event: CustomEvent<any>) => void; @@ -1987,6 +2014,18 @@ declare namespace LocalJSX { menuType?: MenuType; triggerItem?: string; } + interface HyMenuMainGroup { + dataMainMenu?: MainMenu[] | string; + donate?: DonateLink[]; + isMobile?: boolean; + logoLabel?: string; + logoUrl?: string; + menuLabel?: string; + onMobileMenuTopToggle?: (event: CustomEvent<any>) => void; + onUniversityMainMenuToggled?: (event: CustomEvent<any>) => void; + siteLabel?: string; + siteUrl?: string; + } interface HyMenuMobileBreadcrumb { bid?: string; isFirst?: boolean; @@ -2133,11 +2172,13 @@ declare namespace LocalJSX { } interface HySiteHeader { dataDesktopLinks?: DesktopLinks[] | string; + dataMainMenuLinks?: DesktopLinks[] | string; dataMenuDonate?: string; dataMenuLanguage?: string; dataSearchTools?: DesktopLinks[] | string; dataSiteHeaderLabels?: string; dataSiteSearchLabels?: string; + isGroup?: boolean; logoLabel?: string; logoUrl?: string; menuLabel?: string; @@ -2147,9 +2188,13 @@ declare namespace LocalJSX { onHeaderScrollDown?: (event: CustomEvent<any>) => void; onHeaderScrollUp?: (event: CustomEvent<any>) => void; onMenuMobileToggled?: (event: CustomEvent<any>) => void; + onMenuMobileTopToggled?: (event: CustomEvent<any>) => void; + siteLabel?: string; + siteUrl?: string; } interface HySiteLogo { color?: ColorVariant; + isGroup?: boolean; label?: string; size?: SiteLogoSize; type?: FooterVariant; @@ -2159,6 +2204,7 @@ declare namespace LocalJSX { color?: ColorVariant; dataSearchSpecialTools?: string; isAlternative?: boolean; + isGroup?: boolean; labels?: ComponentLabels[] | string; onSearchPanelToggled?: (event: CustomEvent<any>) => void; searchLabels?: string; @@ -2310,6 +2356,7 @@ declare namespace LocalJSX { 'hy-menu-language': HyMenuLanguage; 'hy-menu-language-item': HyMenuLanguageItem; 'hy-menu-level-container': HyMenuLevelContainer; + 'hy-menu-main-group': HyMenuMainGroup; 'hy-menu-mobile-breadcrumb': HyMenuMobileBreadcrumb; 'hy-menu-sidebar': HyMenuSidebar; 'hy-pager': HyPager; @@ -2409,6 +2456,7 @@ declare module '@stencil/core' { 'hy-menu-language-item': LocalJSX.HyMenuLanguageItem & JSXBase.HTMLAttributes<HTMLHyMenuLanguageItemElement>; 'hy-menu-level-container': LocalJSX.HyMenuLevelContainer & JSXBase.HTMLAttributes<HTMLHyMenuLevelContainerElement>; + 'hy-menu-main-group': LocalJSX.HyMenuMainGroup & JSXBase.HTMLAttributes<HTMLHyMenuMainGroupElement>; 'hy-menu-mobile-breadcrumb': LocalJSX.HyMenuMobileBreadcrumb & JSXBase.HTMLAttributes<HTMLHyMenuMobileBreadcrumbElement>; 'hy-menu-sidebar': LocalJSX.HyMenuSidebar & JSXBase.HTMLAttributes<HTMLHyMenuSidebarElement>; diff --git a/src/components/heading/heading.scss b/src/components/heading/heading.scss index 20830bab69040fd15609de39207991767eefb796..abf53e047526e59467bd89b967371a4a0449a34c 100644 --- a/src/components/heading/heading.scss +++ b/src/components/heading/heading.scss @@ -148,7 +148,7 @@ h1.hy-heading__introduction { .hy-heading__container__common { h2.hy-heading__introduction, h2.hy-heading__landingsection { - @include breakpoint($extrawide) { + @include breakpoint($narrow) { @include font-size(34px, 40px); letter-spacing: -0.85px; } @@ -188,7 +188,7 @@ h1.hy-heading__introduction { .hy-heading__container__large { h2.hy-heading__introduction, h2.hy-heading__landingsection { - @include breakpoint($extrawide) { + @include breakpoint($narrow) { @include font-size(34px, 40px); letter-spacing: -0.85px; } diff --git a/src/components/icon/SlimHamburgerMenu.tsx b/src/components/icon/SlimHamburgerMenu.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ef88a442fa04054df470cf86f7a48e171d52cfa8 --- /dev/null +++ b/src/components/icon/SlimHamburgerMenu.tsx @@ -0,0 +1,11 @@ +import {h} from '@stencil/core'; + +function SvgSlimHamburgerMenu(props) { + return ( + <svg viewBox="0 0 13 64" {...props}> + <path d="M12.8,38.4 L12.8,25.6 L0,25.6 L0,38.4 L12.32608,38.4 L12.8,38.4 Z M0,64 L12.8,64 L12.8,51.2 L0,51.2 L0,61.44 L0,64 Z M12.8,12.8 L12.8,0 L0,0 L0,12.8 L12.32608,12.8 L12.8,12.8 Z"></path> + </svg> + ); +} + +export default SvgSlimHamburgerMenu; diff --git a/src/components/icon/icon.tsx b/src/components/icon/icon.tsx index 7923a25d264b38a63ff35af1d9b14cf2c28a7a46..604de46cf75db3082e80084eb018f3c181a120f5 100644 --- a/src/components/icon/icon.tsx +++ b/src/components/icon/icon.tsx @@ -34,6 +34,7 @@ const iconNames: IconName = { 'hy-icon-quote': (p) => <icons.IconQuote {...p} />, 'hy-icon-remove': (p) => <icons.Remove {...p} />, 'hy-icon-search': (p) => <icons.Search {...p} />, + 'hy-icon-slim-hamburger-menu': (p) => <icons.SlimHamburgerMenu {...p} />, 'hy-icon-some-facebook': (p) => <icons.SomeFacebook {...p} />, 'hy-icon-some-instagram': (p) => <icons.SomeInstagram {...p} />, 'hy-icon-some-linkedin': (p) => <icons.SomeLinkedin {...p} />, diff --git a/src/components/icon/icons.tsx b/src/components/icon/icons.tsx index 3e7fbf85bf2e309480f9140182d034fb42bf0855..98a28fbf00782edb199f3dacb617234071b3ab27 100644 --- a/src/components/icon/icons.tsx +++ b/src/components/icon/icons.tsx @@ -158,6 +158,7 @@ export {default as RotateLeft} from './RotateLeft'; export {default as RotateRight} from './RotateRight'; export {default as Search} from './Search'; export {default as Share} from './Share'; +export {default as SlimHamburgerMenu} from './SlimHamburgerMenu'; export {default as SocialMedia} from './SocialMedia'; export {default as SomeFacebook} from './SomeFacebook'; export {default as SomeInstagram} from './SomeInstagram'; diff --git a/src/components/icon/readme.md b/src/components/icon/readme.md index 26a9d79ddd4cd58a379350ea11e06f459780c13b..325bab04a2a84bce132d3678ae777477376db770 100644 --- a/src/components/icon/readme.md +++ b/src/components/icon/readme.md @@ -38,6 +38,7 @@ - [hy-menu-item-sidebar](../navigation/menu-item-sidebar) - [hy-menu-language](../navigation/menu-language) - [hy-menu-level-container](../navigation/menu-level-container) +- [hy-menu-main-group](../navigation/hy-menu-main-group) - [hy-menu-mobile-breadcrumb](../navigation/menu-mobile-breadcrumb) - [hy-menu-sidebar](../navigation/menu-sidebar) - [hy-pager-item](../pagination/hy-pager-item) @@ -79,6 +80,7 @@ graph TD; hy-menu-item-sidebar --> hy-icon hy-menu-language --> hy-icon hy-menu-level-container --> hy-icon + hy-menu-main-group --> hy-icon hy-menu-mobile-breadcrumb --> hy-icon hy-menu-sidebar --> hy-icon hy-pager-item --> hy-icon diff --git a/src/components/navigation/hy-menu-main-group/hy-menu-main-group.scss b/src/components/navigation/hy-menu-main-group/hy-menu-main-group.scss new file mode 100644 index 0000000000000000000000000000000000000000..1dd2531e580925eb8b77d229c49f9bf4dd18c92b --- /dev/null +++ b/src/components/navigation/hy-menu-main-group/hy-menu-main-group.scss @@ -0,0 +1,305 @@ +:host { + display: block; +} + +:host(.menu--main-group) { + align-items: center; + display: flex; + flex-flow: row; + margin-left: 28px; + @include breakpoint($narrow) { + margin-left: 32px; + } + @include breakpoint($wide) { + margin-left: 40px; + } +} + +.menu--main-group__toggle { + @include font-size(14px, 16px); + @include font-weight($semibold); + align-items: center; + background: var(--grayscale-black); + border: 0 none; + color: var(--grayscale-white); + display: flex; + flex-flow: row; + font-family: var(--main-font-family); + letter-spacing: -0.44px; + margin: 0 -4px; + padding: 0; + position: relative; + + &:focus { + outline: none; + } + &:hover { + cursor: pointer; + span { + color: var(--grayscale-medium); + } + svg { + fill: var(--grayscale-medium); + } + } + + .toggle__caret { + svg { + @include breakpoint($wide) { + height: 15.27px; + width: 3px; + } + @include breakpoint($extrawide) { + height: 14px; + width: 3px; + } + } + } + + span { + @include breakpoint($wide) { + margin-left: 17px; + } + } + + &.is-open { + &:after { + border-bottom: 3px solid white; + bottom: -10px; + content: ' '; + position: absolute; + width: 100%; + } + + .toggle__close { + @include breakpoint($wide) { + height: 12px; + width: 12px; + } + } + + span { + @include breakpoint($wide) { + margin-left: 10px; + } + } + } +} + +.menu--main-group__dropdown { + display: none; + visibility: hidden; + + &.is-open { + background-color: var(--grayscale-black); + border-radius: 0 0 5px 5px; + box-shadow: 0 10px 10px rgba(0, 0, 0, 0.2); + color: var(--grayscale-white); + display: flex; + font-family: var(--main-font-family); + left: 0; + margin: 0; + padding: 6px 0 20px; + position: absolute; + top: 0; + visibility: visible; + width: 100%; + z-index: 511; + + .list { + display: flex; + flex-flow: column; + justify-items: center; + position: relative; + } + + .panel-toggle { + background-color: transparent; + border: none; + position: absolute; + right: 0; + top: 0; + + @include breakpoint($wide) { + padding: 26px 32px; + } + + &__label { + @include font-size(16px, 20px); + @include font-weight($bold); + color: var(--grayscale-white); + display: flex; + font-family: var(--main-font-family); + letter-spacing: -0.5px; + text-transform: uppercase; + + &__title { + padding-right: 12px; + } + + &:hover { + cursor: pointer; + span { + color: var(--grayscale-medium); + } + svg { + fill: var(--grayscale-medium); + } + } + } + } + + .menu-main-link { + @include font-size(16px, 20px); + align-items: center; + display: flex; + font-family: var(--main-font-family); + flex-direction: row; + margin-bottom: 20px; + text-decoration: none; + + &:hover { + span { + color: var(--grayscale-medium); + } + svg { + fill: var(--grayscale-medium); + } + } + } + .menu--main-group__label { + color: var(--grayscale-white); + margin-left: 12px; + } + } +} + +:host(.menu--main-group--mobile) { + align-items: center; + display: flex; + flex-flow: row; + position: relative; + + @include breakpoint($wide) { + margin-left: 40px; + } +} + +.menu--main-group__mobile-toggle { + border: none; + background: transparent; + padding: 15px 16px 15px 12px; + + @include breakpoint($narrow) { + padding: 15px 28px 15px 15px; + } + + &:hover { + cursor: pointer; + } +} + +.menu--main-group__dropdown__top { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-bottom: 23px; +} + +.menu--main-group__dropdown__close { + border: none; + background-color: transparent; + padding: 0; + margin: 0; + + &:hover { + cursor: pointer; + } +} + +.menu--main-group__logo-container .hy-site-logo__label.group { + max-width: 250px; +} + +.menu--main-group__dropdown__items { + display: flex; + flex-direction: column; + + .menu-main-link { + @include font-size(15px, 20px); + + background-color: var(--grayscale-dark-text); + color: var(--grayscale-white); + font-family: var(--main-font-family); + letter-spacing: -0.5px; + margin-bottom: 8px; + padding: 14px 20px; + text-decoration: none; + width: 100%; + + &:hover { + text-decoration: underline; + } + } +} + +.menu--main-group__dropdown__donate { + display: flex; + flex-direction: row; + justify-content: center; + background-color: var(--grayscale-dark-text); + position: fixed; + bottom: 0; + margin-left: -20px; + width: 100%; + + .hy-link__donate.group { + @include font-size(16px, 16px); + @include font-weight($semibold); + + display: flex; + color: var(--grayscale-white); + font-family: var(--main-font-family); + margin: 20px auto 16px auto; + text-decoration: none; + + .hy-link__donate__label { + margin-left: 6px; + } + } +} + +.menu--main-group__dropdown--mobile { + -webkit-box-direction: normal; + -webkit-box-orient: vertical; + background-color: var(--grayscale-black); + bottom: 0px; + display: flex; + flex-direction: column; + justify-items: space-between; + max-width: 400px; + overflow: hidden; + padding: 0px; + place-items: stretch; + position: fixed; + right: 0px; + top: 0px; + transform: translateX(100%); + transition: all 0.3s ease 0s; + visibility: hidden; + width: 0px; + + &.is-open { + padding: 50px 20px 20px; + transform: translateX(0px); + transition: transform 0.3s cubic-bezier(0, 0, 0.3, 1); + visibility: visible; + width: 90%; + z-index: 101; + + &::after { + opacity: 1; + visibility: visible; + } + } +} diff --git a/src/components/navigation/hy-menu-main-group/hy-menu-main-group.tsx b/src/components/navigation/hy-menu-main-group/hy-menu-main-group.tsx new file mode 100644 index 0000000000000000000000000000000000000000..216984d762a7a4a09ae13846714bd7a1adf9f01f --- /dev/null +++ b/src/components/navigation/hy-menu-main-group/hy-menu-main-group.tsx @@ -0,0 +1,263 @@ +export interface MainMenu { + label: string; + url: string; + menuLinkId: string; +} + +export interface DonateLink { + url: string; + label: string; +} + +import {Component, Host, h, Element, Prop, State, Watch, Listen, Event, EventEmitter} from '@stencil/core'; +import {ColorVariant, SiteLogoSize} from '../../../utils/utils'; + +let keys = { + enter: 'Enter', +}; + +@Component({ + tag: 'hy-menu-main-group', + styleUrl: 'hy-menu-main-group.scss', + shadow: true, +}) +export class HyMenuMainGroup { + @Element() el: HTMLElement; + @Prop() menuLabel: string = 'University main menu'; + @Prop() dataMainMenu: MainMenu[] | string; + @Prop() isMobile: boolean = false; + @Prop() logoUrl?: string; + @Prop() logoLabel?: string; + @Prop() siteLabel?: string; + @Prop() siteUrl?: string; + @Prop() donate: DonateLink[]; + @State() isMenuOpen: boolean = false; + + @Event() universityMainMenuToggled: EventEmitter; + @Event() mobileMenuTopToggle: EventEmitter; + + private _dataMainMenu: MainMenu[]; + + @Watch('dataMainMenu') + dataMainMenuWatcher(data: MainMenu[] | string) { + this._dataMainMenu = typeof data === 'string' ? JSON.parse(data) : data; + } + + @Listen('click') + handleComponentClick(event) { + event.preventDefault(); + event.stopPropagation(); + this.isMenuOpen = !this.isMenuOpen; + + if (this.isMenuOpen) { + this.emitEvent(); + this.adjustMainMenuPosition(event.target); + } + } + + @Listen('keydown') + handleComponentKeyDown(event: KeyboardEvent) { + event.stopPropagation(); + event.preventDefault(); + const key = event.code; + let target = event.target as HTMLButtonElement; + + if (target && [keys.enter].includes(key)) { + this.isMenuOpen = !this.isMenuOpen; + + if (this.isMenuOpen) { + this.emitEvent(); + this.adjustMainMenuPosition(target); + } + } + } + + emitEvent() { + // Close other panels if they are open (lang menu, search, main menu, ..). + this.universityMainMenuToggled.emit(); + this.mobileMenuTopToggle.emit(); + } + + adjustMainMenuPosition(target) { + let hyTopHeader = this.el.closest('.hy-site-header__content-top') as HTMLElement; + + if (hyTopHeader && !hyTopHeader.hasAttribute('is-mobile')) { + let mainMenuToggle = target.shadowRoot.querySelector('.menu--main-group__toggle') as HTMLElement; + let mainMenuDropdown = target.shadowRoot.querySelector('.menu--main-group__dropdown') as HTMLElement; + let mainMenuList = target.shadowRoot.querySelector('.list') as HTMLElement; + if (mainMenuDropdown && mainMenuList && mainMenuToggle) { + let rectHeader = hyTopHeader.getBoundingClientRect(); + let rectMenuToggle = mainMenuToggle.getBoundingClientRect(); + mainMenuDropdown.style.top = `${rectHeader.height}px`; + + mainMenuList.style.left = `${rectMenuToggle.left}px`; + } + } + } + + componentWillRender() { + this.dataMainMenuWatcher(this.dataMainMenu); + } + + handleMainMenuClose(event) { + this.isMenuOpen = false; + event.stopPropagation(); + } + + handleTopMenuClose(event) { + this.isMenuOpen = false; + this.mobileMenuTopToggle.emit(); + event.stopPropagation(); + } + + // Close the University main menu if user clicks anywhere outside the component. + @Listen('click', {target: 'window'}) + handleOutsideMenuClick(event) { + this.isMenuOpen = false; + this.handleTopMenuClose(event); + event.stopPropagation(); + } + + // CLose the University main menu if user opens the desktop menu panel. + @Listen('menuDesktopToggled', {target: 'document'}) + desktopMenuToggled() { + this.isMenuOpen = false; + } + + // CLose the University main menu if user opens the search panel + @Listen('searchPanelToggled', {target: 'document'}) + searchPanelToggled() { + this.isMenuOpen = false; + } + + // CLose the University main menu if user opens the language menu panel. + @Listen('menuLanguageToggled', {target: 'document'}) + languageMenuToggled() { + this.isMenuOpen = false; + } + + render() { + const white = 'var(--grayscale-white)'; + const logoSizeGroup = this.isMobile ? SiteLogoSize.small : SiteLogoSize.small; + const logoColorGroup = ColorVariant.white; + + return this.isMobile ? ( + <Host + class={{ + 'menu--main-group--mobile': true, + 'menu--main-group--mobile__is-open': this.isMenuOpen, + }} + > + <button + aria-label={this.menuLabel} + class={{ + 'menu--main-group__mobile-toggle': true, + 'is-open': this.isMenuOpen, + }} + > + <hy-icon icon={'hy-icon-slim-hamburger-menu'} size={20} fill={white} /> + </button> + <nav + role="navigation" + aria-hidden={this.isMenuOpen ? 'false' : 'true'} + class={{ + 'menu--main-group__dropdown--mobile': true, + 'is-open': this.isMenuOpen, + }} + > + <div class="menu--main-group__dropdown__top"> + <div class={'menu--main-group__logo-container'} id={'menu-logo'}> + <hy-site-logo + is-group={true} + size={logoSizeGroup} + color={logoColorGroup} + url={this.siteUrl} + label={this.siteLabel} + /> + </div> + <button + aria-label={`Close ${this.menuLabel}`} + class="menu--main-group__dropdown__close" + onClick={(e) => this.handleTopMenuClose(e)} + > + <hy-icon icon={'hy-icon-remove'} size={20} fill={white} /> + </button> + </div> + <div class="menu--main-group__dropdown__items"> + {this._dataMainMenu.map((item) => { + return ( + <a href={item.url} class={{'menu-main-link': true}}> + <span class={'menu--main-group__label'}>{item.label}</span> + </a> + ); + })} + </div> + <div class="menu--main-group__dropdown__donate"> + {this.donate && + this.donate.map((i) => { + return ( + <a class={'menu--secondary__item hy-link__donate group'} href={i.url}> + <hy-icon icon={'hy-icon-heart-support'} size={14} fill={logoColorGroup} /> + <span class={'hy-link__donate__label group'}>{i.label}</span> + </a> + ); + })} + </div> + </nav> + </Host> + ) : ( + <Host + class={{ + 'menu--main-group': true, + 'menu--main-group__is-open': this.isMenuOpen, + }} + > + <button + class={{ + 'menu--main-group__toggle': true, + 'is-open': this.isMenuOpen, + }} + //aria-label={this.isMenuOpen ? this._labels['close'] : this._labels['open']} + > + {this.isMenuOpen ? ( + <hy-icon class={'toggle__close'} icon={'hy-icon-remove'} size={8} fill={white} /> + ) : ( + <hy-icon class={'toggle__caret'} icon={'hy-icon-slim-hamburger-menu'} size={8} fill={white} /> + )} + <span>{this.menuLabel}</span> + </button> + <div + class={{ + 'menu--main-group__dropdown': true, + 'is-open': this.isMenuOpen, + }} + > + <div class="list"> + {this._dataMainMenu.map((item) => { + return ( + <a href={item.url} class={{'menu-main-link': true}}> + <span class="heading-icon"> + <hy-icon icon={'hy-icon-caret-right'} size={10} fill={white} /> + </span> + <span class={'menu--main-group__label'}>{item.label}</span> + </a> + ); + })} + </div> + <button + onClick={(e) => this.handleMainMenuClose(e)} + class={{ + 'panel-toggle': true, + }} + aria-label="Close menu" + > + <span class="panel-toggle__label"> + <span class="panel-toggle__label__title">Close</span> + <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.white} /> + </span> + </button> + </div> + </Host> + ); + } +} diff --git a/src/components/navigation/hy-menu-main-group/readme.md b/src/components/navigation/hy-menu-main-group/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..6892cdb6ccb19901797b6e6e6273ff08398de39f --- /dev/null +++ b/src/components/navigation/hy-menu-main-group/readme.md @@ -0,0 +1,49 @@ +# hy-menu-main-group + +<!-- Auto Generated Below --> + +## Properties + +| Property | Attribute | Description | Type | Default | +| -------------- | ---------------- | ----------- | ---------------------- | ------------------------ | +| `dataMainMenu` | `data-main-menu` | | `MainMenu[] \| string` | `undefined` | +| `donate` | -- | | `DonateLink[]` | `undefined` | +| `isMobile` | `is-mobile` | | `boolean` | `false` | +| `logoLabel` | `logo-label` | | `string` | `undefined` | +| `logoUrl` | `logo-url` | | `string` | `undefined` | +| `menuLabel` | `menu-label` | | `string` | `'University main menu'` | +| `siteLabel` | `site-label` | | `string` | `undefined` | +| `siteUrl` | `site-url` | | `string` | `undefined` | + +## Events + +| Event | Description | Type | +| --------------------------- | ----------- | ------------------ | +| `mobileMenuTopToggle` | | `CustomEvent<any>` | +| `universityMainMenuToggled` | | `CustomEvent<any>` | + +## Dependencies + +### Used by + +- [hy-site-header](../../site-header) + +### Depends on + +- [hy-icon](../../icon) +- [hy-site-logo](../../site-header/site-logo) + +### Graph + +```mermaid +graph TD; + hy-menu-main-group --> hy-icon + hy-menu-main-group --> hy-site-logo + hy-site-logo --> hy-icon + hy-site-header --> hy-menu-main-group + style hy-menu-main-group fill:#f9f,stroke:#333,stroke-width:4px +``` + +--- + +Helsinki University Design System diff --git a/src/components/navigation/menu-item-sidebar/menu-item-sidebar.scss b/src/components/navigation/menu-item-sidebar/menu-item-sidebar.scss index 3e465d6b541e9f674916a278b442cf729dc91eb7..6a349b8d19fcf005672f2dbe99fd6cd8a822a45c 100644 --- a/src/components/navigation/menu-item-sidebar/menu-item-sidebar.scss +++ b/src/components/navigation/menu-item-sidebar/menu-item-sidebar.scss @@ -62,8 +62,14 @@ &:hover { border: 1px solid var(--brand-main); margin: -1px; + margin-left: 4px; text-decoration: underline; cursor: pointer; + + svg { + width: 22px; + height: 22px; + } } } } diff --git a/src/components/navigation/menu-language/menu-language.scss b/src/components/navigation/menu-language/menu-language.scss index 44696d8a8c561af78fc78fc393da48fc13ba2056..1ef48a5e47e842c6028a26631b6609b3a2be068c 100644 --- a/src/components/navigation/menu-language/menu-language.scss +++ b/src/components/navigation/menu-language/menu-language.scss @@ -35,36 +35,35 @@ } .menu--language__toggle { - @include font-size(14px, 24px); align-items: center; - background: var(--grayscale-white); border: 0 none; - color: var(--brand-main-nearly-black); display: flex; flex-flow: row; font-family: var(--main-font-family); - font-weight: 600; - letter-spacing: -0.4px; margin: 0 -4px; padding: 0; text-transform: uppercase; - @include breakpoint($extrawide) { - @include font-size(12px, 12px); - font-weight: 400; - letter-spacing: -0.6px; + &:focus { + outline: solid 2px var(--additional-yellow); + outline-offset: 2px; } - @include breakpoint($xlarge) { - @include font-size(14px, 24px); - letter-spacing: -0.5px; + &.is-open { + .menu--language__toggle__caret { + transform: rotate(180deg); + } } - &:focus { - outline: solid 2px var(--additional-yellow); - outline-offset: 2px; + > * { + padding: 0 4px; + } + span { + padding: 0; } +} +.menu--language__toggle:not(.group) { &:hover { color: var(--brand-main); cursor: pointer; @@ -76,18 +75,43 @@ } } - &.is-open { - .menu--language__toggle__caret { - transform: rotate(180deg); - } + @include font-size(14px, 24px); + @include font-weight($semibold); + background: var(--grayscale-white); + color: var(--brand-main-nearly-black); + letter-spacing: -0.4px; + + @include breakpoint($extrawide) { + @include font-size(12px, 12px); + @include font-weight($regular); + letter-spacing: -0.6px; } - > * { - padding: 0 4px; + @include breakpoint($xlarge) { + @include font-size(14px, 24px); + letter-spacing: -0.5px; } - span { - padding: 0; +} + +.menu--language__toggle.group { + &:hover { + color: var(--grayscale-medium); + cursor: pointer; + span { + color: var(--grayscale-medium); + } + svg { + fill: var(--grayscale-medium); + } } + + background: var(--grayscale-black); + //border: 0 none; + color: var(--grayscale-white); + + @include font-size(14px, 24px); + @include font-weight($semibold); + letter-spacing: -0.5px; } .menu--language__dropdown { @@ -126,7 +150,7 @@ } } -.menu--language__globe-icon svg { +.menu--language__globe-icon:not(.group) svg { @include breakpoint($wide) { height: 16px; width: 16px; diff --git a/src/components/navigation/menu-language/menu-language.tsx b/src/components/navigation/menu-language/menu-language.tsx index 6af56d647fbb051252f2c2293573d683426cfb15..8223824f875c5537aefd7161ee837c29475d253b 100644 --- a/src/components/navigation/menu-language/menu-language.tsx +++ b/src/components/navigation/menu-language/menu-language.tsx @@ -20,6 +20,7 @@ export class MenuLanguage { @Element() el: HTMLElement; @Prop() dataMenuLanguage: MenuLanguage[] | string; @Prop() isMobile: boolean = false; + @Prop() isGroup: boolean = false; @Prop() labels?: ComponentLabels[] | string; @State() isMenuOpen: boolean = false; @@ -55,6 +56,12 @@ export class MenuLanguage { this.isMenuOpen = false; } + // Close the language menu if user opens University main menu + @Listen('universityMainMenuToggled', {target: 'document'}) + universityMainMenuPanelToggled() { + this.isMenuOpen = false; + } + @Listen('focus') handleComponentFocus(event) { // Close desktop menu panel if it's open. @@ -66,24 +73,35 @@ export class MenuLanguage { @Listen('click') handleComponentClick(event) { this.isMenuOpen = !this.isMenuOpen; - const languageMenuSelector = event.target as HTMLElement; if (this.isMenuOpen) { // Close desktop menu panel if it's open. this.menuLanguageToggled.emit(); - let hyHeader = this.el.closest('.hy-site-header') as HTMLElement; + const languageMenuSelector = event.target as HTMLElement; + this.adjustPosition(languageMenuSelector, this.el); + } + + event.stopPropagation(); + } + + adjustPosition(languageMenuSelector, target) { + const languagePanel = languageMenuSelector.shadowRoot.querySelectorAll( + `.menu--language__dropdown` + )[0] as HTMLElement; + let headerHeight = '0'; + let hyHeader = this.isGroup + ? (target.closest('.hy-site-header__content-top') as HTMLElement) + : (target.closest('.hy-site-header') as HTMLElement); + + if (hyHeader) { let rectHeader = hyHeader.getBoundingClientRect(); let rectLangMenu = languageMenuSelector.getBoundingClientRect(); - const headerHeight = `${languageMenuSelector.offsetHeight + rectHeader.bottom + 8 - rectLangMenu.bottom}px`; - const languagePanel = languageMenuSelector.shadowRoot.querySelectorAll( - `.menu--language__dropdown` - )[0] as HTMLElement; - languagePanel.style.top = headerHeight; + headerHeight = `${languageMenuSelector.offsetHeight + rectHeader.bottom + 8 - rectLangMenu.bottom}px`; } - event.stopPropagation(); + languagePanel.style.top = headerHeight; } componentWillRender() { @@ -93,6 +111,9 @@ export class MenuLanguage { render() { const black = 'var(--brand-main-nearly-black)'; + const white = 'var(--grayscale-white)'; + const svgColor = this.isGroup ? white : black; + const globeIconSize = this.isGroup ? 16 : 14; return this.isMobile ? ( <Host class={'menu--language'}> @@ -121,18 +142,24 @@ export class MenuLanguage { class={{ 'menu--language__toggle': true, 'is-open': this.isMenuOpen, + group: this.isGroup, }} aria-label={this.isMenuOpen ? this._labels['close'] : this._labels['open']} > - <hy-icon class={'menu--language__globe-icon'} icon={'hy-icon-globe'} size={14} fill={black} /> - <span> + <hy-icon + class={{'menu--language__globe-icon': true, group: this.isGroup}} + icon={'hy-icon-globe'} + size={globeIconSize} + fill={svgColor} + /> + <span class={{group: this.isGroup}}> {this._dataMenuLanguage.map((item) => { if (item.isActive) { return item.langCode; } })} </span> - <hy-icon class={'menu--language__toggle__caret'} icon={'hy-icon-caret-down'} size={8} fill={black} /> + <hy-icon class={'menu--language__toggle__caret'} icon={'hy-icon-caret-down'} size={8} fill={svgColor} /> </button> <div class={{ diff --git a/src/components/navigation/menu-language/readme.md b/src/components/navigation/menu-language/readme.md index cd19087f41c16dbb1539d4d4f160d5dec500384d..2d76900516d1a16e4e1c49cf8cc81bd237376335 100644 --- a/src/components/navigation/menu-language/readme.md +++ b/src/components/navigation/menu-language/readme.md @@ -7,6 +7,7 @@ | Property | Attribute | Description | Type | Default | | ------------------ | -------------------- | ----------- | ----------------------------- | ----------- | | `dataMenuLanguage` | `data-menu-language` | | `MenuLanguage[] \| string` | `undefined` | +| `isGroup` | `is-group` | | `boolean` | `false` | | `isMobile` | `is-mobile` | | `boolean` | `false` | | `labels` | `labels` | | `ComponentLabels[] \| string` | `undefined` | diff --git a/src/components/navigation/menu/menu.scss b/src/components/navigation/menu/menu.scss index 8ea72d4ebe01f8a578c7a76aa6f86939340b0ecd..5d38d130526d680328434db5715867ff94a000c1 100644 --- a/src/components/navigation/menu/menu.scss +++ b/src/components/navigation/menu/menu.scss @@ -14,6 +14,11 @@ position: absolute; right: 0; top: 0; + z-index: 99; + + &.is-open { + z-index: 101; + } } &--desktop { diff --git a/src/components/navigation/menu/menu.tsx b/src/components/navigation/menu/menu.tsx index 2293aaf43215ed8e494e3cba89fb891b5c1c8e0e..7353db8d4ce6e0ecdbad5fbc9c3d5431b002c14d 100644 --- a/src/components/navigation/menu/menu.tsx +++ b/src/components/navigation/menu/menu.tsx @@ -12,6 +12,7 @@ export class Menu { @Event() menuContainerToggled: EventEmitter; @Prop() dataMenuDonate: string; @Prop() dataMenuLanguage: string; + @Prop() isGroup: boolean = false; @Prop() isDemo: boolean = false; @Prop() labelFrontPage: string; @Prop() logoUrl: string; @@ -193,13 +194,15 @@ export class Menu { <slot /> </div> </div> - <div class={'hy-link__donate'}> - {this.donateLink - ? this.donateLink.map((i) => { - return <a href={i.url}>{i.label}</a>; - }) - : ''} - </div> + {!this.isGroup && ( + <div class={'hy-link__donate'}> + {this.donateLink + ? this.donateLink.map((i) => { + return <a href={i.url}>{i.label}</a>; + }) + : ''} + </div> + )} </nav> ); } diff --git a/src/components/navigation/menu/readme.md b/src/components/navigation/menu/readme.md index 01d7e789433afc32665c088414925cc658858c82..6dce64e59f6434ed616652572b4863a52e248db8 100644 --- a/src/components/navigation/menu/readme.md +++ b/src/components/navigation/menu/readme.md @@ -9,6 +9,7 @@ | `dataMenuDonate` | `data-menu-donate` | | `string` | `undefined` | | `dataMenuLanguage` | `data-menu-language` | | `string` | `undefined` | | `isDemo` | `is-demo` | | `boolean` | `false` | +| `isGroup` | `is-group` | | `boolean` | `false` | | `labelFrontPage` | `label-front-page` | | `string` | `undefined` | | `logoLabel` | `logo-label` | | `string` | `undefined` | | `logoUrl` | `logo-url` | | `string` | `undefined` | diff --git a/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.scss b/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.scss index 414e33890d06748dd3bd8e1c376058f0142bbd5d..9ade9e6a2f678a1dcb9ec0c47c78e25f6bc8c059 100644 --- a/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.scss +++ b/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.scss @@ -58,6 +58,10 @@ padding: 0 9px; } + &.toggle { + text-decoration: none; + } + &__label { position: relative; width: min-content; diff --git a/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx b/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx index 405849de63b0784311cfeba394e6f4e386e50d99..dd4bdca7935cbecb7e5e59e24ab541421143b99b 100644 --- a/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx +++ b/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx @@ -10,6 +10,7 @@ export interface DesktopLinks { labelExtra: string; url: string; description: string; + toggleOff: string; menuLinkId: string; isExternal: string; isActive: string; @@ -271,6 +272,13 @@ export class HyDesktopMenuLinks { this.closePanel(fadeOut); } + // Close the desktop menu panel if user opens University main menu + @Listen('universityMainMenuToggled', {target: 'document'}) + universityMainMenuPanelToggled() { + let fadeOut = true; + this.closePanel(fadeOut); + } + // Close the desktop menu panel if user opens search panel @Listen('searchPanelToggled', {target: 'document'}) searchPanelToggled() { @@ -383,6 +391,7 @@ export class HyDesktopMenuLinks { items, url, description, + toggleOff, label, labelExtra, isExternal, @@ -400,106 +409,118 @@ export class HyDesktopMenuLinks { ].join(' '); let target = isExternal ? '_blank' : '_self'; - menuLinkItems.push( - <li> - <button - type="button" - class={classAttributes} - link-id={id} - onMouseDown={(e) => this.handleDesktopMenuClick(e, id)} - onFocus={(e) => this.handleDesktopMenuFocus(e, id)} - onMouseEnter={(e) => this.handleDesktopMenuEnter(e, id)} - onMouseMove={(e) => this.handleDesktopMenuMove(e, id)} - aria-expanded="false" - > - <span class={classAttributesLabel}>{label}</span> - <hy-icon icon={'hy-icon-caret-down'} size={32} /> - </button> - <div class="hy-desktop-menu-panel" aria-hidden="true"> - <div class="hy-desktop-menu-panel__desktop-menu"> - <div class="hy-desktop-menu-panel__desktop-menu__menu-items"> - <a - aria-current={label} - href={url} - target={target} - class="hy-desktop-menu-panel__desktop-menu__first-level-menu-item" - menu-link-id={id} - > - <span class="heading-icon"> - <hy-icon icon={'hy-icon-arrow-right'} size={40} /> - </span> - {labelExtra ? <span class="label">{labelExtra}</span> : <span class="label">{label}</span>} - {description && <span class="description">{description}</span>} - </a> - <ul class={'hy-desktop-menu-panel__desktop-menu__second-level-menu'} menu-link-id={id}> - {items.map(({label, url, isExternal}) => { - let subitemTarget = isExternal ? '_blank' : '_self'; - return ( - <li> - <a href={url} target={subitemTarget}> - <span class="heading-icon"> - <hy-icon icon={'hy-icon-caret-right'} size={12} /> - </span> - <span class="label">{label}</span> - {isExternal && ( - <span class="external-icon"> - <hy-icon icon={'hy-icon-arrow-right'} size={12} /> - </span> - )} - </a> - </li> - ); - })} - </ul> - </div> - {shortcuts.length > 0 && ( - <ul class="shortcuts-panel"> - <h2 class="shortcuts-panel__title">{shortcutsTitle}</h2> - {shortcuts.map( - ({shortcut_title, shortcut_url, shortcut_is_external, shortcut_aria_label}, index) => { - let target = shortcut_is_external ? '_blank' : '_self'; - - let shortcutClass = [ - 'shortcuts-panel__shortcut-item', - index == 0 ? 'shortcuts-panel__shortcut-item__first' : '', - ].join(' '); - + if (toggleOff == 'true') { + //console.log('toggleOff if true: show as a link: ' + label); + menuLinkItems.push( + <li onMouseEnter={(e) => this.handleDesktopMenuClose(e)}> + <a aria-current={label} href={url} target={target} class="desktop-menu-link toggle" menu-link-id={id}> + {labelExtra ? <span class="label">{labelExtra}</span> : <span class="label">{label}</span>} + </a> + </li> + ); + } else { + //console.log('toggleOff is false: show as a dropdown: ' + label); + menuLinkItems.push( + <li> + <button + type="button" + class={classAttributes} + link-id={id} + onMouseDown={(e) => this.handleDesktopMenuClick(e, id)} + onFocus={(e) => this.handleDesktopMenuFocus(e, id)} + onMouseEnter={(e) => this.handleDesktopMenuEnter(e, id)} + onMouseMove={(e) => this.handleDesktopMenuMove(e, id)} + aria-expanded="false" + > + <span class={classAttributesLabel}>{label}</span> + <hy-icon icon={'hy-icon-caret-down'} size={32} /> + </button> + <div class="hy-desktop-menu-panel" aria-hidden="true"> + <div class="hy-desktop-menu-panel__desktop-menu"> + <div class="hy-desktop-menu-panel__desktop-menu__menu-items"> + <a + aria-current={label} + href={url} + target={target} + class="hy-desktop-menu-panel__desktop-menu__first-level-menu-item" + menu-link-id={id} + > + <span class="heading-icon"> + <hy-icon icon={'hy-icon-arrow-right'} size={40} /> + </span> + {labelExtra ? <span class="label">{labelExtra}</span> : <span class="label">{label}</span>} + {description && <span class="description">{description}</span>} + </a> + <ul class={'hy-desktop-menu-panel__desktop-menu__second-level-menu'} menu-link-id={id}> + {items.map(({label, url, isExternal}) => { + let subitemTarget = isExternal ? '_blank' : '_self'; return ( - <li class={shortcutClass}> - <a - aria-current={shortcut_aria_label} - href={shortcut_url} - class="shortcut-item__link" - target={target} - aria-label={shortcut_aria_label} - > - <span class="label">{shortcut_title}</span> - <span class="icon"> - <hy-icon icon={'hy-icon-arrow-right'} size={24} /> + <li> + <a href={url} target={subitemTarget}> + <span class="heading-icon"> + <hy-icon icon={'hy-icon-caret-right'} size={12} /> </span> + <span class="label">{label}</span> + {isExternal && ( + <span class="external-icon"> + <hy-icon icon={'hy-icon-arrow-right'} size={12} /> + </span> + )} </a> </li> ); - } - )} - </ul> - )} + })} + </ul> + </div> + {shortcuts.length > 0 && ( + <ul class="shortcuts-panel"> + <h2 class="shortcuts-panel__title">{shortcutsTitle}</h2> + {shortcuts.map( + ({shortcut_title, shortcut_url, shortcut_is_external, shortcut_aria_label}, index) => { + let target = shortcut_is_external ? '_blank' : '_self'; + + let shortcutClass = [ + 'shortcuts-panel__shortcut-item', + index == 0 ? 'shortcuts-panel__shortcut-item__first' : '', + ].join(' '); + + return ( + <li class={shortcutClass}> + <a + aria-current={shortcut_aria_label} + href={shortcut_url} + class="shortcut-item__link" + target={target} + aria-label={shortcut_aria_label} + > + <span class="label">{shortcut_title}</span> + <span class="icon"> + <hy-icon icon={'hy-icon-arrow-right'} size={24} /> + </span> + </a> + </li> + ); + } + )} + </ul> + )} + </div> + <button + onClick={(e) => this.handleDesktopMenuClose(e)} + class={{ + 'hy-desktop-menu-panel__panel-toggle': true, + }} + aria-label="Close menu" + > + <span class="hy-desktop-menu-panel__panel-toggle__label"> + <span class="hy-desktop-menu-panel__panel-toggle__label__title">{closeButtonTitle}</span> + <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} /> + </span> + </button> </div> - <button - onClick={(e) => this.handleDesktopMenuClose(e)} - class={{ - 'hy-desktop-menu-panel__panel-toggle': true, - }} - aria-label="Close menu" - > - <span class="hy-desktop-menu-panel__panel-toggle__label"> - <span class="hy-desktop-menu-panel__panel-toggle__label__title">{closeButtonTitle}</span> - <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} /> - </span> - </button> - </div> - </li> - ); + </li> + ); + } } ); } diff --git a/src/components/site-header/readme.md b/src/components/site-header/readme.md index 8395afe73fd1ddc6ce5c213b18c6973417c2ee43..c656f9976e2d6ee297f6cd7e8a03e341ca2e13f5 100644 --- a/src/components/site-header/readme.md +++ b/src/components/site-header/readme.md @@ -7,47 +7,55 @@ | Property | Attribute | Description | Type | Default | | ---------------------- | ------------------------- | ----------- | -------------------------------------------------------------------------------------------------- | ------------------ | | `dataDesktopLinks` | `data-desktop-links` | | `DesktopLinks[] \| string` | `undefined` | +| `dataMainMenuLinks` | `data-main-menu-links` | | `DesktopLinks[] \| string` | `undefined` | | `dataMenuDonate` | `data-menu-donate` | | `string` | `undefined` | | `dataMenuLanguage` | `data-menu-language` | | `string` | `undefined` | | `dataSearchTools` | `data-search-tools` | | `DesktopLinks[] \| string` | `undefined` | | `dataSiteHeaderLabels` | `data-site-header-labels` | | `string` | `undefined` | | `dataSiteSearchLabels` | `data-site-search-labels` | | `string` | `undefined` | +| `isGroup` | `is-group` | | `boolean` | `false` | | `logoLabel` | `logo-label` | | `string` | `undefined` | | `logoUrl` | `logo-url` | | `string` | `undefined` | | `menuLabel` | `menu-label` | | `string` | `'Menu'` | | `menuLabelClose` | `menu-label-close` | | `string` | `undefined` | | `menuLabelOpen` | `menu-label-open` | | `string` | `undefined` | | `menuType` | `menu-type` | | `MenuType.desktop \| MenuType.mobile \| MenuType.sidenav \| MenuType.sidepanel \| MenuType.tablet` | `MenuType.default` | +| `siteLabel` | `site-label` | | `string` | `undefined` | +| `siteUrl` | `site-url` | | `string` | `undefined` | ## Events -| Event | Description | Type | -| ------------------- | ----------- | ------------------ | -| `headerScrollDown` | | `CustomEvent<any>` | -| `headerScrollUp` | | `CustomEvent<any>` | -| `menuMobileToggled` | | `CustomEvent<any>` | +| Event | Description | Type | +| ---------------------- | ----------- | ------------------ | +| `headerScrollDown` | | `CustomEvent<any>` | +| `headerScrollUp` | | `CustomEvent<any>` | +| `menuMobileToggled` | | `CustomEvent<any>` | +| `menuMobileTopToggled` | | `CustomEvent<any>` | ## Dependencies ### Depends on - [hy-site-logo](site-logo) -- [hy-desktop-menu-links](hy-desktop-menu-links) +- [hy-menu-main-group](../navigation/hy-menu-main-group) - [hy-menu-language](../navigation/menu-language) - [hy-site-search](site-search) - [hy-icon](../icon) +- [hy-desktop-menu-links](hy-desktop-menu-links) ### Graph ```mermaid graph TD; hy-site-header --> hy-site-logo - hy-site-header --> hy-desktop-menu-links + hy-site-header --> hy-menu-main-group hy-site-header --> hy-menu-language hy-site-header --> hy-site-search hy-site-header --> hy-icon + hy-site-header --> hy-desktop-menu-links hy-site-logo --> hy-icon - hy-desktop-menu-links --> hy-icon + hy-menu-main-group --> hy-icon + hy-menu-main-group --> hy-site-logo hy-menu-language --> hy-menu-language-item hy-menu-language --> hy-icon hy-site-search --> hy-icon @@ -55,6 +63,7 @@ graph TD; hy-site-search --> hy-paragraph-text hy-search-field --> hy-icon hy-paragraph-text --> hy-box + hy-desktop-menu-links --> hy-icon style hy-site-header fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/src/components/site-header/site-header.scss b/src/components/site-header/site-header.scss index 69c07639f8efdf49bdceade70d30d6ad26814ab7..0125889da69c19db210c2c8bd2732cf3f1c2e34d 100644 --- a/src/components/site-header/site-header.scss +++ b/src/components/site-header/site-header.scss @@ -34,7 +34,6 @@ top: 0; } } - .hy-site-header__content { align-items: center; box-shadow: rgba(14, 104, 139, 0.2) 0 20px 20px -20px; @@ -58,6 +57,52 @@ @include breakpoint($xlarge) { height: 112px; } + + // Group menus on group pages + &.group { + @include breakpoint($narrow) { + justify-content: flex-start; + } + } +} + +.hy-site-header__content-top { + align-items: center; + background-color: var(--grayscale-black); + color: var(--grayscale-white); + display: flex; + flex-flow: row; + place-content: center space-between; + position: relative; + z-index: 99; + + &.is-open { + z-index: 98; + } + + @include breakpoint($narrow) { + margin: 0 auto; + max-width: $fullhd; + } + + &__main-menu-container { + color: var(--grayscale-white); + } + + &__main-menu { + background-color: black; + color: white; + display: none; + position: absolute; + bottom: 0; + left: 0; + } + + .menu--secondary--group { + display: flex; + justify-content: center; + align-items: center; + } } .hy-site-header__logo-container { @@ -67,11 +112,9 @@ @include breakpoint($narrow) { margin: 16px 16px 16px 28px; } - @include breakpoint($wide) { margin: 16px 24px; } - @include breakpoint($extrawide) { margin: 16px; } @@ -86,12 +129,47 @@ fill: var(--brand-main); } } + + &.group { + align-items: center; + display: flex; + flex-direction: row; + + margin: 12px; + @include breakpoint($narrow) { + margin: 12px 24px; + } + @include breakpoint($wide) { + margin: 6px 24px; + } + @include breakpoint($extrawide) { + margin: 8px 24px; + } + @include breakpoint($xlarge) { + margin: 8px 32px; + } + + &:hover { + color: var(--grayscale-medium); + a, + span { + color: var(--grayscale-medium) !important; + } + svg { + fill: var(--grayscale-medium); + } + } + } } .hy-site-header__menu-container { align-items: center; display: flex; - z-index: 510; + z-index: 99; + + &.is-open { + z-index: 101; + } } .hy-site-header__panel { @@ -192,7 +270,15 @@ transition: background-color 300ms; visibility: visible; width: inherit; //?? - z-index: 99; + z-index: 100; + } + + &.is-active-top { + background-color: rgba(0, 0, 0, 0.4); + transition: background-color 300ms; + visibility: visible; + width: inherit; //?? + z-index: 98; } } @@ -240,9 +326,9 @@ } .hy-link__donate { + font-family: var(--main-font-family); + @include breakpoint($wide) { - //margin-left: 10px; - //margin-right: 10px; padding: 0; text-decoration: none; @@ -253,30 +339,43 @@ } @include breakpoint($extrawide) { - //margin-left: 8px; - //margin-right: 32px; margin-right: 0; } - @include breakpoint($xlarge) { - //margin-left: 10px; - //margin-right: 32px; + &__label { + font-family: var(--main-font-family); + margin-left: 4px; + text-decoration: none; } +} - &__label { +.hy-link__donate:not(.group) { + svg { + @include breakpoint($wide) { + height: 16px; + width: 13.64px; + } + @include breakpoint($extrawide) { + height: 12px; + width: 10.23px; + } + @include breakpoint($xlarge) { + height: 16px; + width: 13.64px; + } + } + + .hy-link__donate__label { @include breakpoint($wide) { @include font-size(14px, 24px); + @include font-weight($semibold); color: var(--brand-main-nearly-black); - font-family: var(--main-font-family); - font-weight: 600; letter-spacing: -0.5px; - margin-left: 4px; - text-decoration: none; } @include breakpoint($extrawide) { @include font-size(12px, 12px); - font-weight: 400; + @include font-weight($regular); letter-spacing: -0.6px; } @@ -285,19 +384,25 @@ letter-spacing: -0.5px; } } +} - svg { +.hy-link__donate.group { + .hy-link__donate__label { @include breakpoint($wide) { - height: 16px; - width: 13.64px; + @include font-size(14px, 24px); + @include font-weight($semibold); + color: var(--grayscale-white); + letter-spacing: -0.5px; } - @include breakpoint($extrawide) { - height: 12px; - width: 10.23px; + } + + &:hover { + color: var(--grayscale-medium); + span { + color: var(--grayscale-medium); } - @include breakpoint($xlarge) { - height: 16px; - width: 13.64px; + svg { + fill: var(--grayscale-medium); } } } diff --git a/src/components/site-header/site-header.tsx b/src/components/site-header/site-header.tsx index 85b0dab79199b37bfa841dde9603c19b877e4836..8ceb92a483da7123ee407812547329d85344d6c0 100644 --- a/src/components/site-header/site-header.tsx +++ b/src/components/site-header/site-header.tsx @@ -25,12 +25,15 @@ import {MenuType, ColorVariant, SiteLogoSize} from '../../utils/utils'; }) export class SiteHeader { @Element() el: HTMLElement; + @Prop() isGroup: boolean = false; @Prop() dataMenuLanguage: string; @Prop() dataMenuDonate: string; @Prop() dataSiteHeaderLabels: string; @Prop() dataSiteSearchLabels: string; @Prop() logoUrl?: string; @Prop() logoLabel?: string; + @Prop() siteLabel?: string; + @Prop() siteUrl?: string; @Prop() menuLabel: string = 'Menu'; @Prop() menuLabelOpen?: string; @Prop() menuLabelClose?: string; @@ -39,20 +42,24 @@ export class SiteHeader { First level menu links to be displayed on Desktop screens. * */ @Prop() dataDesktopLinks: DesktopLinks[] | string; + @Prop() dataMainMenuLinks: DesktopLinks[] | string; @Prop() dataSearchTools: DesktopLinks[] | string; @State() isMobile: boolean; @State() isMenuOpen: boolean = false; @State() isDesktopMenuOpen: boolean = false; + @State() isTopMenuOpen: boolean = false; @Event() headerScrollUp: EventEmitter; @Event() headerScrollDown: EventEmitter; @Event() menuMobileToggled: EventEmitter; + @Event() menuMobileTopToggled: EventEmitter; private ro: ResizeObserver; private donateLink: DonateLink[]; private menuLabels: ComponentLabels[]; private searchLabels: ComponentLabels[]; + private groupPages: ComponentLabels[]; private languageLabels: ComponentLabels[]; @State() lastScrollTop = 0; @@ -67,6 +74,13 @@ export class SiteHeader { this.menuMobileToggled.emit(); } + // Listener for toggling mobile menu top panel on or off. + @Listen('mobileMenuTopToggle') mobileMenuTopToggle() { + //this.isMenuOpen = !this.isMenuOpen; + this.isTopMenuOpen = !this.isTopMenuOpen; + this.menuMobileTopToggled.emit(); + } + @Listen('scroll', {target: 'window'}) handleScroll() { if (this.el.getAttribute('menu-type') === 'desktop') { @@ -96,6 +110,7 @@ export class SiteHeader { this.menuLabels = labels.menu_labels; this.languageLabels = labels.language_labels; this.searchLabels = labels.search_labels; + this.groupPages = labels.group_pages; this.el.children[0].setAttribute('menu-button-breadcrumb-home', this.menuLabels['home']); this.el.children[0].setAttribute('menu-button-breadcrumb-main', this.menuLabels['main']); @@ -116,6 +131,8 @@ export class SiteHeader { this.el.children[0].setAttribute('open', this.isMenuOpen.toString()); this.el.children[0].setAttribute('logo-label', this.logoLabel); this.el.children[0].setAttribute('logo-url', this.logoUrl); + this.el.children[0].setAttribute('site-label', this.siteLabel); + this.el.children[0].setAttribute('site-url', this.siteUrl); this.el.children[0].setAttribute('menu-button-submenu-expand', this.menuLabels['expand']); this.el.children[0].setAttribute('menu-button-breadcrumb-return', this.menuLabels['return']); this.el.children[0].setAttribute('menu-button-breadcrumb-home', this.menuLabels['home']); @@ -211,82 +228,194 @@ export class SiteHeader { render() { const logoSize = this.isMobile ? SiteLogoSize.small : SiteLogoSize.big; + const logoSizeGroup = this.isMobile ? SiteLogoSize.small : SiteLogoSize.small; const logoColor = ColorVariant.black; + const logoColorGroup = ColorVariant.white; let classAttributes = ['hy-site-header', 'hy-site-header--' + this.menuType]; - switch (this.menuType) { case MenuType.desktop: + // Larger than 1200px screens return [ <header class={classAttributes.join(' ')}> <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} /> - <div class="hy-site-header__content"> + {this.isGroup && ( + <div class="hy-site-header__content-top"> + <div class={'hy-site-header__logo-container group '} role="navigation"> + <hy-site-logo + is-group={true} + size={logoSizeGroup} + color={logoColorGroup} + url={this.siteUrl} + label={this.siteLabel} + /> + <hy-menu-main-group + tabindex="0" + is-mobile={false} + menu-label={this.groupPages['university_main_menu'] ?? null} + data-main-menu={this.dataMainMenuLinks} + /> + </div> + + <div class={'menu--secondary menu--secondary--group'}> + <hy-menu-language + class={'menu--secondary__item is-first group'} + is-group={true} + is-mobile={false} + data-menu-language={this.dataMenuLanguage} + labels={this.languageLabels} + /> + <hy-site-search + class={'menu--secondary__item group'} + size={16} + color={logoColorGroup} + is-group={true} + show-label={true} + labels={this.searchLabels} + search-labels={this.dataSiteSearchLabels} + search-tools={this.dataSearchTools} + /> + {this.donateLink.map((i) => { + return ( + <a class={'menu--secondary__item hy-link__donate group'} href={i.url}> + <hy-icon icon={'hy-icon-heart-support'} size={16} fill={logoColorGroup} /> + <span class={'hy-link__donate__label group'}>{i.label}</span> + </a> + ); + })} + </div> + </div> + )} + <div class={{'hy-site-header__content': true, group: this.isGroup}}> <div class={'hy-site-header__logo-container'}> - <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} /> + {this.isGroup ? ( + <a class={'group'} href={this.logoUrl}> + {this.logoLabel} + </a> + ) : ( + <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} /> + )} </div> <hy-desktop-menu-links data-desktop-links={this.dataDesktopLinks}></hy-desktop-menu-links> - <div class={'menu--secondary'}> - <hy-menu-language - class={'menu--secondary__item is-first'} - is-mobile={false} - data-menu-language={this.dataMenuLanguage} - labels={this.languageLabels} - /> - <hy-site-search - class={'menu--secondary__item'} - size={14} - color={ColorVariant.black} - show-label={true} - labels={this.searchLabels} - search-labels={this.dataSiteSearchLabels} - search-tools={this.dataSearchTools} - /> - {this.donateLink.map((i) => { - return ( - <a class={'menu--secondary__item hy-link__donate'} href={i.url}> - <hy-icon icon={'hy-icon-heart-support'} size={14} fill={ColorVariant.black} /> - <span class={'hy-link__donate__label'}>{i.label}</span> - </a> - ); - })} - </div> + {!this.isGroup && ( + <div class={'menu--secondary'}> + <hy-menu-language + class={'menu--secondary__item is-first'} + is-mobile={false} + data-menu-language={this.dataMenuLanguage} + labels={this.languageLabels} + /> + <hy-site-search + class={'menu--secondary__item'} + size={14} + color={ColorVariant.black} + show-label={true} + labels={this.searchLabels} + search-labels={this.dataSiteSearchLabels} + search-tools={this.dataSearchTools} + /> + {this.donateLink.map((i) => { + return ( + <a class={'menu--secondary__item hy-link__donate'} href={i.url}> + <hy-icon icon={'hy-icon-heart-support'} size={14} fill={ColorVariant.black} /> + <span class={'hy-link__donate__label'}>{i.label}</span> + </a> + ); + })} + </div> + )} </div> </header>, ]; case MenuType.tablet: + // 960px-1200px screens return ( <header class={classAttributes.join(' ')}> <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} /> + {this.isGroup && ( + <div class="hy-site-header__content-top"> + <div class={'hy-site-header__logo-container group '} role="navigation"> + <hy-site-logo + is-group={true} + size={logoSizeGroup} + color={logoColorGroup} + url={this.siteUrl} + label={this.siteLabel} + /> + <hy-menu-main-group + is-mobile={false} + menu-label={this.groupPages['university_main_menu'] ?? ''} + data-main-menu={this.dataMainMenuLinks} + /> + </div> + + <div class={'menu--secondary menu--secondary--group'}> + <hy-menu-language + class={'menu--secondary__item is-first group'} + is-group={true} + is-mobile={false} + data-menu-language={this.dataMenuLanguage} + labels={this.languageLabels} + /> + <hy-site-search + class={'menu--secondary__item group'} + size={16} + color={logoColorGroup} + show-label={true} + is-group={true} + labels={this.searchLabels} + search-labels={this.dataSiteSearchLabels} + search-tools={this.dataSearchTools} + /> + {this.donateLink.map((i) => { + return ( + <a class={'menu--secondary__item hy-link__donate group'} href={i.url}> + <hy-icon icon={'hy-icon-heart-support'} size={16} fill={logoColorGroup} /> + <span class={'hy-link__donate__label group'}>{i.label}</span> + </a> + ); + })} + </div> + </div> + )} <div class="hy-site-header__content"> <div class={'hy-site-header__logo-container'}> - <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} /> - </div> - <div class={'menu--secondary'}> - <hy-menu-language - class={'menu--secondary__item is-first'} - is-mobile={false} - data-menu-language={this.dataMenuLanguage} - labels={this.languageLabels} - /> - <hy-site-search - class={'menu--secondary__item'} - size={14} - color={ColorVariant.black} - show-label={true} - labels={this.searchLabels} - search-labels={this.dataSiteSearchLabels} - search-tools={this.dataSearchTools} - /> - {this.donateLink.map((i) => { - return ( - <a class={'menu--secondary__item hy-link__donate'} href={i.url}> - <hy-icon icon={'hy-icon-heart-support'} size={14} fill={ColorVariant.black} /> - <span class={'hy-link__donate__label'}>{i.label}</span> - </a> - ); - })} + {this.isGroup ? ( + <a class={'group'} href={this.logoUrl}> + {this.logoLabel} + </a> + ) : ( + <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} /> + )} </div> + {!this.isGroup && ( + <div class={'menu--secondary'}> + <hy-menu-language + class={'menu--secondary__item is-first'} + is-mobile={false} + data-menu-language={this.dataMenuLanguage} + labels={this.languageLabels} + /> + <hy-site-search + class={'menu--secondary__item'} + size={14} + color={ColorVariant.black} + show-label={true} + labels={this.searchLabels} + search-labels={this.dataSiteSearchLabels} + search-tools={this.dataSearchTools} + /> + {this.donateLink.map((i) => { + return ( + <a class={'menu--secondary__item hy-link__donate'} href={i.url}> + <hy-icon icon={'hy-icon-heart-support'} size={14} fill={ColorVariant.black} /> + <span class={'hy-link__donate__label'}>{i.label}</span> + </a> + ); + })} + </div> + )} <div class={'hy-site-header__menu-container'}> <span class={{ @@ -329,23 +458,63 @@ export class SiteHeader { </header> ); case MenuType.mobile: + // Smaller than 960px screens return ( <header class={classAttributes.join(' ')}> <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} /> + <div class={{'hy-backdrop': true, 'is-active-top': this.isTopMenuOpen}} /> + {this.isGroup && ( + <div class={{'hy-site-header__content-top': true, 'is-open': this.isTopMenuOpen}} is-mobile={true}> + <div class={'hy-site-header__logo-container group '}> + <hy-site-logo size={logoSizeGroup} color={logoColorGroup} url={this.siteUrl} label={this.siteLabel} /> + </div> + + <div class={'menu--secondary menu--secondary--group'}> + <hy-site-search + class={'menu--secondary__item group'} + size={18} + color={logoColorGroup} + is-group={true} + show-label={true} + labels={this.searchLabels} + search-labels={this.dataSiteSearchLabels} + search-tools={this.dataSearchTools} + /> + <hy-menu-main-group + site-label={this.siteLabel} + site-url={this.siteUrl} + logo-label={this.logoLabel} + logo-url={this.logoUrl} + is-mobile={true} + donate={this.donateLink} + data-main-menu={this.dataMainMenuLinks} + /> + </div> + </div> + )} <div class="hy-site-header__content"> <div class={'hy-site-header__logo-container'}> - <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} /> + {this.isGroup ? ( + <a class={'group'} href={this.logoUrl}> + {this.logoLabel} + </a> + ) : ( + <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} /> + )} </div> - <div class={'hy-site-header__menu-container'}> - <hy-site-search - class={'menu--secondary__item'} - size={14} - color={ColorVariant.black} - show-label={true} - labels={this.searchLabels} - search-labels={this.dataSiteSearchLabels} - search-tools={this.dataSearchTools} - /> + + <div class={{'hy-site-header__menu-container': true, 'is-open': this.isMenuOpen}}> + {!this.isGroup && ( + <hy-site-search + class={'menu--secondary__item'} + size={14} + color={ColorVariant.black} + show-label={true} + labels={this.searchLabels} + search-labels={this.dataSiteSearchLabels} + search-tools={this.dataSearchTools} + /> + )} <button onClick={() => this.mobileMenuToggle()} class={{ diff --git a/src/components/site-header/site-logo/readme.md b/src/components/site-header/site-logo/readme.md index cdb7cfb5f3b4f5a6b2b6f81859cb1904aeb5215d..5b2a3221c1313901f62b6ee418ac9a32cf366c9d 100644 --- a/src/components/site-header/site-logo/readme.md +++ b/src/components/site-header/site-logo/readme.md @@ -4,13 +4,14 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| -------- | --------- | ----------- | -------------------------------------------------------------- | ---------------------- | -| `color` | `color` | | `ColorVariant.black \| ColorVariant.white` | `ColorVariant.black` | -| `label` | `label` | | `string` | `undefined` | -| `size` | `size` | | `SiteLogoSize.big \| SiteLogoSize.large \| SiteLogoSize.small` | `SiteLogoSize.big` | -| `type` | `type` | | `FooterVariant.footer \| FooterVariant.header` | `FooterVariant.header` | -| `url` | `url` | | `string` | `undefined` | +| Property | Attribute | Description | Type | Default | +| --------- | ---------- | ----------- | -------------------------------------------------------------- | ---------------------- | +| `color` | `color` | | `ColorVariant.black \| ColorVariant.white` | `ColorVariant.black` | +| `isGroup` | `is-group` | | `boolean` | `false` | +| `label` | `label` | | `string` | `undefined` | +| `size` | `size` | | `SiteLogoSize.big \| SiteLogoSize.large \| SiteLogoSize.small` | `SiteLogoSize.big` | +| `type` | `type` | | `FooterVariant.footer \| FooterVariant.header` | `FooterVariant.header` | +| `url` | `url` | | `string` | `undefined` | ## Dependencies @@ -18,6 +19,7 @@ - [hy-footer-base](../../footer/hy-footer-base) - [hy-menu](../../navigation/menu) +- [hy-menu-main-group](../../navigation/hy-menu-main-group) - [hy-menu-sidebar](../../navigation/menu-sidebar) - [hy-site-header](..) - [hy-user-login-form](../../hy-user-login-form) @@ -33,6 +35,7 @@ graph TD; hy-site-logo --> hy-icon hy-footer-base --> hy-site-logo hy-menu --> hy-site-logo + hy-menu-main-group --> hy-site-logo hy-menu-sidebar --> hy-site-logo hy-site-header --> hy-site-logo hy-user-login-form --> hy-site-logo diff --git a/src/components/site-header/site-logo/site-logo.scss b/src/components/site-header/site-logo/site-logo.scss index 3bd9dc7ddc3164be745d2f4d4693d28ef7c55f95..a1cc0345c5938a04ce495f3b2654bbac5168e752 100644 --- a/src/components/site-header/site-logo/site-logo.scss +++ b/src/components/site-header/site-logo/site-logo.scss @@ -52,35 +52,82 @@ letter-spacing: -0.7px; margin-left: 4px; } + + &.group { + @include font-size(12px, 14px); + color: var(--grayscale-white); + letter-spacing: -0.6px; + margin-left: 3px; + + @include breakpoint($wide) { + @include font-size(14px, 14px); + letter-spacing: -0.7px; + } + + @include breakpoint($xlarge) { + margin-left: 8px; + } + } } - &__icon svg { - height: 32px; - width: 33.41px; + &__icon { + svg { + height: 32px; + width: 33.41px; - @include breakpoint($narrow) { - height: 48px; - width: 51px; + @include breakpoint($narrow) { + height: 48px; + width: 51px; + } + + @include breakpoint($xlarge) { + height: 60px; + width: 64px; + } } - @include breakpoint($xlarge) { - height: 60px; - width: 64px; + &.group { + svg { + height: 32px; + width: 34px; + } } } &__header { - &:hover { - color: var(--brand-main); - a, - span { - color: var(--brand-main) !important; + //&:hover { + &__page { + &:hover { + color: var(--brand-main); + + a, + span { + color: var(--brand-main) !important; + } + + svg { + fill: var(--brand-main); + } } - svg { - fill: var(--brand-main); + } + &__group { + &:hover { + color: var(--grayscale-medium); + + a, + span { + color: var(--grayscale-medium) !important; + } + + svg { + fill: var(--grayscale-medium); + } } } + + //} } + &__footer { &:hover { span { @@ -92,3 +139,25 @@ } } } + +.hy-site-header__logo-container { + a.group { + @include font-size(14px, 16px); + @include font-weight($bold); + + color: var(--grayscale-black); + font-family: var(--main-font-family); + letter-spacing: -0.5px; + text-decoration: none; + text-transform: uppercase; + + @include breakpoint($narrow) { + @include font-size(24px, 28px); + letter-spacing: -0.8px; + } + + @include breakpoint($xlarge) { + @include font-size(26px, 30px); + } + } +} diff --git a/src/components/site-header/site-logo/site-logo.tsx b/src/components/site-header/site-logo/site-logo.tsx index 723cb51aad1da1427038ff420c307ff5d7e48588..cfd68d4d19d863b2937962616862c575e0b1077b 100644 --- a/src/components/site-header/site-logo/site-logo.tsx +++ b/src/components/site-header/site-logo/site-logo.tsx @@ -9,25 +9,41 @@ import {ColorVariant, FooterVariant, SiteLogoSize} from '../../../utils/utils'; export class SiteLogo { @Prop() type: FooterVariant = FooterVariant.header; @Prop() color: ColorVariant = ColorVariant.black; + @Prop() isGroup: boolean = false; @Prop() label?: string; @Prop() size: SiteLogoSize = SiteLogoSize.big; @Prop() url?: string; render() { - const classAttributes = ['hy-site-logo', `hy-site-logo__${this.type}`].join(' '); + const isGroupClass = this.isGroup ? 'group' : 'page'; + const classAttributes = [ + 'hy-site-logo', + `hy-site-logo__${this.type}__${isGroupClass}`, + `hy-site-logo__${this.type}`, + ].join(' '); return this.url ? ( <Host class={classAttributes}> <a href={this.url}> - <hy-icon class={'hy-site-logo__icon'} icon={'hy-icon-hy-logo'} size={this.size} fill={this.color} /> - <span class={'hy-site-logo__label'} style={{color: this.color}}> + <hy-icon + class={{'hy-site-logo__icon': true, group: this.isGroup}} + icon={'hy-icon-hy-logo'} + size={this.size} + fill={this.color} + /> + <span class={{'hy-site-logo__label': true, group: this.isGroup}} style={{color: this.color}}> {this.label} </span> </a> </Host> ) : this.label ? ( <Host class={classAttributes}> - <hy-icon class={'hy-site-logo__icon'} icon={'hy-icon-hy-logo'} size={this.size} fill={this.color} /> - <span class={'hy-site-logo__label'} style={{color: this.color}}> + <hy-icon + class={{'hy-site-logo__icon': true, group: this.isGroup}} + icon={'hy-icon-hy-logo'} + size={this.size} + fill={this.color} + /> + <span class={{'hy-site-logo__label': true, group: this.isGroup}} style={{color: this.color}}> {this.label} </span> </Host> diff --git a/src/components/site-header/site-search/readme.md b/src/components/site-header/site-search/readme.md index bf84fb50cd608d7d05876503a6179572ac22eece..332551f9c633854a9f2066e65e1eb622d29cc37c 100644 --- a/src/components/site-header/site-search/readme.md +++ b/src/components/site-header/site-search/readme.md @@ -9,6 +9,7 @@ | `color` | `color` | | `ColorVariant.black \| ColorVariant.white` | `ColorVariant.black` | | `dataSearchSpecialTools` | `data-search-special-tools` | | `string` | `undefined` | | `isAlternative` | `is-alternative` | | `boolean` | `false` | +| `isGroup` | `is-group` | | `boolean` | `false` | | `labels` | `labels` | | `ComponentLabels[] \| string` | `undefined` | | `searchLabels` | `search-labels` | | `string` | `undefined` | | `searchTools` | `search-tools` | | `string` | `undefined` | diff --git a/src/components/site-header/site-search/site-search.scss b/src/components/site-header/site-search/site-search.scss index bfe7698ccc48afd42c081914a37a8af843286a59..bf1d97e71cf4f8e3a9ed949992399577e8267be1 100644 --- a/src/components/site-header/site-search/site-search.scss +++ b/src/components/site-header/site-search/site-search.scss @@ -5,6 +5,7 @@ display: flex; padding: 12px; flex-direction: row; + font-family: var(--main-font-family); @include breakpoint($narrow) { padding: 15px 5px; @@ -28,13 +29,48 @@ } &__label { + font-family: var(--main-font-family); + margin-left: 4px; + } +} + +.button--search:not(.group) { + &:hover { + color: var(--brand-main); + cursor: pointer; + + span { + color: var(--brand-main); + } + svg { + fill: var(--brand-main); + } + } + + svg { + height: 20px; + width: 20px; + + @include breakpoint($wide) { + height: 16px; + width: 16px; + } + @include breakpoint($extrawide) { + height: 12px; + width: 12px; + } + @include breakpoint($xlarge) { + height: 16px; + width: 16px; + } + } + + .button--search__label { @include font-size(14px, 14px); @include font-weight($bold); color: var(--site-logo-color); display: none; - font-family: var(--main-font-family); letter-spacing: -0.9px; - margin-left: 4px; visibility: hidden; @include breakpoint($narrow) { @@ -45,8 +81,8 @@ @include breakpoint($wide) { @include font-size(14px, 24px); + @include font-weight($semibold); display: block; - font-weight: 600; letter-spacing: -0.5px; text-transform: none; visibility: visible; @@ -54,7 +90,7 @@ @include breakpoint($extrawide) { @include font-size(12px, 12px); - font-weight: 400; + @include font-weight($regular); letter-spacing: -0.6px; } @@ -63,34 +99,32 @@ letter-spacing: -0.5px; } } +} - svg { - height: 20px; - width: 20px; - - @include breakpoint($wide) { - height: 16px; - width: 16px; - } - @include breakpoint($extrawide) { - height: 12px; - width: 12px; - } - @include breakpoint($xlarge) { - height: 16px; - width: 16px; - } - } - +.button--search.group { &:hover { - color: var(--brand-main); + color: var(--grayscale-medium); cursor: pointer; span { - color: var(--brand-main); + color: var(--grayscale-medium); } + svg { - fill: var(--brand-main); + fill: var(--grayscale-medium); + } + } + + .button--search__label { + color: var(--grayscale-white); + display: none; + + @include breakpoint($wide) { + @include font-size(14px, 24px); + @include font-weight($semibold); + + display: block; + letter-spacing: -0.5px; } } } diff --git a/src/components/site-header/site-search/site-search.tsx b/src/components/site-header/site-search/site-search.tsx index 0d3589d60738c1d1bc600f7aa62e9165d87bbd13..05a1f295cda39e66b5e9f8a83aa33034f12f19bf 100644 --- a/src/components/site-header/site-search/site-search.tsx +++ b/src/components/site-header/site-search/site-search.tsx @@ -30,6 +30,7 @@ export class SiteSearch { @Prop() color: ColorVariant = ColorVariant.black; @Prop() isAlternative: boolean = false; + @Prop() isGroup: boolean = false; @Prop() labels?: ComponentLabels[] | string; @Prop() searchLabels: string; @Prop() searchTools: string; @@ -92,6 +93,12 @@ export class SiteSearch { this.closeSearchPanel(); } + // Close the search panel if user opens University main menu + @Listen('universityMainMenuToggled', {target: 'document'}) + universityMainMenuPanelToggled() { + this.closeSearchPanel(); + } + // CLose the search panel on Scroll down. @Listen('headerScrollDown', {target: 'document'}) headerScrollDown() { @@ -121,12 +128,7 @@ export class SiteSearch { // Close desktop menu panel and lang menu panel if they are open. this.searchPanelToggled.emit(); - let hyHeader = this.el.closest('.hy-site-header') as HTMLElement; - const headerHeight = hyHeader.classList.contains('hy-site-header--sticky-active') - ? `${hyHeader.offsetHeight}px` - : `${hyHeader.offsetTop + hyHeader.offsetHeight}px`; - const searchPanel = this.el.shadowRoot.querySelectorAll(`.site-search__panel`)[0] as HTMLElement; - searchPanel.style.top = headerHeight; + this.adjustPosition(this.el); // Remove hidden class from cludo suggestions let cludoSayt = document.querySelectorAll('stencil-cludo-sayt')[0] as HTMLElement; @@ -134,14 +136,6 @@ export class SiteSearch { cludoSayt.classList.remove('hidden'); } - // Add shadow backdrop - let rect = searchPanel.getBoundingClientRect(); - - let shadowTop = hyHeader.classList.contains('hy-site-header--sticky-active') - ? hyHeader.offsetHeight + rect.height - : hyHeader.offsetTop + hyHeader.offsetHeight + rect.height; - this.showBackdropShadow('open', shadowTop); - // Without setTimeout it will not focus the input because it hasn't rendered yet. setTimeout(() => { const searchInput = this.el.shadowRoot.querySelector('input#search') as HTMLElement; @@ -153,6 +147,47 @@ export class SiteSearch { event.stopPropagation(); } + adjustPosition(target) { + let headerHeight = '0'; + let shadowTop = 0; + const searchPanel = target.shadowRoot.querySelectorAll(`.site-search__panel`)[0] as HTMLElement; + let rect = searchPanel.getBoundingClientRect(); + + if (this.isGroup) { + let hyHeader = target.closest('.hy-site-header__content-top') as HTMLElement; + if (hyHeader) { + let rectHeader = hyHeader.getBoundingClientRect(); + headerHeight = `${rectHeader.height}px`; + + // Add shadow backdrop + //@todo For some reason rect (Search Panel) is { + // "x": 0, + // "y": 0, + // "width": 0, + // "height": 0, + // "top": 0, + // "right": 0, + // "bottom": 0, + // "left": 0 + // } + shadowTop = hyHeader.offsetHeight + rect.height; + } + } else { + let hyHeader = target.closest('.hy-site-header') as HTMLElement; + headerHeight = hyHeader.classList.contains('hy-site-header--sticky-active') + ? `${hyHeader.offsetHeight}px` + : `${hyHeader.offsetTop + hyHeader.offsetHeight}px`; + + // Add shadow backdrop + shadowTop = hyHeader.classList.contains('hy-site-header--sticky-active') + ? hyHeader.offsetHeight + rect.height + : hyHeader.offsetTop + hyHeader.offsetHeight + rect.height; + } + + searchPanel.style.top = headerHeight; + this.showBackdropShadow('open', shadowTop); + } + showBackdropShadow(state = 'close', top = 0) { let hyHeader = this.el.closest('.hy-site-header') as HTMLElement; let hyBackdropDiv = hyHeader.children[0] as HTMLElement; @@ -184,12 +219,19 @@ export class SiteSearch { aria-expanded={`${this.isSearchPanelOpen}`} class={{ 'button--search': true, + group: this.isGroup, 'is-open--menu': this.isAlternative, 'is-open': this.isSearchPanelOpen, }} onClick={(e) => this.handleSearchPanelToggle(e)} > - {this.showLabel ? <span class={'button--search__label'}>{this._labels['label']}</span> : ''} + {this.showLabel ? ( + <span class={{'button--search__label': true, 'button--search__label__group': this.isGroup}}> + {this._labels['label']} + </span> + ) : ( + '' + )} <hy-icon icon={'hy-icon-search'} size={this.size} fill={this.color} /> </button> <div