-theme demo
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ThemeService } from './services/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -6,6 +7,13 @@ import { Component } from '@angular/core';
|
||||
standalone: false,
|
||||
styleUrl: './app.component.css'
|
||||
})
|
||||
export class AppComponent {
|
||||
export class AppComponent implements OnInit {
|
||||
constructor(private themeService: ThemeService) {}
|
||||
title = 'ng-ttc-frontend';
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
// โหลดธีมเมื่อคอมโพเนนต์เริ่มต้นทำงาน
|
||||
this.themeService.getCurrentTheme();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import { MainProject } from './component/main-project/main-project';
|
||||
import { MainProjectContent } from './content/main-project-content/main-project-content';
|
||||
import { MainProjectAdd } from './component/main-project-add/main-project-add';
|
||||
import { BudgetAprovalContent } from './content/budget-aproval-content/budget-aproval-content';
|
||||
import { ThemeSwitcherComponent } from './component/theme-switcher/theme-switcher';
|
||||
// import { BudgetAproval } from './component/budget-aproval/budget-aproval';
|
||||
// import { AccDateFormatPipe } from './pipe/dtmtodatetime.pipe';
|
||||
// import { DtmtodatetimePipe } from './dtmtodatetime.pipe';
|
||||
@@ -41,6 +42,7 @@ import { BudgetAprovalContent } from './content/budget-aproval-content/budget-ap
|
||||
SidebarComponent,
|
||||
LicensePrivacyTermsComponent,
|
||||
TokenTimerComponent,
|
||||
// ThemeSwitcherComponent,
|
||||
// BudgetAprovalContent
|
||||
// MainProjectAdd,
|
||||
// MainProject,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<p>theme-switcher works!</p>
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ThemeService } from '../../services/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-theme-switcher',
|
||||
template: `
|
||||
<div class="flex items-center gap-2 p-2 bg-white rounded-lg shadow-sm border border-gray-200">
|
||||
<span class="text-sm font-medium text-gray-600">Theme:</span>
|
||||
|
||||
<!-- ปุ่มสีแดง -->
|
||||
<button (click)="changeTheme('theme-red')"
|
||||
class="w-6 h-6 rounded-full bg-red-900 border-2 border-white shadow-sm hover:scale-110 transition-transform ring-1 ring-gray-200"
|
||||
[class.ring-red-500]="currentTheme === 'theme-red'">
|
||||
</button>
|
||||
|
||||
<!-- ปุ่มสีน้ำเงิน -->
|
||||
<button (click)="changeTheme('theme-blue')"
|
||||
class="w-6 h-6 rounded-full bg-blue-900 border-2 border-white shadow-sm hover:scale-110 transition-transform ring-1 ring-gray-200"
|
||||
[class.ring-blue-500]="currentTheme === 'theme-blue'">
|
||||
</button>
|
||||
|
||||
<!-- ปุ่มสีเขียว -->
|
||||
<button (click)="changeTheme('theme-green')"
|
||||
class="w-6 h-6 rounded-full bg-green-900 border-2 border-white shadow-sm hover:scale-110 transition-transform ring-1 ring-gray-200"
|
||||
[class.ring-green-500]="currentTheme === 'theme-green'">
|
||||
</button>
|
||||
</div>
|
||||
`,
|
||||
standalone: true
|
||||
})
|
||||
export class ThemeSwitcherComponent {
|
||||
currentTheme: string;
|
||||
|
||||
constructor(
|
||||
private themeService: ThemeService
|
||||
) {
|
||||
this.currentTheme = this.themeService.getCurrentTheme();
|
||||
}
|
||||
|
||||
changeTheme(theme: string) {
|
||||
this.themeService.setTheme(theme);
|
||||
this.currentTheme = theme;
|
||||
}
|
||||
}
|
||||
41
ng-ttc-frontend/src/app/services/theme.service.ts
Normal file
41
ng-ttc-frontend/src/app/services/theme.service.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ThemeService {
|
||||
private currentTheme: string = 'theme-red'; // ธีมเริ่มต้น
|
||||
|
||||
constructor() {
|
||||
this.loadTheme();
|
||||
}
|
||||
|
||||
// โหลดธีมจาก LocalStorage หรือใช้ค่าเริ่มต้น
|
||||
private loadTheme() {
|
||||
const savedTheme = localStorage.getItem('app-theme');
|
||||
if (savedTheme) {
|
||||
this.currentTheme = savedTheme;
|
||||
}
|
||||
this.applyTheme(this.currentTheme);
|
||||
}
|
||||
|
||||
// ฟังก์ชันเปลี่ยนธีม
|
||||
setTheme(themeName: string) {
|
||||
this.currentTheme = themeName;
|
||||
localStorage.setItem('app-theme', themeName);
|
||||
this.applyTheme(themeName);
|
||||
}
|
||||
|
||||
// อัปเดต Class ที่ <html> tag
|
||||
private applyTheme(theme: string) {
|
||||
// ลบธีมเก่าออกทั้งหมด (สมมติมี theme-red, theme-blue, theme-green)
|
||||
document.documentElement.classList.remove('theme-red', 'theme-blue', 'theme-green');
|
||||
|
||||
// เพิ่มธีมใหม่
|
||||
document.documentElement.classList.add(theme);
|
||||
}
|
||||
|
||||
getCurrentTheme() {
|
||||
return this.currentTheme;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,40 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
/* กำหนดตัวแปรสีพื้นฐาน */
|
||||
:root {
|
||||
/* Default (Red Theme) */
|
||||
--color-primary-50: #fef2f2;
|
||||
--color-primary-100: #fee2e2;
|
||||
--color-primary-500: #ef4444;
|
||||
--color-primary-600: #dc2626;
|
||||
--color-primary-900: #7f1d1d; /* สีแดงเข้มที่คุณใช้บ่อย */
|
||||
--color-primary-950: #450a0a;
|
||||
}
|
||||
|
||||
/* Blue Theme Override */
|
||||
.theme-blue {
|
||||
--color-primary-50: #eff6ff;
|
||||
--color-primary-100: #dbeafe;
|
||||
--color-primary-500: #3b82f6;
|
||||
--color-primary-600: #2563eb;
|
||||
--color-primary-900: #1e3a8a; /* สีน้ำเงินเข้ม */
|
||||
--color-primary-950: #172554;
|
||||
}
|
||||
|
||||
/* Green Theme Override */
|
||||
.theme-green {
|
||||
--color-primary-50: #f0fdf4;
|
||||
--color-primary-100: #dcfce7;
|
||||
--color-primary-500: #22c55e;
|
||||
--color-primary-600: #16a34a;
|
||||
--color-primary-900: #14532d;
|
||||
--color-primary-950: #052e16;
|
||||
}
|
||||
|
||||
/* ... CSS อื่นๆ ของคุณ ... */
|
||||
html, body { height: 100%; }
|
||||
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
|
||||
|
||||
/* Global base styles for the app. Keep lightweight and self-contained so
|
||||
the login component can reliably fill the viewport without producing
|
||||
an outer page scrollbar. */
|
||||
@@ -92,7 +127,7 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
/* Prevent the browser from showing a scroll bar for the page itself;
|
||||
the login card will scroll internally if needed. */
|
||||
the login card will scroll internally if needed. */
|
||||
}
|
||||
|
||||
/* Simple utilities used by nested components in this workspace */
|
||||
@@ -108,7 +143,7 @@ body {
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
/* Use flex centering so nested components (like the login widget)
|
||||
are centered without forcing the document to scroll. */
|
||||
are centered without forcing the document to scroll. */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
Reference in New Issue
Block a user