mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Merge pull request #243 from paperless-ngx/css-variables
Custom color theming
This commit is contained in:
		| @@ -19,7 +19,7 @@ export class AppComponent implements OnInit, OnDestroy { | |||||||
|   constructor (private settings: SettingsService, private consumerStatusService: ConsumerStatusService, private toastService: ToastService, private router: Router) { |   constructor (private settings: SettingsService, private consumerStatusService: ConsumerStatusService, private toastService: ToastService, private router: Router) { | ||||||
|     let anyWindow = (window as any) |     let anyWindow = (window as any) | ||||||
|     anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.js'; |     anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.js'; | ||||||
|     this.settings.updateDarkModeSettings() |     this.settings.updateAppearanceSettings() | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ngOnDestroy(): void { |   ngOnDestroy(): void { | ||||||
|   | |||||||
| @@ -92,7 +92,7 @@ | |||||||
|               <svg class="sidebaricon" fill="currentColor"> |               <svg class="sidebaricon" fill="currentColor"> | ||||||
|                 <use xlink:href="assets/bootstrap-icons.svg#file-text"/> |                 <use xlink:href="assets/bootstrap-icons.svg#file-text"/> | ||||||
|               </svg> {{d.title | documentTitle}} |               </svg> {{d.title | documentTitle}} | ||||||
|               <span class="close bg-light" (click)="closeDocument(d); $event.preventDefault()"> |               <span class="close" (click)="closeDocument(d); $event.preventDefault()"> | ||||||
|                 <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16"> |                 <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16"> | ||||||
|                   <use xlink:href="assets/bootstrap-icons.svg#x"/> |                   <use xlink:href="assets/bootstrap-icons.svg#x"/> | ||||||
|                 </svg> |                 </svg> | ||||||
| @@ -169,7 +169,7 @@ | |||||||
|           </li> |           </li> | ||||||
|           <li class="nav-item"> |           <li class="nav-item"> | ||||||
|             <div class="d-flex w-100 flex-wrap"> |             <div class="d-flex w-100 flex-wrap"> | ||||||
|               <a class="nav-link pe-0 pb-0" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx"> |               <a class="nav-link pe-2 pb-1" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx"> | ||||||
|                 <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon bi bi-github" viewBox="0 0 16 16"> |                 <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon bi bi-github" viewBox="0 0 16 16"> | ||||||
|                   <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/> |                   <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/> | ||||||
|                 </svg> <ng-container i18n>GitHub</ng-container> |                 </svg> <ng-container i18n>GitHub</ng-container> | ||||||
|   | |||||||
| @@ -35,16 +35,14 @@ | |||||||
|  |  | ||||||
| .sidebar .nav-link { | .sidebar .nav-link { | ||||||
|   font-weight: 500; |   font-weight: 500; | ||||||
|   color: #333; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| .sidebar .nav-link .sidebaricon { | .sidebar .nav-link .sidebaricon { | ||||||
|   margin-right: 4px; |   margin-right: 4px; | ||||||
|   color: #999; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| .sidebar .nav-link.active { | .sidebar .nav-link.active { | ||||||
|   color: $primary; |   color: var(--bs-primary); | ||||||
|   font-weight: bold; |   font-weight: bold; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -172,8 +170,7 @@ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     &:focus { |     &:focus { | ||||||
|       background-color: #fff; |       background-color: rgba(0, 0, 0, 0.3); | ||||||
|       color: #212529; |  | ||||||
|       flex-grow: 1; |       flex-grow: 1; | ||||||
|       padding-left: 0.5rem; |       padding-left: 0.5rem; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
|       <p *ngIf="message">{{message}}</p> |       <p *ngIf="message">{{message}}</p> | ||||||
|     </div> |     </div> | ||||||
|     <div class="modal-footer"> |     <div class="modal-footer"> | ||||||
|       <button type="button" class="btn btn-outline-dark" (click)="cancel()" [disabled]="!buttonsEnabled" i18n>Cancel</button> |       <button type="button" class="btn btn-outline-secondary" (click)="cancel()" [disabled]="!buttonsEnabled" i18n>Cancel</button> | ||||||
|       <button type="button" class="btn" [class]="btnClass" (click)="confirm()" [disabled]="!confirmButtonEnabled || !buttonsEnabled"> |       <button type="button" class="btn" [class]="btnClass" (click)="confirm()" [disabled]="!confirmButtonEnabled || !buttonsEnabled"> | ||||||
|         {{btnCaption}} |         {{btnCaption}} | ||||||
|         <span *ngIf="!confirmButtonEnabled"> ({{seconds}})</span> |         <span *ngIf="!confirmButtonEnabled"> ({{seconds}})</span> | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ | |||||||
|   filter: brightness(0.5); |   filter: brightness(0.5); | ||||||
|  |  | ||||||
|   &.active { |   &.active { | ||||||
|     background-color: lighten($primary, 30%); |     background-color: var(--ngx-primary-lighten-30); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <div class="mb-3"> | <div class="mb-3"> | ||||||
|   <label [for]="inputId">{{title}}</label> |   <label *ngIf="title" [for]="inputId">{{title}}</label> | ||||||
|  |  | ||||||
|   <div class="input-group" [class.is-invalid]="error"> |   <div class="input-group" [class.is-invalid]="error"> | ||||||
|     <span class="input-group-text" [style.background-color]="value">   </span> |     <span class="input-group-text" [style.background-color]="value">   </span> | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| <app-widget-frame [title]="savedView.name"> | <app-widget-frame [title]="savedView.name"> | ||||||
|  |  | ||||||
|   <a header-buttons [routerLink]="[]" (click)="showAll()" i18n>Show all</a> |   <a class="btn-link" header-buttons [routerLink]="[]" (click)="showAll()" i18n>Show all</a> | ||||||
|  |  | ||||||
|  |  | ||||||
|   <table content class="table table-sm bg-light table-hover table-borderless mb-0"> |   <table content class="table table-sm table-hover table-borderless mb-0"> | ||||||
|     <thead> |     <thead> | ||||||
|       <tr> |       <tr> | ||||||
|         <th i18n>Created</th> |         <th i18n>Created</th> | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|   </div> |   </div> | ||||||
|   <div class="card-body text-dark"> |   <div class="card-body text-dark bg-light"> | ||||||
|     <ng-content select ="[content]"></ng-content> |     <ng-content select ="[content]"></ng-content> | ||||||
|   </div> |   </div> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ | |||||||
|         <div class="d-flex justify-content-between align-items-center"> |         <div class="d-flex justify-content-between align-items-center"> | ||||||
|           <h5 class="card-title"> |           <h5 class="card-title"> | ||||||
|             <ng-container *ngIf="document.correspondent"> |             <ng-container *ngIf="document.correspondent"> | ||||||
|               <a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold">{{(document.correspondent$ | async)?.name}}</a> |               <a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name}}</a> | ||||||
|               <ng-template #nolink>{{(document.correspondent$ | async)?.name}}</ng-template>: |               <ng-template #nolink>{{(document.correspondent$ | async)?.name}}</ng-template>: | ||||||
|             </ng-container> |             </ng-container> | ||||||
|             {{document.title | documentTitle}} |             {{document.title | documentTitle}} | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .card-selected { | .card-selected { | ||||||
|   border-color: $primary; |   border-color: var(--bs-primary); | ||||||
|  |  | ||||||
|   .document-card-check { |   .document-card-check { | ||||||
|     display: block; |     display: block; | ||||||
| @@ -60,7 +60,7 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .doc-img-background-selected { | .doc-img-background-selected { | ||||||
|   background-color: $primaryFaded; |   background-color: var(--ngx-primary-faded); | ||||||
| } | } | ||||||
|  |  | ||||||
| .card-info { | .card-info { | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ | |||||||
|     <div class="card-body p-2"> |     <div class="card-body p-2"> | ||||||
|       <p class="card-text"> |       <p class="card-text"> | ||||||
|         <ng-container *ngIf="document.correspondent"> |         <ng-container *ngIf="document.correspondent"> | ||||||
|           <a [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold">{{(document.correspondent$ | async)?.name}}</a>: |           <a [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name}}</a>: | ||||||
|         </ng-container> |         </ng-container> | ||||||
|         {{document.title | documentTitle}} |         {{document.title | documentTitle}} | ||||||
|       </p> |       </p> | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .card-selected { | .card-selected { | ||||||
|   border-color: $primary; |   border-color:var(--bs-primary); | ||||||
|  |  | ||||||
|   .document-card-check { |   .document-card-check { | ||||||
|     display: block; |     display: block; | ||||||
| @@ -45,7 +45,7 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .doc-img-background-selected { | .doc-img-background-selected { | ||||||
|   background-color: $primaryFaded; |   background-color: var(--ngx-primary-faded); | ||||||
| } | } | ||||||
|  |  | ||||||
| .card-info { | .card-info { | ||||||
| @@ -57,7 +57,7 @@ | |||||||
|     &:hover, |     &:hover, | ||||||
|     &:focus { |     &:focus { | ||||||
|       background-color: transparent !important; |       background-color: transparent !important; | ||||||
|       color: $primary; |       color: var(--bs-primary); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ tr { | |||||||
| } | } | ||||||
|  |  | ||||||
| .table-row-selected { | .table-row-selected { | ||||||
|   background-color: $primaryFaded; |   background-color: var(--ngx-primary-faded); | ||||||
| } | } | ||||||
|  |  | ||||||
| $paperless-card-breakpoints: ( | $paperless-card-breakpoints: ( | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|     <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive" novalidate></app-input-check> |     <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive" novalidate></app-input-check> | ||||||
|   </div> |   </div> | ||||||
|   <div class="modal-footer"> |   <div class="modal-footer"> | ||||||
|     <button type="button" class="btn btn-outline-dark" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> |     <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> | ||||||
|     <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> |     <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> | ||||||
|   </div> |   </div> | ||||||
| </form> | </form> | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
|  |  | ||||||
|     </div> |     </div> | ||||||
|     <div class="modal-footer"> |     <div class="modal-footer"> | ||||||
|       <button type="button" class="btn btn-outline-dark" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> |       <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> | ||||||
|       <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> |       <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> | ||||||
|     </div> |     </div> | ||||||
|   </form> |   </form> | ||||||
|   | |||||||
| @@ -100,6 +100,22 @@ | |||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  |         <div class="row mb-3"> | ||||||
|  |           <div class="col-md-3 col-form-label"> | ||||||
|  |             <span i18n>Theme Color</span> | ||||||
|  |           </div> | ||||||
|  |           <div class="col-3"> | ||||||
|  |             <app-input-color i18n-title formControlName="themeColor" [error]="error?.color"></app-input-color> | ||||||
|  |           </div> | ||||||
|  |           <div class="col-2"> | ||||||
|  |             <button class="btn btn-link btn-sm pt-2 ps-0" [disabled]="!this.settingsForm.get('themeColor').value" (click)="clearThemeColor()"> | ||||||
|  |               <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> | ||||||
|  |                 <path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/> | ||||||
|  |               </svg><ng-container i18n>Reset</ng-container> | ||||||
|  |             </button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|         <h4 class="mt-4" i18n>Bulk editing</h4> |         <h4 class="mt-4" i18n>Bulk editing</h4> | ||||||
|  |  | ||||||
|         <div class="row mb-3"> |         <div class="row mb-3"> | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent { | |||||||
|     'darkModeUseSystem': new FormControl(null), |     'darkModeUseSystem': new FormControl(null), | ||||||
|     'darkModeEnabled': new FormControl(null), |     'darkModeEnabled': new FormControl(null), | ||||||
|     'darkModeInvertThumbs': new FormControl(null), |     'darkModeInvertThumbs': new FormControl(null), | ||||||
|  |     'themeColor': new FormControl(null), | ||||||
|     'useNativePdfViewer': new FormControl(null), |     'useNativePdfViewer': new FormControl(null), | ||||||
|     'savedViews': this.savedViewGroup, |     'savedViews': this.savedViewGroup, | ||||||
|     'displayLanguage': new FormControl(null), |     'displayLanguage': new FormControl(null), | ||||||
| @@ -40,6 +41,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent { | |||||||
|   store: BehaviorSubject<any> |   store: BehaviorSubject<any> | ||||||
|   storeSub: Subscription |   storeSub: Subscription | ||||||
|   isDirty$: Observable<boolean> |   isDirty$: Observable<boolean> | ||||||
|  |   isDirty: Boolean = false | ||||||
|  |  | ||||||
|   get computedDateLocale(): string { |   get computedDateLocale(): string { | ||||||
|     return this.settingsForm.value.dateLocale || this.settingsForm.value.displayLanguage || this.currentLocale |     return this.settingsForm.value.dateLocale || this.settingsForm.value.displayLanguage || this.currentLocale | ||||||
| @@ -63,6 +65,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent { | |||||||
|         'darkModeUseSystem': this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM), |         'darkModeUseSystem': this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM), | ||||||
|         'darkModeEnabled': this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED), |         'darkModeEnabled': this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED), | ||||||
|         'darkModeInvertThumbs': this.settings.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED), |         'darkModeInvertThumbs': this.settings.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED), | ||||||
|  |         'themeColor': this.settings.get(SETTINGS_KEYS.THEME_COLOR), | ||||||
|         'useNativePdfViewer': this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER), |         'useNativePdfViewer': this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER), | ||||||
|         'savedViews': {}, |         'savedViews': {}, | ||||||
|         'displayLanguage': this.settings.getLanguage(), |         'displayLanguage': this.settings.getLanguage(), | ||||||
| @@ -97,10 +100,21 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent { | |||||||
|  |  | ||||||
|       // Initialize dirtyCheck |       // Initialize dirtyCheck | ||||||
|       this.isDirty$ = dirtyCheck(this.settingsForm, this.store.asObservable()) |       this.isDirty$ = dirtyCheck(this.settingsForm, this.store.asObservable()) | ||||||
|  |  | ||||||
|  |       // Record dirty in case we need to 'undo' appearance settings if not saved on close | ||||||
|  |       this.isDirty$.subscribe(dirty => { | ||||||
|  |         this.isDirty = dirty | ||||||
|  |       }) | ||||||
|  |        | ||||||
|  |       // "Live" visual changes prior to save | ||||||
|  |       this.settingsForm.valueChanges.subscribe(() => { | ||||||
|  |         this.settings.updateAppearanceSettings(this.settingsForm.get('darkModeUseSystem').value, this.settingsForm.get('darkModeEnabled').value, this.settingsForm.get('themeColor').value) | ||||||
|  |       }) | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ngOnDestroy() { |   ngOnDestroy() { | ||||||
|  |     if (this.isDirty) this.settings.updateAppearanceSettings() // in case user changed appearance but didnt save | ||||||
|     this.storeSub && this.storeSub.unsubscribe(); |     this.storeSub && this.storeSub.unsubscribe(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -119,6 +133,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent { | |||||||
|     this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem) |     this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem) | ||||||
|     this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString()) |     this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString()) | ||||||
|     this.settings.set(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, (this.settingsForm.value.darkModeInvertThumbs == true).toString()) |     this.settings.set(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, (this.settingsForm.value.darkModeInvertThumbs == true).toString()) | ||||||
|  |     this.settings.set(SETTINGS_KEYS.THEME_COLOR, (this.settingsForm.value.themeColor).toString()) | ||||||
|     this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer) |     this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer) | ||||||
|     this.settings.set(SETTINGS_KEYS.DATE_LOCALE, this.settingsForm.value.dateLocale) |     this.settings.set(SETTINGS_KEYS.DATE_LOCALE, this.settingsForm.value.dateLocale) | ||||||
|     this.settings.set(SETTINGS_KEYS.DATE_FORMAT, this.settingsForm.value.dateFormat) |     this.settings.set(SETTINGS_KEYS.DATE_FORMAT, this.settingsForm.value.dateFormat) | ||||||
| @@ -129,7 +144,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent { | |||||||
|     this.settings.setLanguage(this.settingsForm.value.displayLanguage) |     this.settings.setLanguage(this.settingsForm.value.displayLanguage) | ||||||
|     this.store.next(this.settingsForm.value) |     this.store.next(this.settingsForm.value) | ||||||
|     this.documentListViewService.updatePageSize() |     this.documentListViewService.updatePageSize() | ||||||
|     this.settings.updateDarkModeSettings() |     this.settings.updateAppearanceSettings() | ||||||
|     this.toastService.showInfo($localize`Settings saved successfully.`) |     this.toastService.showInfo($localize`Settings saved successfully.`) | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -165,4 +180,8 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   clearThemeColor() { | ||||||
|  |     this.settingsForm.get('themeColor').patchValue(''); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
|       <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></app-input-check> |       <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></app-input-check> | ||||||
|     </div> |     </div> | ||||||
|     <div class="modal-footer"> |     <div class="modal-footer"> | ||||||
|       <button type="button" class="btn btn-outline-dark" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> |       <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> | ||||||
|       <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> |       <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> | ||||||
|     </div> |     </div> | ||||||
|   </form> |   </form> | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| import { DOCUMENT } from '@angular/common'; | import { DOCUMENT } from '@angular/common'; | ||||||
| import { Inject, Injectable, LOCALE_ID, Renderer2, RendererFactory2 } from '@angular/core'; | import { Inject, Injectable, LOCALE_ID, Renderer2, RendererFactory2, RendererStyleFlags2 } from '@angular/core'; | ||||||
| import { Meta } from '@angular/platform-browser'; | import { Meta } from '@angular/platform-browser'; | ||||||
| import { CookieService } from 'ngx-cookie-service'; | import { CookieService } from 'ngx-cookie-service'; | ||||||
|  | import { hexToHsl } from 'src/app/utils/color'; | ||||||
|  |  | ||||||
| export interface PaperlessSettings { | export interface PaperlessSettings { | ||||||
|   key: string |   key: string | ||||||
| @@ -27,6 +28,7 @@ export const SETTINGS_KEYS = { | |||||||
|   DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system', |   DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system', | ||||||
|   DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled', |   DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled', | ||||||
|   DARK_MODE_THUMB_INVERTED: 'general-settings:dark-mode:thumb-inverted', |   DARK_MODE_THUMB_INVERTED: 'general-settings:dark-mode:thumb-inverted', | ||||||
|  |   THEME_COLOR: 'general-settings:theme:color', | ||||||
|   USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer', |   USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer', | ||||||
|   DATE_LOCALE: 'general-settings:date-display:date-locale', |   DATE_LOCALE: 'general-settings:date-display:date-locale', | ||||||
|   DATE_FORMAT: 'general-settings:date-display:date-format', |   DATE_FORMAT: 'general-settings:date-display:date-format', | ||||||
| @@ -43,6 +45,7 @@ const SETTINGS: PaperlessSettings[] = [ | |||||||
|   {key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true}, |   {key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true}, | ||||||
|   {key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false}, |   {key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false}, | ||||||
|   {key: SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, type: "boolean", default: true}, |   {key: SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, type: "boolean", default: true}, | ||||||
|  |   {key: SETTINGS_KEYS.THEME_COLOR, type: "string", default: ""}, | ||||||
|   {key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false}, |   {key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false}, | ||||||
|   {key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""}, |   {key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""}, | ||||||
|   {key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"}, |   {key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"}, | ||||||
| @@ -68,12 +71,13 @@ export class SettingsService { | |||||||
|   ) { |   ) { | ||||||
|     this.renderer = rendererFactory.createRenderer(null, null); |     this.renderer = rendererFactory.createRenderer(null, null); | ||||||
|  |  | ||||||
|     this.updateDarkModeSettings() |     this.updateAppearanceSettings() | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   updateDarkModeSettings(): void { |   public updateAppearanceSettings(darkModeUseSystem = null, darkModeEnabled = null, themeColor = null): void { | ||||||
|     let darkModeUseSystem = this.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM) |     darkModeUseSystem ??= this.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM) | ||||||
|     let darkModeEnabled = this.get(SETTINGS_KEYS.DARK_MODE_ENABLED) |     darkModeEnabled ??= this.get(SETTINGS_KEYS.DARK_MODE_ENABLED) | ||||||
|  |     themeColor ??= this.get(SETTINGS_KEYS.THEME_COLOR); | ||||||
|  |  | ||||||
|     if (darkModeUseSystem) { |     if (darkModeUseSystem) { | ||||||
|       this.renderer.addClass(this.document.body, 'color-scheme-system') |       this.renderer.addClass(this.document.body, 'color-scheme-system') | ||||||
| @@ -83,6 +87,14 @@ export class SettingsService { | |||||||
|       darkModeEnabled ? this.renderer.addClass(this.document.body, 'color-scheme-dark') : this.renderer.removeClass(this.document.body, 'color-scheme-dark') |       darkModeEnabled ? this.renderer.addClass(this.document.body, 'color-scheme-dark') : this.renderer.removeClass(this.document.body, 'color-scheme-dark') | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (themeColor) { | ||||||
|  |       const hsl = hexToHsl(themeColor) | ||||||
|  |       this.renderer.setStyle(document.documentElement, '--pngx-primary',`${+hsl.h * 360},${hsl.s * 100}%`, RendererStyleFlags2.DashCase) | ||||||
|  |       this.renderer.setStyle(document.documentElement, '--pngx-primary-lightness',`${hsl.l * 100}%`, RendererStyleFlags2.DashCase) | ||||||
|  |     } else { | ||||||
|  |       this.renderer.removeStyle(document.documentElement, '--pngx-primary', RendererStyleFlags2.DashCase) | ||||||
|  |       this.renderer.removeStyle(document.documentElement, '--pngx-primary-lightness', RendererStyleFlags2.DashCase) | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   getLanguageOptions(): LanguageOption[] { |   getLanguageOptions(): LanguageOption[] { | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import { HSL } from "ngx-color" | ||||||
|  |  | ||||||
| function componentToHex(c) { | function componentToHex(c) { | ||||||
|   var hex = Math.floor(c).toString(16) |   var hex = Math.floor(c).toString(16) | ||||||
| @@ -5,8 +6,8 @@ function componentToHex(c) { | |||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c |  | ||||||
|  * |  * | ||||||
|  |  * https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c | ||||||
|  * Converts an HSL color value to RGB. Conversion formula |  * Converts an HSL color value to RGB. Conversion formula | ||||||
|  * adapted from http://en.wikipedia.org/wiki/HSL_color_space. |  * adapted from http://en.wikipedia.org/wiki/HSL_color_space. | ||||||
|  * Assumes h, s, and l are contained in the set [0, 1] and |  * Assumes h, s, and l are contained in the set [0, 1] and | ||||||
| @@ -42,6 +43,46 @@ function hslToRgb(h, s, l){ | |||||||
|   return [r * 255, g * 255, b * 255] |   return [r * 255, g * 255, b * 255] | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c | ||||||
|  |  * Converts an RGB color value to HSL. Conversion formula | ||||||
|  |  * adapted from http://en.wikipedia.org/wiki/HSL_color_space. | ||||||
|  |  * Assumes r, g, and b are contained in the set [0, 255] and | ||||||
|  |  * returns h, s, and l in the set [0, 1]. | ||||||
|  |  * | ||||||
|  |  * @param   Number  r       The red color value | ||||||
|  |  * @param   Number  g       The green color value | ||||||
|  |  * @param   Number  b       The blue color value | ||||||
|  |  * @return  Array           The HSL representation | ||||||
|  |  */ | ||||||
|  |  export function rgbToHsl(r, g, b){ | ||||||
|  |   r /= 255, g /= 255, b /= 255; | ||||||
|  |   var max = Math.max(r, g, b), min = Math.min(r, g, b); | ||||||
|  |   var h, s, l = (max + min) / 2; | ||||||
|  |  | ||||||
|  |   if(max == min){ | ||||||
|  |       h = s = 0; // achromatic | ||||||
|  |   }else{ | ||||||
|  |       var d = max - min; | ||||||
|  |       s = l > 0.5 ? d / (2 - max - min) : d / (max + min); | ||||||
|  |       switch(max){ | ||||||
|  |           case r: h = (g - b) / d + (g < b ? 6 : 0); break; | ||||||
|  |           case g: h = (b - r) / d + 2; break; | ||||||
|  |           case b: h = (r - g) / d + 4; break; | ||||||
|  |       } | ||||||
|  |       h /= 6; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return [h, s, l]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function hexToHsl(hex: string): HSL { | ||||||
|  |   hex = hex.replace('#', '') | ||||||
|  |   let aRgbHex = hex.match(/.{1,2}/g) | ||||||
|  |   const hsl = rgbToHsl(parseInt(aRgbHex[0], 16), parseInt(aRgbHex[1], 16), parseInt(aRgbHex[2], 16)) | ||||||
|  |   return { h: hsl[0], s: hsl[1], l: hsl[2] } | ||||||
|  | } | ||||||
|  |  | ||||||
| export function randomColor() { | export function randomColor() { | ||||||
|   let rgb = hslToRgb(Math.random(), 0.6, Math.random() * 0.4 + 0.4) |   let rgb = hslToRgb(Math.random(), 0.6, Math.random() * 0.4 + 0.4) | ||||||
|   return `#${componentToHex(rgb[0])}${componentToHex(rgb[1])}${componentToHex(rgb[2])}` |   return `#${componentToHex(rgb[0])}${componentToHex(rgb[1])}${componentToHex(rgb[2])}` | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
|  | // bs options | ||||||
|  | $enable-negative-margins: true; | ||||||
|  |  | ||||||
|  | @import "node_modules/bootstrap/scss/bootstrap"; | ||||||
|  | @import "~@ng-select/ng-select/themes/default.theme.css"; | ||||||
| @import "theme"; | @import "theme"; | ||||||
| @import "theme_dark"; | @import "theme_dark"; | ||||||
| @import "print"; | @import "print"; | ||||||
| @import "node_modules/bootstrap/scss/bootstrap"; |  | ||||||
| @import "~@ng-select/ng-select/themes/default.theme.css"; |  | ||||||
|  |  | ||||||
| .toolbaricon { | .toolbaricon { | ||||||
|   width: 1.2em; |   width: 1.2em; | ||||||
| @@ -113,10 +116,6 @@ body { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| .ngx-file-drop__drop-zone--over { |  | ||||||
|   background-color: $primaryFaded !important; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Bootstrap 5 tweaks | // Bootstrap 5 tweaks | ||||||
| a.badge { | a.badge { | ||||||
|   text-decoration: none; |   text-decoration: none; | ||||||
| @@ -130,6 +129,6 @@ a.badge { | |||||||
| } | } | ||||||
|  |  | ||||||
| .btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle { | .btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle { | ||||||
|     background-color: $paperless-green; |     background-color: var(--bs-primary); | ||||||
|     border-color: $paperless-green; |     border-color: var(--bs-primary); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,8 +1,294 @@ | |||||||
| $paperless-green: #17541f; | :root { | ||||||
| $primary: #17541f; |   // base color e.g. #17541f = hsl(128, 57%, 21%) | ||||||
| $primaryFaded: #d1ddd2; |   --pngx-primary: 128, 57%; | ||||||
| $enable-negative-margins: true; |   --pngx-primary-lightness: 21%; | ||||||
|  |  | ||||||
|  |   --bs-primary: hsl(var(--pngx-primary), var(--pngx-primary-lightness)); | ||||||
|  |   --bs-border-color: var(--bs-gray-400); | ||||||
|  |   --ngx-primary-faded: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 72%)); | ||||||
|  |   --ngx-primary-lighten-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 10%)); | ||||||
|  |   --ngx-primary-lighten-30: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 30%)); | ||||||
|  |   --ngx-primary-darken-10: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%)); | ||||||
|  |   --ngx-primary-darken-15: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 15%)); | ||||||
|  |   --ngx-primary-darken-18: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%)); | ||||||
|  |   --ngx-bg-darker: var(--bs-gray-100); | ||||||
|  |   --ngx-focus-alpha: 0.3; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | svg.logo { | ||||||
|  |   .leaf { | ||||||
|  |     fill: var(--bs-primary) !important; | ||||||
|  |   } | ||||||
|  |   .text { | ||||||
|  |     fill: var(--bs-body-color) !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-link, .list-group-item { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  | } | ||||||
|  |  | ||||||
| .bg-body { | .bg-body { | ||||||
|   background-color: #fff; |   background-color: var(--bs-body-bg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .bg-primary { | ||||||
|  |   background-color: var(--bs-primary) !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .btn-primary { | ||||||
|  |   background-color: var(--bs-primary); | ||||||
|  |   border-color: var(--bs-primary); | ||||||
|  |  | ||||||
|  |   &:hover, &:focus { | ||||||
|  |     background-color: var(--ngx-primary-darken-10); | ||||||
|  |     border-color: var(--ngx-primary-darken-10); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   &:disabled, &.disabled { | ||||||
|  |     background-color: var(--ngx-primary-darken-10) !important; | ||||||
|  |     border-color: var(--ngx-primary-darken-10) !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .btn-outline-primary { | ||||||
|  |   border-color: var(--bs-primary) !important; | ||||||
|  |   color: var(--bs-primary) !important; | ||||||
|  |  | ||||||
|  |   &:hover, &:focus, &.active, &:active { | ||||||
|  |     background-color: var(--bs-primary) !important; | ||||||
|  |     color: var(--bs-light) !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .btn-outline-secondary { | ||||||
|  |   color: var(--bs-secondary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-item .sidebaricon { | ||||||
|  |   color: var(--bs-secondary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .btn:focus, | ||||||
|  | .btn:active:focus, | ||||||
|  | .dropdown-item:focus, | ||||||
|  | .btn-check:focus + .btn, | ||||||
|  | .form-control:focus, | ||||||
|  | .form-check-input:focus, | ||||||
|  | .form-check-radio:focus, | ||||||
|  | .form-select:focus { | ||||||
|  |   box-shadow: 0 0 0 0.25rem hsla(var(--pngx-primary), var(--pngx-primary-lightness), var(--ngx-focus-alpha)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .form-switch .form-check-input:focus { | ||||||
|  |   background-image: escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#bbb'/></svg>")); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-link:focus-visible, .nav-item a:focus-visible { | ||||||
|  |   outline: none; | ||||||
|  |   background-color: var(--ngx-bg-darker); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a.navbar-brand:focus-visible { | ||||||
|  |   outline: none; | ||||||
|  |   color: var(--ngx-primary-darken-10); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .dropdown.show { | ||||||
|  |   > .btn-primary { | ||||||
|  |     background-color: var(--bs-primary); | ||||||
|  |     border-color: var(--bs-primary); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   > .btn-outline-primary { | ||||||
|  |     color: var(--bs-body-color) !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a, a:hover, .btn-link, .btn-link:hover { | ||||||
|  |   color: var(--bs-primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .form-control:not(.btn), | ||||||
|  | input, | ||||||
|  | select, | ||||||
|  | textarea, | ||||||
|  | .form-select:not(.is-invalid):not(:disabled), | ||||||
|  | .form-check-input { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  |   background-color: var(--bs-body-bg); | ||||||
|  |   border-color: var(--bs-border-color); | ||||||
|  |  | ||||||
|  |   &:focus { | ||||||
|  |     background-color: var(--ngx-bg-darker); | ||||||
|  |     color: var(--bs-body-color) !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .form-check-input:checked { | ||||||
|  |   background-color: var(--bs-primary); | ||||||
|  |   border-color: var(--bs-primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .form-check-input:focus { | ||||||
|  |   border-color: var(--bs-primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .page-link { | ||||||
|  |   color: var(--bs-light); | ||||||
|  |   background-color: var(--bs-body-bg); | ||||||
|  |   border-color: var(--bs-border-color) !important; | ||||||
|  |  | ||||||
|  |   &:hover, &:focus { | ||||||
|  |     background-color: var(--bs-primary) !important; | ||||||
|  |     color: var(--bs-light) !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .page-item.active .page-link { | ||||||
|  |   background-color: var(--bs-primary); | ||||||
|  |   border-color: var(--bs-primary) !important; | ||||||
|  |   color: var(--bs-light); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .page-item.disabled .page-link { | ||||||
|  |   background-color: var(--ngx-bg-darker); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .nav-tabs { | ||||||
|  |   border-bottom: 1px solid var(--bs-border-color); | ||||||
|  |  | ||||||
|  |   .nav-link { | ||||||
|  |     color: var(--bs-primary); | ||||||
|  |  | ||||||
|  |     &.active, &:hover { | ||||||
|  |       border-color: var(--bs-border-color); | ||||||
|  |       background-color: var(--bs-body-bg); | ||||||
|  |       color: var(--bs-body-color); | ||||||
|  |       border-bottom: 1px solid transparent; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &:focus { | ||||||
|  |       border-color: var(--bs-border-color); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &.active:focus, &:active { | ||||||
|  |       border-bottom: 1px solid transparent; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .ng-select-container, | ||||||
|  | .ng-select.ng-select-opened > .ng-select-container, | ||||||
|  | .ng-dropdown-panel, | ||||||
|  | .ng-dropdown-panel .ng-dropdown-panel-items .ng-option { | ||||||
|  |   background-color: var(--bs-body-bg) !important; | ||||||
|  |   color: var(--bs-body-color) !important; | ||||||
|  |   border-color: var(--bs-border-color) !important; | ||||||
|  |  | ||||||
|  |   input:focus { | ||||||
|  |     background-color: transparent !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .input-group-text { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  |   background-color: var(--bs-body-bg); | ||||||
|  |   border-color: var(--bs-border-color); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .list-group-item { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  |   background-color: var(--bs-body-bg); | ||||||
|  |   border-color: var(--bs-border-color); | ||||||
|  |  | ||||||
|  |   &:hover, &:focus { | ||||||
|  |     background-color: var(--bs-body-bg); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .dropdown-menu { | ||||||
|  |   background-color: var(--bs-body-bg); | ||||||
|  |  | ||||||
|  |   .dropdown-divider { | ||||||
|  |     border-color: var(--bs-border-color); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .dropdown-item { | ||||||
|  |     color: var(--bs-body-color); | ||||||
|  |  | ||||||
|  |     &:hover { | ||||||
|  |       background-color: var(--ngx-bg-darker); | ||||||
|  |       color: var(--bs-body-color); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &.active { | ||||||
|  |       background-color: var(--bs-primary); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.table { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  |  | ||||||
|  |   .des,.asc { | ||||||
|  |     background-color: var(--bs-body-bg) !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .close { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .modal .btn-close { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .ngx-file-drop__drop-zone--over { | ||||||
|  |   background-color: var(--ngx-primary-faded) !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .alert-danger { | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  |   background-color: var(--bs-danger); | ||||||
|  |   border-color: var(--bs-danger); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .alert-secondary { | ||||||
|  |   background-color: var(--ngx-primary-darken-18); | ||||||
|  |   border-color: var(--ngx-primary-darken-15); | ||||||
|  |   color: var(--bs-body-color); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .ngb-dp-header, | ||||||
|  | .ngb-dp-weekdays, | ||||||
|  | .ngb-dp-month { | ||||||
|  |   background-color: var(--bs-body-bg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .popover { | ||||||
|  |   .popover-header, | ||||||
|  |   .popover-body { | ||||||
|  |     background-color: var(--ngx-bg-alt); | ||||||
|  |     border-color: var(--bs-border-color); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // fix popover carat colors | ||||||
|  | .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="left"] { | ||||||
|  |   border-left-color: var(--ngx-bg-alt); | ||||||
|  | } | ||||||
|  | .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="right"] { | ||||||
|  |   border-right-color: var(--ngx-bg-alt); | ||||||
|  | } | ||||||
|  | .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="top"] { | ||||||
|  |   border-top-color: var(--ngx-bg-alt); | ||||||
|  | } | ||||||
|  | .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="bottom"] { | ||||||
|  |   border-bottom-color: var(--ngx-bg-alt); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .bs-popover-bottom .popover-header::before, | ||||||
|  | .bs-popover-auto[x-placement^=bottom] .popover-header::before { | ||||||
|  |   border-bottom-color: var(--ngx-bg-alt); | ||||||
| } | } | ||||||
| @@ -1,8 +1,14 @@ | |||||||
| $primary-dark-mode: #45973a; | $primary-dark-mode: #45973a; | ||||||
|  | $primary-dark-mode-rgb: 69, 151, 58; | ||||||
|  | $primary-dark-mode-darken-10: darken($primary-dark-mode, 10%); | ||||||
| $danger-dark-mode: #b71631; | $danger-dark-mode: #b71631; | ||||||
|  | $danger-dark-mode-rgb: 183, 22, 49; | ||||||
| $bg-dark-mode: #161618; | $bg-dark-mode: #161618; | ||||||
| $bg-dark-mode-accent: #21262d; | $bg-dark-mode-rgb: 22, 22, 24; | ||||||
|  | $bg-dark-mode-accent: #101216; | ||||||
|  | $bg-dark-mode-alt: #242529; | ||||||
| $bg-light-dark-mode: #1c1c1f; | $bg-light-dark-mode: #1c1c1f; | ||||||
|  | $bg-light-dark-mode-rgb: 28, 28, 31; | ||||||
| $text-color-dark-mode: #abb2bf; | $text-color-dark-mode: #abb2bf; | ||||||
| $text-color-dark-mode-accent: lighten($text-color-dark-mode, 10%); | $text-color-dark-mode-accent: lighten($text-color-dark-mode, 10%); | ||||||
| $border-color-dark-mode: #47494f; | $border-color-dark-mode: #47494f; | ||||||
| @@ -12,141 +18,79 @@ $border-color-dark-mode: #47494f; | |||||||
| } | } | ||||||
|  |  | ||||||
| @mixin dark-mode { | @mixin dark-mode { | ||||||
|   background-color: $bg-dark-mode !important; |   --bs-primary: hsl(var(--pngx-primary), calc(var(--pngx-primary-lightness) + 10%)); | ||||||
|   color: $text-color-dark-mode; |   --bs-danger: #{$danger-dark-mode}; | ||||||
|  |   --bs-danger-rgb: #{$danger-dark-mode-rgb}; | ||||||
|  |   --bs-body-bg: #{$bg-dark-mode}; | ||||||
|  |   --bs-body-bg-rgb: #{$bg-dark-mode-rgb}; | ||||||
|  |   --bs-body-color: #{$text-color-dark-mode}; | ||||||
|  |   --bs-light: #{$bg-light-dark-mode}; | ||||||
|  |   --bs-light-rgb: #{$bg-light-dark-mode-rgb}; | ||||||
|  |   --bs-border-color: #{$border-color-dark-mode}; | ||||||
|  |   --ngx-bg-darker: #{$bg-dark-mode-accent}; | ||||||
|  |   --ngx-bg-alt: #{$bg-dark-mode-alt}; | ||||||
|  |   --ngx-body-color-accent: #{$text-color-dark-mode-accent}; | ||||||
|  |   --ngx-focus-alpha: 0.7; | ||||||
|  |  | ||||||
|  |   .navbar.bg-primary{ | ||||||
|  |     --bs-primary: hsl(var(--pngx-primary),var(--pngx-primary-lightness)); | ||||||
|  |     --bs-primary-rgb: var(--bs-primary); | ||||||
|  |   } | ||||||
|    |    | ||||||
|   .navbar-brand { |   .navbar-brand { | ||||||
|     color: $text-color-dark-mode; |     color: var(--bs-body-color); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   svg.logo { |  | ||||||
|     .leaf { |  | ||||||
|       color: $primary-dark-mode !important; |  | ||||||
|     } |  | ||||||
|     .text { |  | ||||||
|       fill: $text-color-dark-mode !important; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .bg-light { |  | ||||||
|     background-color: $bg-light-dark-mode !important; |  | ||||||
|  |  | ||||||
|     a, |  | ||||||
|     div { |  | ||||||
|       color: $text-color-dark-mode; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .bg-body { |  | ||||||
|     background-color: $bg-dark-mode !important; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .text-light { |  | ||||||
|     color: $text-color-dark-mode !important; |  | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   .border { |   .border { | ||||||
|     border-color: $border-color-dark-mode !important; |     border-color: var(--bs-border-color) !important; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .border-end { |   .border-end { | ||||||
|     border-right: 1px solid $border-color-dark-mode !important; |     border-right: 1px solid var(--bs-border-color) !important; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .border-start { |   .border-start { | ||||||
|     border-left: 1px solid $border-color-dark-mode !important; |     border-left: 1px solid var(--bs-border-color) !important; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .border-bottom { |   .border-bottom { | ||||||
|     border-bottom: 1px solid $border-color-dark-mode !important; |     border-bottom: 1px solid var(--bs-border-color) !important; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .nav-link { |   .text-dark, .text-light { | ||||||
|     color: $text-color-dark-mode !important; |     color: var(--bs-body-color) !important; | ||||||
|  |   } | ||||||
|  |  | ||||||
|     &.active { |   .btn-outline-primary, .btn-primary { | ||||||
|       background-color: $bg-dark-mode; |     &:hover, &:focus, &.active, &:active { | ||||||
|       color: $text-color-dark-mode; |       color: var(--ngx-body-color-accent) !important; | ||||||
|       border-color: $border-color-dark-mode $border-color-dark-mode $bg-dark-mode; |  | ||||||
|  |  | ||||||
|       .close { |  | ||||||
|         background-color: inherit !important; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|     &:hover { |   .btn-outline-secondary { | ||||||
|       color: $text-color-dark-mode-accent !important; |     &:hover, &:focus, &.active, &:active { | ||||||
|       border-color: $border-color-dark-mode $border-color-dark-mode $bg-dark-mode; |       background-color: var(--ngx-bg-darker); | ||||||
|     } |       color: var(--bs-primary); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .page-item.active .page-link { |  | ||||||
|     background-color: darken($primary-dark-mode, 10%); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .nav-tabs { |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|  |  | ||||||
|     .nav-link { |  | ||||||
|       color: $primary-dark-mode !important; |  | ||||||
|  |  | ||||||
|       &.active { |  | ||||||
|         color: $text-color-dark-mode !important; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .dropdown-menu { |  | ||||||
|     background-color: $bg-light-dark-mode; |  | ||||||
|  |  | ||||||
|     .dropdown-divider { |  | ||||||
|       border-color: $border-color-dark-mode; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .dropdown-item { |  | ||||||
|       color: $text-color-dark-mode; |  | ||||||
|  |  | ||||||
|       &:hover { |  | ||||||
|         background-color: $bg-light-dark-mode; |  | ||||||
|         color: $text-color-dark-mode; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .dropdown-item.disabled { |  | ||||||
|       color: darken($text-color-dark-mode, 20%); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .card { |   .card { | ||||||
|     background-color: $bg-light-dark-mode; |     background-color: var(--bs-body-bg); | ||||||
|  |  | ||||||
|     .card-text { |     .card-header { | ||||||
|       color: $text-color-dark-mode; |       background-color: rgba(0, 0, 0, 0.12); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .text-dark { |  | ||||||
|     color: $text-color-dark-mode !important; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .modal-content, .modal-header, .modal-body, .modal-footer { |   .modal-content, .modal-header, .modal-body, .modal-footer { | ||||||
|     background-color: $bg-light-dark-mode; |     background-color: var(--bs-body-bg); | ||||||
|     border-color: $border-color-dark-mode; |     border-color: var(--bs-border-color); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   app-tag .badge { |   app-tag .badge { | ||||||
|     filter: brightness(.8); |     filter: brightness(.8); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .badge-light { |  | ||||||
|     background-color: darken($bg-dark-mode, 20%); |  | ||||||
|     color: $text-color-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .badge.border-light { |  | ||||||
|     border-color: $bg-dark-mode !important; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .doc-img-container { |   .doc-img-container { | ||||||
|     border: none !important; |     border: none !important; | ||||||
|     border-top-left-radius: .25rem; |     border-top-left-radius: .25rem; | ||||||
| @@ -157,8 +101,9 @@ $border-color-dark-mode: #47494f; | |||||||
|   .doc-img { |   .doc-img { | ||||||
|     mix-blend-mode: normal; |     mix-blend-mode: normal; | ||||||
|     border-radius: 0; |     border-radius: 0; | ||||||
|     border-color: $bg-dark-mode; |     border-color: var(--bs-border-color); | ||||||
|     filter: invert(10%); |     filter: invert(10%); | ||||||
|  |  | ||||||
|     &.border-end { |     &.border-end { | ||||||
|       border-right: none !important; |       border-right: none !important; | ||||||
|     } |     } | ||||||
| @@ -172,34 +117,14 @@ $border-color-dark-mode: #47494f; | |||||||
|     mix-blend-mode: luminosity; |     mix-blend-mode: luminosity; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .toast { |   .ng-dropdown-panel .ng-dropdown-panel-items .ng-option:hover, | ||||||
|     background-color: opacify($bg-light-dark-mode, .85); |   .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked { | ||||||
|   } |     background-color: $bg-light-dark-mode; | ||||||
|  |  | ||||||
|   .toast-header { |  | ||||||
|     background-color: opacify($bg-dark-mode, .85); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   a, |  | ||||||
|   .card-title a { |  | ||||||
|     color: $primary-dark-mode; |  | ||||||
|  |  | ||||||
|     &:hover { |  | ||||||
|       color: lighten($primary, 10%); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   table { |   table { | ||||||
|     background-color: $bg-dark-mode; |  | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|  |  | ||||||
|     .des, |     .des, | ||||||
|     .asc { |     .asc { | ||||||
|       background-color: transparent !important; |  | ||||||
|       color: $text-color-dark-mode; |  | ||||||
|       border-color: $border-color-dark-mode; |  | ||||||
|  |  | ||||||
|       &::after { |       &::after { | ||||||
|         filter: invert(0.8); /* arrow is a black inline png bkgd image (!) so use filter */ |         filter: invert(0.8); /* arrow is a black inline png bkgd image (!) so use filter */ | ||||||
|       } |       } | ||||||
| @@ -209,238 +134,31 @@ $border-color-dark-mode: #47494f; | |||||||
|       background-color: $bg-light-dark-mode; |       background-color: $bg-light-dark-mode; | ||||||
|       color: $text-color-dark-mode-accent; |       color: $text-color-dark-mode-accent; | ||||||
|     } |     } | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .table td, |  | ||||||
|   .table th { |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .table-row-selected { |  | ||||||
|     background-color: $bg-light-dark-mode; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .table-striped > tbody > tr:nth-of-type(odd) > * { |   .table-striped > tbody > tr:nth-of-type(odd) > * { | ||||||
|     color: $text-color-dark-mode-accent; |     color: $text-color-dark-mode-accent; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .close { |   .close, .modal .btn-close { | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|     text-shadow: 0 1px 0 #666; |     text-shadow: 0 1px 0 #666; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .modal .btn-close { |   .modal .btn-close { | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|     text-shadow: 0 1px 0 #666; |  | ||||||
|     filter: invert(1) grayscale(100%) brightness(200%); |     filter: invert(1) grayscale(100%) brightness(200%); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .btn-outline-primary { |  | ||||||
|     border-color: $primary-dark-mode; |  | ||||||
|     color: $primary-dark-mode; |  | ||||||
|  |  | ||||||
|     &:not(:disabled):not(.disabled).active, |  | ||||||
|     &:not(:disabled):not(.disabled):hover { |  | ||||||
|       background-color: darken($primary-dark-mode, 10%); |  | ||||||
|       border-color: darken($primary-dark-mode, 10%); |  | ||||||
|       color: $text-color-dark-mode-accent; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     &.disabled.active { |  | ||||||
|       background-color: darken($primary-dark-mode, 10%); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .btn-outline-secondary { |  | ||||||
|     border-color: darken($text-color-dark-mode, 30%); |  | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|  |  | ||||||
|     &:not(:disabled):not(.disabled):hover { |  | ||||||
|       background-color: $bg-dark-mode; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .btn-outline-danger { |  | ||||||
|     border-color: $danger-dark-mode; |  | ||||||
|     color: $danger-dark-mode; |  | ||||||
|  |  | ||||||
|     &:not(:disabled):not(.disabled):hover { |  | ||||||
|       background-color: darken($danger-dark-mode, 10%); |  | ||||||
|       border-color: darken($danger-dark-mode, 10%); |  | ||||||
|       color: $text-color-dark-mode-accent; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .btn-outline-dark { |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|  |  | ||||||
|     &:not(:disabled):not(.disabled):hover { |  | ||||||
|       color: $text-color-dark-mode-accent; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .btn-light:not(:disabled):not(.disabled) { |  | ||||||
|     background-color: $bg-dark-mode; |  | ||||||
|     color: $text-color-dark-mode-accent; |  | ||||||
|  |  | ||||||
|     &:hover { |  | ||||||
|       background-color: $text-color-dark-mode; |  | ||||||
|       color: $bg-dark-mode; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .btn-link:not(:disabled):not(.disabled) { |  | ||||||
|     color: $primary-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .btn-link:hover, |  | ||||||
|   .btn-outline-primary:not(:disabled):not(.disabled).active, |  | ||||||
|   .btn-outline-primary:not(:disabled):not(.disabled):active, |  | ||||||
|   .show > .btn-outline-primary.dropdown-toggle { |  | ||||||
|     color: $text-color-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   button.bg-light:hover { |  | ||||||
|     background-color: $bg-dark-mode !important; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .card-footer button:hover { |  | ||||||
|     color: $primary-dark-mode !important; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .form-control:not(.is-invalid):not(.btn), |  | ||||||
|   input:not(.is-invalid), |  | ||||||
|   textarea:not(.is-invalid) { |  | ||||||
|     border-color: $border-color-dark-mode; /* we dont want to override controls that get highlighting for errors */ |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .form-control:not(.btn), |  | ||||||
|   input, |  | ||||||
|   select, |  | ||||||
|   textarea { |  | ||||||
|     background-color: $bg-dark-mode; |  | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|  |  | ||||||
|     &::placeholder { |  | ||||||
|       color: $text-color-dark-mode; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     &:focus { |  | ||||||
|       background-color: $bg-light-dark-mode !important; |  | ||||||
|       color: darken($text-color-dark-mode, 10%) !important; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .form-select:not(.is-invalid):not(:disabled) { |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .ng-select-container, |  | ||||||
|   .ng-select.ng-select-opened > .ng-select-container, |  | ||||||
|   .ng-dropdown-panel, |  | ||||||
|   .ng-dropdown-panel .ng-dropdown-panel-items .ng-option { |  | ||||||
|     background-color: $bg-dark-mode; |  | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|  |  | ||||||
|     input:focus { |  | ||||||
|       background-color: transparent !important; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .ng-dropdown-panel .ng-dropdown-panel-items .ng-option:hover, |  | ||||||
|   .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked { |  | ||||||
|     background-color: $bg-light-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .input-group-text { |  | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|     background-color: $bg-light-dark-mode; |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .list-group-item { |  | ||||||
|     color: $text-color-dark-mode; |  | ||||||
|     background-color: $bg-light-dark-mode; |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .page-item.disabled .page-link { |  | ||||||
|     background-color: $bg-dark-mode; |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .list-group-item, |  | ||||||
|   .page-link { |  | ||||||
|     background-color: $bg-light-dark-mode; |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .page-item.active .page-link { |  | ||||||
|     border-color: $border-color-dark-mode; |  | ||||||
|     color: $text-color-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .progress { |  | ||||||
|     background-color: $border-color-dark-mode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .alert-danger { |  | ||||||
|     color: $text-color-dark-mode-accent; |  | ||||||
|     background-color: darken($danger-dark-mode, 20%); |  | ||||||
|     border-color: darken($danger-dark-mode, 20%); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .bg-dark { |  | ||||||
|     background-color: $bg-light-dark-mode !important; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .ngx-file-drop__drop-zone--over { |   .ngx-file-drop__drop-zone--over { | ||||||
|     background-color: darken($primary-dark-mode, 35%) !important; |     background-color: var(--ngx-primary-darken-15) !important; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .alert-secondary { |   .toast { | ||||||
|     background-color: $bg-light-dark-mode; |     background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 18%), 0.9); | ||||||
|     border-color: darken($bg-light-dark-mode, 10%); |  | ||||||
|     color: $text-color-dark-mode-accent; |  | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   .progress-bar.bg-primary { |   .toast-header { | ||||||
|     background-color: darken($primary-dark-mode, 5%) !important; |     background-color: hsla(var(--pngx-primary), calc(var(--pngx-primary-lightness) - 10%), 0.9); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .popover { |  | ||||||
|     .popover-header, |  | ||||||
|     .popover-body { |  | ||||||
|       background-color: $bg-dark-mode-accent; |  | ||||||
|       border-color: $border-color-dark-mode; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // fix popover carat colors |  | ||||||
|   .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="left"] { |  | ||||||
|     border-left-color: $bg-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|   .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="right"] { |  | ||||||
|     border-right-color: $bg-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|   .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="top"] { |  | ||||||
|     border-top-color: $bg-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|   .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="bottom"] { |  | ||||||
|     border-bottom-color: $bg-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .bs-popover-bottom .popover-header::before, |  | ||||||
|   .bs-popover-auto[x-placement^=bottom] .popover-header::before { |  | ||||||
|     border-bottom-color: $bg-dark-mode-accent; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .ngb-dp-header, |  | ||||||
|   .ngb-dp-weekdays, |  | ||||||
|   .ngb-dp-month { |  | ||||||
|     background-color: $bg-light-dark-mode; |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 shamoon
					shamoon