Skip to content

Commit

Permalink
feat: introduce color selector
Browse files Browse the repository at this point in the history
  • Loading branch information
isqua committed May 8, 2024
1 parent 35dd00e commit 9dd3dad
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 14 deletions.
22 changes: 22 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,21 @@ <h1 class="hero-title">Showcase your journey</h1>
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
</svg>
</button>
<button class="sidebar-tab" id="theme-tab" type="button" role="tab" aria-selected="false" aria-controls="theme" tabindex="-1">
<svg class="sidebar-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.53 16.122a3 3 0 0 0-5.78 1.128 2.25 2.25 0 0 1-2.4 2.245 4.5 4.5 0 0 0 8.4-2.245c0-.399-.078-.78-.22-1.128Zm0 0a15.998 15.998 0 0 0 3.388-1.62m-5.043-.025a15.994 15.994 0 0 1 1.622-3.395m3.42 3.42a15.995 15.995 0 0 0 4.764-4.648l3.876-5.814a1.151 1.151 0 0 0-1.597-1.597L14.146 6.32a15.996 15.996 0 0 0-4.649 4.763m3.42 3.42a6.776 6.776 0 0 0-3.42-3.42" />
</svg>
</button>
</div>
<form action="#" class="sidebar-content form">
<div id="countries" role="tabpanel" tabindex="0" aria-labelledby="countries-tab" class="sidebar-tabpanel">
<ul class="countries-list">
</ul>
</div>
<div id="theme" role="tabpanel" tabindex="0" aria-labelledby="theme-tab" class="sidebar-tab sidebar-tabpanel-hidden">
<ul class="colors-list">
</ul>
</div>
</form>
</aside>
<div class="workbench">
Expand Down Expand Up @@ -79,6 +88,19 @@ <h1 class="hero-title">Showcase your journey</h1>
</label>
</li>
</template>
<template id="color">
<li class="color-item">
<input
type="radio"
name="background"
class="color-radio"
/>
<label class="color-label">
<span class="color-flag"></span>
<span class="color-name"></span>
</label>
</li>
</template>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
9 changes: 7 additions & 2 deletions src/images/ImageGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const FLAG_HEIGHT = 30 * DPI;
const FLAG_WIDTH = 40 * DPI;
const FLAG_GAP = 8 * DPI;

export type RenderParams = {
flags: HTMLImageElement[];
background: string;
}

