Skip to content

Commit

Permalink
feat: allow to switch themes
Browse files Browse the repository at this point in the history
  • Loading branch information
isqua committed Jun 1, 2024
1 parent 47e0841 commit 4bfa874
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 69 deletions.
126 changes: 73 additions & 53 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
<body>
<div id="app">
<form class="settings" action="#">
<label for="theme">Theme:</label>
<select id="theme">
<option value="theme-dark" selected>Dark</option>
<option value="theme-light">Light</option>
</select>
<label for="title">Title:</label>
<textarea id="title" rows="8">Hello world</textarea>
<label for="font">Font size:</label>
Expand All @@ -26,70 +31,85 @@
xmlns="http://www.w3.org/2000/svg"
>
<style>
.background {
fill: #343a42;
}
.year,
.title {
fill: #fefefd;
}
.camp-outline,
.camp-side,
.location {
.theme-dark .background,
.theme-light .background {
fill: #343a42;
}
.theme-dark .camp-outline,
.theme-dark .camp-side,
.theme-dark .location {
fill: #3986cf;
}
.stripe-light {
.theme-dark .stripe-light {
fill: #20aabb;
}
.stripe-dark {
.theme-dark .stripe-dark {
fill: #1770bb;
}

.theme-light .camp-outline,
.theme-light .camp-side,
.theme-light .location {
fill: #4ac3d6;
}
.theme-light .stripe-light {
fill: #20aabb;
}
.theme-light .stripe-dark {
fill: #3986cf;
}
</style>
<rect class="background" width="100%" height="100%" />
<g class="stripes"></g>
<path class="camp-side" d="M88 124H63l52-70v42z" />
<path
class="camp-outline"
d="M67 122h96l-48-65zm103 8H59q-1.1 0-2.2-.5-.9-.7-1.5-1.5a4 4 0 0 1 .4-4.1L110 50 95 30.2a4 4 0 0 1 .9-5.4 4 4 0 0 1 5.4.7L115 43l12.8-17.4a4 4 0 0 1 5.5-.9q1.3 1 1.5 2.6.3 1.5-.7 2.9L119 50l54.5 73.9a4 4 0 0 1-1 5.6c-.6.3-1.8.5-2.5.5"
/>
<text
class="location"
font-family="Jost"
font-weight="700"
letter-spacing="0.2em"
text-anchor="middle"
x="120"
y="175"
font-size="32"
/>
<text
class="year"
font-family="Jost"
font-weight="700"
letter-spacing="0.2em"
text-anchor="middle"
x="46"
y="88"
font-size="26"
/>
<text
class="year"
font-family="Jost"
font-weight="700"
letter-spacing="0.2em"
text-anchor="middle"
x="186"
y="88"
font-size="26"
/>
<text
class="title"
x="320"
y="400"
font-family="Jost"
font-weight="700"
text-anchor="start"
/>
<g class="theme theme-dark">
<rect class="background" width="100%" height="100%" />
<g class="stripes"></g>
<path class="camp-side" d="M88 124H63l52-70v42z" />
<path
class="camp-outline"
d="M67 122h96l-48-65zm103 8H59q-1.1 0-2.2-.5-.9-.7-1.5-1.5a4 4 0 0 1 .4-4.1L110 50 95 30.2a4 4 0 0 1 .9-5.4 4 4 0 0 1 5.4.7L115 43l12.8-17.4a4 4 0 0 1 5.5-.9q1.3 1 1.5 2.6.3 1.5-.7 2.9L119 50l54.5 73.9a4 4 0 0 1-1 5.6c-.6.3-1.8.5-2.5.5"
/>
<text
class="location"
font-family="Jost"
font-weight="700"
letter-spacing="0.2em"
text-anchor="middle"
x="120"
y="175"
font-size="32"
/>
<text
class="year"
font-family="Jost"
font-weight="700"
letter-spacing="0.2em"
text-anchor="middle"
x="46"
y="88"
font-size="26"
/>
<text
class="year"
font-family="Jost"
font-weight="700"
letter-spacing="0.2em"
text-anchor="middle"
x="186"
y="88"
font-size="26"
/>
<text
class="title"
x="320"
y="400"
font-family="Jost"
font-weight="700"
text-anchor="start"
/>
</g>
</svg>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const THEMES = ["theme-light", "theme-dark"];
export const STRIPE_COLORS = ["stripe-light", "stripe-dark"];
7 changes: 5 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ if (!form) {

const settings = new SettingsManager(form);

settings.onTitleChange((data) => {
settings.onSettingsChange((data) => {
cover.setTitle({
text: data.title,
fontSize: data.fontSize,
});

cover.setTheme(data.theme);
});

const cover = new SvgBuilder(svg);

cover
.setTheme(settings.theme)
.addStripes(STRIPE_COLORS)
.setYear(new Date().getUTCFullYear())
.setLocation("Пермь")
.setTitle({ text: settings.title, fontSize: 80 });
.setTitle({ text: settings.title, fontSize: settings.fontSize });
31 changes: 22 additions & 9 deletions src/settings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
type SettingsData = {
theme: string;
title: string;
fontSize: number;
};
Expand All @@ -10,10 +11,20 @@ interface SettingsChangeHandler {
const DEFAULT_FONT_SIZE = 80;

export class SettingsManager {
private readonly themeSelect: HTMLSelectElement;
private readonly textarea: HTMLTextAreaElement;
private readonly fontSizeInput: HTMLInputElement;

constructor(private readonly form: HTMLFormElement) {
const themeSelect =
this.form.querySelector<HTMLSelectElement>("select");

if (!themeSelect) {
throw new Error("Cannot find theme select");
}

this.themeSelect = themeSelect;

const inputTextArea =
this.form.querySelector<HTMLTextAreaElement>("textarea");

Expand All @@ -33,20 +44,22 @@ export class SettingsManager {
this.fontSizeInput = fontSizeInput;
}

onTitleChange(callback: SettingsChangeHandler) {
this.textarea.addEventListener("input", () => {
onSettingsChange(callback: SettingsChangeHandler) {
const handler = () => {
callback({
theme: this.theme,
title: this.title,
fontSize: this.fontSize,
});
});
};

this.fontSizeInput.addEventListener("change", () => {
callback({
title: this.title,
fontSize: this.fontSize,
});
});
this.themeSelect.addEventListener("change", handler);
this.textarea.addEventListener("input", handler);
this.fontSizeInput.addEventListener("change", handler);
}

get theme() {
return this.themeSelect.value;
}

get title() {
Expand Down
19 changes: 14 additions & 5 deletions src/svg.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { THEMES } from "./constants";
import { randomInt } from "./utils";

type TextOptions = {
Expand Down Expand Up @@ -28,20 +29,20 @@ const minVisibleWidth = 20;
export class SvgBuilder {
private readonly nameSpace = "http://www.w3.org/2000/svg";

private readonly theme: SVGGraphicsElement;
private readonly title: SVGTextElement;
private readonly stripes: SVGElement;
private readonly year: [SVGTextElement, SVGTextElement];
private readonly location: SVGTextElement;

constructor(private readonly element: SVGElement) {
const background =
this.element.querySelector<SVGGeometryElement>(".background");
const theme = this.element.querySelector<SVGGeometryElement>(".theme");

if (!background) {
throw new Error("Cannot find background element");
if (!theme) {
throw new Error("Cannot find theme element");
}

this.background = background;
this.theme = theme;

const title = this.element.querySelector<SVGTextElement>(".title");

Expand Down Expand Up @@ -78,6 +79,14 @@ export class SvgBuilder {
this.location = location;
}

setTheme(newTheme: string) {
THEMES.forEach((theme) => this.theme.classList.remove(theme));

this.theme.classList.add(newTheme);

return this;
}

setTitle(options: TextOptions) {
const lines = options.text.split("\n");

Expand Down

0 comments on commit 4bfa874

Please sign in to comment.