Attempt 1 to add a darkmode

This commit is contained in:
2025-10-17 12:35:48 +01:00
parent 8df71a6457
commit 59d16ebde1
10 changed files with 200 additions and 43 deletions

View File

@@ -1,44 +1,38 @@
import type { Metadata } from "next";
import Link from 'next/link';
import "./scss/nbn.scss";
import "@/scss/nbn.scss";
import NavbarClient from "@/components/Navbar";
export const metadata: Metadata = {
title: "Spectrum Next Registers",
description: "A platform for exploring the Spectrum Next registers",
robots: { index: true, follow: true },
formatDetection: { email: false, address: false, telephone: false },
title: "Spectrum Next Explorer",
description: "A platform for exploring the Spectrum Next hardware",
robots: { index: true, follow: true },
formatDetection: { email: false, address: false, telephone: false },
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
<nav className="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div className="container-fluid">
<Link className="navbar-brand" href="/">Next Explorer</Link>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className="nav-item">
<Link className="nav-link" href="/">Home</Link>
</li>
<li className="nav-item">
<Link className="nav-link" href="/registers">Registers</Link>
</li>
</ul>
</div>
</div>
</nav>
<div className="container-fluid py-3">
{children}
</div>
</body>
</html>
);
}
const noFlashThemeScript = `
(function() {
try {
var cookieMatch = document.cookie.match(/(?:^|; )theme=([^;]+)/);
var stored = cookieMatch ? decodeURIComponent(cookieMatch[1]) : null;
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
var effective = (stored === 'light' || stored === 'dark') ? stored : (prefersDark ? 'dark' : 'light');
var el = document.documentElement;
if (el.getAttribute('data-bs-theme') !== effective) {
el.setAttribute('data-bs-theme', effective);
}
} catch(_) {}
})();`;
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{ __html: noFlashThemeScript }} />
</head>
<body>
<NavbarClient />
<div className="container-fluid py-3">{children}</div>
</body>
</html>
);
}

View File