export class ImageGenerator {
constructor(
private canvas: CanvasManager,
Expand Down Expand Up @@ -41,10 +46,10 @@ export class ImageGenerator {
this.image.classList.add(READY_CLASS_NAME);
}

async render(flags: HTMLImageElement[]) {
async render({ flags, background }: RenderParams) {
this.canvas
.setSize(INITIAL_WIDTH, INITIAL_HEIGHT)
.fill(INITIAL_COLOR);
.fill(background);

const centerX = this.canvas.width / 2;
const centerY = this.canvas.height / 2;
Expand Down
24 changes: 16 additions & 8 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { countries, getFlagSrc } from "./flags";
import { CanvasManager, ImageGenerator } from "./images";
import { Landing } from "./landing";
import { CountrySelector, Settings } from "./settings";
import { ColorSelector, CountrySelector, Settings } from "./settings";
import { getFullfiled, loadImage, querySelectorSafe } from "./shared/utils";
import { Sidebar } from "./sidebar";
import { StateManager } from "./state";

import type { SettingsData } from "./settings";

import "./style.css";

const state = new StateManager();
Expand All @@ -25,30 +27,36 @@ const countrySelector = new CountrySelector(
querySelectorSafe<HTMLTemplateElement>("#country"),
);

const colorSelector = new ColorSelector(
querySelectorSafe<HTMLUListElement>(".colors-list"),
querySelectorSafe<HTMLTemplateElement>("#color"),
);

const settings = new Settings(querySelectorSafe<HTMLFormElement>("form"));
const manager = new CanvasManager(querySelectorSafe<HTMLCanvasElement>(".canvas"));
const generator = new ImageGenerator(manager, querySelectorSafe<HTMLImageElement>(".device-screen"));

async function draw(codes: string[]) {
async function draw({ countries, background }: SettingsData) {
const flags = await getFullfiled(
codes.map(code => loadImage(getFlagSrc(code)))
countries.map(code => loadImage(getFlagSrc(code)))
);

generator.render(flags);
generator.render({ flags, background });
}

function main() {
const codes = state.getCodes();

countrySelector.initialize(countries);
colorSelector.initialize();
settings.initialize({ countries: codes });
generator.initialize();
draw(codes);
draw(settings.getData());

settings.onChange(({ countries }) => {
state.writeCodes(countries);
settings.onChange(data => {
state.writeCodes(data.countries);

return draw(countries);
return draw(data);
});

sidebar.initialize();
Expand Down
38 changes: 38 additions & 0 deletions src/settings/ColorSelector.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.colors-list {
margin: 0;
padding: 0;
list-style-type: none;
}

.color-radio {
display: none;
}

.color-item {
margin: 0 0 4px;
}

.color-label {
display: flex;
padding: 6px 8px;
border-radius: 6px;
display: flex;
line-height: 20px;
}

.color-flag {
display: inline-block;
width: 24px;
height: 18px;
margin-block-start: 1px;
margin-inline-end: 12px;
outline: 1px solid rgba(255,255,255,0.5);
}

input:checked + .color-label {
background-color: #94a3b8;
}

input:checked + .color-label .color-flag {
outline: none;
}
53 changes: 53 additions & 0 deletions src/settings/ColorSelector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { querySelectorSafe } from "../shared/utils";

import "./ColorSelector.css";

type Color = {
name: string;
code: string;
}

const colors: Color[] = [
{
name: "Olive",
code: "#5f6a5e",
},
{
name: "Stone",
code: "#a8a29e",
},
{
name: "Silver",
code: "#f1f5f9",
},
{
name: "Sand",
code: "#eed9c4",
},
{
name: "Rose",
code: "#ecc5c0",
},
];

export class ColorSelector {
constructor(
private container: HTMLElement,
private template: HTMLTemplateElement,
) { }

initialize() {
colors.forEach(color => {
const clone = this.template.content.cloneNode(true) as HTMLLIElement;
const id = color.code.replace("#", "");

querySelectorSafe<HTMLInputElement>("input", clone).value = color.code;
querySelectorSafe<HTMLInputElement>("input", clone).id = id;
querySelectorSafe<HTMLLabelElement>("label", clone).setAttribute("for", id);
querySelectorSafe<HTMLSpanElement>(".color-name", clone).innerText = color.name;
querySelectorSafe<HTMLSpanElement>(".color-flag", clone).style.backgroundColor = color.code;

this.container.appendChild(clone);
});
}
}
15 changes: 12 additions & 3 deletions src/settings/Settings.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { isCheckable, toArrayOfStrings } from "../shared/utils";
import { isCheckable, toArrayOfStrings, toString } from "../shared/utils";

type SettingsData = {
export type SettingsData = {
countries: string[];
background: string;
}

type SettingsListener = (data: SettingsData) => void;
Expand All @@ -23,6 +24,12 @@ export class Settings {
}
}
}

const firstBackgroundColor = this.form.querySelector("input[name=background]");

if (firstBackgroundColor && isCheckable(firstBackgroundColor)) {
firstBackgroundColor.checked = true;
}
}

onChange(callback: SettingsListener) {
Expand All @@ -34,9 +41,11 @@ export class Settings {
getData(): SettingsData {
const data = new FormData(this.form);
const countries = toArrayOfStrings(data.getAll("country"));
const background = toString(data.get("background"));

return {
countries: countries,
countries,
background,
};
}
}
3 changes: 2 additions & 1 deletion src/settings/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { ColorSelector } from "./ColorSelector";
export { CountrySelector } from "./CountrySelector";
export { Settings } from "./Settings";
export { Settings, type SettingsData } from "./Settings";
8 changes: 8 additions & 0 deletions src/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ export function querySelectorSafe<T extends Element = Element>(selector: string,
return element;
}

export function toString(data: FormDataEntryValue | null): string {
if (typeof data !== "string") {
return "";
}

return data;
}

export function toArrayOfStrings(data: FormDataEntryValue[]): string[] {
if (!data) {
return [];
Expand Down

0 comments on commit 9dd3dad

Please sign in to comment.