diff --git a/.eslintrc.js b/.eslintrc.js index 66c1bb990..588e062be 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,6 @@ module.exports = { extends: '@mate-academy/eslint-config', + env: { + browser: true, + }, }; diff --git a/.github/workflows/test.yml-template b/.github/workflows/test.yml-template new file mode 100644 index 000000000..8b5743ecb --- /dev/null +++ b/.github/workflows/test.yml-template @@ -0,0 +1,29 @@ +name: Test + +on: + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test + - name: Upload HTML report(backstop data) + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: report + path: backstop_data diff --git a/.linthtmlrc.json b/.linthtmlrc.json index 477c99b1b..35dfc75fb 100644 --- a/.linthtmlrc.json +++ b/.linthtmlrc.json @@ -9,7 +9,7 @@ ], "attr-name-ignore-regex": "viewBox", "attr-no-dup": true, - "attr-quote-style": "double", + "attr-quote-style": ["double", "single"], "attr-req-value": true, "class-no-dup": true, "doctype-first": true, @@ -26,16 +26,7 @@ "indent-width-cont": true, "input-radio-req-name": true, "spec-char-escape": true, - "tag-bans": [ - "b", - "i", - "u", - "center", - "style", - "marquee", - "font", - "s" - ], + "tag-bans": ["b", "i", "u", "center", "style", "marquee", "font", "s"], "tag-name-lowercase": true, "tag-name-match": true, "tag-self-close": false, diff --git a/.stylelintrc.js b/.stylelintrc.js index 2e345321d..457488cb7 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -1,7 +1,17 @@ module.exports = { - extends: "@mate-academy/stylelint-config", - plugins: [ - "stylelint-scss" - ], - rules: {} + extends: '@mate-academy/stylelint-config', + plugins: ['stylelint-scss'], + rules: { + 'at-rule-empty-line-before': [ + 'always', + { + ignore: [ + 'inside-block', + 'first-nested', + 'blockless-after-same-name-blockless', + ], + ignoreAtRules: ['@else'], + }, + ], + }, }; diff --git a/README.md b/README.md index a95e97afe..6ddcc078f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # Kickstarter landing page (HARD) -**⚠️ Attention: this is a hard landing page for development. We highly recommend choosing this landing page only if you didn't have a lot of troubles with previous homework tasks and if you sent all homework in time (didn't miss deadlines).** +**⚠️ Attention: this is a hard landing page for development. We highly recommend choosing this landing page only if you didn't have a lot of troubles with previous homework tasks and if you sent all homework in time (didn't miss deadlines).** + +Implement landing page according to [Figma design]() - Use BEM and SCSS -Implement landing page according to [Figma design](https://www.figma.com/file/Ujp7bCFuvuJlkn8TSbQPSZ/%E2%84%9611-(kickstarter)?node-id=19655%3A33) - Use BEM and SCSS - The design 1440px - Desktop 1280px - Tablet 640px @@ -18,7 +19,6 @@ Implement landing page according to [Figma design](https://www.figma.com/file/Uj 1. Implement `Questions` block 1. Implement the footer. - ## Github flow 1. **Fork** the repo. @@ -34,7 +34,7 @@ Implement landing page according to [Figma design](https://www.figma.com/file/Uj 11. `git push origin develop` - to send you code for PR 12. Create a Pull Request (PR) from your branch `develop` to branch `master` of original repo. 13. Replace `` with your Github username in the - [DEMO LINK](https://.github.io/Kickstarter/) + [DEMO LINK](https://podvax.github.io/Kickstarter/) 14. Copy `DEMO LINK` to the PR description > To update you PR repeat steps 7-11 diff --git a/index.html b/index.html index d339e6856..ca036a395 100644 --- a/index.html +++ b/index.html @@ -2,18 +2,1068 @@ + - Title + + CrazyBaby + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - -

Hello Mate Academy

- + + + + + + + + + + +
+ + +
+
+
+ Compass icon +
+ +

+ Futuristic Design +

+ +

+ To give Luna a truly flawless look, we specifically picked aircraft + grade aluminum as its material and adopted both three-dimensional + stretch-bending technology and a high precision cold forging + technique. +

+
+ +
+
+ Speaker icon +
+ +

+ Tweeter Speaker System +

+ +

+ To deliver a more layered sound performance better than a sole + full-range speaker, our team equipped Luna with one more tweeter + speaker responsible for high-frequency sound independently. +

+
+ +
+
+ Wi-Fi icon +
+ +

+ Multiroom System +

+ +

+ Luna is natively compatible with your home Wi-Fi. Set up multiple + speakers in different rooms to expand your music experience into the + entire house. +

+
+ +
+
+ Sun icon +
+ +

+ Intuitive Lighting System +

+ +

+ An intuitive user interface allows you to adjust the hue and + saturation of color for lighting that fits any mood and situation. +

+
+
+ + + + + Meet Luna image + + +
+
+

+ Designed for the Future +

+ + + + + Designed for the future image + + +

+ In 2014, a group of geeky industrial designers, engineering veterans + and acoustic experts formed crazybaby. This is a bunch of passionate + people who are crazy enough to think they can challenge the industry + with disruptive audio products. +

+ + +
+ +
+

+ Luna Eye +

+ + + + + Luna eye image + + +

+ Luna Eye is to the essence of this innovative light and audio + system. It comprises an independent tweeter speaker, a light guiding + component, a dome and a ring ornament. +

+ + +
+
+ +
+
+ + It really took me by surprise honestly to have such full beautiful + sound that coming out of this small compact device. And with the + brush aluminum surface, it feels so familiar. Like my iPhone. + + + Martin Garrett's avatar + +
Martin Garret
+ +

+ Creative Director +

+
+
+ +
+

+ Features +

+ +
+
+
+
+

+ Connectivity +

+ +
    +
  • + Hands Free Wireless Audio +
  • + +
  • Bluetooth 4.0 LE
  • + +
  • Wi-Fi 2.4 GHz (802.11 b/g/n)
  • + +
  • + Smart Multiroom System Set Up +
  • + +
  • + Party Mode with 6.0 Units and above +
  • + +
  • + MESHNET Multi Speaker Network +
  • +
+
+
+ +
+
+

+ Sound & Music +

+ +
    +
  • + Feel-in-chest Base Power +
  • + +
  • + Lossless Digital Audio Transmission +
  • + +
  • + Easy & Stable Stereo Pairing +
  • + +
  • + Crisp and Clear High Frequency Sound +
  • + +
  • + Streams from Cloud Music and Local Library +
  • + +
  • + Auto Music Playback from Last Song Stopped +
  • +
+
+
+ +
+
+

+ App Features +

+ +
    +
  • + Customize Music Schedule +
  • +
  • + Wake Up with Favorite Songs +
  • +
  • + Home Detection Auto Wake Up +
  • +
  • + Color Wheel +
  • +
+
+
+
+ +
+
+
+ + +
+ +
+
+ + + + + Feature Luna image + +
+
+
+ +
+

+ DO YOU HAVE ANY QUESTIONS? +