@@ -3,7 +3,7 @@ import Link from 'next/link';
import { Register } from '@/utils/register_parser';
import RegisterDetail from '@/app/registers/RegisterDetail';
import {Container, Row} from "react-bootstrap";
import { getRegisters } from '@/app/services/register.service';
import { getRegisters } from '@/services/register.service';
export default async function RegisterDetailPage({ params }: { params: { hex: string } }) {
const registers = await getRegisters();

View File

@@ -1,12 +1,12 @@
import RegisterBrowser from '@/app/registers/RegisterBrowser';
import { getRegisters } from '@/app/services/register.service';
import { getRegisters } from '@/services/register.service';
export default async function RegistersPage() {
const registers = await getRegisters();
return (
<div className="container-fluid py-4">
<h1 className="mb-4">Spectrum Next Registers</h1>
<h1 className="mb-4">NextReg Explorer</h1>
<RegisterBrowser registers={registers} />
</div>
);

View File

@@ -1,155 +0,0 @@
// Pulse 5.3.8
// Bootswatch
// Variables
// Buttons
.btn {
&:focus,
&:active,
&:active:focus,
&.active:focus {
outline: none;
}
&-secondary {
color: $gray-900;
background-color: $white;
border-color: #ccc;
&:hover {
color: $gray-900;
background-color: $gray-300;
border-color: $gray-500;
}
&.disabled {
color: tint-color($gray-900, 5%);
background-color: $white;
border-color: tint-color(#ccc, 5%);
}
}
&-warning {
color: $white;
}
&-primary:focus {
box-shadow: 0 0 5px tint-color($primary, 10%);
}
&-secondary:focus {
box-shadow: 0 0 5px $gray-400;
}
&-success:focus {
box-shadow: 0 0 5px tint-color($success, 10%);
}
&-info:focus {
box-shadow: 0 0 5px tint-color($info, 10%);
}
&-warning:focus {
box-shadow: 0 0 5px tint-color($warning, 10%);
}
&-danger:focus {
box-shadow: 0 0 5px tint-color($danger, 10%);
}
&.disabled:focus {
box-shadow: none;
}
}
// Tables
.table .thead-dark th {
background-color: $secondary;
border-color: $table-border-color;
}
.table-primary,
.table-secondary,
.table-success,
.table-warning,
.table-danger,
.table-info,
.table-light {
--#{$prefix}table-color: #{$body-color};
}
// Forms
.form-control:focus {
box-shadow: 0 0 5px rgba(100, 65, 164, .4);
}
// Navs
.nav-tabs {
.nav-link,
.nav-link.active, {
border-width: 0 0 1px;
}
.nav-link:hover,
.nav-link.active,
.nav-link.active:hover,
.nav-link.active:focus {
border-bottom: 1px solid $primary;
}
.nav-item + .nav-item {
margin-left: 0;
}
}
.breadcrumb {
&-item.active {
color: $gray-700;
}
}
// Indicators
.badge {
&.bg-light {
color: $dark;
}
}
// Progress bars
.progress {
height: 8px;
}
// Containers
.list-group {
&-item {
color: rgba(255, 255, 255, .8);
&.active,
&:hover,
&:focus {
color: $white;
}
&.active {
font-weight: 700;
&:hover {
background-color: $list-group-hover-bg;
}
}
&.disabled:hover {
color: $list-group-disabled-color;
}
}
}

View File

@@ -1,18 +0,0 @@
.footnote-anchor {
color: $secondary;
margin-left: 4px;
font-weight: bold;
}
.footnote-ref {
@extend .footnote-anchor;
cursor: pointer;
}
.bits-table th:first-child,
.bits-table td:first-child {
width: 60px;
}
.bits-table td:last-child {
white-space: pre-wrap;
}

View File

@@ -1,93 +0,0 @@
// Pulse 5.3.8
// Bootswatch
@use 'sass:color';
$theme: "pulse" !default;
//
// Color system
//
$white: #fff !default;
$gray-100: #fafafa !default;
$gray-200: #f9f8fc !default;
$gray-300: #ededed !default;
$gray-400: #cbc8d0 !default;
$gray-500: #adb5bd !default;
$gray-600: #868e96 !default;
$gray-700: #444 !default;
$gray-800: #343a40 !default;
$gray-900: #17141f !default;
$black: #000 !default;
$blue: #007bff !default;
$indigo: #6610f2 !default;
$purple: #593196 !default;
$pink: #e83e8c !default;
$red: #fc3939 !default;
$orange: #fd7e14 !default;
$yellow: #efa31d !default;
$green: #13b955 !default;
$teal: #20c997 !default;
$cyan: #009cdc !default;
$primary: $purple !default;
$secondary: #a991d4 !default;
$success: $green !default;
$info: $cyan !default;
$warning: $yellow !default;
$danger: $red !default;
$light: $gray-200 !default;
$dark: $gray-900 !default;
$min-contrast-ratio: 2.1 !default;
// Options
$enable-rounded: false !default;
// Body
$body-color: $gray-700 !default;
// Links
$link-hover-color: $primary !default;
// Tables
$table-color: initial !default;
$table-border-color: rgba(0, 0, 0, .05) !default;
// Forms
$input-focus-border-color: $primary !default;
// Dropdowns
$dropdown-link-hover-color: $white !default;
$dropdown-link-hover-bg: $primary !default;
// Navs
$nav-tabs-border-color: $gray-300 !default;
$nav-tabs-link-hover-border-color: $primary !default;
// Navbar
$navbar-padding-y: 1.2rem !default;
// Progress bars
$progress-bg: $gray-300 !default;
$progress-bar-bg: $primary !default;
// List group
$list-group-bg: $gray-900 !default;
$list-group-border-color: transparent !default;
$list-group-hover-bg: color.scale($list-group-bg, $lightness:10%) !default;
$list-group-active-color: $white !default;
$list-group-active-bg: $list-group-bg !default;
$list-group-disabled-color: color.scale($list-group-bg, $lightness:30%) !default;

View File

@@ -1,14 +0,0 @@
/**
* Set custom bootstrap 5 variables here to overwrite defaults
*
* @see node_modules/bootstrap/scss/_variables.scss
*/
@import "variables";
@import "~bootstrap/scss/bootstrap";
@import "bootswatch";
@import "explorer";

View File

@@ -1,20 +0,0 @@
import { promises as fs } from 'fs';
import path from 'path';
import { Register } from '@/utils/register_parser';
import { parseNextReg } from '@/utils/register_parser';
let registers: Register[] = [];
/**
* Gets the registers from the in-memory cache, or loads them from the file if not already loaded.
* @returns A promise that resolves to an array of Register objects.
*/
export async function getRegisters(): Promise<Register[]> {
// if (registers.length === 0) {
const filePath = path.join(process.cwd(), 'data', 'nextreg.txt');
const fileContent = await fs.readFile(filePath, 'utf8');
registers = await parseNextReg(fileContent);
// }
return registers;
}