diff --git a/README.md b/README.md index 1ff4000..d1ef255 100644 --- a/README.md +++ b/README.md @@ -80,18 +80,18 @@ Configures what state of the toggle button should be shown to the user. ## Customize Dark Mode -You can exclude elements from being inverted in dark mode using the `.nightowl-daylight` CSS class. Just add it to an element and it will show the element in the same way as the light mode. +You can exclude elements from being inverted in dark mode using the `.nightowl-daylight` CSS class. Just add it to an element and it will show the element in the same way as the light mode. ```html
-

I'm inverted in Dark Mode

-

I'm not inverted in Dark Mode

+

I'm inverted in Dark Mode

+

I'm not inverted in Dark Mode

``` ## Contribution Guidelines -Please open an issue and wait for one of the Maintainers to approve it until you open a merge request. +Please open an issue and wait for one of the Maintainers to approve it until you open a merge request. ## Credits diff --git a/index.html b/index.html index dc92526..bb453f6 100644 --- a/index.html +++ b/index.html @@ -2,9 +2,16 @@ - - Vite + TS + Nightowl + + + + + - +
-

Nightowl Demo Site

- + + - + + + + + + Contact Us +
+
+
+
+

Lorem ipsum dolor sit amet consectetur adipisicing

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing + elit. A assumenda blanditiis esse ex inventore molestias + odit perferendis qui reprehenderit totam. Atque beatae + dicta, fuga illo laudantium porro rerum ullam vitae. +

+ + Contact Us + +
+
+
+ A tall skyscraper among many buildings in a city +
+
+
+
+

Features

+

+ Aut consequuntur cum esse ex explicabo iure, magnam maiores + perferendis qui tempora? +

+ +
+
+
+ A pie chart that represents some fake data for illustration purpose +
+
+

Statistics

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing + elit. A, aliquid, animi assumenda blanditiis cupiditate + debitis eligendi, enim facere fuga fugiat fugit ipsa + labore magnam quibusdam quo quos sapiente sunt velit + vitae voluptate! Accusantium aliquam animi assumenda, + necessitatibus quod rem repudiandae? +

+ + Read More + +
+
+
+

Our Team

+

Aliquid architecto nisi quisquam sapiente sed.

+ +
+
+

Contact Us

+

Nulla placeat quod tempore unde voluptates voluptatum?

+
+
+ Teammates gathering around a table and working together +
+
+
+ + + + +
+
+
diff --git a/public/assets/illustrations/chart.svg b/public/assets/illustrations/chart.svg new file mode 100644 index 0000000..74089c3 --- /dev/null +++ b/public/assets/illustrations/chart.svg @@ -0,0 +1 @@ +DirectEmailUnion Ads Video Ads \ No newline at end of file diff --git a/public/assets/images/contact.webp b/public/assets/images/contact.webp new file mode 100644 index 0000000..4477582 Binary files /dev/null and b/public/assets/images/contact.webp differ diff --git a/public/assets/images/hero.webp b/public/assets/images/hero.webp new file mode 100644 index 0000000..59879af Binary files /dev/null and b/public/assets/images/hero.webp differ diff --git a/public/assets/images/teammate-1.jpg b/public/assets/images/teammate-1.jpg new file mode 100644 index 0000000..71f449a Binary files /dev/null and b/public/assets/images/teammate-1.jpg differ diff --git a/public/assets/images/teammate-2.jpg b/public/assets/images/teammate-2.jpg new file mode 100644 index 0000000..c97640f Binary files /dev/null and b/public/assets/images/teammate-2.jpg differ diff --git a/public/assets/images/teammate-3.jpg b/public/assets/images/teammate-3.jpg new file mode 100644 index 0000000..8de99f8 Binary files /dev/null and b/public/assets/images/teammate-3.jpg differ diff --git a/src/main.ts b/src/main.ts index 0fa8334..dfe8413 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,3 +1,12 @@ +import './styles/global.css' +import './styles/button.css' +import './styles/header.css' +import './styles/intro.css' +import './styles/features.css' +import './styles/statistics.css' +import './styles/team.css' +import './styles/contact.css' + const LOCAL_STORAGE_KEY = 'nightowl-color-scheme' const LIGHT = 'light' const DARK = 'dark' diff --git a/src/scripts/header.ts b/src/scripts/header.ts new file mode 100644 index 0000000..534c60e --- /dev/null +++ b/src/scripts/header.ts @@ -0,0 +1,75 @@ +class HeaderService { + private headerElement = document.querySelector('body > header')! + private menuButton = document.querySelector('body > header button.menu')! + private closeButton = document.querySelector('body > header button.close')! + private navElement = document.querySelector('body > header nav')! + private navLinks = document.querySelectorAll( + 'body > header nav a' + ) + + public init(): void { + this.addMenuButtonClickListener() + this.addNavLinksClickListener() + this.addWindowResizeObserver() + this.addDocumentScrollListener() + + this.updateStickiness() + } + + private addMenuButtonClickListener(): void { + this.menuButton.addEventListener('click', () => { + this.showMobileNav() + }) + + this.closeButton.addEventListener('click', () => { + this.hideMobileNav() + }) + } + + private showMobileNav(): void { + this.navElement.classList.remove('hidden') + this.menuButton.classList.add('hidden') + this.closeButton.classList.remove('hidden') + } + + private hideMobileNav(): void { + this.navElement.classList.add('hidden') + this.menuButton.classList.remove('hidden') + this.closeButton.classList.add('hidden') + } + + private addNavLinksClickListener(): void { + this.navLinks.forEach((navLink) => { + navLink.addEventListener('click', () => { + this.hideMobileNav() + }) + }) + } + + private addWindowResizeObserver(): void { + const observer = new ResizeObserver(() => { + if (window.innerWidth >= 800) { + this.hideMobileNav() + } + }) + + observer.observe(document.body) + } + + private addDocumentScrollListener(): void { + document.addEventListener('scroll', () => { + this.updateStickiness() + }) + } + + private updateStickiness(): void { + if (window.scrollY > 50) { + this.headerElement.classList.add('stuck') + } else if (window.scrollY === 0) { + this.headerElement.classList.remove('stuck') + } + } +} + +const headerService = new HeaderService() +headerService.init() diff --git a/src/styles/button.css b/src/styles/button.css new file mode 100644 index 0000000..5c0d5f1 --- /dev/null +++ b/src/styles/button.css @@ -0,0 +1,54 @@ +.button { + border-radius: var(--border-radius); + + font-weight: 500; + + text-decoration: none; + text-transform: uppercase; + + cursor: pointer; + + &.button--solid { + background-color: var(--color-primary); + color: var(--color-primary-opposite); + + padding: 1em 2em; + + border: none; + + transition: background-color var(--animation-duration-fast) ease-in-out; + + &:hover { + background-color: var(--color-primary-darker); + } + } + + &.button--outlined { + background-color: transparent; + color: var(--color-primary); + + padding: 0.5em 1em; + + border: 1px solid var(--color-primary); + + transition: var(--animation-duration-fast) ease-in-out; + transition-property: background-color, color; + + &:hover { + background-color: var(--color-primary); + color: var(--color-primary-opposite); + } + } + + &.button--icon { + background-color: transparent; + + border: none; + + transition: background-color var(--animation-duration-fast) ease-in-out; + + &:hover { + background-color: var(--color-gray-90); + } + } +} diff --git a/src/styles/contact.css b/src/styles/contact.css new file mode 100644 index 0000000..ef19dab --- /dev/null +++ b/src/styles/contact.css @@ -0,0 +1,84 @@ +#contact { + display: grid; + grid-template-areas: 'h2' 'p' 'visuals' 'form'; + grid-template-columns: 1fr; + gap: 1rem; + + padding-block: 4rem; + padding-inline: var(--page-padding-inline); + + h2 { + grid-area: h2; + } + + > p { + grid-area: p; + + margin-block-end: 1rem; + } + + .visuals { + grid-area: visuals; + + display: grid; + place-items: center; + + .shape { + box-shadow: var(--box-shadow-normal); + + overflow: hidden; + + max-block-size: 25rem; + max-inline-size: 80%; + aspect-ratio: 1; + + border-radius: var(--border-radius-blob); + + img { + block-size: 100%; + inline-size: 100%; + max-inline-size: unset; + object-fit: cover; + } + } + } + + form { + grid-area: form; + + display: grid; + align-content: start; + gap: 1.5rem; + + label { + display: grid; + gap: 0.25rem; + + input, + textarea { + padding: 0.5rem; + + border: 1px solid var(--color-gray-50); + border-radius: var(--border-radius); + + font-size: 1.25rem; + } + + textarea { + resize: vertical; + } + } + + button { + font-size: 1.2rem; + } + } +} + +@media (width >= 800px) { + #contact { + grid-template-areas: 'h2 h2' 'p p' 'visuals form'; + grid-template-columns: 1fr 1fr; + gap: 1rem; + } +} diff --git a/src/styles/features.css b/src/styles/features.css new file mode 100644 index 0000000..8946595 --- /dev/null +++ b/src/styles/features.css @@ -0,0 +1,70 @@ +#features { + display: grid; + gap: 1rem; + + padding-block: 4rem; + padding-inline: var(--page-padding-inline); + + > p { + margin-block-end: 1rem; + } + + > ul { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); + gap: 2rem; + + > li { + background-color: var(--color-gray-98); + box-shadow: var(--box-shadow-normal); + + display: grid; + align-content: start; + justify-items: center; + + padding: 1rem; + + border-radius: var(--border-radius); + + text-align: center; + + .visual { + svg { + block-size: 1em; + inline-size: 1em; + + font-size: 4rem; + + path { + fill: var(--color); + } + } + } + + .title { + color: var(--color); + + margin-block-end: 1rem; + + font-size: 1.5rem; + font-weight: 700; + } + + &:nth-of-type(1) { + --color: hsl(10deg 70% 50%); + } + + &:nth-of-type(2) { + --color: hsl(40deg 70% 50%); + } + + &:nth-of-type(3) { + --color: hsl(90deg 70% 50%); + } + + &:nth-of-type(4) { + --color: hsl(160deg 70% 50%); + } + } + } +} diff --git a/src/styles/global.css b/src/styles/global.css new file mode 100644 index 0000000..084635a --- /dev/null +++ b/src/styles/global.css @@ -0,0 +1,110 @@ +:root { + --color-gray-98: hsl(0deg 0% 98%); + --color-gray-95: hsl(0deg 0% 95%); + --color-gray-90: hsl(0deg 0% 90%); + --color-gray-80: hsl(0deg 0% 80%); + --color-gray-70: hsl(0deg 0% 70%); + --color-gray-60: hsl(0deg 0% 60%); + --color-gray-50: hsl(0deg 0% 50%); + --color-gray-40: hsl(0deg 0% 40%); + --color-gray-30: hsl(0deg 0% 30%); + --color-gray-20: hsl(0deg 0% 20%); + --color-gray-16: hsl(0deg 0% 16%); + --color-gray-14: hsl(0deg 0% 14%); + --color-gray-12: hsl(0deg 0% 12%); + --color-gray-10: hsl(0deg 0% 10%); + + --color-primary: hsl(261deg 66% 69%); + --color-primary-darker: hsl(261deg 66% 60%); + --color-primary-opposite: var(--color-gray-98); + + --color-box-shadow-subtle: hsl(0deg 0% 10% / 12%); + --box-shadow-subtle: 0 0.2rem 0.5rem 0 var(--color-box-shadow-subtle); + + --color-box-shadow-normal: hsl(0deg 0% 10% / 20%); + --box-shadow-normal: 0 0.5rem 1rem 0 var(--color-box-shadow-subtle); + + --border-radius: 0.25rem; + --border-radius-blob: 33% 67% 38% 62% / 26% 32% 68% 74%; + + --page-max-inline-size: 75rem; + --page-padding-inline: calc( + max(100% - var(--page-max-inline-size), 2rem) / 2 + ); + + --animation-duration-fast: 0.2s; + --animation-duration-normal: 0.5s; + --animation-duration-slow: 1s; +} + +*, +*::before, +*::after { + box-sizing: border-box; + + margin: 0; + padding: 0; +} + +html { + accent-color: var(--color-primary); + + scroll-behavior: smooth; + scroll-padding: 4rem; + + font-family: 'Inter', sans-serif; + font-optical-sizing: auto; + font-weight: 400; + font-style: normal; + font-variation-settings: 'slnt' 0; +} + +input, +label, +select, +textarea, +button, +fieldset, +legend, +datalist, +output, +option, +optgroup { + font-family: inherit; +} + +p { + color: var(--color-gray-40); + + line-height: 1.4; +} + +ul { + list-style: none; +} + +img { + block-size: auto; + max-inline-size: 100%; +} + +body { + background-color: var(--color-gray-95); + color: var(--color-gray-10); + + min-block-size: 100dvh; +} + +h1 { + font-size: 3rem; + font-weight: 700; + + line-height: 1; +} + +h2 { + font-size: 2rem; + font-weight: 700; + + line-height: 1; +} diff --git a/src/styles/header.css b/src/styles/header.css new file mode 100644 index 0000000..00d4e19 --- /dev/null +++ b/src/styles/header.css @@ -0,0 +1,124 @@ +header { + background-color: inherit; + + position: sticky; + inset-block-start: 0; + z-index: 2; + + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 2rem; + + padding-block: 2rem; + padding-inline: var(--page-padding-inline); + + transition: var(--animation-duration-fast) ease-in-out; + transition-property: background-color, box-shadow, padding-block; + + .logo { + margin-inline-end: auto; + + font-size: 1.5rem; + font-weight: 700; + } + + button { + z-index: 2; + } + + nav { + ul { + li { + a { + color: inherit; + + position: relative; + + font-weight: 500; + + text-decoration: none; + + &::after { + content: ''; + + background-color: currentcolor; + + position: absolute; + inset-block-end: 0; + inset-inline: 0; + + block-size: 1px; + + transform: scaleX(0); + + transition: transform var(--animation-duration-fast) + ease-in-out; + } + + &:hover { + &::after { + transform: scaleX(100%); + } + } + } + } + } + } + + &.stuck { + background-color: var(--color-gray-98); + box-shadow: var(--box-shadow-subtle); + + padding-block: 1rem; + } +} + +@media (width < 800px) { + header { + button { + order: 3; + } + + nav { + background-color: var(--color-gray-98); + + position: fixed; + inset: 0; + overflow: auto; + z-index: 1; + + display: grid; + align-content: start; + + padding: inherit; + + font-size: 1.5rem; + + ul { + display: grid; + gap: 2rem; + } + } + + .hidden { + display: none; + } + } +} + +@media (width >= 800px) { + header { + button { + display: none; + } + + nav { + ul { + display: flex; + align-items: center; + gap: 2rem; + } + } + } +} diff --git a/src/styles/intro.css b/src/styles/intro.css new file mode 100644 index 0000000..db4eacb --- /dev/null +++ b/src/styles/intro.css @@ -0,0 +1,89 @@ +#intro { + display: grid; + grid-template-areas: 'writings visuals'; + grid-template-columns: 1fr 1fr; + align-items: center; + gap: 4rem; + + padding-block: 8rem; + padding-inline: var(--page-padding-inline); + + .writings { + grid-area: writings; + + display: grid; + justify-items: start; + gap: 1rem; + + p { + margin-block-end: 1rem; + + font-size: 1.25rem; + } + + a { + font-size: 1.2rem; + } + } + + .visuals { + grid-area: visuals; + + .shape { + --rotation: 45deg; + + box-shadow: var(--box-shadow-normal); + + overflow: hidden; + + inline-size: 70%; + aspect-ratio: 1; + + margin-inline: auto; + + border-radius: 2rem; + + transform: rotate(var(--rotation)); + + img { + block-size: 140%; + inline-size: 140%; + max-inline-size: unset; + object-fit: cover; + + transform: translate(-15%, -15%) + rotate(calc(-1 * var(--rotation) + 0deg)); + } + } + } +} + +@media (width < 1000px) { + #intro { + grid-template-areas: 'visuals' 'writings'; + grid-template-columns: 1fr; + justify-items: center; + + padding-block: 4rem; + + text-align: center; + + .writings { + justify-items: center; + + h1 { + max-inline-size: 20ch; + } + + p { + max-inline-size: 50ch; + } + } + + .visuals { + .shape { + max-inline-size: 20rem; + } + } + } +} diff --git a/src/styles/statistics.css b/src/styles/statistics.css new file mode 100644 index 0000000..5f0712c --- /dev/null +++ b/src/styles/statistics.css @@ -0,0 +1,40 @@ +#statistics { + display: grid; + align-items: center; + grid-template-columns: 1fr 1fr; + gap: 4rem; + + padding-block: 4rem; + padding-inline: var(--page-padding-inline); + + .visuals { + img { + max-block-size: 30rem; + inline-size: 100%; + } + } + + .writings { + display: grid; + justify-items: start; + gap: 1rem; + + p { + margin-block-end: 1rem; + + max-inline-size: 60ch; + } + } +} + +@media (width < 1000px) { + #statistics { + grid-template-columns: 1fr; + + text-align: center; + + .writings { + justify-items: center; + } + } +} diff --git a/src/styles/team.css b/src/styles/team.css new file mode 100644 index 0000000..d420f25 --- /dev/null +++ b/src/styles/team.css @@ -0,0 +1,46 @@ +#team { + display: grid; + gap: 1rem; + + padding-block: 4rem; + padding-inline: var(--page-padding-inline); + + > p { + margin-block-end: 1rem; + } + + > ul { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); + gap: 2rem; + + > li { + background-color: var(--color-gray-98); + box-shadow: var(--box-shadow-normal); + + display: grid; + align-content: start; + justify-items: center; + gap: 1rem; + + padding: 1rem; + + border-radius: var(--border-radius); + + text-align: center; + + .writings { + .name { + font-size: 1.25rem; + font-weight: 700; + + text-transform: capitalize; + } + + p { + max-inline-size: 45ch; + } + } + } + } +}