diff --git a/.postcssrc b/.postcssrc index 3f3c53d..01dbf5d 100644 --- a/.postcssrc +++ b/.postcssrc @@ -1,5 +1,8 @@ { "plugins": { + "postcss-modules": { + generateScopedName: "[name]_[local]_[hash:base64:5]" + }, "autoprefixer": { "grid": true } diff --git a/src/index.html b/src/index.html index ba51871..5c4bc10 100644 --- a/src/index.html +++ b/src/index.html @@ -7,31 +7,53 @@ - + + The UAM Times
-
-
-
+
+
+
+
+
+

THE TAJMS

+
+

Sports

-
-
- Free kick -
Free kick at second half.
-
+
+
+ Free kick +
Free kick at second half.
+

We won versus some other team.

-
+
diff --git a/src/index.scss b/src/index.scss index f44f553..47005f9 100644 --- a/src/index.scss +++ b/src/index.scss @@ -3,26 +3,185 @@ padding: 0; box-sizing: border-box; } +$secondary: green; + +body { + font-family: 'Lato', sans-serif; + padding: 2rem 2rem 2rem 2rem; + + #click-catcher { + display: none; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + z-index: 2; + + &.active { + display: block; + } + } +} + +.hover-pointer { + &:hover { + cursor: pointer; + } +} + +nav { + $bg-color: white; + position: fixed; + top: 0; + left: 0; + transform: translateX(-100%); + transition: transform 500ms ease-in-out; + background-color: $bg-color; + min-height: 100vh; + padding: 1rem; + z-index: 10; + + ul { + overflow-y: auto; + li { + list-style-type: none; + padding: 5px; + margin-top: 0.2rem; + font-weight: 500; + border-radius: 0.5rem; + &.active { + font-weight: 600; + } + &:hover { + cursor: pointer; + background-color: mix($secondary, darken($bg-color, 10%), 10%); + } + } + } + + &.active { + transform: translateX(0); + } +} header#main-header { display: flex; - flex-direction: column; width: 100%; + flex-direction: row; + align-items: center; + border-bottom: 2px solid mix(black, $secondary, 50%); + padding-bottom: 1rem; + margin-bottom: 1rem; - #top { - height: 10rem; + $input-width: 10rem; - #hamburger { - width: 1.5rem; - height: 3rem; + #date { + align-self: end; + small { + font-style: italic; + color: $secondary; + } + } - &:after { - content: ''; - display: block; - width: 100%; - height: 2px; - background-color: black; + h1 { + $font-size: 4rem; + font-weight: 100; + font-size: $font-size; + font-family: 'Bungee Inline', serif; + transform: translateX(-#{$input-width/2}); + margin-left: auto; + user-select: none; + width: 100%; + //text-align: center; + height: $font-size; + display: flex; + //align-items: ; +justify-content: center; + align-items: center; + + span { + &:hover { + transform: translateY(5px); + transition-duration: 0.2s; } + &.empty { + width: $font-size/4; + } + //height: $font-size; + display: inline-block; + //height: $font-size; + transform: translateY(0px); + transition: 0.3s transform ease-in-out; + } + } + + div#search { + color: $secondary; + display: inline-flex; + flex-direction: row; + + &.active { + input.hidden-input { + transform: scaleX(1) translateX(-2px) !important; + transition-duration: 0.2s; + border: 2px solid black !important; + } + } + + input.hidden-input { + margin-left: 1rem; + transform: scaleX(0); + transform-origin: left; + width: $input-width; + height: 1rem; + padding: 10px 12px; + border-width: 0; + transition-property: transform, border-width; + transition-duration: 1s; + transition-timing-function: ease-in-out; + } + + i { + margin-left: 1rem; + } + } + + #hamburger { + $gap: 4px; + $size: 4px; + $width: 2rem; + + width: $width; + display: flex; + flex-direction: column; + + &:hover { + #top { + transform: translateX(-3px); + } + + #bottom { + transform: translateX(3px); + } + } + + + & > div { + width: 100%; + background-color: black; + height: $size; + border-radius: 3px; + } + + #top { + transition: transform 1s cubic-bezier(0.2, -2, 0.2, 2); + margin-bottom: $gap; + } + + #bottom { + transition: transform 1s cubic-bezier(0.2, -2, 0.2, 2); + margin-top: $gap; } } } diff --git a/src/index.ts b/src/index.ts index 7148a9d..40f90ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,93 @@ -window.onload = function() { - console.log("Hello world") -}; \ No newline at end of file +let search = { + icon: document.querySelector("div#search i"), + input: document.querySelector("div#search input") as HTMLInputElement, + onInputClick: () => search.active(search.icon.parentElement), + isActive: false, + active: (elem: HTMLElement) => { + search.isActive = !search.isActive; + if(search.isActive) { + elem.classList.add("active"); + } else { + search.input.value = ""; + elem.classList.remove("active"); + } + } +}; + +search.icon.addEventListener("click", search.onInputClick); + +let nav = { + clickCatcher: document.querySelector("div#click-catcher"), + nav: document.querySelector("body > nav"), + hamburger: document.querySelector("#hamburger"), + isActive: false, + listItems: null as NodeListOf, + activeListItem: null as HTMLLIElement, + active: () => { + nav.isActive = !nav.isActive; + if(nav.isActive) { + [nav.nav, nav.clickCatcher] + .forEach( + (x) => x.classList.remove("active")); + } else { + [nav.nav, nav.clickCatcher] + .forEach( + (x) => x.classList.add("active")); + } + }, + onClickCatcherClick: (e: Event) => { + console.log("Click catcher click"); + e.stopPropagation(); + nav.active(); + }, + hamburgerOnClick: () => { + nav.active(); + console.log("hamburgerOnClick"); + }, + navOnClick: () => { + nav.active(); + }, + setActiveListItem: (elem: HTMLLIElement) => { + nav.activeListItem.classList.remove("active"); + nav.activeListItem = elem; + nav.activeListItem.classList.add("active"); + }, + listItemClick: (e: Event) => { + nav.setActiveListItem(e.target as HTMLLIElement); + } +}; +nav.listItems = nav.nav.querySelectorAll("ul > li"); +nav.listItems.forEach( + (x) => x.addEventListener("click", nav.listItemClick) +); + +nav.activeListItem = nav.listItems[0]; +nav.activeListItem.classList.add("active"); + +nav.hamburger.addEventListener("click", nav.hamburgerOnClick); +nav.nav.addEventListener("click", nav.navOnClick); +nav.clickCatcher.addEventListener("click", nav.onClickCatcherClick); + +let header = { + h1: document.querySelector("header > h1") as HTMLHeadingElement, + makeHeaderAnimatable: () => { + const text = header.h1.innerText.trim(); + header.h1.innerHTML = ""; + for(const letter of text) { + const span = document.createElement("span"); + span.innerText = letter; + if(letter === " ") { + span.classList.add("empty"); + } + header.h1.appendChild(span); + } + }, + date: document.querySelector("header > div#date"), + setDate: () => { + header.date.innerHTML = ` + Today is + ${new Date().toISOString()}`; + } +}; +header.makeHeaderAnimatable(); +header.setDate(); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9c34d8b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["esnext", "dom", "dom.iterable"] + } +} \ No newline at end of file