Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds support for color-mode selection #65

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/Ignite/Elements/HTML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public struct HTML: PageElement {
/// - Returns: The HTML for this element.
public func render(context: PublishingContext) -> String {
var output = "<!doctype html>"
output += "<html lang=\"\(context.site.language.rawValue)\" data-bs-theme=\"light\"\(attributes.description)>"
output += "<html lang=\"\(context.site.language.rawValue)\" data-bs-theme=\"\(context.site.colorScheme)\"\(attributes.description)>"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change alone will not work for the case auto since there is no observation taking place without calling the colorSchema modifier. What about we remove the data-bs-theme here completely and move the content of the colorSchema function to a static func on Script. We could than add a line after body content like this.

output += Script.colorSchema(context.site.colorSchema).render(context: context)

output += head?.render(context: context) ?? ""
output += body?.render(context: context) ?? ""
output += "</html>"
Expand Down
62 changes: 62 additions & 0 deletions Sources/Ignite/Framework/ColorScheme.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// ColorScheme.swift
// Ignite
// https://www.github.com/twostraws/Ignite
// See LICENSE for license information.
//

import Foundation

public enum ColorScheme: String, CustomStringConvertible {
case auto, light, dark

public var description: String {
rawValue
}
}

public extension Body {
func colorScheme(_ colorScheme: ColorScheme) -> Self {
var copy = self
switch colorScheme {
case .auto:
copy.items.append(setBasedOnUserPreference())
default:
copy.items.append(setColorSchema(colorScheme))
}
return copy
}

func setColorSchema(_ colorSchema: ColorScheme) -> Script {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make setColorSchema() and setBasedOnUserPreference() private here? They were intended as helpers and only colorSchema(_:) as an API to be used from outside.

Script(code: "document.documentElement.setAttribute('data-bs-theme', '\(colorSchema)');")
}

func setBasedOnUserPreference() -> Script {
Script(code: """
document.addEventListener('DOMContentLoaded', (event) => {
// Function to set the theme based on user preference
function setThemeBasedOnPreference() {
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;

if (prefersDarkScheme) {
document.documentElement.setAttribute('data-bs-theme', 'dark');
} else {
document.documentElement.setAttribute('data-bs-theme', 'light');
}
}

// Set the theme based on user preference when the page loads
setThemeBasedOnPreference();

// Listen for changes to the user's color scheme preference
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', setThemeBasedOnPreference);
});
""")
}
}

public extension PageElement {
func colorScheme(_ colorScheme: ColorScheme) -> Self {
data("bs-theme", "\(colorScheme)")
}
}
6 changes: 6 additions & 0 deletions Sources/Ignite/Framework/Site.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ public protocol Site {
/// explicitly override the theme with something custom.
var theme: ThemeType { get }

/// The color mode to apply to the site, default is light mode
var colorScheme: ColorScheme { get }

/// The path to the favicon
var favicon: URL? { get }

Expand Down Expand Up @@ -147,6 +150,9 @@ extension Site {
/// An empty tag page by default, which triggers no tag pages being made.
public var tagPage: EmptyTagPage { EmptyTagPage() }

/// The default color mode being light
public var colorScheme: ColorScheme { .light }

/// The default favicon being nil
public var favicon: URL? { nil }

Expand Down