Feat(UI): Light / dark mode themes and toggle utility added.
This commit is contained in:
@@ -1,16 +1,60 @@
|
||||
var activeFlag = 'active';
|
||||
var darkThemeFlag = 'dark';
|
||||
var darkThemeIconFlag = 'dark-mode-icon';
|
||||
var hashAttribute = 'data-hash';
|
||||
var homePageHash = 'home';
|
||||
var lightThemeFlag = 'light';
|
||||
var lightThemeIconFlag = 'light-mode-icon';
|
||||
var themeAttribute = 'data-theme';
|
||||
var themeFlag = 'theme';
|
||||
var themeIconFlag = 'theme-icon';
|
||||
var themeSwitchFlag = 'theme-switch';
|
||||
|
||||
function hookupPage() {
|
||||
console.log("Hooking up home page...");
|
||||
hookupPageLocalStorage();
|
||||
hookupNav();
|
||||
hookupThemeSwitch();
|
||||
hookupScroll();
|
||||
// hookupProjectThumbnails();
|
||||
hookupProjectDetailButtons();
|
||||
}
|
||||
function hookupPageLocalStorage() {
|
||||
let pageLocalStorage = getPageLocalStorage();
|
||||
// Colour theme
|
||||
let theme = pageLocalStorage[themeFlag];
|
||||
if (!theme) {
|
||||
let prefersDark = window.matchMedia(`(prefers-color-scheme: ${darkThemeFlag})`).matches;
|
||||
theme = prefersDark ? darkThemeFlag : lightThemeFlag;
|
||||
}
|
||||
setPageTheme(theme);
|
||||
}
|
||||
function getPageLocalStorage() {
|
||||
let pageHash = getPageHash();
|
||||
let pageLocalStorage = localStorage.getItem(pageHash);
|
||||
let decodedPageLocalStorage;
|
||||
if (pageLocalStorage) {
|
||||
decodedPageLocalStorage = JSON.parse(pageLocalStorage);
|
||||
}
|
||||
else {
|
||||
decodedPageLocalStorage = {};
|
||||
}
|
||||
return decodedPageLocalStorage;
|
||||
}
|
||||
function getPageHash() {
|
||||
return document.documentElement.getAttribute(hashAttribute) || homePageHash;
|
||||
}
|
||||
function setPageTheme(theme) {
|
||||
document.documentElement.setAttribute(themeAttribute, theme);
|
||||
let pageLocalStorage = getPageLocalStorage();
|
||||
pageLocalStorage[themeFlag] = theme;
|
||||
setPageLocalStorage(pageLocalStorage);
|
||||
}
|
||||
function setPageLocalStorage(pageLocalStorage) {
|
||||
let pageHash = getPageHash();
|
||||
localStorage.setItem(pageHash, JSON.stringify(pageLocalStorage));
|
||||
}
|
||||
function hookupNav() {
|
||||
console.log("Hooking up nav...");
|
||||
document.querySelectorAll('nav a').forEach(anchor => {
|
||||
console.log("Hooking up nav anchor...");
|
||||
anchor.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const section = document.querySelector(this.getAttribute('href'));
|
||||
@@ -20,8 +64,104 @@ function hookupNav() {
|
||||
});
|
||||
});
|
||||
}
|
||||
function hookupThemeSwitch() {
|
||||
makeLightThemeIcon();
|
||||
/*
|
||||
let themeSwitch = document.querySelector('#' + themeSwitchId);
|
||||
themeSwitch.addEventListener('click', function() {
|
||||
let theme = document.documentElement.getAttribute(themeAttribute);
|
||||
let newTheme = theme === darkThemeFlag ? lightThemeFlag : darkThemeFlag;
|
||||
setPageTheme(newTheme);
|
||||
});
|
||||
*/
|
||||
let themeSwitch = getThemeSwitchButton();
|
||||
themeSwitch.addEventListener('click', function() {
|
||||
let theme = getPageTheme();
|
||||
let newTheme = theme === darkThemeFlag ? lightThemeFlag : darkThemeFlag;
|
||||
setPageTheme(newTheme);
|
||||
});
|
||||
}
|
||||
function makeLightThemeIcon() {
|
||||
let themeSwitch = getThemeSwitchButton();
|
||||
const backgroundRadius = 500;
|
||||
const sunRadius = 250;
|
||||
// const sunColour = "var(--text-colour)"; // "var(--text-background-colour)";
|
||||
// const backgroundColour = "var(--secondary-colour)";
|
||||
|
||||
// Create the SVG element
|
||||
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
||||
svg.setAttribute("viewBox", "0 0 1000 1000");
|
||||
svg.classList.add(themeIconFlag);
|
||||
svg.classList.add(lightThemeIconFlag);
|
||||
|
||||
// Create the background circle
|
||||
const background = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
||||
background.setAttribute("cx", backgroundRadius);
|
||||
background.setAttribute("cy", backgroundRadius);
|
||||
background.setAttribute("r", backgroundRadius);
|
||||
// background.setAttribute("fill", backgroundColour);
|
||||
background.setAttribute("class", "background");
|
||||
|
||||
// Create the sun body
|
||||
const sunBody = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
||||
sunBody.setAttribute("cx", backgroundRadius);
|
||||
sunBody.setAttribute("cy", backgroundRadius);
|
||||
sunBody.setAttribute("r", sunRadius);
|
||||
// sunBody.setAttribute("fill", sunColour);
|
||||
sunBody.setAttribute("class", "sun");
|
||||
|
||||
// Add background and sun body to the SVG
|
||||
svg.appendChild(background);
|
||||
svg.appendChild(sunBody);
|
||||
|
||||
// Parameters for rays
|
||||
const centerX = 500;
|
||||
const centerY = 500;
|
||||
const numberOfRays = 8;
|
||||
const rayRadialSpacing = 75;
|
||||
const innerRadius = sunRadius + rayRadialSpacing; // Where the sun body ends
|
||||
const outerRadius = sunRadius + rayRadialSpacing + (backgroundRadius - sunRadius - rayRadialSpacing) * 0.5; // Where the rays extend to
|
||||
const strokeWidth = 75;
|
||||
|
||||
// Create rays using a loop and trigonometry
|
||||
for (let i = 0; i < numberOfRays; i++) {
|
||||
// Calculate angle in radians
|
||||
const angle = (i * 2 * Math.PI) / numberOfRays;
|
||||
|
||||
// Calculate start point (inner circle)
|
||||
const startX = centerX + innerRadius * Math.cos(angle);
|
||||
const startY = centerY + innerRadius * Math.sin(angle);
|
||||
|
||||
// Calculate end point (outer radius)
|
||||
const endX = centerX + outerRadius * Math.cos(angle);
|
||||
const endY = centerY + outerRadius * Math.sin(angle);
|
||||
|
||||
// Create the line element
|
||||
const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
||||
line.setAttribute("x1", startX);
|
||||
line.setAttribute("y1", startY);
|
||||
line.setAttribute("x2", endX);
|
||||
line.setAttribute("y2", endY);
|
||||
// line.setAttribute("stroke", sunColour);
|
||||
line.setAttribute("class", "sun");
|
||||
line.setAttribute("stroke-width", strokeWidth);
|
||||
line.setAttribute("stroke-linecap", "round");
|
||||
|
||||
// Append the line to the SVG
|
||||
svg.appendChild(line);
|
||||
}
|
||||
|
||||
// Append the completed SVG to the container
|
||||
themeSwitch.appendChild(svg);
|
||||
}
|
||||
function getThemeSwitchButton() {
|
||||
return document.querySelector('button.' + themeSwitchFlag);
|
||||
}
|
||||
function getPageTheme() {
|
||||
return document.documentElement.getAttribute(themeAttribute);
|
||||
}
|
||||
function hookupScroll() {
|
||||
console.log("Hooking up scroll...");
|
||||
window.addEventListener('scroll', function() {
|
||||
const sections = document.querySelectorAll('section');
|
||||
const navLinks = document.querySelectorAll('nav a');
|
||||
@@ -45,12 +185,9 @@ function hookupScroll() {
|
||||
}
|
||||
/*
|
||||
function hookupProjectThumbnails() {
|
||||
console.log("Hooking up project thumbnails...");
|
||||
let demoButtonSelector = '.project-links .button';
|
||||
document.querySelectorAll(demoButtonSelector).forEach(demoButton => {
|
||||
console.log("Hooking up project thumbnail...");
|
||||
let projectName = getProjectNameFromDemoButton(demoButton);
|
||||
console.log({projectName});
|
||||
demoButton.addEventListener('mouseover', function() {
|
||||
let projectName = getProjectNameFromDemoButton(this);
|
||||
let thumbnailContainer = getProjectThumbnailContainer(projectName);
|
||||
@@ -65,20 +202,16 @@ function hookupProjectThumbnails() {
|
||||
}
|
||||
function getProjectNameFromDemoButton(demoButton) {
|
||||
let projectName = demoButton.getAttribute('data-project');
|
||||
console.log({projectName});
|
||||
return projectName;
|
||||
}
|
||||
function getProjectThumbnailContainer(projectName) {
|
||||
let container = document.querySelector(`div.project-thumbnail[data-project="${projectName}"]`);
|
||||
console.log({container});
|
||||
return container;
|
||||
}
|
||||
*/
|
||||
function hookupProjectDetailButtons() {
|
||||
console.log("Hooking up project detail buttons...");
|
||||
let detailButtonSelector = '.project-detail-button';
|
||||
document.querySelectorAll(detailButtonSelector).forEach(detailButton => {
|
||||
console.log("Hooking up project detail button...");
|
||||
detailButton.addEventListener('click', function() {
|
||||
let projectDetailContainer = this.parentElement.querySelector('.project-detail-container');
|
||||
let wasActive = projectDetailContainer.classList.contains(activeFlag);
|
||||
|
||||
Reference in New Issue
Block a user