Moved website data to /www/
This commit is contained in:
BIN
www/fag.png
Normal file
BIN
www/fag.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
1
www/icons/glass-water.svg
Normal file
1
www/icons/glass-water.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-glass-water-icon lucide-glass-water"><path d="M5.116 4.104A1 1 0 0 1 6.11 3h11.78a1 1 0 0 1 .994 1.105L17.19 20.21A2 2 0 0 1 15.2 22H8.8a2 2 0 0 1-2-1.79z"/><path d="M6 12a5 5 0 0 1 6 0 5 5 0 0 0 6 0"/></svg>
|
||||
|
After Width: | Height: | Size: 410 B |
1
www/icons/house.svg
Normal file
1
www/icons/house.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-house-icon lucide-house"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 401 B |
1
www/icons/image.svg
Normal file
1
www/icons/image.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-image-icon lucide-image"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>
|
||||
|
After Width: | Height: | Size: 371 B |
1
www/icons/spanner.svg
Normal file
1
www/icons/spanner.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wrench-icon lucide-wrench"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/></svg>
|
||||
|
After Width: | Height: | Size: 440 B |
62
www/index.html
Normal file
62
www/index.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Hello fellow nerd!
|
||||
-->
|
||||
|
||||
<head>
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
<script src="/main.js"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header><div>
|
||||
<button id="button-home" onclick="switchTab(this);"><img src="/icons/house.svg"> Home</button>
|
||||
<button id="button-pics" onclick="switchTab(this);"><img src="/icons/image.svg"> Pictures</button>
|
||||
<button id="button-projects" onclick="switchTab(this);"><img src="/icons/spanner.svg"> Cool things I've done</button>
|
||||
<button id="button-drinking" onclick="switchTab(this);"><img src="/icons/glass-water.svg"> Drinking</button>
|
||||
</div></header>
|
||||
|
||||
<main>
|
||||
<article id="tab-home" default>
|
||||
<h1 id="helloText"><noscript>Hewwo!</noscript></h1>
|
||||
<h2><span id="imaText"><noscript>I'm a <span class="textHighlight">dumbass</span></noscript></span>.</h2>
|
||||
<div class="mainContent">
|
||||
<img src="/fag.png">
|
||||
<div>
|
||||
<h3>Hi there! I'm <b>Brosef</b>, as you can see by the <i>very fancy</i> changing text about this, I'm interested in a lot of things!</h3>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article id="tab-pics">
|
||||
|
||||
</article>
|
||||
|
||||
<article id="tab-projects">
|
||||
|
||||
</article>
|
||||
|
||||
<article id="tab-drinking">
|
||||
<h1>Take a look at this alcoholic!</h1>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<!-- Left side -->
|
||||
<div>
|
||||
<p>Icons from <a href="https://lucide.dev/">Lucide</a>.</p>
|
||||
</div>
|
||||
<!-- Right side -->
|
||||
<div>
|
||||
<div style="height: 50px;" class="imgRightText">
|
||||
<img src="/pfp.png">
|
||||
<p>Brosef</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
156
www/main.js
Normal file
156
www/main.js
Normal file
@ -0,0 +1,156 @@
|
||||
const Maths = Math; // Yes, I'm that patriotic.
|
||||
const hellos = ['Hewwo!', 'Hello!', 'Awoo!'];
|
||||
|
||||
const imaTypingSpeed = 75;
|
||||
const imaDeletingSpeed = 50;
|
||||
const imaElipsisDelay = 750;
|
||||
const imaGapTime = 1500;
|
||||
const imaTexts = shuffle([
|
||||
'I\'m a $dumbass$.dog',
|
||||
'I\'m a $network engineer',
|
||||
'I\'m an $Arch Linux user',
|
||||
'I\'m a $programmer',
|
||||
'I\'m a $furry...$ duh',
|
||||
'I\'m a $massive nerd',
|
||||
'I\'m a $Home Assistant addict',
|
||||
'I\'m a $House M.D. enjoyer',
|
||||
'I\'m a $DJ',
|
||||
'I\'m an $ice skater',
|
||||
'I\'m a $masochist'
|
||||
]);
|
||||
|
||||
function shuffle(array) {
|
||||
return array
|
||||
.map(value => ({ value, sort: Maths.random() }))
|
||||
.sort((a, b) => a.sort - b.sort)
|
||||
.map(({ value }) => value);
|
||||
}
|
||||
|
||||
function pickRandom(array) {
|
||||
return array[Maths.floor(Maths.random() * array.length)];
|
||||
}
|
||||
|
||||
function switchTab(tabID, playAnimation=true) {
|
||||
// Get tab ID from button
|
||||
if (typeof(tabID) == 'object') {
|
||||
tabID = tabID.id.split('button-')[1];
|
||||
}
|
||||
|
||||
let tabTransitionTime = Number(getComputedStyle(document.body).getPropertyValue('--tab-transition-time').slice(0, -2));
|
||||
let tabs = document.getElementsByTagName('main')[0].children;
|
||||
let tab = document.getElementById(`tab-${tabID}`);
|
||||
let buttons = document.getElementsByTagName('header')[0].getElementsByTagName('button');
|
||||
let button = document.getElementById(`button-${tabID}`)
|
||||
|
||||
// Error checking
|
||||
if (tab == undefined) {
|
||||
console.error(`Error switching tab: Tab ID "${tabID}" not found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide all tabs
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
if (tabs[i] == tab) { continue; }
|
||||
tabs[i].classList.add('hiddenTab');
|
||||
if (playAnimation) {
|
||||
setTimeout(() => { tabs[i].style.display = 'none'; }, tabTransitionTime);
|
||||
} else {
|
||||
tabs[i].style.display = 'none';
|
||||
}
|
||||
|
||||
if (button != null) {
|
||||
button.classList.remove('buttonHighlight');
|
||||
}
|
||||
}
|
||||
|
||||
// Un-highlight all buttons
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
buttons[i].classList.remove('buttonHighlight');
|
||||
}
|
||||
|
||||
// Show selected tab
|
||||
if (playAnimation) {
|
||||
setTimeout(() => { tab.style.display = null; }, tabTransitionTime);
|
||||
} else {
|
||||
tab.style.display = null;
|
||||
}
|
||||
// Required for animation to play
|
||||
let intervalID = setInterval(() => {
|
||||
if (tab.checkVisibility()) {
|
||||
tab.classList.remove('hiddenTab');
|
||||
clearInterval(intervalID);
|
||||
}
|
||||
}, 10);
|
||||
|
||||
// Highlight button
|
||||
button.classList.add('buttonHighlight');
|
||||
}
|
||||
|
||||
window.addEventListener('load', (e) => {
|
||||
switchTab('home', false);
|
||||
|
||||
// ----- Hellos section -----
|
||||
const helloEl = document.getElementById('helloText');
|
||||
helloEl.innerText = pickRandom(hellos);
|
||||
|
||||
// ----- I'm a text section -----
|
||||
const imaEl = document.getElementById('imaText');
|
||||
let currentEl = document.createElement('span');
|
||||
imaEl.appendChild(currentEl);
|
||||
let imaSelection = 0;
|
||||
let imaCharIdx = 0;
|
||||
|
||||
const typeFunc = () => {
|
||||
let controlChar = imaTexts[imaSelection][imaCharIdx] == '$';
|
||||
if (controlChar) {
|
||||
let highlight = !currentEl.classList.contains('textHighlight');
|
||||
currentEl = document.createElement('span');
|
||||
if (highlight) {
|
||||
currentEl.classList.add('textHighlight');
|
||||
}
|
||||
imaEl.appendChild(currentEl);
|
||||
} else {
|
||||
currentEl.innerText += imaTexts[imaSelection][imaCharIdx];
|
||||
}
|
||||
imaCharIdx++;
|
||||
|
||||
let nextTime = imaTypingSpeed;
|
||||
|
||||
if (imaTexts[imaSelection].slice(imaCharIdx, imaCharIdx+3) == '...') {
|
||||
nextTime = imaElipsisDelay;
|
||||
}
|
||||
|
||||
nextTime *= !controlChar;
|
||||
|
||||
if (imaCharIdx >= imaTexts[imaSelection].length) {
|
||||
setTimeout(deleteFunc, imaGapTime);
|
||||
} else {
|
||||
setTimeout(typeFunc, nextTime);
|
||||
}
|
||||
};
|
||||
|
||||
const deleteFunc = () => {
|
||||
// This is honestly quite disgusting, but it does work...
|
||||
let textAttrib = imaEl.lastChild.nodeName == '#text' ? 'data' : 'innerText';
|
||||
imaEl.lastChild.innerText = imaEl.lastChild.innerText.slice(0, -1);
|
||||
if (imaEl.lastChild.innerText == '') {
|
||||
imaEl.lastChild.remove();
|
||||
}
|
||||
|
||||
if (imaEl.innerText == '') {
|
||||
currentEl = imaEl;
|
||||
imaCharIdx = 0;
|
||||
imaSelection += 1;
|
||||
if (imaSelection >= imaTexts.length) {
|
||||
imaSelection = 0;
|
||||
}
|
||||
currentEl = document.createElement('span');
|
||||
imaEl.appendChild(currentEl);
|
||||
setTimeout(typeFunc, imaTypingSpeed);
|
||||
} else {
|
||||
setTimeout(deleteFunc, imaDeletingSpeed);
|
||||
}
|
||||
};
|
||||
|
||||
typeFunc();
|
||||
});
|
||||
BIN
www/pfp.png
Normal file
BIN
www/pfp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
167
www/styles.css
Normal file
167
www/styles.css
Normal file
@ -0,0 +1,167 @@
|
||||
:root {
|
||||
--header-colour: #00000031;
|
||||
--main-colour: #393e41;
|
||||
--footer-colour: #00000031;
|
||||
--text-colour: #f6f7eb;
|
||||
--text-accent-colour: #e94f37;
|
||||
--button-border-colour: var(--text-accent-colour);
|
||||
--button-border-highlight-colour: #f7b3a9;
|
||||
|
||||
--header-size: 50px;
|
||||
--tab-transition-time: 250ms; /* Must be in ms for JS parsing */
|
||||
}
|
||||
|
||||
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text-colour);
|
||||
font-family: sans-serif;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
background-color: var(--main-colour);
|
||||
}
|
||||
|
||||
|
||||
|
||||
header, main, footer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
background-color: var(--header-colour);
|
||||
}
|
||||
|
||||
/* Required to set the width and height of the header, as `fixed` elements can't have their size set. */
|
||||
header > div {
|
||||
width: 100vw;
|
||||
height: var(--header-size);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
header > div > * {
|
||||
height: var(--header-size);
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1 1 auto;
|
||||
margin-top: var(--header-size);
|
||||
text-align: center;
|
||||
background-color: var(--main-colour);
|
||||
}
|
||||
|
||||
main > article {
|
||||
display: unset;
|
||||
transition: filter var(--tab-transition-time), opacity var(--tab-transition-time);
|
||||
}
|
||||
|
||||
.hiddenTab {
|
||||
filter: blur(10px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
flex: 0 1 auto;
|
||||
display: flex;
|
||||
padding: 20px 0 20px 0;
|
||||
background-color: var(--footer-colour);
|
||||
}
|
||||
|
||||
footer > div {
|
||||
width: 50%;
|
||||
height: fit-content;
|
||||
margin: auto 0 auto 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer > div > * {
|
||||
margin: 0 auto 0 auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.mainContent {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 10px;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mainContent > img {
|
||||
max-height: 75vh;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.mainContent > div {
|
||||
flex: 1 1 auto;
|
||||
min-width: 25em;
|
||||
width: min-content;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#tab-pics {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#tab-pics > * {
|
||||
margin: 10px;
|
||||
flex: 1 1 auto;
|
||||
max-width: 50vw;
|
||||
max-height: 50vh;
|
||||
object-fit: scale-down;
|
||||
}
|
||||
|
||||
|
||||
|
||||
button {
|
||||
display: inline-flex;
|
||||
padding: 5px;
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--text-accent-colour);
|
||||
background-color: #212425;
|
||||
color: var(--text-colour);
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
transition: border-bottom-color 0.5s;
|
||||
}
|
||||
|
||||
button > img {
|
||||
filter: invert();
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
button:hover, .buttonHighlight {
|
||||
border-bottom-color: var(--button-border-highlight-colour);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.textHighlight {
|
||||
color: var(--text-accent-colour);
|
||||
}
|
||||
|
||||
/* Used to make text appear to the right of an image */
|
||||
.imgRightText {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.imgRightText > img {
|
||||
height: 100%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.imgRightText > p {
|
||||
margin: auto;
|
||||
}
|
||||
Reference in New Issue
Block a user