Skip to content

Commit

Permalink
ThemeService to handle themes
Browse files Browse the repository at this point in the history
  • Loading branch information
shvkhzod committed Dec 25, 2023
1 parent 4030697 commit fa744ea
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 45 deletions.
93 changes: 93 additions & 0 deletions src/application/services/themeService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// themeService.ts
import { reactive } from 'vue';

interface ThemeState {
primaryColor: string;
secondaryColor: string;
backgroundColor: string;
textColor: string;
linkColor: string;
whiteColor: string;
}

type ThemeName = 'default' | 'choco' | 'graphite' | 'blue';
/**
* Gets the initial theme name from local storage or sets it to 'default'
*/
const initialThemeName: ThemeName = (localStorage.getItem('theme') as ThemeName) || 'default';

const themes: Record<ThemeName, ThemeState> = {
default: {
primaryColor: '#0C0D0D',
secondaryColor: '#424448',
backgroundColor: '#1D1E20',
textColor: '#FFFFFF',
linkColor: '#F2F2F3',
whiteColor: '#FFFFFF',
},
choco: {
primaryColor: '#0D0C0D',
secondaryColor: '#484246',
backgroundColor: '#201D1F',
textColor: '#FFFFFF',
linkColor: '#898086',
whiteColor: '#FFFFFF',
},
graphite: {
primaryColor: '#0B0C0E',
secondaryColor: '#3E434C',
backgroundColor: '#222429',
textColor: '#FFFFFF',
linkColor: '#ABB0BA',
whiteColor: '#F1F2F4',
},
blue: {
primaryColor: '#040A16',
secondaryColor: '#153575',
backgroundColor: '#0F2757',
textColor: '#FFFFFF',
linkColor: '#A8C0F0',
whiteColor: '#E9EFFB',
},
};

/**
* Represents the state of the theme.
*/
const themeState: ThemeState = reactive(themes[initialThemeName]);


/**
* Sets the theme
*
* @param themeName - The name of the theme to set
*/
function setTheme(themeName: ThemeName): void {
console.log(`Setting theme '${themeName}'`);
const selectedTheme = themes[themeName];

if (typeof selectedTheme !== 'undefined') {
console.log(`Applying '${themeName}'`);

// Iterate over the keys of the selected theme and applies them to the themeState object
Object.keys(selectedTheme).forEach((key) => {
themeState[key as keyof ThemeState] = selectedTheme[key as keyof ThemeState];
});

// Save the theme to local storage
localStorage.setItem('theme', themeName);
} else {
console.error(`Theme '${themeName}' not found. Applying default theme.`);
Object.keys(themes.default).forEach((key) => {
themeState[key as keyof ThemeState] = themes.default[key as keyof ThemeState];
});
}

const themeChangeEvent = new CustomEvent('theme-change', {
detail: { theme: themeState },
});

document.dispatchEvent(themeChangeEvent);
}

export { themeState, setTheme };
81 changes: 50 additions & 31 deletions src/presentation/components/webComponents/button.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { themeState } from '../../../application/services/themeService';

/**
* Button Web Component
*/
Expand All @@ -22,6 +24,7 @@ class Btn extends HTMLElement {

/**
* Called when an attribute is changed, appended, removed, or replaced on the element.
*
* @param name - The name of the attribute that changed.
*/
public attributeChangedCallback(name: string): void {
Expand All @@ -34,40 +37,24 @@ class Btn extends HTMLElement {
* Renders the component
*/
public render(): void {
const type = (this.getAttribute('type') ?? "") || 'primary';
const iconType = (this.getAttribute('icon-type') ?? "") || 'none';
const type = (this.getAttribute('type') ?? '') || 'primary';
const iconType = (this.getAttribute('icon-type') ?? '') || 'none';

this._shadowRoot.innerHTML = `
<style>
button {
display: inline-block;
padding: 8px 12px;
margin: 10px;
text-align: center;
text-decoration: none;
font-size: 16px;
border:none;
border-radius: 8px;
align-items: center;
}
/* Primary styles */
.primary {
background-color: #24A3FF;
color: white;
}
/* Secondary styles */
.secondary {
background-color: #EBEBEC;
color: #333;
}
/* Danger styles */
.danger {
background-color: #E32121;
color: white;
}
button {
display: inline-block;
padding: 8px 12px;
margin: 10px;
text-align: center;
text-decoration: none;
font-size: 16px;
border: none;
border-radius: 8px;
align-items: center;
background-color: ${this.getBackgroundColor(type)};
color: ${this.getTextColor()};
}
/* Style for icons */
.icon {
Expand Down Expand Up @@ -101,6 +88,38 @@ class Btn extends HTMLElement {
public connectedCallback(): void {
this.render();
this.addEventListener('click', () => this.dispatchCustomEvent());

/**
* Listens for the theme-change event
*/
document.addEventListener('theme-change', () => {
console.log('Button heard the change');
this.render();
});
}

/**
* Returns the background color
*
* @param type - The type of the button
*/
private getBackgroundColor(type: string): string {
console.log(`Getting background color for type '${type}'`);
switch (type) {
case 'primary':
return themeState.secondaryColor;
case 'secondary':
return themeState.secondaryColor;
default:
return themeState.secondaryColor;
}
}

/**
* Returns the text color
*/
private getTextColor(): string {
return themeState.textColor;
}

/**
Expand Down
48 changes: 34 additions & 14 deletions src/presentation/pages/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,50 @@
<div>
<h1>{{ $t('home.title') }}</h1>
<p>This page will contain your Notes you recently worked with </p>
<my-btn
:type="buttonType"
@click="toggleButtonType"
>
Toggle Type
<my-btn>
Example button
</my-btn>
<label for="themeSelect">Select Theme:</label>
<select
id="themeSelect"
v-model="selectedTheme"
@change="changeTheme"
>
<option value="default">
Default
</option>
<option value="choco">
Choco
</option>
<option value="graphite">
Graphite
</option>
<option value="blue">
Blue
</option>
</select>
</div>
</template>

<script setup lang="ts">
import { setTheme } from '../../application/services/themeService';
import '../components/webComponents/button';
import { ref } from 'vue';
const buttonType = ref('primary');
type ThemeName = 'default' | 'choco' | 'graphite' | 'blue';
const toggleButtonType = () => {
if (buttonType.value === 'primary') {
buttonType.value = 'secondary';
} else if (buttonType.value === 'secondary') {
buttonType.value = 'danger';
} else {
buttonType.value = 'primary';
}
const selectedTheme = ref<ThemeName>('default');
const changeTheme = () => {
setTheme(selectedTheme.value);
};
/**
* Toggle theme between default and choco
*/
</script>

<style lang="postcss" scoped>
Expand Down

0 comments on commit fa744ea

Please sign in to comment.