+ +
+ + + +
+ + +
+
+ + + + + +
+ + + + + +
+ + + + + + + diff --git a/package-lock.json b/package-lock.json index ace1ce6c0..d7ffc9733 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,16 @@ "version": "1.0.0", "hasInstallScript": true, "license": "GPL-3.0", + "dependencies": { + "normalize.css": "^8.0.1", + "swiper": "^12.1.0" + }, "devDependencies": { "@linthtml/linthtml": "^0.9.6", "@mate-academy/eslint-config": "latest", "@mate-academy/jest-mochawesome-reporter": "^1.0.0", "@mate-academy/linthtml-config": "latest", - "@mate-academy/scripts": "^2.1.1", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/stylelint-config": "latest", "cypress": "^13.13.0", "eslint": "^8.57.0", @@ -1875,10 +1879,11 @@ "dev": true }, "node_modules/@mate-academy/scripts": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-2.1.2.tgz", - "integrity": "sha512-gUXFdqqOfYzF9R3RSx2pCa5GLdOkxB9bFbF+dpUpzucdgGAANqOGdqpmNnMj+e3xA9YHraUWq3xo9cwe5vD9pQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-2.1.3.tgz", + "integrity": "sha512-a07wHTj/1QUK2Aac5zHad+sGw4rIvcNl5lJmJpAD7OxeSbnCdyI6RXUHwXhjF5MaVo9YHrJ0xVahyERS2IIyBQ==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/rest": "^17.11.2", "@types/get-port": "^4.2.0", @@ -9549,6 +9554,12 @@ "node": ">=0.10.0" } }, + "node_modules/normalize.css": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz", + "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==", + "license": "MIT" + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -11879,6 +11890,25 @@ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, + "node_modules/swiper": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-12.1.0.tgz", + "integrity": "sha512-BD4CpAOOyEvZ2f0CDx362ea+vmOwukVcmbsQx+0BhRIaBUz8wvcCd//E7RFmvBZCrfyqXCHUVqmgUwts6ywlxw==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "license": "MIT", + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index 19d2ac56e..1fd25e201 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@mate-academy/eslint-config": "latest", "@mate-academy/jest-mochawesome-reporter": "^1.0.0", "@mate-academy/linthtml-config": "latest", - "@mate-academy/scripts": "^2.1.1", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/stylelint-config": "latest", "cypress": "^13.13.0", "eslint": "^8.57.0", @@ -55,5 +55,9 @@ "backstop": false, "cypress": true } + }, + "dependencies": { + "normalize.css": "^8.0.1", + "swiper": "^12.1.0" } } diff --git a/public/favicons/apple-touch-icon.png b/public/favicons/apple-touch-icon.png new file mode 100644 index 000000000..caf2b895f Binary files /dev/null and b/public/favicons/apple-touch-icon.png differ diff --git a/public/favicons/favicon-96x96.png b/public/favicons/favicon-96x96.png new file mode 100644 index 000000000..1a9c9c16d Binary files /dev/null and b/public/favicons/favicon-96x96.png differ diff --git a/public/favicons/favicon.ico b/public/favicons/favicon.ico new file mode 100644 index 000000000..a58724240 Binary files /dev/null and b/public/favicons/favicon.ico differ diff --git a/public/favicons/favicon.svg b/public/favicons/favicon.svg new file mode 100644 index 000000000..0bbbd4d3a --- /dev/null +++ b/public/favicons/favicon.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/public/favicons/favicon_lg.png b/public/favicons/favicon_lg.png new file mode 100644 index 000000000..18a0fd54f Binary files /dev/null and b/public/favicons/favicon_lg.png differ diff --git a/public/favicons/favicon_lg.svg b/public/favicons/favicon_lg.svg new file mode 100644 index 000000000..da5158e73 --- /dev/null +++ b/public/favicons/favicon_lg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/favicons/favicon_sm.png b/public/favicons/favicon_sm.png new file mode 100644 index 000000000..ccfcd9ff5 Binary files /dev/null and b/public/favicons/favicon_sm.png differ diff --git a/public/favicons/favicon_sm.svg b/public/favicons/favicon_sm.svg new file mode 100644 index 000000000..f8f13f02c --- /dev/null +++ b/public/favicons/favicon_sm.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/favicons/site.webmanifest b/public/favicons/site.webmanifest new file mode 100644 index 000000000..0a0fb7c0c --- /dev/null +++ b/public/favicons/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "CrazyBaby - Luna Speaker", + "short_name": "CrazyBaby", + "icons": [ + { + "src": "/images/icons/favicons/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/images/icons/favicons/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} \ No newline at end of file diff --git a/public/favicons/web-app-manifest-192x192.png b/public/favicons/web-app-manifest-192x192.png new file mode 100644 index 000000000..938455b70 Binary files /dev/null and b/public/favicons/web-app-manifest-192x192.png differ diff --git a/public/favicons/web-app-manifest-512x512.png b/public/favicons/web-app-manifest-512x512.png new file mode 100644 index 000000000..376e384a6 Binary files /dev/null and b/public/favicons/web-app-manifest-512x512.png differ diff --git a/public/meet_luna_lg.png b/public/meet_luna_lg.png new file mode 100644 index 000000000..1012f9d25 Binary files /dev/null and b/public/meet_luna_lg.png differ diff --git a/src/fonts/Inter-Italic-VariableFont_opsz,wght.ttf b/src/fonts/Inter-Italic-VariableFont_opsz,wght.ttf new file mode 100644 index 000000000..43ed4f5ee Binary files /dev/null and b/src/fonts/Inter-Italic-VariableFont_opsz,wght.ttf differ diff --git a/src/fonts/Inter-VariableFont_opsz,wght.ttf b/src/fonts/Inter-VariableFont_opsz,wght.ttf new file mode 100644 index 000000000..e31b51e3e Binary files /dev/null and b/src/fonts/Inter-VariableFont_opsz,wght.ttf differ diff --git a/src/fonts/static/Inter_18pt-Black.ttf b/src/fonts/static/Inter_18pt-Black.ttf new file mode 100644 index 000000000..89673de1c Binary files /dev/null and b/src/fonts/static/Inter_18pt-Black.ttf differ diff --git a/src/fonts/static/Inter_18pt-BlackItalic.ttf b/src/fonts/static/Inter_18pt-BlackItalic.ttf new file mode 100644 index 000000000..b33602f1e Binary files /dev/null and b/src/fonts/static/Inter_18pt-BlackItalic.ttf differ diff --git a/src/fonts/static/Inter_18pt-Bold.ttf b/src/fonts/static/Inter_18pt-Bold.ttf new file mode 100644 index 000000000..57704d104 Binary files /dev/null and b/src/fonts/static/Inter_18pt-Bold.ttf differ diff --git a/src/fonts/static/Inter_18pt-BoldItalic.ttf b/src/fonts/static/Inter_18pt-BoldItalic.ttf new file mode 100644 index 000000000..d53a199e2 Binary files /dev/null and b/src/fonts/static/Inter_18pt-BoldItalic.ttf differ diff --git a/src/fonts/static/Inter_18pt-ExtraBold.ttf b/src/fonts/static/Inter_18pt-ExtraBold.ttf new file mode 100644 index 000000000..e71c601c0 Binary files /dev/null and b/src/fonts/static/Inter_18pt-ExtraBold.ttf differ diff --git a/src/fonts/static/Inter_18pt-ExtraBoldItalic.ttf b/src/fonts/static/Inter_18pt-ExtraBoldItalic.ttf new file mode 100644 index 000000000..df450629b Binary files /dev/null and b/src/fonts/static/Inter_18pt-ExtraBoldItalic.ttf differ diff --git a/src/fonts/static/Inter_18pt-ExtraLight.ttf b/src/fonts/static/Inter_18pt-ExtraLight.ttf new file mode 100644 index 000000000..f9c6cfc5b Binary files /dev/null and b/src/fonts/static/Inter_18pt-ExtraLight.ttf differ diff --git a/src/fonts/static/Inter_18pt-ExtraLightItalic.ttf b/src/fonts/static/Inter_18pt-ExtraLightItalic.ttf new file mode 100644 index 000000000..275f305e2 Binary files /dev/null and b/src/fonts/static/Inter_18pt-ExtraLightItalic.ttf differ diff --git a/src/fonts/static/Inter_18pt-Italic.ttf b/src/fonts/static/Inter_18pt-Italic.ttf new file mode 100644 index 000000000..14d3595bc Binary files /dev/null and b/src/fonts/static/Inter_18pt-Italic.ttf differ diff --git a/src/fonts/static/Inter_18pt-Light.ttf b/src/fonts/static/Inter_18pt-Light.ttf new file mode 100644 index 000000000..acae36128 Binary files /dev/null and b/src/fonts/static/Inter_18pt-Light.ttf differ diff --git a/src/fonts/static/Inter_18pt-LightItalic.ttf b/src/fonts/static/Inter_18pt-LightItalic.ttf new file mode 100644 index 000000000..f69e18b03 Binary files /dev/null and b/src/fonts/static/Inter_18pt-LightItalic.ttf differ diff --git a/src/fonts/static/Inter_18pt-Medium.ttf b/src/fonts/static/Inter_18pt-Medium.ttf new file mode 100644 index 000000000..71d90172f Binary files /dev/null and b/src/fonts/static/Inter_18pt-Medium.ttf differ diff --git a/src/fonts/static/Inter_18pt-MediumItalic.ttf b/src/fonts/static/Inter_18pt-MediumItalic.ttf new file mode 100644 index 000000000..5c8c8b145 Binary files /dev/null and b/src/fonts/static/Inter_18pt-MediumItalic.ttf differ diff --git a/src/fonts/static/Inter_18pt-Regular.ttf b/src/fonts/static/Inter_18pt-Regular.ttf new file mode 100644 index 000000000..ce097c825 Binary files /dev/null and b/src/fonts/static/Inter_18pt-Regular.ttf differ diff --git a/src/fonts/static/Inter_18pt-SemiBold.ttf b/src/fonts/static/Inter_18pt-SemiBold.ttf new file mode 100644 index 000000000..053185e5d Binary files /dev/null and b/src/fonts/static/Inter_18pt-SemiBold.ttf differ diff --git a/src/fonts/static/Inter_18pt-SemiBoldItalic.ttf b/src/fonts/static/Inter_18pt-SemiBoldItalic.ttf new file mode 100644 index 000000000..d9c9896d3 Binary files /dev/null and b/src/fonts/static/Inter_18pt-SemiBoldItalic.ttf differ diff --git a/src/fonts/static/Inter_18pt-Thin.ttf b/src/fonts/static/Inter_18pt-Thin.ttf new file mode 100644 index 000000000..e68ec4704 Binary files /dev/null and b/src/fonts/static/Inter_18pt-Thin.ttf differ diff --git a/src/fonts/static/Inter_18pt-ThinItalic.ttf b/src/fonts/static/Inter_18pt-ThinItalic.ttf new file mode 100644 index 000000000..134e8372f Binary files /dev/null and b/src/fonts/static/Inter_18pt-ThinItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-Black.ttf b/src/fonts/static/Inter_24pt-Black.ttf new file mode 100644 index 000000000..dbb1b3bc7 Binary files /dev/null and b/src/fonts/static/Inter_24pt-Black.ttf differ diff --git a/src/fonts/static/Inter_24pt-BlackItalic.ttf b/src/fonts/static/Inter_24pt-BlackItalic.ttf new file mode 100644 index 000000000..b89d61c1f Binary files /dev/null and b/src/fonts/static/Inter_24pt-BlackItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-Bold.ttf b/src/fonts/static/Inter_24pt-Bold.ttf new file mode 100644 index 000000000..e974d96fc Binary files /dev/null and b/src/fonts/static/Inter_24pt-Bold.ttf differ diff --git a/src/fonts/static/Inter_24pt-BoldItalic.ttf b/src/fonts/static/Inter_24pt-BoldItalic.ttf new file mode 100644 index 000000000..1c3d251c0 Binary files /dev/null and b/src/fonts/static/Inter_24pt-BoldItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-ExtraBold.ttf b/src/fonts/static/Inter_24pt-ExtraBold.ttf new file mode 100644 index 000000000..b775c0843 Binary files /dev/null and b/src/fonts/static/Inter_24pt-ExtraBold.ttf differ diff --git a/src/fonts/static/Inter_24pt-ExtraBoldItalic.ttf b/src/fonts/static/Inter_24pt-ExtraBoldItalic.ttf new file mode 100644 index 000000000..3461a928f Binary files /dev/null and b/src/fonts/static/Inter_24pt-ExtraBoldItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-ExtraLight.ttf b/src/fonts/static/Inter_24pt-ExtraLight.ttf new file mode 100644 index 000000000..2ec6ca3fe Binary files /dev/null and b/src/fonts/static/Inter_24pt-ExtraLight.ttf differ diff --git a/src/fonts/static/Inter_24pt-ExtraLightItalic.ttf b/src/fonts/static/Inter_24pt-ExtraLightItalic.ttf new file mode 100644 index 000000000..c634a5d21 Binary files /dev/null and b/src/fonts/static/Inter_24pt-ExtraLightItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-Italic.ttf b/src/fonts/static/Inter_24pt-Italic.ttf new file mode 100644 index 000000000..1048b07a1 Binary files /dev/null and b/src/fonts/static/Inter_24pt-Italic.ttf differ diff --git a/src/fonts/static/Inter_24pt-Light.ttf b/src/fonts/static/Inter_24pt-Light.ttf new file mode 100644 index 000000000..1a2a6f252 Binary files /dev/null and b/src/fonts/static/Inter_24pt-Light.ttf differ diff --git a/src/fonts/static/Inter_24pt-LightItalic.ttf b/src/fonts/static/Inter_24pt-LightItalic.ttf new file mode 100644 index 000000000..ded5a7539 Binary files /dev/null and b/src/fonts/static/Inter_24pt-LightItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-Medium.ttf b/src/fonts/static/Inter_24pt-Medium.ttf new file mode 100644 index 000000000..5c88739bd Binary files /dev/null and b/src/fonts/static/Inter_24pt-Medium.ttf differ diff --git a/src/fonts/static/Inter_24pt-MediumItalic.ttf b/src/fonts/static/Inter_24pt-MediumItalic.ttf new file mode 100644 index 000000000..be091b1dc Binary files /dev/null and b/src/fonts/static/Inter_24pt-MediumItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-Regular.ttf b/src/fonts/static/Inter_24pt-Regular.ttf new file mode 100644 index 000000000..6b088a711 Binary files /dev/null and b/src/fonts/static/Inter_24pt-Regular.ttf differ diff --git a/src/fonts/static/Inter_24pt-SemiBold.ttf b/src/fonts/static/Inter_24pt-SemiBold.ttf new file mode 100644 index 000000000..ceb8576ab Binary files /dev/null and b/src/fonts/static/Inter_24pt-SemiBold.ttf differ diff --git a/src/fonts/static/Inter_24pt-SemiBoldItalic.ttf b/src/fonts/static/Inter_24pt-SemiBoldItalic.ttf new file mode 100644 index 000000000..6921df226 Binary files /dev/null and b/src/fonts/static/Inter_24pt-SemiBoldItalic.ttf differ diff --git a/src/fonts/static/Inter_24pt-Thin.ttf b/src/fonts/static/Inter_24pt-Thin.ttf new file mode 100644 index 000000000..3505b357e Binary files /dev/null and b/src/fonts/static/Inter_24pt-Thin.ttf differ diff --git a/src/fonts/static/Inter_24pt-ThinItalic.ttf b/src/fonts/static/Inter_24pt-ThinItalic.ttf new file mode 100644 index 000000000..a3e6febe5 Binary files /dev/null and b/src/fonts/static/Inter_24pt-ThinItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-Black.ttf b/src/fonts/static/Inter_28pt-Black.ttf new file mode 100644 index 000000000..66a252f8f Binary files /dev/null and b/src/fonts/static/Inter_28pt-Black.ttf differ diff --git a/src/fonts/static/Inter_28pt-BlackItalic.ttf b/src/fonts/static/Inter_28pt-BlackItalic.ttf new file mode 100644 index 000000000..3c8fdf968 Binary files /dev/null and b/src/fonts/static/Inter_28pt-BlackItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-Bold.ttf b/src/fonts/static/Inter_28pt-Bold.ttf new file mode 100644 index 000000000..14db99406 Binary files /dev/null and b/src/fonts/static/Inter_28pt-Bold.ttf differ diff --git a/src/fonts/static/Inter_28pt-BoldItalic.ttf b/src/fonts/static/Inter_28pt-BoldItalic.ttf new file mode 100644 index 000000000..704b12b20 Binary files /dev/null and b/src/fonts/static/Inter_28pt-BoldItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-ExtraBold.ttf b/src/fonts/static/Inter_28pt-ExtraBold.ttf new file mode 100644 index 000000000..6d87caec3 Binary files /dev/null and b/src/fonts/static/Inter_28pt-ExtraBold.ttf differ diff --git a/src/fonts/static/Inter_28pt-ExtraBoldItalic.ttf b/src/fonts/static/Inter_28pt-ExtraBoldItalic.ttf new file mode 100644 index 000000000..1a5673590 Binary files /dev/null and b/src/fonts/static/Inter_28pt-ExtraBoldItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-ExtraLight.ttf b/src/fonts/static/Inter_28pt-ExtraLight.ttf new file mode 100644 index 000000000..d42b3f54d Binary files /dev/null and b/src/fonts/static/Inter_28pt-ExtraLight.ttf differ diff --git a/src/fonts/static/Inter_28pt-ExtraLightItalic.ttf b/src/fonts/static/Inter_28pt-ExtraLightItalic.ttf new file mode 100644 index 000000000..90e2f20cb Binary files /dev/null and b/src/fonts/static/Inter_28pt-ExtraLightItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-Italic.ttf b/src/fonts/static/Inter_28pt-Italic.ttf new file mode 100644 index 000000000..c2a143ac2 Binary files /dev/null and b/src/fonts/static/Inter_28pt-Italic.ttf differ diff --git a/src/fonts/static/Inter_28pt-Light.ttf b/src/fonts/static/Inter_28pt-Light.ttf new file mode 100644 index 000000000..5eeff3a59 Binary files /dev/null and b/src/fonts/static/Inter_28pt-Light.ttf differ diff --git a/src/fonts/static/Inter_28pt-LightItalic.ttf b/src/fonts/static/Inter_28pt-LightItalic.ttf new file mode 100644 index 000000000..6b90b7668 Binary files /dev/null and b/src/fonts/static/Inter_28pt-LightItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-Medium.ttf b/src/fonts/static/Inter_28pt-Medium.ttf new file mode 100644 index 000000000..00120fe72 Binary files /dev/null and b/src/fonts/static/Inter_28pt-Medium.ttf differ diff --git a/src/fonts/static/Inter_28pt-MediumItalic.ttf b/src/fonts/static/Inter_28pt-MediumItalic.ttf new file mode 100644 index 000000000..7481e7ba8 Binary files /dev/null and b/src/fonts/static/Inter_28pt-MediumItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-Regular.ttf b/src/fonts/static/Inter_28pt-Regular.ttf new file mode 100644 index 000000000..855b6f476 Binary files /dev/null and b/src/fonts/static/Inter_28pt-Regular.ttf differ diff --git a/src/fonts/static/Inter_28pt-SemiBold.ttf b/src/fonts/static/Inter_28pt-SemiBold.ttf new file mode 100644 index 000000000..8b84efcf8 Binary files /dev/null and b/src/fonts/static/Inter_28pt-SemiBold.ttf differ diff --git a/src/fonts/static/Inter_28pt-SemiBoldItalic.ttf b/src/fonts/static/Inter_28pt-SemiBoldItalic.ttf new file mode 100644 index 000000000..2e22c5ac2 Binary files /dev/null and b/src/fonts/static/Inter_28pt-SemiBoldItalic.ttf differ diff --git a/src/fonts/static/Inter_28pt-Thin.ttf b/src/fonts/static/Inter_28pt-Thin.ttf new file mode 100644 index 000000000..94e61089e Binary files /dev/null and b/src/fonts/static/Inter_28pt-Thin.ttf differ diff --git a/src/fonts/static/Inter_28pt-ThinItalic.ttf b/src/fonts/static/Inter_28pt-ThinItalic.ttf new file mode 100644 index 000000000..d3d44cdb1 Binary files /dev/null and b/src/fonts/static/Inter_28pt-ThinItalic.ttf differ diff --git a/src/images/avatar_garrett.png b/src/images/avatar_garrett.png new file mode 100644 index 000000000..0651fa867 Binary files /dev/null and b/src/images/avatar_garrett.png differ diff --git a/src/images/icons/icon-arrow-up.svg b/src/images/icons/icon-arrow-up.svg new file mode 100644 index 000000000..bc809f94c --- /dev/null +++ b/src/images/icons/icon-arrow-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-bullet.svg b/src/images/icons/icon-bullet.svg new file mode 100644 index 000000000..3fc01ef23 --- /dev/null +++ b/src/images/icons/icon-bullet.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-burger-menu.svg b/src/images/icons/icon-burger-menu.svg new file mode 100644 index 000000000..4df42c36f --- /dev/null +++ b/src/images/icons/icon-burger-menu.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/images/icons/icon-close.svg b/src/images/icons/icon-close.svg new file mode 100644 index 000000000..df1397add --- /dev/null +++ b/src/images/icons/icon-close.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-compass.svg b/src/images/icons/icon-compass.svg new file mode 100644 index 000000000..ff5307f10 --- /dev/null +++ b/src/images/icons/icon-compass.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-fb.svg b/src/images/icons/icon-fb.svg new file mode 100644 index 000000000..2f5d0bec2 --- /dev/null +++ b/src/images/icons/icon-fb.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-inst.svg b/src/images/icons/icon-inst.svg new file mode 100644 index 000000000..acc91ab7f --- /dev/null +++ b/src/images/icons/icon-inst.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-next.svg b/src/images/icons/icon-next.svg new file mode 100644 index 000000000..bf3bd358a --- /dev/null +++ b/src/images/icons/icon-next.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/images/icons/icon-prev.svg b/src/images/icons/icon-prev.svg new file mode 100644 index 000000000..cfab7d543 --- /dev/null +++ b/src/images/icons/icon-prev.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/images/icons/icon-speaker.svg b/src/images/icons/icon-speaker.svg new file mode 100644 index 000000000..294373872 --- /dev/null +++ b/src/images/icons/icon-speaker.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-sun.svg b/src/images/icons/icon-sun.svg new file mode 100644 index 000000000..49ba7eac6 --- /dev/null +++ b/src/images/icons/icon-sun.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/images/icons/icon-twitter.svg b/src/images/icons/icon-twitter.svg new file mode 100644 index 000000000..1d928f615 --- /dev/null +++ b/src/images/icons/icon-twitter.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon-wifi.svg b/src/images/icons/icon-wifi.svg new file mode 100644 index 000000000..68188e3c9 --- /dev/null +++ b/src/images/icons/icon-wifi.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/icon_logo.svg b/src/images/icons/icon_logo.svg new file mode 100644 index 000000000..fcb8169eb --- /dev/null +++ b/src/images/icons/icon_logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/images/large/design_luna_lg.png b/src/images/large/design_luna_lg.png new file mode 100644 index 000000000..45cc9acf4 Binary files /dev/null and b/src/images/large/design_luna_lg.png differ diff --git a/src/images/large/feature_luna_lg-removedBg.png b/src/images/large/feature_luna_lg-removedBg.png new file mode 100644 index 000000000..51b9c6f57 Binary files /dev/null and b/src/images/large/feature_luna_lg-removedBg.png differ diff --git a/src/images/large/feature_luna_lg.png b/src/images/large/feature_luna_lg.png new file mode 100644 index 000000000..628a7dbc6 Binary files /dev/null and b/src/images/large/feature_luna_lg.png differ diff --git a/src/images/large/luna_eye_lg.png b/src/images/large/luna_eye_lg.png new file mode 100644 index 000000000..b716e09a5 Binary files /dev/null and b/src/images/large/luna_eye_lg.png differ diff --git a/src/images/large/main_luna_lg.png b/src/images/large/main_luna_lg.png new file mode 100644 index 000000000..c71f6c326 Binary files /dev/null and b/src/images/large/main_luna_lg.png differ diff --git a/src/images/large/meet_luna_lg.png b/src/images/large/meet_luna_lg.png new file mode 100644 index 000000000..1012f9d25 Binary files /dev/null and b/src/images/large/meet_luna_lg.png differ diff --git a/src/images/mid/design_luna_md.png b/src/images/mid/design_luna_md.png new file mode 100644 index 000000000..424a8b760 Binary files /dev/null and b/src/images/mid/design_luna_md.png differ diff --git a/src/images/mid/feature_luna_md-removedBg.png b/src/images/mid/feature_luna_md-removedBg.png new file mode 100644 index 000000000..b34356f22 Binary files /dev/null and b/src/images/mid/feature_luna_md-removedBg.png differ diff --git a/src/images/mid/feature_luna_md.png b/src/images/mid/feature_luna_md.png new file mode 100644 index 000000000..9f05df0e4 Binary files /dev/null and b/src/images/mid/feature_luna_md.png differ diff --git a/src/images/mid/luna_eye_md.png b/src/images/mid/luna_eye_md.png new file mode 100644 index 000000000..7fac9164d Binary files /dev/null and b/src/images/mid/luna_eye_md.png differ diff --git a/src/images/mid/main_luna_md.png b/src/images/mid/main_luna_md.png new file mode 100644 index 000000000..e0851e41a Binary files /dev/null and b/src/images/mid/main_luna_md.png differ diff --git a/src/images/mid/meet_luna_md.png b/src/images/mid/meet_luna_md.png new file mode 100644 index 000000000..55a974c11 Binary files /dev/null and b/src/images/mid/meet_luna_md.png differ diff --git a/src/images/quote.png b/src/images/quote.png new file mode 100644 index 000000000..46fef106d Binary files /dev/null and b/src/images/quote.png differ diff --git a/src/images/small/design_luna_sm.png b/src/images/small/design_luna_sm.png new file mode 100644 index 000000000..77e03d148 Binary files /dev/null and b/src/images/small/design_luna_sm.png differ diff --git a/src/images/small/luna_eye_sm.png b/src/images/small/luna_eye_sm.png new file mode 100644 index 000000000..19902efe7 Binary files /dev/null and b/src/images/small/luna_eye_sm.png differ diff --git a/src/images/small/main_luna_sm.png b/src/images/small/main_luna_sm.png new file mode 100644 index 000000000..d9faf7136 Binary files /dev/null and b/src/images/small/main_luna_sm.png differ diff --git a/src/images/small/meet_luna_sm.png b/src/images/small/meet_luna_sm.png new file mode 100644 index 000000000..986c449a5 Binary files /dev/null and b/src/images/small/meet_luna_sm.png differ diff --git a/src/scripts/form-submit.js b/src/scripts/form-submit.js new file mode 100644 index 000000000..d56f2a926 --- /dev/null +++ b/src/scripts/form-submit.js @@ -0,0 +1,178 @@ +'use strict'; + +const ID_MODAL = 'success-message'; +const ID_BTN_CLOSE_MODAL = 'close-success-message-btn'; +const ID_CONTACT_FORM = 'contact-form'; + +const CLASS_INPUT = 'text-input'; +const CLASS_INPUT_SUCCESS = 'text-input--success'; + +const CLASS_MODAL_CONTENT = 'modal__content'; +const CLASS_VISIBLE_MODAL_CONTENT = 'modal__content--visible'; +const CLASS_MODAL_OPEN = 'modal--open'; + +const FOCUSABLE_SELECTOR = ` + a[href], + button:not([disabled]), + input:not([disabled]), + select:not([disabled]), + textarea:not([disabled]), + [tabindex]:not([tabindex="-1"]) +`; + +let focusableElements = []; +let firstFocusableEl = null; +let lastFocusableEl = null; + +let autoCloserTimer = null; + +const updateFocusableElements = () => { + focusableElements = Array.from( + modal.querySelectorAll(FOCUSABLE_SELECTOR), + ).filter((el) => el.offsetParent !== null); + + firstFocusableEl = focusableElements[0]; + lastFocusableEl = focusableElements[focusableElements.length - 1]; +}; + +const handleKeydown = (e) => { + if (e.key === 'Escape') { + e.preventDefault(); + hideModal(); + + return; + } + + if (e.key !== 'Tab') { + return; + } + + updateFocusableElements(); + + if (!focusableElements.length) { + return; + } + + if (e.shiftKey) { + // SHIFT + TAB + if (document.activeElement === firstFocusableEl) { + e.preventDefault(); + lastFocusableEl.focus(); + } + } else { + // TAB + if (document.activeElement === lastFocusableEl) { + e.preventDefault(); + firstFocusableEl.focus(); + } + } +}; + +const activateFocusTrap = () => { + document.addEventListener('keydown', handleKeydown); +}; + +const deactivateFocusTrap = () => { + document.removeEventListener('keydown', handleKeydown); +}; + +const contactForm = document.getElementById(ID_CONTACT_FORM); +const contactFormInputs = document.querySelectorAll(`.${CLASS_INPUT}`); +const modal = document.getElementById(ID_MODAL); +const closeModalBtn = document.getElementById(ID_BTN_CLOSE_MODAL); +const modalContent = modal.querySelector(`.${CLASS_MODAL_CONTENT}`); + +const showModal = () => { + modal.classList.add(CLASS_MODAL_OPEN); + modal.removeAttribute('inert'); + modalContent.classList.add(CLASS_VISIBLE_MODAL_CONTENT); + + updateFocusableElements(); + firstFocusableEl?.focus(); + + activateFocusTrap(); +}; + +const hideModal = () => { + modalContent.classList.remove(CLASS_VISIBLE_MODAL_CONTENT); + + const onTransitionEnd = (e) => { + modal.setAttribute('inert', true); + modal.classList.remove(CLASS_MODAL_OPEN); + + deactivateFocusTrap(); + }; + + modalContent.addEventListener('transitionend', onTransitionEnd, { + once: true, + }); +}; + +const handleSubmitForm = (e) => { + e.preventDefault(); + + if (autoCloserTimer) { + clearTimeout(autoCloserTimer); + } + + contactForm.reset(); + contactFormInputs.forEach(markInputAsSuccessful); + showModal(); + + setTimeout(() => { + contactFormInputs.forEach(unmarkInputAsSuccessful); + }, 10000); + + autoCloserTimer = setTimeout(() => { + hideModal(); + autoCloserTimer = null; + }, 10000); +}; + +const markInputAsSuccessful = (input) => { + input.classList.add(CLASS_INPUT_SUCCESS); + input.blur(); + input.disabled = true; +}; + +const unmarkInputAsSuccessful = (input) => { + input.classList.remove(CLASS_INPUT_SUCCESS); + input.disabled = false; +}; + +const handleClickCloseModalBtn = (e) => { + e.preventDefault(); + + if (autoCloserTimer) { + clearTimeout(autoCloserTimer); + autoCloserTimer = null; + } + + hideModal(); +}; + +const handleKeyDownOnForm = (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + + if (typeof contactForm.requestSubmit === 'function') { + contactForm.requestSubmit(); + } else { + const submitBtn = contactForm.querySelector( + '[type="submit"], button:not([type])', + ); + + if (submitBtn) { + submitBtn.click(); + } else { + contactForm.dispatchEvent(new Event('submit')); + } + } + } +}; + +closeModalBtn.addEventListener('click', handleClickCloseModalBtn); + +contactForm.addEventListener('submit', handleSubmitForm); + +contactForm.addEventListener('keydown', handleKeyDownOnForm); diff --git a/src/scripts/main.js b/src/scripts/main.js deleted file mode 100644 index ad9a93a7c..000000000 --- a/src/scripts/main.js +++ /dev/null @@ -1 +0,0 @@ -'use strict'; diff --git a/src/scripts/mobile-menu.js b/src/scripts/mobile-menu.js new file mode 100644 index 000000000..460d572c8 --- /dev/null +++ b/src/scripts/mobile-menu.js @@ -0,0 +1,146 @@ +'use strict'; + +const ID_MOBILE_MENU = 'mobile-menu'; +const CLASS_MOBILE_MENU_OPEN = 'mobile-menu--open'; +const CLASS_MOBILE_MENU_CONTENT = 'mobile-menu__content'; +const CLASS_VISIBLE_MOBILE_MENU_CONTENT = 'mobile-menu__content--visible'; +const ID_MENU_OPEN_BTN = 'menu-btn'; +const ID_MENU_CLOSE_BTN = 'close-menu-btn'; +const CLASS_PAGE_NO_SCROLL = 'page--no-scroll'; +const BREAKPOINT_LARGE = 1440; +const FOCUSABLE_SELECTOR = ` + a[href], + button:not([disabled]), + input:not([disabled]), + select:not([disabled]), + textarea:not([disabled]), + [tabindex]:not([tabindex="-1"]) +`; + +let focusableElements = []; +let firstFocusableEl = null; +let lastFocusableEl = null; + +const updateFocusableElements = () => { + focusableElements = Array.from( + mobileMenu.querySelectorAll(FOCUSABLE_SELECTOR), + ).filter((el) => el.offsetParent !== null); + + firstFocusableEl = focusableElements[0]; + lastFocusableEl = focusableElements[focusableElements.length - 1]; +}; + +const handleKeydown = (e) => { + if (e.key === 'Escape') { + e.preventDefault(); + closeMenu(); + + return; + } + + if (e.key !== 'Tab') { + return; + } + + updateFocusableElements(); + + if (!focusableElements.length) { + return; + } + + if (e.shiftKey) { + // SHIFT + TAB + if (document.activeElement === firstFocusableEl) { + e.preventDefault(); + lastFocusableEl.focus(); + } + } else { + // TAB + if (document.activeElement === lastFocusableEl) { + e.preventDefault(); + firstFocusableEl.focus(); + } + } +}; + +const activateFocusTrap = () => { + document.addEventListener('keydown', handleKeydown); +}; + +const deactivateFocusTrap = () => { + document.removeEventListener('keydown', handleKeydown); +}; + +const mobileMenu = document.getElementById(ID_MOBILE_MENU); +const openMenuBtn = document.getElementById(ID_MENU_OPEN_BTN); +const closeMenuBtn = document.getElementById(ID_MENU_CLOSE_BTN); +const mobileMenuContent = mobileMenu.querySelector( + `.${CLASS_MOBILE_MENU_CONTENT}`, +); + +const largeMQ = window.matchMedia(`(min-width: ${BREAKPOINT_LARGE}px)`); + +const closeMenu = () => { + mobileMenuContent.classList.remove(CLASS_VISIBLE_MOBILE_MENU_CONTENT); + + const onTransitionEnd = (e) => { + if (e.target !== mobileMenuContent) { + return; + } + + if (e.propertyName !== 'opacity' && e.propertyName !== 'transform') { + return; + } + + openMenuBtn.setAttribute('aria-expanded', false); + mobileMenu.setAttribute('inert', true); + document.body.classList.remove(CLASS_PAGE_NO_SCROLL); + mobileMenu.classList.remove(CLASS_MOBILE_MENU_OPEN); + + deactivateFocusTrap(); + + mobileMenuContent.removeEventListener('transitionend', onTransitionEnd); + }; + + mobileMenuContent.addEventListener('transitionend', onTransitionEnd); +}; + +const openMenu = () => { + openMenuBtn.setAttribute('aria-expanded', true); + mobileMenu.removeAttribute('inert'); + document.body.classList.add(CLASS_PAGE_NO_SCROLL); + mobileMenu.classList.add(CLASS_MOBILE_MENU_OPEN); + mobileMenuContent.classList.add(CLASS_VISIBLE_MOBILE_MENU_CONTENT); + updateFocusableElements(); + firstFocusableEl?.focus(); + + activateFocusTrap(); +}; + +const handleOpenMenuBtnClick = (e) => { + e.preventDefault(); + openMenu(); +}; + +const handleCloseMenuBtnClick = (e) => { + e.preventDefault(); + closeMenu(); + openMenuBtn.focus(); +}; + +largeMQ.addEventListener('change', (e) => { + if (e.matches && mobileMenu.classList.contains(CLASS_MOBILE_MENU_OPEN)) { + closeMenu(); + } +}); + +openMenuBtn.addEventListener('click', handleOpenMenuBtnClick); +closeMenuBtn.addEventListener('click', handleCloseMenuBtnClick); + +mobileMenu.addEventListener('click', (e) => { + const anchor = e.target.closest('a'); + + if (anchor) { + closeMenu(); + } +}); diff --git a/src/scripts/swiper.js b/src/scripts/swiper.js new file mode 100644 index 000000000..721513514 --- /dev/null +++ b/src/scripts/swiper.js @@ -0,0 +1,110 @@ +import Swiper from 'swiper'; +import { + Pagination, + Navigation, + Mousewheel, + Keyboard, + EffectFade, +} from 'swiper/modules'; + +import 'swiper/css'; +import 'swiper/css/pagination'; +import 'swiper/css/navigation'; +import 'swiper/css/mousewheel'; +import 'swiper/css/keyboard'; +import 'swiper/css/effect-fade'; + +const CLASS_SWIPER = 'swiper'; +const SELECTOR_SWIPER = `.${CLASS_SWIPER}`; + +const baseOptions = { + direction: 'horizontal', + modules: [Navigation, Pagination, Mousewheel, Keyboard], + pagination: { + el: '.my-swiper__pagination', + type: 'fraction', + renderFraction: (currentClass, totalClass) => { + return ` + + / + + `; + }, + }, + + navigation: { + nextEl: '.my-swiper__button--next', + prevEl: '.my-swiper__button--prev', + }, + grabCursor: true, + + mousewheel: { + enabled: true, + forceToAxis: true, + }, + + keyboard: { + enabled: true, + onlyInViewport: true, + pageUpDown: false, + }, +}; + +const mobileOptions = { + ...baseOptions, + modules: [EffectFade, ...baseOptions.modules], + effect: 'fade', + fadeEffect: { + crossFade: true, + }, +}; + +const tabletOptions = { + ...baseOptions, + + slidesPerView: 2, + spaceBetween: 45, +}; + +// const swiper = new Swiper(SELECTOR_SWIPER, MY_SWIPER_OPTIONS); + +// const swiper = document.querySelector(SELECTOR_SWIPER); + +let swiperInstance = null; +const mqTablet = window.matchMedia('(min-width: 768px)'); +const mqDesktop = window.matchMedia('(min-width: 1440px)'); + +function getOptions() { + if (mqDesktop.matches) { + return null; + } + + if (mqTablet.matches) { + return tabletOptions; + } + + return mobileOptions; +} + +function updateSwiper() { + const options = getOptions(); + + if (!options) { + if (swiperInstance) { + swiperInstance.destroy(true, true); + swiperInstance = null; + } + + return; + } + + if (swiperInstance) { + swiperInstance.destroy(true, true); + } + + swiperInstance = new Swiper(SELECTOR_SWIPER, options); +} + +mqTablet.addEventListener('change', updateSwiper); +mqDesktop.addEventListener('change', updateSwiper); +updateSwiper(); diff --git a/src/scripts/to-top.js b/src/scripts/to-top.js new file mode 100644 index 000000000..b24b960d5 --- /dev/null +++ b/src/scripts/to-top.js @@ -0,0 +1,31 @@ +const ID_BTN_TO_TOP = 'to-top'; +const CLASS_VISIBLE_BTN_TO_TOP = 'page__button--visible'; +const CLASS_LOGO = 'logo'; + +const toTopBtn = document.getElementById(ID_BTN_TO_TOP); +const logo = document.querySelector(`.${CLASS_LOGO}`); + +const toggleToTop = () => { + const triggerPoint = window.innerHeight * 0.8; + + if (window.scrollY > triggerPoint) { + toTopBtn.classList.add(CLASS_VISIBLE_BTN_TO_TOP); + } else { + toTopBtn.classList.remove(CLASS_VISIBLE_BTN_TO_TOP); + } +}; + +const handleToTopBtnClick = (e) => { + e.preventDefault(); + + window.scrollTo({ + top: 0, + behavior: 'smooth', + }); + + logo.focus(); +}; + +toTopBtn.addEventListener('click', handleToTopBtnClick); + +window.addEventListener('scroll', toggleToTop); diff --git a/src/scripts/translate-en.json b/src/scripts/translate-en.json new file mode 100644 index 000000000..a7ee23dae --- /dev/null +++ b/src/scripts/translate-en.json @@ -0,0 +1,117 @@ +{ + "navigation": { + "goto": "Go to the {pageName} page", + "change-lng": "Change language to {lng}", + "open": "Open {modal}", + "close": "Close {modal}", + "see": "See more about us", + "next": "Go to the next feature block", + "prev": "Go to the prev feature block", + "gotop": "Go to the top of the page" + }, + "pages": { + "main": "Main", + "specs": "Specifications", + "about": "About Us", + "features": "Features", + "contact": "Contact", + "story": "Our Story", + "fb": "Facebook", + "x": "X", + "inst": "Instagram" + }, + "languages": { + "en": "English", + "ua": "Ukrainian" + }, + "imgs": { + "logo": "CrazyBaby logo", + "menu": "Menu icon", + "luna-speaker": "Luna speaker img", + "close-icon": "Close icon", + "compass": "Compass icon", + "speaker": "Speaker icon", + "meet": "Meet Luna image", + "design": "Designed for the future image", + "eye": "Luna eye image", + "feature": "Feature Luna image", + "fb": "Facebook icon", + "x": "X icon", + "inst": "Instagram icon", + "arUp": "Arrow up icon" + }, + "common": { + "buy": "Buy", + "menu": "Menu", + "send": "Send" + }, + "special": { + "specs-btn": "Specs", + "buy-btn": "Buy Luna speaker", + "contact": "Get in Touch" + }, + "titles": { + "header": "Futuristic Wireless Speaker", + "contact": "DO YOU HAVE ANY QUESTIONS?", + "benefits": { + "design": "Futuristic Design", + "speaker": "Tweeter Speaker System", + "wifi": "Multiroom System", + "sun": "Intuitive Lighting System" + }, + "article": { + "design": "Designed for the future", + "eye": "Luna Eye" + }, + "features": { + "connectivity": "Connectivity", + "sound": "Sound & Music", + "app": "App Features" + } + }, + "text": { + "header": "Luna’s performance is balanced and smooth in all frequency ranges which makes the music both naturally pleasant and distinctly more exciting.", + "benefits": { + "design": "To give Luna a truly flawless look, we specifically picked aircraft grade aluminum as its material and adopted both three-dimensional stretch-bending technology and a high precision cold forging technique.", + "speaker": "To deliver a more layered sound performance better than a sole full-range speaker, our team equipped Luna with one more tweeter speaker responsible for high-frequency sound independently.", + "wifi": "Luna is natively compatible with your home Wi-Fi. Set up multiple speakers in different rooms to expand your music experience into the entire house.", + "sun": "An intuitive user interface allows you to adjust the hue and saturation of color for lighting that fits any mood and situation." + }, + "article": { + "design": "In 2014, a group of geeky industrial designers, engineering veterans and acoustic experts formed crazybaby. This is a bunch of passionate people who are crazy enough to think they can challenge the industry with disruptive audio products.", + "eye": "Luna Eye is to the essence of this innovative light and audio system. It comprises an independent tweeter speaker, a light guiding component, a dome and a ring ornament." + }, + "comments": { + "garrett": { + "comment": "It really took me by surprise honestly to have such full beautiful sound that coming out of this small compact device. And with the brush aluminum surface, it feels so familiar. Like my iPhone.", + "position": "Creative Director" + } + }, + "features": { + "connectivity": { + "1": "Hands Free Wireless Audio", + "2": "Smart Multiroom System Set Up", + "3": "Party Mode with 6.0 Units and above", + "4": "MESHNET Multi Speaker Network" + }, + "sound": { + "1": "Feel-in-chest Base Power", + "2": "Lossless Digital Audio Transmission", + "3": "Easy & Stable Stereo Pairing", + "4": "Crisp and Clear High Frequency Sound", + "5": "Streams from Cloud Music and Local Library", + "6": "Auto Music Playback from Last Song Stopped" + }, + "app": { + "1": "Customize Music Schedule", + "2": "Wake Up with Favorite Songs", + "3": "Home Detection Auto Wake Up", + "4": "Color Wheel" + } + } + }, + "placeholder": { + "email": "Your email", + "message": "Your message" + } +} diff --git a/src/scripts/translate-ua.json b/src/scripts/translate-ua.json new file mode 100644 index 000000000..b43d3bc62 --- /dev/null +++ b/src/scripts/translate-ua.json @@ -0,0 +1,117 @@ +{ + "navigation": { + "goto": "Перейти до сторінки {pageName}", + "change-lng": "Змінити мову на {lng}", + "open": "Відкрити {modal}", + "close": "Закрити {modal}", + "see": "Дізнайтеся більше про нас", + "next": "Перейти до наступного блоку особливостей", + "prev": "Перейти до попереднього блоку особливостей", + "gotop": "Перейти до початку сторінки" + }, + "pages": { + "main": "Головна", + "specs": "Специфікації", + "about": "Про нас", + "features": "Особливості", + "contact": "Контакти", + "story": "Наша історія", + "fb": "Facebook", + "x": "X", + "inst": "Instagram" + }, + "languages": { + "en": "Англійська", + "ua": "Українська" + }, + "imgs": { + "logo": "CrazyBaby логотип", + "menu": "іконка Меню", + "luna-speaker": "зображення Колонки Luna", + "close-icon": "іконка Закриття", + "compass": "іконка Циркуля", + "speaker": "іконка Динаміка", + "meet": "зображення 'Зустрічай Luna'", + "design": "зображення 'Розроблена для майбутнього'", + "eye": "зображення Око Luna", + "feature": "зображення особливості Luna", + "fb": "іконка Facebook", + "x": "іконка X", + "inst": "іконка Instagram", + "arUp": "іконка Стрілка вгору" + }, + "common": { + "buy": "Купити", + "menu": "Меню", + "send": "Відправити" + }, + "special": { + "specs-btn": "Спец.", + "buy-btn": "Купити колонку Luna", + "contact": "Зв'язатися" + }, + "titles": { + "header": "Футуристична бездротова колонка", + "contact": "У ВАС Є ПИТАННЯ?", + "benefits": { + "design": "Футуристичний дизайн", + "speaker": "Система високого частотного динаміка", + "wifi": "Мультирумна система", + "sun": "Інтуїтивна система освітлення" + }, + "article": { + "design": "Розроблена для майбутнього", + "eye": "Око Luna" + }, + "features": { + "connectivity": "Підключення", + "sound": "Звук і Музика", + "app": "Особливості додатка" + } + }, + "text": { + "header": "Продуктивність Luna збалансована і плавна у всіх частотних діапазонах, що робить музику природно приємною і виразно більш захоплюючою.", + "benefits": { + "design": "Щоб надати Luna справді бездоганний вигляд, ми спеціально вибрали алюміній авіаційного класу як матеріал і застосували як технологію тривимірного розтягування-згинання, так і високоточну техніку холодного кування.", + "speaker": "Щоб забезпечити більш багатошарове звучання, краще ніж у випадку з одним повнодіапазонним динаміком, наша команда оснастила Luna ще одним твітером, який відповідає за високі частоти.", + "wifi": "Luna сумісна з домашньою мережею Wi-Fi. Встановіть кілька колонок у різних кімнатах, щоб насолоджуватися музикою в усьому будинку.", + "sun": "Інтуїтивно зрозумілий інтерфейс дозволяє регулювати відтінок і насиченість кольорів освітлення, щоб воно відповідало будь-якому настрою та ситуації." + }, + "article": { + "design": "У 2014 році група захоплених промислових дизайнерів, досвідчених інженерів та експертів з акустики заснувала компанію crazybaby. Це група палких ентузіастів, які настільки божевільні, що вважають, що можуть кинути виклик галузі завдяки революційним аудіопродуктам.", + "eye": "Luna Eye — це суть цієї інноваційної світлової та аудіосистеми. Вона складається з незалежного високого динаміка, світлопровідного компонента, купола та кільцевого орнаменту." + }, + "comments": { + "garrett": { + "comment": "Чесно кажучи, я був дуже здивований, що з такого маленького компактного пристрою виходить такий повний і красивий звук. А завдяки матовій алюмінієвій поверхні він здається таким знайомим. Як мій iPhone.", + "position": "Креативний Директор" + } + }, + "features": { + "connectivity": { + "1": "Бездротовий аудіопристрій Hands Free", + "2": "Налаштування інтелектуальної Мультирум-Системи", + "3": "Режим Вечірки з 6.0 одиницями і вище", + "4": "MESHNET Мережа з декількома динаміками" + }, + "sound": { + "1": "Потужність, що відчувається в грудях", + "2": "Безвтратна цифрова передача аудіоданих", + "3": "Просте та стабільне стереопарне з'єднання", + "4": "Чіткий і чистий звук високої частоти", + "5": "Потоки з Cloud Music та локальної бібліотеки", + "6": "Автоматичне відтворення музики з останньої зупиненої пісні" + }, + "app": { + "1": "Налаштування музичного розкладу", + "2": "Прокидайтеся під улюблені пісні", + "3": "Автоматичне пробудження при виявленні будинку", + "4": "Колірне колесо" + } + } + }, + "placeholder": { + "email": "Ваш email", + "message": "Ваше повідомлення" + } +} diff --git a/src/scripts/translate.js b/src/scripts/translate.js new file mode 100644 index 000000000..d1cc8e20e --- /dev/null +++ b/src/scripts/translate.js @@ -0,0 +1,118 @@ +'use strict'; + +/* eslint-disable no-console */ +import translationEnglish from './translate-en.json'; +import translationUkrainian from './translate-ua.json'; + +const DATA_ACTION_TRANSLATE_EN = 'translate-en'; +const DATA_ACTION_TRANSLATE_UA = 'translate-ua'; +const DATA_TRANSLATE_PREFIX = 'data-translate-'; +const ATTR_DATA_TRANSLATE_VARS = `${DATA_TRANSLATE_PREFIX}vars`; +const CLASS_SELECTED_LNG_BTN = 'language-selector__button--selected'; +const KEY_EN = 'en'; +const KEY_UA = 'ua'; +const STORAGE_LANG_KEY = 'pref-lang'; + +const languageEnBtns = document.querySelectorAll( + `[data-action="${DATA_ACTION_TRANSLATE_EN}"]`, +); +const languageUaBtns = document.querySelectorAll( + `[data-action="${DATA_ACTION_TRANSLATE_UA}"]`, +); + +const LANG_BUTTONS = { + [KEY_EN]: languageEnBtns, + [KEY_UA]: languageUaBtns, +}; + +const TRANSLATE_TARGETS = { + text: 'textContent', + 'aria-label': 'aria-label', + placeholder: 'placeholder', + alt: 'alt', +}; + +let currentLang = null; + +if (!languageEnBtns.length || !languageUaBtns.length) { + console.error('Language buttons not found in DOM'); +} + +const getValue = (key, dictionary) => { + return key.split('.').reduce((obj, part) => { + return obj && obj[part] ? obj[part] : null; + }, dictionary); +}; + +const translate = (lang) => { + const dictionary = + lang === KEY_UA ? translationUkrainian : translationEnglish; + + Object.entries(TRANSLATE_TARGETS).forEach(([dataKey, target]) => { + document + .querySelectorAll(`[${DATA_TRANSLATE_PREFIX}${dataKey}]`) + .forEach((el) => { + const key = el.getAttribute(`${DATA_TRANSLATE_PREFIX}${dataKey}`); + const vars = el.hasAttribute(ATTR_DATA_TRANSLATE_VARS) + ? JSON.parse(el.getAttribute(ATTR_DATA_TRANSLATE_VARS)) + : {}; + let value = getValue(key, dictionary); + + if (!value) { + return; + } + + Object.entries(vars).forEach(([varKey, varValue]) => { + const varTranslation = getValue(varValue, dictionary) || varValue; + + value = value.replaceAll(`{${varKey}}`, varTranslation); + }); + + if (target === 'textContent') { + el.textContent = value; + } else { + el.setAttribute(target, value); + } + }); + }); +}; + +const updateLangBtns = (lang) => { + Object.entries(LANG_BUTTONS).forEach(([key, btns]) => { + btns.forEach((btn) => { + btn.classList.toggle(CLASS_SELECTED_LNG_BTN, key === lang); + }); + }); +}; + +const applyLang = (lang) => { + if (lang === currentLang) { + localStorage.setItem(STORAGE_LANG_KEY, lang); + + return; + } + translate(lang); + updateLangBtns(lang); + currentLang = lang; + localStorage.setItem(STORAGE_LANG_KEY, lang); +}; + +const addBtnListeners = () => { + Object.entries(LANG_BUTTONS).forEach(([key, btns]) => { + btns.forEach((btn) => { + btn.addEventListener('click', (e) => { + applyLang(key); + }); + }); + }); +}; + +window.addEventListener('load', (e) => { + const storedLang = localStorage?.getItem(STORAGE_LANG_KEY); + + const lang = storedLang || KEY_EN; + + applyLang(lang); + + addBtnListeners(); +}); diff --git a/src/styles/_fonts.scss b/src/styles/_fonts.scss deleted file mode 100644 index 45cdd5400..000000000 --- a/src/styles/_fonts.scss +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - font-family: Roboto, Arial, Helvetica, sans-serif; - src: url('../fonts/Roboto-Regular-webfont.woff') format('woff'); - font-weight: normal; - font-style: normal; -} diff --git a/src/styles/_typography.scss b/src/styles/_typography.scss deleted file mode 100644 index 1837eb46e..000000000 --- a/src/styles/_typography.scss +++ /dev/null @@ -1,3 +0,0 @@ -h1 { - @extend %h1; -} diff --git a/src/styles/_utils.scss b/src/styles/_utils.scss deleted file mode 100644 index 3280c3fe1..000000000 --- a/src/styles/_utils.scss +++ /dev/null @@ -1,3 +0,0 @@ -@import 'utils/vars'; -@import 'utils/mixins'; -@import 'utils/extends'; diff --git a/src/styles/base/_base.scss b/src/styles/base/_base.scss new file mode 100644 index 000000000..6628d7e7d --- /dev/null +++ b/src/styles/base/_base.scss @@ -0,0 +1,16 @@ +*, +*::after, +*::before { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; + + font-family: $primary-font-family; + font-size: 100%; + font-weight: 400; + font-style: normal; + color: $text-primary-neutral-color; + -webkit-text-size-adjust: 100%; +} diff --git a/src/styles/base/_fonts.scss b/src/styles/base/_fonts.scss new file mode 100644 index 000000000..fad3e0fd6 --- /dev/null +++ b/src/styles/base/_fonts.scss @@ -0,0 +1,13 @@ +@font-face { + font-family: Roboto, Arial, Helvetica, sans-serif; + font-weight: normal; + font-style: normal; + src: url('../fonts/Roboto-Regular-webfont.woff') format('woff'); +} + +@font-face { + font-family: Inter, Helvetica, Arial, sans-serif; + font-weight: 100 900; + font-style: normal; + src: url('../fonts/Inter-VariableFont_opsz\,wght.ttf') format('truetype'); +} diff --git a/src/styles/base/_typography.scss b/src/styles/base/_typography.scss new file mode 100644 index 000000000..fa046d8b9 --- /dev/null +++ b/src/styles/base/_typography.scss @@ -0,0 +1,43 @@ +h1 { + @extend %h1; +} + +h2 { + @extend %h2; +} + +h3 { + @extend %h3; +} + +h4 { + @extend %h4; +} + +h5 { + @extend %h5; +} + +h6 { + @extend %h6; +} + +button { + @extend %button; +} + +p { + @extend %main-text; +} + +.secondary-text { + @extend %secondary-text; +} + +.thirdary-text { + @extend %thirdary-text; +} + +q { + @extend %quote; +} diff --git a/src/styles/blocks/_article.scss b/src/styles/blocks/_article.scss new file mode 100644 index 000000000..33fd0ff48 --- /dev/null +++ b/src/styles/blocks/_article.scss @@ -0,0 +1,133 @@ +.article { + @extend %base-grid-column; + + grid-auto-rows: min-content; + + &__title { + grid-column: 1 / -1; + margin: 0; + + @include respond-to(md) { + grid-row: 1; + } + + &--right { + @include respond-to(md) { + grid-column: 5 / -1; + } + + @include respond-to(lg) { + grid-column: 7 / -1; + } + } + + &--left { + @include respond-to(md) { + grid-column: 1 / 5; + } + + @include respond-to(lg) { + grid-column: 1 / 7; + } + } + } + + &__picture { + display: flex; + grid-column: 1 / -1; + justify-content: center; + margin-top: 30px; + + @include respond-to(md) { + grid-row: 1 / span 4; + margin-top: 0; + } + + &--right { + @include respond-to(md) { + grid-column: 5 / -1; + justify-content: flex-start; + } + + @include respond-to(lg) { + grid-column: 7 / -1; + } + } + + &--left { + @include respond-to(md) { + grid-column: 1 / 5; + justify-content: flex-end; + } + + @include respond-to(lg) { + grid-column: 1 / 7; + } + } + } + + &__text { + @extend %main-text; + + grid-column: 1 / -1; + margin-top: 20px; + margin-bottom: 0; + color: $text-muted-color; + + @include respond-to(md) { + grid-row: 2; + margin-top: 30px; + } + + &--right { + @include respond-to(md) { + grid-column: 5 / -1; + } + + @include respond-to(lg) { + grid-column: 7 / -1; + } + } + + &--left { + @include respond-to(md) { + grid-column: 1 / 5; + } + + @include respond-to(lg) { + grid-column: 1 / 7; + } + } + } + + &__button { + grid-column: 1 / -1; + width: fit-content; + margin-top: 30px; + + @include respond-to(md) { + grid-row: 3; + margin-top: 60px; + } + + &--right { + @include respond-to(md) { + grid-column: 5 / -1; + } + + @include respond-to(lg) { + grid-column: 7 / -1; + } + } + + &--left { + @include respond-to(md) { + grid-column: 1 / 5; + } + + @include respond-to(lg) { + grid-column: 1 / 7; + } + } + } +} diff --git a/src/styles/blocks/_benefits.scss b/src/styles/blocks/_benefits.scss new file mode 100644 index 000000000..02b9e6d6c --- /dev/null +++ b/src/styles/blocks/_benefits.scss @@ -0,0 +1,26 @@ +.benefits { + @extend %base-grid-column; + + row-gap: 65px; + margin-inline: 30px; + + @include respond-to(md) { + margin: 0; + } + + @include respond-to(lg) { + margin-top: 60px; + } + + &__benefit { + grid-column: 1 / -1; + + @include respond-to(md) { + grid-column: span 4; + } + + @include respond-to(lg) { + grid-column: span 3; + } + } +} diff --git a/src/styles/blocks/_comment.scss b/src/styles/blocks/_comment.scss new file mode 100644 index 000000000..46d84f0ea --- /dev/null +++ b/src/styles/blocks/_comment.scss @@ -0,0 +1,59 @@ +.comment { + display: flex; + flex-direction: column; + align-items: center; + + background-image: url('../images/quote.png'); + background-repeat: no-repeat; + background-position: top center; + + &__quote { + margin-top: 50px; + text-align: center; + + @include respond-to(md) { + margin-top: 60px; + } + + @include respond-to(lg) { + margin-top: 42px; + } + } + + &__avatar { + display: block; + + width: 62px; + height: 62px; + margin-top: 30px; + border-radius: 50%; + + object-fit: cover; + object-position: center; + + @include respond-to(md) { + margin-top: 40px; + } + + @include respond-to(lg) { + margin-top: 30px; + } + } + + &__title { + margin-top: 10px; + margin-bottom: 0; + + @include respond-to(md) { + margin-top: 20px; + } + } + + &__position { + @extend %secondary-text; + + margin-top: 5px; + margin-bottom: 0; + color: $text-muted-color; + } +} diff --git a/src/styles/blocks/_comments.scss b/src/styles/blocks/_comments.scss new file mode 100644 index 000000000..5273a9c7a --- /dev/null +++ b/src/styles/blocks/_comments.scss @@ -0,0 +1,11 @@ +.comments { + @extend %base-grid-column; + + &__comment { + grid-column: 1 / -1; + + @include respond-to(lg) { + grid-column: 3 / 11; + } + } +} diff --git a/src/styles/blocks/_contact-form.scss b/src/styles/blocks/_contact-form.scss new file mode 100644 index 000000000..4175635d7 --- /dev/null +++ b/src/styles/blocks/_contact-form.scss @@ -0,0 +1,14 @@ +.contact-form { + display: flex; + flex-direction: column; + gap: 20px; + align-items: flex-start; + + &__text-input { + width: 100%; + } + + &__button { + margin-top: 10px; + } +} diff --git a/src/styles/blocks/_contact-us.scss b/src/styles/blocks/_contact-us.scss new file mode 100644 index 000000000..0b330b36b --- /dev/null +++ b/src/styles/blocks/_contact-us.scss @@ -0,0 +1,30 @@ +.contact-us { + @extend %base-grid-column; + + &__title { + grid-column: 1 / -1; + margin: 0; + + @include respond-to(md) { + grid-column: 1 / span 4; + } + + @include respond-to(lg) { + grid-column: 1 / span 6; + } + } + + &__contact-form { + grid-column: 1 / -1; + margin-top: 30px; + + @include respond-to(md) { + grid-column: 5 / -1; + margin: 0; + } + + @include respond-to(lg) { + grid-column: 7 / -1; + } + } +} diff --git a/src/styles/blocks/_feature.scss b/src/styles/blocks/_feature.scss new file mode 100644 index 000000000..ceb31203e --- /dev/null +++ b/src/styles/blocks/_feature.scss @@ -0,0 +1,53 @@ +.feature { + padding-top: 30px; + padding-inline: 30px; + + @include respond-to(md) { + padding: 0; + } + + &__title { + margin: 0; + color: $text-accent-color; + } + + &__list { + display: flex; + flex-direction: column; + gap: 10px; + + max-width: 260px; + margin-top: 20px; + margin-bottom: 0; + padding: 0; + + @include respond-to(lg) { + max-width: none; + margin-top: 30px; + } + } + + &__item { + @extend %secondary-text; + + display: flex; + gap: 10px; + align-items: center; + + &::before { + content: ''; + + display: flex; + flex-grow: 0; + flex-shrink: 0; + + width: 6px; + height: 6px; + + background-image: url('../images/icons/icon-bullet.svg'); + background-repeat: no-repeat; + background-position: center; + background-size: 6px 6px; + } + } +} diff --git a/src/styles/blocks/_features.scss b/src/styles/blocks/_features.scss new file mode 100644 index 000000000..811ade3a2 --- /dev/null +++ b/src/styles/blocks/_features.scss @@ -0,0 +1,83 @@ +.features { + &__title { + margin-block: 0; + margin-inline: 30px; + + @include respond-to(md) { + margin: 0; + } + } + + &__my-swiper { + margin-top: 30px; + } + + // *Need this specificity to override default swiper styles. + // *Default swiper styles connects later than these styles. + & &__my-swiper { + position: relative; + + @include respond-to(md) { + padding-top: 60px; + padding-inline: 45px; + } + + @include respond-to(lg) { + padding-block: 60px; + } + } + + &__picture { + display: flex; + width: auto; + height: fit-content; + + @include respond-to(md) { + justify-content: flex-end; + width: auto; + } + + @include respond-to(lg) { + position: absolute; + right: 50px; + bottom: 0; + } + } + + &__img { + width: 100%; + @include respond-to(md) { + width: auto; + } + } + + &__navigation { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 50px; + + @include respond-to(md) { + margin-left: 50px; + } + + @include respond-to(lg) { + display: none; + } + } + + &__container { + display: flex; + flex-direction: column; + + @include respond-to(md) { + flex-direction: row; + justify-content: space-between; + } + + @include respond-to(lg) { + display: block; + margin: 0; + } + } +} diff --git a/src/styles/blocks/_footer.scss b/src/styles/blocks/_footer.scss new file mode 100644 index 000000000..40f5913f8 --- /dev/null +++ b/src/styles/blocks/_footer.scss @@ -0,0 +1,33 @@ +.footer { + display: flex; + flex-direction: column; + gap: 30px; + align-items: center; + justify-content: center; + + @include respond-to(md) { + gap: 60px; + } + + &__logo { + display: none; + + @include respond-to(md) { + display: block; + } + } + + &__rights { + @extend %secondary-text; + + margin: 0; + color: $text-subtle-color; + text-align: center; + } + + &__links { + display: flex; + gap: 40px; + justify-content: center; + } +} diff --git a/src/styles/blocks/_header.scss b/src/styles/blocks/_header.scss new file mode 100644 index 000000000..13c327d55 --- /dev/null +++ b/src/styles/blocks/_header.scss @@ -0,0 +1,114 @@ +.header { + &__interactive { + display: flex; + align-items: center; + justify-content: space-between; + padding: 22px 30px; + + @include respond-to(md) { + padding: 0; + } + } + + &__picture { + position: relative; + z-index: $z-index-zero; + + display: block; + grid-column: 1 / -1; + place-self: center; + + @include respond-to(md) { + grid-column: 4 / -1; + grid-row: 1 / span 2; + place-self: end center; + } + + @include respond-to(lg) { + place-self: end; + } + } + + &__img { + display: block; + max-width: 100%; + } + + &__title { + grid-column: 1 / -1; + max-width: 13ch; + margin: 40px 30px 0; + word-wrap: break-word; + + @include respond-to(md) { + grid-column: 1 / 5; + grid-row: 1 / span 1; + align-self: end; + + margin: 0; + + word-wrap: normal; + } + } + + &__text { + grid-column: 1 / -1; + margin: 20px 30px 0; + + @include respond-to(md) { + grid-column: 1 / 4; + grid-row: 2 / span 1; + margin: 30px 0 0; + } + } + + &__static { + @extend %base-grid-column; + + grid-auto-rows: min-content; + + @include respond-to(md) { + margin-top: 130px; + } + + @include respond-to(lg) { + margin-top: 90px; + } + } + + &__options { + display: flex; + gap: 30px; + align-items: center; + } + + &__language-selector { + display: none; + + @include respond-to(md) { + display: flex; + } + } + + &__specs-btn { + display: none; + + @include respond-to(md) { + display: block; + } + } + + &__buy-btn { + display: none; + + @include respond-to(md) { + display: block; + } + } + + &__menu-btn { + @include respond-to(lg) { + display: none; + } + } +} diff --git a/src/styles/blocks/_main.scss b/src/styles/blocks/_main.scss new file mode 100644 index 000000000..17679eaaf --- /dev/null +++ b/src/styles/blocks/_main.scss @@ -0,0 +1,82 @@ +.main { + &__nav { + display: none; + + @include respond-to(lg) { + display: flex; + justify-content: center; + padding-block: 28px; + } + } + + &__picture { + display: block; + + width: fit-content; + height: fit-content; + margin-top: 110px; + margin-inline: auto; + + @include respond-to(md) { + margin-top: 140px; + } + + @include respond-to(lg) { + margin-top: 170px; + } + } + + &__article { + margin-top: 110px; + margin-inline: 30px; + + @include respond-to(md) { + margin-top: 140px; + margin-inline: 0; + } + + @include respond-to(lg) { + margin-top: 170px; + } + } + + &__comments { + margin-top: 110px; + margin-inline: 30px; + + @include respond-to(md) { + margin-top: 140px; + margin-inline: 0; + } + + @include respond-to(lg) { + margin-top: 170px; + } + } + + &__features { + margin-top: 110px; + + @include respond-to(md) { + margin-top: 140px; + } + + @include respond-to(lg) { + margin-top: 170px; + } + } + + &__contact-us { + margin-top: 110px; + margin-inline: 30px; + + @include respond-to(md) { + margin-top: 140px; + margin-inline: 0; + } + + @include respond-to(lg) { + margin-top: 170px; + } + } +} diff --git a/src/styles/blocks/_mobile_menu.scss b/src/styles/blocks/_mobile_menu.scss new file mode 100644 index 000000000..491477d7c --- /dev/null +++ b/src/styles/blocks/_mobile_menu.scss @@ -0,0 +1,73 @@ +.mobile-menu { + pointer-events: none; + + position: fixed; + z-index: $z-index-last; + inset: 0; + + opacity: 0; + background-color: rgba(0, 0, 0, 0.25); + + &--open { + pointer-events: all; + opacity: 1; + } + + &__content { + @extend %block-max-width; + + transform: translateX(100%); + + width: 100%; + height: 100dvh; + max-height: none; + border: none; + + opacity: 0; + background-color: $page-bg-color; + + transition: + transform $transition-long ease-out, + opacity $transition-long ease-out; + + &--visible { + transform: translateX(0); + opacity: 1; + } + + @include respond-to(md) { + padding-top: 39px; + } + } + + &__nav { + margin: 30px 30px 0; + + @include respond-to(md) { + margin: 40px 0 0; + } + } + + &__options { + display: flex; + gap: 20px; + margin: 50px 30px 0; + + @include respond-to(md) { + display: none; + } + } + + &__buy-btn { + position: absolute; + right: 0; + bottom: 0; + left: 0; + + margin: auto 30px 30px; + + @include respond-to(md) { + display: none; + } + } +} diff --git a/src/styles/blocks/_my-swiper.scss b/src/styles/blocks/_my-swiper.scss new file mode 100644 index 000000000..b1b24f888 --- /dev/null +++ b/src/styles/blocks/_my-swiper.scss @@ -0,0 +1,100 @@ +.my-swiper { + background-color: $bg-color-accent-block; + + // *Need this specificity to override default swiper styles. + // *Default swiper styles connects later than these styles. + & .swiper-wrapper { + @include respond-to(lg) { + display: grid; + grid-auto-rows: min-content; + grid-template-columns: repeat(12, 1fr); + gap: 50px 30px; + + box-sizing: border-box; + } + } + + &__slide { + &--first { + grid-column: 2 / span 4; + grid-row: 1; + } + + &--second { + grid-column: 2 / span 4; + grid-row: 2; + } + + &--third { + grid-column: 7 / span 4; + grid-row: 1; + } + } + + &__navigation { + position: relative; + display: flex; + justify-content: center; + + @include respond-to(lg) { + display: none; + } + } + + &__pagination { + display: flex; + gap: 4px; + align-items: flex-end; + justify-content: center; + + font-size: 0.7rem; + line-height: 100%; + } + + &__divider, + &__total { + color: $text-accent-color; + } + + &__current { + font-size: 1rem; + line-height: 150%; + color: $text-primary-neutral-color; + } + + &__button { + cursor: pointer; + + position: relative; + + padding: 0; + border: none; + + color: $text-primary-neutral-color; + + background-color: transparent; + + transition-property: color; + + &:disabled { + cursor: not-allowed; + color: $text-accent-color; + } + @include base-interaction; + @include hover { + color: $text-accent-hovered-color; + } + @include active { + color: $text-accent-hovered-color; + } + + &--next { + right: 2px; + } + + &--prev { + top: 2px; + left: 2px; + } + } +} diff --git a/src/styles/blocks/_nav.scss b/src/styles/blocks/_nav.scss new file mode 100644 index 000000000..1883d8d4c --- /dev/null +++ b/src/styles/blocks/_nav.scss @@ -0,0 +1,22 @@ +.nav { + &__list { + display: flex; + flex-direction: column; + gap: 25px; + + margin: 0; + padding: 0; + + list-style: none; + + @include respond-to(lg) { + flex-direction: row; + gap: 84px; + justify-content: center; + } + } + + &__link { + color: $text-primary-neutral-color; + } +} diff --git a/src/styles/blocks/_page.scss b/src/styles/blocks/_page.scss new file mode 100644 index 000000000..8818c1bfc --- /dev/null +++ b/src/styles/blocks/_page.scss @@ -0,0 +1,76 @@ +.page { + background-color: $page-bg-color; + + &--no-scroll { + overflow: hidden; + } + + &__header { + @extend %block-max-width; + + @include respond-to(md) { + margin-top: 30px; + } + } + + // &__mobile-menu { + // @extend %block-max-width; + + // @include respond-to(md) { + // padding-top: 39px; + // } + // } + + &__main { + @extend %block-max-width; + + overflow: hidden; + margin-top: 110px; + + @include respond-to(md) { + margin-top: 140px; + } + + @include respond-to(lg) { + margin-top: 170px; + } + } + + &__footer { + @extend %block-max-width; + + margin-top: 110px; + margin-bottom: 20px; + + @include respond-to(md) { + margin-top: 140px; + margin-bottom: 30px; + } + + @include respond-to(lg) { + margin-top: 170px; + } + } + + &__button { + pointer-events: none; + + position: fixed; + z-index: $z-index-last; + right: 35px; + bottom: 170px; + transform: translateX(20px); + + opacity: 0; + + transition: + opacity 0.7s ease-out, + transform 0.7s ease-out; + + &--visible { + pointer-events: auto; + transform: translateX(0); + opacity: 1; + } + } +} diff --git a/src/styles/components/_benefit.scss b/src/styles/components/_benefit.scss new file mode 100644 index 000000000..382fef852 --- /dev/null +++ b/src/styles/components/_benefit.scss @@ -0,0 +1,33 @@ +.benefit { + text-align: center; + + &__img { + display: flex; + align-self: center; + justify-content: center; + height: 40px; + + @include respond-to(lg) { + height: 50px; + } + } + + &__title { + margin: 40px 0 0; + + @include respond-to(lg) { + height: 54px; + } + } + + &__text { + @extend %secondary-text; + + margin: 20px 0 0; + color: $text-muted-color; + + @include respond-to(lg) { + margin-top: 24px; + } + } +} diff --git a/src/styles/components/_button.scss b/src/styles/components/_button.scss new file mode 100644 index 000000000..75900f229 --- /dev/null +++ b/src/styles/components/_button.scss @@ -0,0 +1,164 @@ +.button { + cursor: pointer; + + border: none; + + font-family: $secondary-font-family; + font-weight: 500; + text-align: center; + text-decoration: none; + + &--thirdary { + @extend %thirdary-text; + + padding: 0; + color: $text-secondary-color; + background-color: transparent; + transition-property: color, text-shadow; + + @include base-interaction; + @include hover { + color: $text-primary-neutral-color; + text-shadow: + 0.5px 0 0 $text-primary-neutral-color, + -0.5px 0 0 $text-primary-neutral-color; + } + @include active { + color: $text-primary-neutral-color; + text-shadow: + 0.5px 0 0 $text-primary-neutral-color, + -0.5px 0 0 $text-primary-neutral-color; + } + } + + &--icon { + display: inline-flex; + align-items: center; + justify-content: center; + + width: 32px; + height: 32px; + padding: 0; + + background-color: transparent; + + transition-property: transform; + + @include base-interaction; + @include hover { + transform: scale(1.2); + } + + @include active { + transform: scale(0.8); + } + } + + &--primary-accent { + @include button-text( + $bg-color: $bg-color-accent-btn, + $hover-bg-color: $bg-color-accent-hover-btn, + $disabled-bg-color: $bg-color-accent-disabled-btn, + $text-color: $text-inverse-color + ); + } + + &--primary-neutral { + @include button-text( + $bg-color: $bg-color-neutral-btn, + $hover-bg-color: $bg-color-neutral-hover-btn, + $disabled-bg-color: $bg-color-neutral-disabled-btn, + $text-color: $text-inverse-color + ); + } + + &--secondary-accent { + @include button-text( + $bg-color: transparent, + $hover-bg-color: $bg-color-accent-hover-btn, + $disabled-bg-color: transparent, + $text-color: $text-accent-color, + $border: 1px solid $bg-color-accent-btn, + $text-hover-color: $text-inverse-color, + $disabled-text-color: $text-accent-disabled-color, + $disabled-border-color: $bg-color-accent-disabled-btn + ); + } + + &--secondary-neutral { + @include button-text( + $bg-color: transparent, + $hover-bg-color: $bg-color-neutral-hover-btn, + $disabled-bg-color: transparent, + $text-color: $text-primary-neutral-color, + $border: 1px solid $bg-color-neutral-btn, + $text-hover-color: $text-inverse-color, + $disabled-text-color: $text-lightest-color, + $disabled-border-color: $bg-color-neutral-disabled-btn + ); + } + + &--unbordered-accent { + padding: 0; + color: $text-accent-color; + background-color: transparent; + + @include base-interaction; + + transition-property: color; + + &::after { + content: ''; + + display: block; + + width: 40%; + height: 1px; + margin-top: 8px; + + background-color: $bg-color-accent-btn; + + transition-property: width, background-color; + @include base-interaction; + } + + @include hover { + color: $text-accent-hovered-color; + &::after { + width: 100%; + background-color: $bg-color-accent-hover-btn; + } + } + + @include active { + color: $text-accent-hovered-color; + + &::after { + width: 100%; + background-color: $bg-color-accent-hover-btn; + } + } + + &:disabled { + cursor: not-allowed; + color: $text-accent-disabled-color; + &::after { + background-color: $bg-color-accent-disabled-btn; + } + } + } + + &--unbordered-neutral { + @include button-text( + $bg-color: transparent, + $hover-bg-color: transparent, + $disabled-bg-color: transparent, + $text-color: $text-secondary-color, + $border: 1px solid transparent, + $disabled-text-color: $text-lightest-color, + $hovered-border-color: $bg-color-neutral-hover-btn + ); + + font-weight: 400; + } +} diff --git a/src/styles/components/_language-selector.scss b/src/styles/components/_language-selector.scss new file mode 100644 index 000000000..b08836f65 --- /dev/null +++ b/src/styles/components/_language-selector.scss @@ -0,0 +1,13 @@ +.language-selector { + display: flex; + gap: 3px; + align-items: center; + + &__button { + color: $text-subtle-color; + + &--selected { + color: $text-primary-neutral-color; + } + } +} diff --git a/src/styles/components/_logo.scss b/src/styles/components/_logo.scss new file mode 100644 index 000000000..db3fd515d --- /dev/null +++ b/src/styles/components/_logo.scss @@ -0,0 +1,17 @@ +.logo { + display: inline-flex; + align-items: center; + justify-content: center; + + text-decoration: none; + + transition-property: transform; + + @include base-interaction; + @include hover { + transform: scale(1.2); + } + @include active { + transform: scale(0.8); + } +} diff --git a/src/styles/components/_modal.scss b/src/styles/components/_modal.scss new file mode 100644 index 000000000..60081d08e --- /dev/null +++ b/src/styles/components/_modal.scss @@ -0,0 +1,49 @@ +.modal { + pointer-events: none; + + position: fixed; + z-index: $z-index-last; + inset: 0; + + display: flex; + align-items: center; + justify-content: center; + + opacity: 0; + background-color: rgba(0, 0, 0, 0.5); + + &--open { + pointer-events: all; + opacity: 1; + } + + &__content { + position: relative; + + padding: 1rem; + border: 3px solid $color-green-500; + + opacity: 0; + background-color: $page-bg-color; + + transition: opacity $transition-long ease-out; + + &--visible { + opacity: 1; + } + } + + &__close-button { + position: absolute; + top: 10px; + right: 10px; + } + + &__title { + color: $text-primary-accent-color; + } + + &__message { + color: $text-secondary-color; + } +} diff --git a/src/styles/components/_text-input.scss b/src/styles/components/_text-input.scss new file mode 100644 index 000000000..1d21f2b13 --- /dev/null +++ b/src/styles/components/_text-input.scss @@ -0,0 +1,73 @@ +.text-input { + resize: none; + + padding: 12px clamp(1.3rem, 4vw, 2.4rem); + border: 1px solid $border-color-default-input; + + font-family: $primary-font-family; + font-size: 1rem; + font-weight: 500; + line-height: 1.5rem; + color: $text-primary-neutral-color; + + outline: none; + + transition-property: border-color; + + &::placeholder { + font-family: $primary-font-family; + font-size: 1rem; + font-weight: 400; + line-height: 1.5rem; + color: $text-placeholder-color; + } + + &:focus { + border-color: $border-color-selected-input; + font-family: $secondary-font-family; + } + + &:disabled { + cursor: not-allowed; + background-color: $bg-color-disabled-input; + } + + &:-webkit-autofill, + &:-webkit-autofill:hover, + &:-webkit-autofill:focus { + border-color: $border-color-selected-input; + box-shadow: 0 0 0 1000px $bg-color-autofill-input inset; + + -webkit-text-fill-color: $text-primary-neutral-color; + } + + &--success { + border-color: $border-color-success-input; + + &::placeholder { + color: $text-placehoder-success-color; + } + } + + @include base-interaction; + + @include hover { + border-color: $border-color-selected-input; + } + + @include active { + border-color: $border-color-selected-input; + } + + &--textarea { + height: 128px; + + @include respond-to(md) { + height: 200px; + } + + @include respond-to(lg) { + height: 128px; + } + } +} diff --git a/src/styles/main.scss b/src/styles/main.scss index fb9195d12..db943e5b7 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -1,7 +1,30 @@ -@import 'utils'; -@import 'fonts'; -@import 'typography'; +@import 'normalize.css'; -body { - background: $c-gray; -} +@import 'utils/index'; + +@import 'base/fonts'; +@import 'base/base'; +@import 'base/typography'; + +@import 'components/button'; +@import 'components/text-input'; +@import 'components/modal'; +@import 'components/logo'; +@import 'components/language-selector'; +@import 'components/benefit'; + +@import 'blocks/footer'; +@import 'blocks/contact-form'; +@import 'blocks/contact-us'; +@import 'blocks/feature'; +@import 'blocks/features'; +@import 'blocks/my-swiper'; +@import 'blocks/comment'; +@import 'blocks/comments'; +@import 'blocks/article'; +@import 'blocks/benefits'; +@import 'blocks/nav'; +@import 'blocks/mobile_menu'; +@import 'blocks/main'; +@import 'blocks/header'; +@import 'blocks/page'; diff --git a/src/styles/utils/_animations.scss b/src/styles/utils/_animations.scss new file mode 100644 index 000000000..3507e84f5 --- /dev/null +++ b/src/styles/utils/_animations.scss @@ -0,0 +1,43 @@ +@keyframes fade-in { + 0% { + display: none; + opacity: 0; + } + + 100% { + display: block; + opacity: 1; + } +} + +@keyframes fade-out { + 0% { + display: block; + opacity: 1; + } + + 100% { + display: none; + opacity: 0; + } +} + +@keyframes slide-in-left { + 0% { + transform: translateX(100%); + } + + 100% { + transform: translateX(0%); + } +} + +@keyframes slide-out-left { + 0% { + transform: translateX(0%); + } + + 100% { + transform: translateX(100%); + } +} diff --git a/src/styles/utils/_extends.scss b/src/styles/utils/_extends.scss index d7201e7b3..47be40541 100644 --- a/src/styles/utils/_extends.scss +++ b/src/styles/utils/_extends.scss @@ -1,4 +1,136 @@ +%heading-base { + font-family: $primary-font-family; + font-weight: 700; + line-height: 125%; + text-transform: uppercase; +} + %h1 { - font-family: Roboto, sans-serif; - font-weight: 400; + @extend %heading-base; + + font-size: 2.5rem; + line-height: 130%; + + @include respond-to(md) { + font-size: 3rem; + } + + @include respond-to(lg) { + font-size: 4rem; + } +} + +%h2 { + @extend %heading-base; + + font-size: 1.9rem; + line-height: 130%; + + @include respond-to(md) { + font-size: 2.25rem; + } + + @include respond-to(lg) { + font-size: 3.5rem; + } +} + +%h3 { + @extend %heading-base; + + font-size: 1.13rem; + + @include respond-to(md) { + font-size: 1.5rem; + } + + @include respond-to(lg) { + font-size: 2.15rem; + } +} + +%h4 { + @extend %heading-base; + + font-size: 1.38rem; +} + +%h5 { + @extend %heading-base; + + font-size: 1rem; + line-height: 140%; + text-transform: capitalize; +} + +%h6 { + @extend %heading-base; + + font-size: 0.88rem; + line-height: 145%; +} + +%button { + font-family: $secondary-font-family; + font-size: 0.75rem; + font-weight: 700; + line-height: 120%; + text-transform: uppercase; +} + +%main-text { + font-size: 1rem; + line-height: 150%; +} + +%secondary-text { + font-size: 0.88rem; + line-height: 150%; +} + +%thirdary-text { + font-size: 0.88rem; + line-height: 150%; + text-transform: uppercase; +} + +%quote { + font-family: $primary-font-family; + font-size: 0.88rem; + font-weight: 700; + line-height: 145%; + + @include respond-to(md) { + font-size: 1.5rem; + line-height: 150%; + } +} + +%block-max-width { + max-width: 1200 + 68px; + margin-inline: auto; + + @include respond-to(md) { + padding-inline: min(4vw, 34px); + } + + @include respond-to(lg) { + max-width: 1194px; + padding-inline: 0; + } +} + +%base-grid-column { + display: grid; + grid-template-columns: repeat($column-grid-sm, 1fr); + column-gap: 20px; + + @include respond-to(md) { + grid-template-columns: repeat($column-grid-md, 1fr); + column-gap: 30px; + } + + @include respond-to(lg) { + grid-template-columns: repeat($column-grid-lg, 1fr); + } } diff --git a/src/styles/utils/_index.scss b/src/styles/utils/_index.scss new file mode 100644 index 000000000..36ca674f7 --- /dev/null +++ b/src/styles/utils/_index.scss @@ -0,0 +1,4 @@ +@import 'vars'; +@import 'mixins'; +@import 'extends'; +@import 'animations'; diff --git a/src/styles/utils/_mixins.scss b/src/styles/utils/_mixins.scss index 80c79780d..316499a99 100644 --- a/src/styles/utils/_mixins.scss +++ b/src/styles/utils/_mixins.scss @@ -1,6 +1,111 @@ -@mixin hover($_property, $_toValue) { - transition: #{$_property} 0.3s; - &:hover { - #{$_property}: $_toValue; +@mixin base-interaction { + transition-timing-function: ease; + transition-duration: $transiton-short; + + -webkit-tap-highlight-color: transparent; +} + +@mixin hover() { + @media (hover: hover) { + &:not(:disabled) { + &:hover { + @content; + } + } + } +} + +@mixin active() { + &:not(:disabled) { + &:active { + @content; + } + } +} + +@mixin respond-to($breakpoint) { + @if $breakpoint == md { + @media (min-width: $breakpoint-md) { + @content; + } + } @else if $breakpoint == lg { + @media (min-width: $breakpoint-lg) { + @content; + } + } +} + +@mixin base-grid-column { + display: grid; + grid-template-columns: repeat($column-grid-sm, 1fr); + column-gap: 20px; + + @include respond-to(md) { + grid-template-columns: repeat($column-grid-md, 1fr); + column-gap: 30px; + } + + @include respond-to(lg) { + grid-template-columns: repeat($column-grid-lg, 1fr); + } +} + +@mixin button-text( + $bg-color, + $hover-bg-color, + $disabled-bg-color, + $text-color, + $border: none, + $text-hover-color: none, + $disabled-text-color: none, + $disabled-border-color: none, + $hovered-border-color: none +) { + padding: 17px 40px; + border: $border; + + color: $text-color; + + background-color: $bg-color; + + transition-property: color, border-color, background-color; + + @include base-interaction; + + @include hover { + @if $text-hover-color != none { + color: $text-hover-color; + } + + @if $hovered-border-color != none { + border-color: $hovered-border-color; + } + + background-color: $hover-bg-color; + } + + @include active { + @if $text-hover-color != none { + color: $text-hover-color; + } + + @if $hovered-border-color != none { + border-color: $hovered-border-color; + } + + background-color: $hover-bg-color; + } + + &:disabled { + cursor: not-allowed; + background-color: $disabled-bg-color; + + @if $disabled-border-color != none { + border-color: $disabled-border-color; + } + + @if $disabled-text-color != none { + color: $disabled-text-color; + } } } diff --git a/src/styles/utils/_vars.scss b/src/styles/utils/_vars.scss index aeb006ffb..54f00424c 100644 --- a/src/styles/utils/_vars.scss +++ b/src/styles/utils/_vars.scss @@ -1 +1,50 @@ -$c-gray: #eee; +$color-green-600: #0c797a; +$color-green-500: #0db2b3; +$color-green-400: #39bebf; +$color-green-300: #cfeff0; +$color-green-200: #eefafa; +$color-black: #131313; +$color-gray-500: #333; +$color-gray-400: #4f4f4f; +$color-gray-300: #7c7c7c; +$color-gray-200: #bdbdbd; +$color-gray-100: #d0d0d0; +$color-gray-90: #f7f7f7; +$bg-color-accent-btn: $color-green-400; +$bg-color-accent-hover-btn: $color-green-600; +$bg-color-accent-disabled-btn: $color-green-300; +$bg-color-neutral-btn: $color-gray-500; +$bg-color-neutral-hover-btn: $color-black; +$bg-color-neutral-disabled-btn: $color-gray-100; +$bg-color-accent-block: $color-green-300; +$text-inverse-color: #fff; +$text-accent-color: $color-green-500; +$text-accent-hovered-color: $color-green-600; +$text-accent-disabled-color: $color-green-300; +$text-primary-accent-color: $color-black; +$text-primary-neutral-color: $color-gray-500; +$text-secondary-color: $color-gray-400; +$text-muted-color: $color-gray-300; +$text-subtle-color: $color-gray-200; +$text-lightest-color: $color-gray-100; +$text-placeholder-color: $color-gray-200; +$text-placehoder-success-color: #eb57574d; +$border-color-default-input: $color-gray-300; +$border-color-selected-input: $color-green-500; +$border-color-success-input: #eb5757; +$bg-color-autofill-input: $color-green-300; +$bg-color-disabled-input: $color-gray-90; +$z-index-zero: -10; +$z-index-first: 10; +$z-index-last: 100; +$z-index-second: 20; +$breakpoint-md: 768px; +$breakpoint-lg: 1440px; +$primary-font-family: Inter, Helvetica, Roboto, Arial, sans-serif; +$secondary-font-family: Helvetica, Inter, Roboto, Arial, sans-serif; +$page-bg-color: $color-gray-90; +$column-grid-sm: 4; +$column-grid-md: 8; +$column-grid-lg: 12; +$transiton-short: 0.3s; +$transition-long: 0.7s;