Compare commits
	
		
			No commits in common. "c1ed021196c5d030af5d5d2aa272e4a280e210e2" and "678ce12de4fb9921c03df563a207db2f3963aa13" have entirely different histories.
		
	
	
		
			c1ed021196
			...
			678ce12de4
		
	
		
							
								
								
									
										69
									
								
								README.md
								
								
								
								
							
							
						
						
									
										69
									
								
								README.md
								
								
								
								
							|  | @ -264,75 +264,6 @@ export class AppComponent { | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### Card Components |  | ||||||
| 
 |  | ||||||
| **Selectors:** `ui-card`, `ui-card-title`, `ui-card-menu`, `ui-card-footer`   |  | ||||||
| **Description:** Zestaw komponentów do tworzenia kart z opcjonalnym nagłówkiem, menu i stopką. |  | ||||||
| 
 |  | ||||||
| **CardComponent (`ui-card`) Properties:** |  | ||||||
| - `title?: string` - Tytuł karty wyświetlany w nagłówku |  | ||||||
| - `margin: 0.5rem` - Domyślny margin karty |  | ||||||
| - Kolory jak ui-menu (--ui-color-menu-bg, --ui-color-menu-text) |  | ||||||
| 
 |  | ||||||
| **Standalone Components:** |  | ||||||
| - `ui-card-title` - Tytuł karty z własnymi stylami |  | ||||||
| - `ui-card-menu` - Menu/przyciski w nagłówku |  | ||||||
| - `ui-card-footer` - Stopka karty z własnymi stylami |  | ||||||
| 
 |  | ||||||
| **Usage:** |  | ||||||
| ```html |  | ||||||
| <!-- Podstawowe użycie --> |  | ||||||
| <ui-card title="Tytuł karty"> |  | ||||||
|   <p>Zawartość karty</p> |  | ||||||
| </ui-card> |  | ||||||
| 
 |  | ||||||
| <!-- Pełne użycie z wszystkimi slotami --> |  | ||||||
| <ui-card title="Statystyki"> |  | ||||||
|   <ui-card-menu> |  | ||||||
|     <button class="btn btn-sm">Edytuj</button> |  | ||||||
|     <button class="btn btn-sm">Usuń</button> |  | ||||||
|   </ui-card-menu> |  | ||||||
|    |  | ||||||
|   <div class="stats"> |  | ||||||
|     <div class="stat-item"> |  | ||||||
|       <span class="value">123</span> |  | ||||||
|       <span class="label">Użytkownicy</span> |  | ||||||
|     </div> |  | ||||||
|   </div> |  | ||||||
|    |  | ||||||
|   <ui-card-footer> |  | ||||||
|     <small class="text-muted">Ostatnia aktualizacja: dziś</small> |  | ||||||
|   </ui-card-footer> |  | ||||||
| </ui-card> |  | ||||||
| 
 |  | ||||||
| <!-- Niestandardowy tytuł --> |  | ||||||
| <ui-card> |  | ||||||
|   <ui-card-title> |  | ||||||
|     <div class="d-flex align-items-center"> |  | ||||||
|       <i class="icon-chart"></i> |  | ||||||
|       <span>Raporty sprzedaży</span> |  | ||||||
|     </div> |  | ||||||
|   </ui-card-title> |  | ||||||
|    |  | ||||||
|   <ui-card-menu> |  | ||||||
|     <span class="text-success">+12%</span> |  | ||||||
|   </ui-card-menu> |  | ||||||
|    |  | ||||||
|   <div class="chart-container"> |  | ||||||
|     <!-- wykres --> |  | ||||||
|   </div> |  | ||||||
| </ui-card> |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| **CSS Variables:** |  | ||||||
| - `--ui-color-card-bg` - tło karty |  | ||||||
| - `--ui-color-card-border` - kolor obramowania |  | ||||||
| - `--ui-color-card-title` - kolor tytułu |  | ||||||
| - `--ui-color-card-text` - kolor tekstu |  | ||||||
| - `--ui-color-card-footer-bg` - tło stopki |  | ||||||
| - `--ui-shadow-card` - standardowy cień karty |  | ||||||
| - `--ui-shadow-card-hover` - cień przy hover |  | ||||||
| 
 |  | ||||||
| ## Development | ## Development | ||||||
| 
 | 
 | ||||||
| ### Building | ### Building | ||||||
|  |  | ||||||
|  | @ -4,133 +4,9 @@ | ||||||
|     align-items: center; |     align-items: center; | ||||||
|     justify-content: center; |     justify-content: center; | ||||||
|     padding: 0px 0.75rem; |     padding: 0px 0.75rem; | ||||||
|     min-height: 2rem; |  | ||||||
|     border-radius: 4px; |  | ||||||
| 
 |  | ||||||
|     --border-color-rgb: var(--ui-color-background-rgb); |  | ||||||
|     --text-color-rgb: var(--ui-color-text-rgb); |  | ||||||
|     --background-color-rgb: var(--ui-color-background-rgb); |  | ||||||
|     --border-color-alpha: 0; |  | ||||||
|     --background-color-alpha: 0; |  | ||||||
|     --background-hover-rgb: var(--ui-color-content-bg-rgb); |  | ||||||
| 
 |  | ||||||
|     --border-color: rgb(var(--border-color-rgb)); |  | ||||||
|     --text-color: rgb(var(--text-color-rgb)); |  | ||||||
|     --background-color: rgb(var(--background-color-rgb)); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     background: rgba(var(--background-color-rgb), var(--background-color-alpha)); |  | ||||||
|     color: var(--text-color); |  | ||||||
|     border: 1px solid rgba(var(--border-color-rgb), var(--border-color-alpha)); |  | ||||||
| 
 |  | ||||||
|     &[size="small"] { |  | ||||||
|         font-size: 0.85rem; |  | ||||||
|         padding: 0px 0.5rem; |  | ||||||
|         min-height: 1.5rem; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[size="large"] { |  | ||||||
|         font-size: 1.2rem; |  | ||||||
|         padding: 0px 1rem; |  | ||||||
|         min-height: 2.5rem; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[theme="primary"] { |  | ||||||
|         --background-color-alpha: 1; |  | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --background-color-rgb: var(--ui-color-primary-rgb); |  | ||||||
|         --background-hover-rgb: var(--ui-color-primary-hard-rgb); |  | ||||||
|         --text-color-rgb: var(--ui-color-primary-contrast-rgb); |  | ||||||
|         --text-hover-rgb: var(--ui-color-background-rgb); |  | ||||||
|         --border-color-rgb: var(--ui-color-primary-rgb); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[theme="secondary"] { |  | ||||||
|         --background-color-alpha: 1; |  | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --background-color-rgb: var(--ui-color-secondary-rgb); |  | ||||||
|         --background-hover-rgb: var(--ui-color-secondary-hard-rgb); |  | ||||||
|         --text-color-rgb: var(--ui-color-secondary-contrast-rgb); |  | ||||||
|         --text-hover-rgb: var(--ui-color-background-rgb); |  | ||||||
|         --border-color-rgb: var(--ui-color-secondary-rgb); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[theme="danger"] { |  | ||||||
|         --background-color-alpha: 1; |  | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --background-color-rgb: var(--ui-color-danger-rgb); |  | ||||||
|         --background-hover-rgb: var(--ui-color-danger-hard-rgb); |  | ||||||
|         --text-color-rgb: var(--ui-color-danger-contrast-rgb); |  | ||||||
|         --text-hover-rgb: var(--ui-color-background-rgb); |  | ||||||
|         --border-color-rgb: var(--ui-color-danger-rgb); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[theme="warning"] { |  | ||||||
|         --background-color-alpha: 1; |  | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --background-color-rgb: var(--ui-color-warning-rgb); |  | ||||||
|         --background-hover-rgb: var(--ui-color-warning-hard-rgb); |  | ||||||
|         --text-color-rgb: var(--ui-color-warning-contrast-rgb); |  | ||||||
|         --text-hover-rgb: var(--ui-color-background-rgb); |  | ||||||
|         --border-color-rgb: var(--ui-color-warning-rgb); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[theme="info"] { |  | ||||||
|         --background-color-alpha: 1; |  | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --background-color-rgb: var(--ui-color-info-rgb); |  | ||||||
|         --background-hover-rgb: var(--ui-color-info-hard-rgb); |  | ||||||
|         --text-color-rgb: var(--ui-color-info-contrast-rgb); |  | ||||||
|         --text-hover-rgb: var(--ui-color-background-rgb); |  | ||||||
|         --border-color-rgb: var(--ui-color-info-rgb); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[theme="success"] { |  | ||||||
|         --background-color-alpha: 1; |  | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --background-color-rgb: var(--ui-color-success-rgb); |  | ||||||
|         --background-hover-rgb: var(--ui-color-success-hard-rgb); |  | ||||||
|         --text-hover-rgb: var(--ui-color-background-rgb); |  | ||||||
|         --border-color-rgb: var(--ui-color-success-rgb); |  | ||||||
|         &:not(&[outlined=true]) { |  | ||||||
|             --text-color-rgb: var(--ui-color-success-contrast-rgb); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &[outlined="true"] { |  | ||||||
|         --background-color-alpha: 0; |  | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --text-color-rgb: var(--border-color-rgb); |  | ||||||
|         &[theme="default"] { |  | ||||||
|             --text-color-rgb: var(--ui-color-text-rgb); |  | ||||||
|             --border-color-rgb: var(--ui-color-text-rgb); |  | ||||||
|             --background-hover-rgb: var(--ui-color-text-rgb); |  | ||||||
|             --text-hover-rgb: var(--ui-color-background-rgb); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &.active, |  | ||||||
|     &.focus, |     &.focus, | ||||||
|     &:active, |     &:active, | ||||||
|     &:hover{ |     &:hover{ | ||||||
|         --background-color-alpha: 1; |         background: var(--ui-color-button-hover, rgba(255, 255, 255, 0.1)); | ||||||
|         --border-color-alpha: 1; |  | ||||||
|         --background-color-rgb: var(--background-hover-rgb); |  | ||||||
|         --border-color-rgb: var(--background-hover-rgb); |  | ||||||
|         --text-color-rgb: var(--text-hover-rgb); |  | ||||||
| 
 |  | ||||||
|         &[outlined=true] { |  | ||||||
|             --text-color-rgb: var(--text-hover-rgb); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     & ::ng-deep ~ ui-button{ |  | ||||||
|         margin-left: 0.25rem; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| ::ng-deep ui-header > ui-button{ |  | ||||||
|     border-radius: 0px !important; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,4 @@ | ||||||
| import { Component, HostBinding, Input } from '@angular/core'; | import { Component } from '@angular/core'; | ||||||
| 
 |  | ||||||
| export type ButtonTheme = 'default' | 'primary' | 'secondary' | 'danger' | 'warning' | 'info' | 'success'; |  | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ui-button', |   selector: 'ui-button', | ||||||
|  | @ -9,16 +7,5 @@ export type ButtonTheme = 'default' | 'primary' | 'secondary' | 'danger' | 'warn | ||||||
|   styleUrl: './button.component.scss' |   styleUrl: './button.component.scss' | ||||||
| }) | }) | ||||||
| export class ButtonComponent { | export class ButtonComponent { | ||||||
|     @Input() |  | ||||||
|     @HostBinding('attr.theme') |  | ||||||
|     theme: ButtonTheme = 'default'; |  | ||||||
| 
 |  | ||||||
|     @Input() |  | ||||||
|     @HostBinding('attr.outlined') |  | ||||||
|     outlined: boolean | string = false; |  | ||||||
| 
 |  | ||||||
|     @Input() |  | ||||||
|     @HostBinding('attr.size') |  | ||||||
|     size: 'small' | 'large' | 'default' = 'default'; |  | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,186 +0,0 @@ | ||||||
| # Card Components |  | ||||||
| 
 |  | ||||||
| Zestaw komponentów do tworzenia kart z opcjonalnym nagłówkiem, menu i stopką. |  | ||||||
| 
 |  | ||||||
| ## Komponenty |  | ||||||
| 
 |  | ||||||
| - `ui-card` - główny kontener karty |  | ||||||
| - `ui-card-title` - tytuł karty (standalone komponent) |  | ||||||
| - `ui-card-menu` - menu/przyciski w nagłówku (standalone komponent)   |  | ||||||
| - `ui-card-footer` - stopka karty (standalone komponent) |  | ||||||
| 
 |  | ||||||
| ## Użycie |  | ||||||
| 
 |  | ||||||
| ### Podstawowe użycie z tytułem jako Input |  | ||||||
| 
 |  | ||||||
| ```html |  | ||||||
| <ui-card title="Tytuł karty"> |  | ||||||
|   <p>Zawartość karty</p> |  | ||||||
| </ui-card> |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ### Użycie z komponentem ui-card-title |  | ||||||
| 
 |  | ||||||
| ```html |  | ||||||
| <ui-card> |  | ||||||
|   <ui-card-title> |  | ||||||
|     <h2>Niestandardowy tytuł</h2> |  | ||||||
|     <span class="badge">Nowy</span> |  | ||||||
|   </ui-card-title> |  | ||||||
|   <p>Zawartość karty</p> |  | ||||||
| </ui-card> |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ### Pełne użycie z wszystkimi komponentami |  | ||||||
| 
 |  | ||||||
| ```html |  | ||||||
| <ui-card title="Statystyki"> |  | ||||||
|   <ui-card-menu> |  | ||||||
|     <button class="btn btn-sm">Edytuj</button> |  | ||||||
|     <button class="btn btn-sm">Usuń</button> |  | ||||||
|   </ui-card-menu> |  | ||||||
|    |  | ||||||
|   <div class="stats"> |  | ||||||
|     <div class="stat-item"> |  | ||||||
|       <span class="value">123</span> |  | ||||||
|       <span class="label">Użytkownicy</span> |  | ||||||
|     </div> |  | ||||||
|     <div class="stat-item"> |  | ||||||
|       <span class="value">456</span> |  | ||||||
|       <span class="label">Zamówienia</span> |  | ||||||
|     </div> |  | ||||||
|   </div> |  | ||||||
|    |  | ||||||
|   <ui-card-footer> |  | ||||||
|     <small class="text-muted">Ostatnia aktualizacja: dziś</small> |  | ||||||
|   </ui-card-footer> |  | ||||||
| </ui-card> |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ### Użycie z komponentami ui-card-title i ui-card-menu |  | ||||||
| 
 |  | ||||||
| ```html |  | ||||||
| <ui-card> |  | ||||||
|   <ui-card-title> |  | ||||||
|     <div class="d-flex align-items-center"> |  | ||||||
|       <i class="icon-chart"></i> |  | ||||||
|       <span>Raporty sprzedaży</span> |  | ||||||
|     </div> |  | ||||||
|   </ui-card-title> |  | ||||||
|    |  | ||||||
|   <ui-card-menu> |  | ||||||
|     <div class="stats-mini"> |  | ||||||
|       <span class="text-success">+12%</span> |  | ||||||
|     </div> |  | ||||||
|     <button class="btn btn-outline-primary btn-sm">Szczegóły</button> |  | ||||||
|   </ui-card-menu> |  | ||||||
|    |  | ||||||
|   <div class="chart-container"> |  | ||||||
|     <!-- wykres --> |  | ||||||
|   </div> |  | ||||||
|    |  | ||||||
|   <ui-card-footer> |  | ||||||
|     <div class="d-flex justify-content-between"> |  | ||||||
|       <span>Okres: ostatnie 30 dni</span> |  | ||||||
|       <a href="#" class="text-primary">Zobacz więcej</a> |  | ||||||
|     </div> |  | ||||||
|   </ui-card-footer> |  | ||||||
| </ui-card> |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## API |  | ||||||
| 
 |  | ||||||
| ### CardComponent (`ui-card`) |  | ||||||
| 
 |  | ||||||
| **Inputs:** |  | ||||||
| | Właściwość | Typ | Domyślna | Opis | |  | ||||||
| |------------|-----|----------|------| |  | ||||||
| | `title` | `string` | `undefined` | Tytuł karty wyświetlany w nagłówku | |  | ||||||
| 
 |  | ||||||
| **Content Projection:** |  | ||||||
| | Selektor | Opis | |  | ||||||
| |----------|------| |  | ||||||
| | `ui-card-title` | Komponent tytułu karty | |  | ||||||
| | `ui-card-menu` | Komponent menu w nagłówku | |  | ||||||
| | (default) | Główna zawartość karty | |  | ||||||
| | `ui-card-footer` | Komponent stopki karty | |  | ||||||
| 
 |  | ||||||
| ### CardTitleComponent (`ui-card-title`) |  | ||||||
| 
 |  | ||||||
| **Opis:** Standalone komponent do wyświetlania tytułu karty z własnymi stylami. |  | ||||||
| 
 |  | ||||||
| ### CardMenuComponent (`ui-card-menu`) |  | ||||||
| 
 |  | ||||||
| **Opis:** Standalone komponent do wyświetlania menu/przycisków w nagłówku karty. |  | ||||||
| 
 |  | ||||||
| ### CardFooterComponent (`ui-card-footer`) |  | ||||||
| 
 |  | ||||||
| **Opis:** Standalone komponent do wyświetlania stopki karty z własnymi stylami. |  | ||||||
| 
 |  | ||||||
| ## Zmienne CSS |  | ||||||
| 
 |  | ||||||
| Komponent używa następujących zmiennych CSS z systemu motywów: |  | ||||||
| 
 |  | ||||||
| ### Kolory |  | ||||||
| - `--ui-color-card-bg` - tło karty |  | ||||||
| - `--ui-color-card-border` - kolor obramowania |  | ||||||
| - `--ui-color-card-title` - kolor tytułu |  | ||||||
| - `--ui-color-card-text` - kolor tekstu |  | ||||||
| - `--ui-color-card-footer-bg` - tło stopki |  | ||||||
| 
 |  | ||||||
| ### Spacing |  | ||||||
| - `--ui-spacing-xs` (4px) - małe odstępy |  | ||||||
| - `--ui-spacing-sm` (8px) - średnie odstępy   |  | ||||||
| - `--ui-spacing-md` (16px) - standardowe padding |  | ||||||
| - `--ui-spacing-lg` (24px) - duże odstępy |  | ||||||
| 
 |  | ||||||
| ### Layout |  | ||||||
| - `--ui-border-radius` (8px) - zaokrąglenie rogów |  | ||||||
| - `--ui-font-size-lg` (18px) - rozmiar czcionki tytułu |  | ||||||
| - `--ui-font-weight-semibold` (600) - grubość czcionki tytułu |  | ||||||
| - `--ui-card-header-min-height` (40px) - minimalna wysokość nagłówka |  | ||||||
| 
 |  | ||||||
| ### Cienie |  | ||||||
| - `--ui-shadow-card` - standardowy cień karty |  | ||||||
| - `--ui-shadow-card-hover` - cień przy hover |  | ||||||
| 
 |  | ||||||
| ## Responsywność |  | ||||||
| 
 |  | ||||||
| Na urządzeniach mobilnych (max-width: 768px): |  | ||||||
| - Nagłówek karty zmienia się na układ kolumnowy |  | ||||||
| - Menu wyrównuje się do prawej strony |  | ||||||
| - Zachowane są wszystkie funkcjonalności |  | ||||||
| 
 |  | ||||||
| ## Przykłady stylizacji |  | ||||||
| 
 |  | ||||||
| ### Karta z kolorowym nagłówkiem |  | ||||||
| 
 |  | ||||||
| ```scss |  | ||||||
| .custom-card { |  | ||||||
|   .ui-card-header { |  | ||||||
|     background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |  | ||||||
|     color: white; |  | ||||||
|     margin: -16px -16px 0; |  | ||||||
|     padding: 16px; |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   .ui-card-title { |  | ||||||
|     color: white; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ### Karta z ikoną |  | ||||||
| 
 |  | ||||||
| ```html |  | ||||||
| <ui-card> |  | ||||||
|   <ui-card-title> |  | ||||||
|     <div class="d-flex align-items-center gap-2"> |  | ||||||
|       <i class="icon-settings"></i> |  | ||||||
|       <span>Ustawienia</span> |  | ||||||
|     </div> |  | ||||||
|   </ui-card-title> |  | ||||||
|    |  | ||||||
|   <!-- zawartość --> |  | ||||||
| </ui-card> |  | ||||||
| ``` |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| :host { |  | ||||||
|     padding: 0.5rem; |  | ||||||
|     display: flex; |  | ||||||
|     &:empty{ |  | ||||||
|         display: none; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| import { Component } from '@angular/core'; |  | ||||||
| 
 |  | ||||||
| @Component({ |  | ||||||
|   selector: 'ui-card-footer', |  | ||||||
|   standalone: true, |  | ||||||
|   imports: [], |  | ||||||
|   template: '<ng-content />', |  | ||||||
|   styleUrl: './card-footer.component.scss' |  | ||||||
| }) |  | ||||||
| export class CardFooterComponent { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| :host { |  | ||||||
|   display: flex; |  | ||||||
|   gap: var(--ui-spacing-sm, 8px); |  | ||||||
|   align-items: flex-start; |  | ||||||
|   flex-shrink: 0; |  | ||||||
|   padding: 1rem; |  | ||||||
| } |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| import { Component } from '@angular/core'; |  | ||||||
| 
 |  | ||||||
| @Component({ |  | ||||||
|   selector: 'ui-card-menu', |  | ||||||
|   standalone: true, |  | ||||||
|   imports: [], |  | ||||||
|   template: '<ng-content />', |  | ||||||
|   styleUrl: './card-menu.component.scss' |  | ||||||
| }) |  | ||||||
| export class CardMenuComponent { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| :host { |  | ||||||
|   display: block; |  | ||||||
|   margin: 0; |  | ||||||
|   font-size: var(--ui-font-size-lg, 18px); |  | ||||||
|   font-weight: var(--ui-font-weight-semibold, 600); |  | ||||||
|   color: var(--ui-color-menu-text, #ffffff); |  | ||||||
|   line-height: 1.2; |  | ||||||
|   padding: 1rem; |  | ||||||
| } |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| import { Component } from '@angular/core'; |  | ||||||
| 
 |  | ||||||
| @Component({ |  | ||||||
|   selector: 'ui-card-title', |  | ||||||
|   standalone: true, |  | ||||||
|   imports: [], |  | ||||||
|   template: `<ng-content />`, |  | ||||||
|   styleUrl: './card-title.component.scss' |  | ||||||
| }) |  | ||||||
| export class CardTitleComponent { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,15 +1 @@ | ||||||
| <div class="header"> | <p>card works!</p> | ||||||
|     @if (title) { |  | ||||||
|         <div class="title">{{ title }}</div> |  | ||||||
|     } @else { |  | ||||||
|         <ng-content select="ui-card-title"></ng-content> |  | ||||||
|     } |  | ||||||
|     <ng-content select="ui-card-menu"></ng-content> |  | ||||||
| 
 |  | ||||||
| </div> |  | ||||||
| 
 |  | ||||||
| <div class="content"> |  | ||||||
|   <ng-content></ng-content> |  | ||||||
| </div> |  | ||||||
| 
 |  | ||||||
| <ng-content select="ui-card-footer"></ng-content> |  | ||||||
|  |  | ||||||
|  | @ -1,23 +0,0 @@ | ||||||
| :host { |  | ||||||
|   display: block; |  | ||||||
|   margin: var(--ui-spacing-sm, 0.5rem); |  | ||||||
|   background: var(--ui-color-menu-bg, #343a40); |  | ||||||
|   border: 1px solid var(--ui-color-menu-border, #d0d0d0); |  | ||||||
|   border-radius: var(--ui-border-radius, 8px); |  | ||||||
|   box-shadow: var(--ui-shadow-card, 0 2px 4px rgba(0, 0, 0, 0.1)); |  | ||||||
|   overflow: hidden; |  | ||||||
|   transition: box-shadow 0.2s ease; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .content { |  | ||||||
|   padding: var(--ui-spacing-md, 16px); |  | ||||||
|   color: var(--ui-color-menu-text, #ffffff); |  | ||||||
|   line-height: 1.5; |  | ||||||
| } |  | ||||||
| .header{ |  | ||||||
|     display: flex; |  | ||||||
|     .title, |  | ||||||
|     ::ng-deep ui-card-title{ |  | ||||||
|         flex-grow: 1; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,13 +1,11 @@ | ||||||
| import { Component, Input } from '@angular/core'; | import { Component } from '@angular/core'; | ||||||
| import { CommonModule } from '@angular/common'; |  | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ui-card', |   selector: 'ui-card', | ||||||
|   standalone: true, |   imports: [], | ||||||
|   imports: [CommonModule], |  | ||||||
|   templateUrl: './card.component.html', |   templateUrl: './card.component.html', | ||||||
|   styleUrl: './card.component.scss' |   styleUrl: './card.component.scss' | ||||||
| }) | }) | ||||||
| export class CardComponent { | export class CardComponent { | ||||||
|   @Input() title?: string; | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,18 +1 @@ | ||||||
| <div  (click)="stopPropagation($event)"> | <p>input works!</p> | ||||||
|     <ng-content select="[place=before]"></ng-content> |  | ||||||
| </div> |  | ||||||
| <input |  | ||||||
|     #input |  | ||||||
|     [type]="type" |  | ||||||
|     [value]="value" |  | ||||||
|     [disabled]="disabled" |  | ||||||
|     [required]="required" |  | ||||||
|     (input)="onInputChange($event)" |  | ||||||
|     (focus)="onInputFocus()" |  | ||||||
|     (blur)="onInputBlur()" |  | ||||||
|     class="ui-input-field" |  | ||||||
| /> |  | ||||||
| <label class="ui-input-label" [class.floating]="isFocused || filled">{{ placeholder }}</label> |  | ||||||
| <div (click)="stopPropagation($event)"> |  | ||||||
|     <ng-content select="[place=after]"></ng-content> |  | ||||||
| </div> |  | ||||||
|  |  | ||||||
|  | @ -1,94 +0,0 @@ | ||||||
| :host { |  | ||||||
|     display: block; |  | ||||||
|     width: 100%; |  | ||||||
| 
 |  | ||||||
|     --background-color-rgb: var(--ui-color-input-bg-rgb, 255, 255, 255); |  | ||||||
|     --accent-color-rgb: var(--ui-color-input-label-focus-rgb, 0, 123, 255); |  | ||||||
|     --text-color-rgb: var(--ui-color-input-text-rgb, 33, 37, 41); |  | ||||||
| 
 |  | ||||||
|     --background-color: var(--ui-color-input-bg, rgb(var(--background-color-rgb))); |  | ||||||
|     --accent-color: var(--ui-color-input-label-focus, rgb(var(--accent-color-rgb))); |  | ||||||
|     --text-color: var(--ui-color-input-text, rgb(var(--text-color-rgb))); |  | ||||||
| 
 |  | ||||||
|     background-color: var(--background-color); |  | ||||||
|     box-shadow: 0px 0px 0px 0px var(--background-color), 0px 0px 0px 0px var(--accent-color); |  | ||||||
|     transition: all 0.2s ease-in-out; |  | ||||||
| 
 |  | ||||||
|     position: relative; |  | ||||||
|     display: flex; |  | ||||||
|     align-items: stretch; |  | ||||||
|     gap: 0.5rem; |  | ||||||
|     cursor: text; |  | ||||||
|     min-height: 2rem; |  | ||||||
|     &.invalid{ |  | ||||||
|         --accent-color: var(--ui-color-input-label-invalid, #dc3545); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &.active:not(.disabled), |  | ||||||
|     &.focused{ |  | ||||||
|         box-shadow: 0px 0px 0px 9px var(--background-color), 0px 0px 0px 10px var(--accent-color); |  | ||||||
|     } |  | ||||||
|     &.hovered { |  | ||||||
|         box-shadow: 0px 0px 0px 0px var(--background-color), 0px 0px 0px 1px var(--accent-color); |  | ||||||
|     } |  | ||||||
|     &.active:not(.disabled), |  | ||||||
|     &.focused, |  | ||||||
|     &.hovered { |  | ||||||
|         --background-color: var(--ui-color-input-bg-hover, #313b44); |  | ||||||
|     } |  | ||||||
|     &.disabled { |  | ||||||
|         opacity: 0.6; |  | ||||||
|         cursor: not-allowed; |  | ||||||
|     } |  | ||||||
|     .ui-input-label { |  | ||||||
|         position: absolute; |  | ||||||
|         left: 0.5rem; |  | ||||||
|         top: 50%; |  | ||||||
|         transform: translateY(-50%); |  | ||||||
|         font-size: 1rem; |  | ||||||
|         color: rgba(var(--accent-color-rgb), 0.4); |  | ||||||
|         pointer-events: none; |  | ||||||
|         transition: all 0.2s ease-in-out; |  | ||||||
|         background-color: transparent; |  | ||||||
|         border-radius: 6px; |  | ||||||
|         padding: 0 0.25rem; |  | ||||||
|         white-space: nowrap; |  | ||||||
| 
 |  | ||||||
|         &.floating { |  | ||||||
|             top: 0; |  | ||||||
|             color: var(--accent-color); |  | ||||||
|             transform: translateY(-50%); |  | ||||||
|             font-size: 0.7rem; |  | ||||||
|             background-color: var(--background-color); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     ::ng-deep { |  | ||||||
|         > div { |  | ||||||
|             display: flex; |  | ||||||
|             > [place] { |  | ||||||
|                 display: flex; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ui-input-field { |  | ||||||
|     flex: 1; |  | ||||||
|     padding: 0.5rem 0.25rem; |  | ||||||
|     border: none; |  | ||||||
|     outline: none; |  | ||||||
|     background: transparent; |  | ||||||
|     font-size: 1rem; |  | ||||||
|     line-height: 1.5; |  | ||||||
|     color: var(--ui-color-input-text, #212529); |  | ||||||
| 
 |  | ||||||
|     &::placeholder { |  | ||||||
|         color: transparent; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     &:disabled { |  | ||||||
|         cursor: not-allowed; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||||||
|  | 
 | ||||||
|  | import { InputComponent } from './input.component'; | ||||||
|  | 
 | ||||||
|  | describe('InputComponent', () => { | ||||||
|  |   let component: InputComponent; | ||||||
|  |   let fixture: ComponentFixture<InputComponent>; | ||||||
|  | 
 | ||||||
|  |   beforeEach(async () => { | ||||||
|  |     await TestBed.configureTestingModule({ | ||||||
|  |       imports: [InputComponent] | ||||||
|  |     }) | ||||||
|  |     .compileComponents(); | ||||||
|  | 
 | ||||||
|  |     fixture = TestBed.createComponent(InputComponent); | ||||||
|  |     component = fixture.componentInstance; | ||||||
|  |     fixture.detectChanges(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should create', () => { | ||||||
|  |     expect(component).toBeTruthy(); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | @ -1,134 +1,11 @@ | ||||||
| import { Component, Input, HostBinding, ElementRef, forwardRef, HostListener } from '@angular/core'; | import { Component } from '@angular/core'; | ||||||
| import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; |  | ||||||
| import { CommonModule } from '@angular/common'; |  | ||||||
| import { FormModule } from '../../form-module'; |  | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'ui-input', |   selector: 'ui-input', | ||||||
|   exportAs: 'uiInput', |   imports: [], | ||||||
|   standalone: true, |  | ||||||
|   imports: [CommonModule], |  | ||||||
|   templateUrl: './input.component.html', |   templateUrl: './input.component.html', | ||||||
|   styleUrl: './input.component.scss', |   styleUrl: './input.component.scss' | ||||||
|   providers: [ |  | ||||||
|     { |  | ||||||
|       provide: NG_VALUE_ACCESSOR, |  | ||||||
|       useExisting: forwardRef(() => InputComponent), |  | ||||||
|       multi: true |  | ||||||
|     } |  | ||||||
|   ] |  | ||||||
| }) | }) | ||||||
| export class InputComponent implements ControlValueAccessor { | export class InputComponent { | ||||||
|   @Input() |  | ||||||
|   placeholder: string = ''; |  | ||||||
| 
 | 
 | ||||||
|   @Input() |  | ||||||
|   type: string = 'text'; |  | ||||||
| 
 |  | ||||||
|   @Input() |  | ||||||
|   @HostBinding('class.disabled') |  | ||||||
|   disabled: boolean = false; |  | ||||||
| 
 |  | ||||||
|   @Input() |  | ||||||
|   required: boolean = false; |  | ||||||
| 
 |  | ||||||
|   value: string = ''; |  | ||||||
| 
 |  | ||||||
|   @HostBinding('class.focused') |  | ||||||
|   isFocused: boolean = false; |  | ||||||
| 
 |  | ||||||
|   @HostBinding('class.hovered') |  | ||||||
|   isHovered: boolean = false; |  | ||||||
| 
 |  | ||||||
|   isTouched: boolean = false; |  | ||||||
| 
 |  | ||||||
|   @HostBinding('class.active') |  | ||||||
|   isActive: boolean = false; |  | ||||||
| 
 |  | ||||||
|   private onChange = (value: string) => {}; |  | ||||||
|   private onTouched = () => {}; |  | ||||||
| 
 |  | ||||||
|   @HostBinding('class.filled') |  | ||||||
|   get filled() { |  | ||||||
|     return this.value && this.value.length > 0; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   @HostBinding('class.invalid') |  | ||||||
|   get invalid() { |  | ||||||
|     return this.required && this.isTouched && (!this.value || this.value.length === 0); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   constructor(private elementRef: ElementRef) {} |  | ||||||
| 
 |  | ||||||
|   public stopPropagation(event: Event) { |  | ||||||
|     event.stopPropagation(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public focus() { |  | ||||||
|     console.log({elementRef: this.elementRef.nativeElement}); |  | ||||||
|     this.elementRef.nativeElement.querySelector('input')?.focus(); |  | ||||||
|     this.onInputFocus(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   public blur() { |  | ||||||
|     this.elementRef.nativeElement.querySelector('input')?.blur(); |  | ||||||
|     this.onInputBlur(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   @HostListener('mouseenter') |  | ||||||
|   public hover() { |  | ||||||
|     this.isHovered = true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   @HostListener('mouseleave') |  | ||||||
|   public leave() { |  | ||||||
|     this.isHovered = false; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   onInputChange(event: Event): void { |  | ||||||
|     const target = event.target as HTMLInputElement; |  | ||||||
|     this.value = target.value; |  | ||||||
|     this.onChange(this.value); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   onInputFocus(): void { |  | ||||||
|     this.isFocused = true; |  | ||||||
|     this.isActive = true; |  | ||||||
|     FormModule.ActiveInput = this; |  | ||||||
|     (window as any).KeyEventSafeModeEnabled = true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   onInputBlur(): void { |  | ||||||
|     this.isFocused = false; |  | ||||||
|     this.isActive = false; |  | ||||||
|     this.isTouched = true; |  | ||||||
|     this.onTouched(); |  | ||||||
|     FormModule.ActiveInput = undefined; |  | ||||||
|     (window as any).KeyEventSafeModeEnabled = undefined; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   @HostListener('click') |  | ||||||
|   onContainerClick(): void { |  | ||||||
|     const input = this.elementRef.nativeElement.querySelector('input'); |  | ||||||
|     if (input && !this.disabled) { |  | ||||||
|       this.focus(); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // ControlValueAccessor implementation
 |  | ||||||
|   writeValue(value: string): void { |  | ||||||
|     this.value = value || ''; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   registerOnChange(fn: (value: string) => void): void { |  | ||||||
|     this.onChange = fn; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   registerOnTouched(fn: () => void): void { |  | ||||||
|     this.onTouched = fn; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   setDisabledState(isDisabled: boolean): void { |  | ||||||
|     this.disabled = isDisabled; |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,17 +1,12 @@ | ||||||
| import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||||
| import { CommonModule } from '@angular/common'; | import { CommonModule } from '@angular/common'; | ||||||
| import { InputComponent } from './components/input/input.component'; | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|   declarations: [], |   declarations: [], | ||||||
|   imports: [ |   imports: [ | ||||||
|     CommonModule, |     CommonModule | ||||||
|     InputComponent |  | ||||||
|   ], |  | ||||||
|   exports: [ |  | ||||||
|     InputComponent |  | ||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
| export class FormModule { | export class FormModule { } | ||||||
|     public static ActiveInput?: InputComponent; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,141 +0,0 @@ | ||||||
| # UI Contrast Color Function |  | ||||||
| 
 |  | ||||||
| ## Opis |  | ||||||
| 
 |  | ||||||
| Funkcja `ui-contrast-color()` automatycznie wybiera najlepszy kolor kontrastujący na podstawie jasności koloru bazowego. Jest to narzędzie do zapewnienia optymalnej czytelności tekstu na różnych tłach. |  | ||||||
| 
 |  | ||||||
| ## Składnia |  | ||||||
| 
 |  | ||||||
| ```scss |  | ||||||
| @function ui-contrast-color($base-color, $light-color, $dark-color) |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ### Parametry |  | ||||||
| 
 |  | ||||||
| - `$base-color` - Kolor bazowy, dla którego sprawdzana jest jasność |  | ||||||
| - `$light-color` - Kolor zwracany dla ciemnych kolorów bazowych (zwykle kolor tekstu w jasnym motywie lub tła w ciemnym motywie) |  | ||||||
| - `$dark-color` - Kolor zwracany dla jasnych kolorów bazowych (zwykle kolor tła w jasnym motywie lub tekstu w ciemnym motywie) |  | ||||||
| 
 |  | ||||||
| ### Zwracana wartość |  | ||||||
| 
 |  | ||||||
| Funkcja zwraca: |  | ||||||
| - `$dark-color` jeśli jasność `$base-color` > 50% (kolor bliżej białego) |  | ||||||
| - `$light-color` jeśli jasność `$base-color` ≤ 50% (kolor bliżej czarnego) |  | ||||||
| 
 |  | ||||||
| ## Mechanizm działania |  | ||||||
| 
 |  | ||||||
| 1. Funkcja oblicza jasność koloru bazowego używając `color.channel($base-color, "lightness", $space: hsl)` |  | ||||||
| 2. Porównuje jasność z progiem 50% |  | ||||||
| 3. Zwraca odpowiedni kolor kontrastujący |  | ||||||
| 
 |  | ||||||
| ## Przykłady użycia |  | ||||||
| 
 |  | ||||||
| ### Podstawowe użycie |  | ||||||
| 
 |  | ||||||
| ```scss |  | ||||||
| @use 'theme-mixins' as theme; |  | ||||||
| 
 |  | ||||||
| .button { |  | ||||||
|   $bg: #007bff; // Niebieski |  | ||||||
|   background-color: $bg; |  | ||||||
|   color: theme.ui-contrast-color($bg, #ffffff, #333333); |  | ||||||
|   // Wynik: biały tekst, bo niebieski jest ciemny |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ### Kolory statusów |  | ||||||
| 
 |  | ||||||
| ```scss |  | ||||||
| .status-badge { |  | ||||||
|   &.success { |  | ||||||
|     $color: #28a745; // Zielony |  | ||||||
|     background-color: $color; |  | ||||||
|     color: theme.ui-contrast-color($color, white, black); |  | ||||||
|     // Wynik: biały tekst |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   &.warning { |  | ||||||
|     $color: #ffc107; // Żółty |  | ||||||
|     background-color: $color; |  | ||||||
|     color: theme.ui-contrast-color($color, white, black); |  | ||||||
|     // Wynik: czarny tekst (żółty jest jasny) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ### Użycie z motywami |  | ||||||
| 
 |  | ||||||
| ```scss |  | ||||||
| // Dla jasnego motywu |  | ||||||
| .component.light-theme { |  | ||||||
|   $bg: var(--ui-color-primary); |  | ||||||
|   $primary: #2c3e50; // Wartość z motywu |  | ||||||
|    |  | ||||||
|   background-color: $primary; |  | ||||||
|   color: theme.ui-contrast-color($primary, #ffffff, #333333); |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## Integracja z systemem motywów |  | ||||||
| 
 |  | ||||||
| Funkcja jest już zintegrowana z systemem motywów biblioteki UI i automatycznie generuje zmienne contrast: |  | ||||||
| 
 |  | ||||||
| ### Zmienne HEX |  | ||||||
| - `--ui-color-primary-contrast` |  | ||||||
| - `--ui-color-secondary-contrast` |  | ||||||
| - `--ui-color-success-contrast` |  | ||||||
| - `--ui-color-warning-contrast` |  | ||||||
| - `--ui-color-danger-contrast` |  | ||||||
| - `--ui-color-info-contrast` |  | ||||||
| 
 |  | ||||||
| ### Zmienne RGB |  | ||||||
| - `--ui-color-primary-contrast-rgb` |  | ||||||
| - `--ui-color-secondary-contrast-rgb` |  | ||||||
| - `--ui-color-success-contrast-rgb` |  | ||||||
| - `--ui-color-warning-contrast-rgb` |  | ||||||
| - `--ui-color-danger-contrast-rgb` |  | ||||||
| - `--ui-color-info-contrast-rgb` |  | ||||||
| 
 |  | ||||||
| ## Użycie zmiennych CSS |  | ||||||
| 
 |  | ||||||
| ```scss |  | ||||||
| .dynamic-component { |  | ||||||
|   background-color: var(--ui-color-primary); |  | ||||||
|   color: var(--ui-color-primary-contrast); |  | ||||||
|    |  | ||||||
|   // Z przezroczystością |  | ||||||
|   background-color: rgba(var(--ui-color-primary-rgb), 0.8); |  | ||||||
|   color: var(--ui-color-primary-contrast); |  | ||||||
|    |  | ||||||
|   // Obramowanie z przezroczystym kontrastem |  | ||||||
|   border: 1px solid rgba(var(--ui-color-primary-contrast-rgb), 0.3); |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## Zalety |  | ||||||
| 
 |  | ||||||
| 1. **Automatyczny dobór** - Nie musisz ręcznie sprawdzać, czy kolor jest jasny czy ciemny |  | ||||||
| 2. **Spójność** - Wszystkie komponenty używają tej samej logiki kontrastowania |  | ||||||
| 3. **Dostępność** - Zapewnia lepszą czytelność dla użytkowników |  | ||||||
| 4. **Elastyczność** - Możesz definiować własne kolory jasne i ciemne dla różnych kontekstów |  | ||||||
| 5. **Integracja z motywami** - Automatycznie generuje zmienne CSS dla wszystkich motywów |  | ||||||
| 
 |  | ||||||
| ## Uwagi techniczne |  | ||||||
| 
 |  | ||||||
| - Funkcja działa w czasie kompilacji SCSS z konkretnymi wartościami kolorów |  | ||||||
| - Dla dynamicznych kolorów CSS używaj pre-wygenerowanych zmiennych `*-contrast` |  | ||||||
| - Próg 50% jasności jest optymalny dla większości przypadków użycia |  | ||||||
| - Używa nowoczesnej składni Sass (`color.channel()`) bez ostrzeżeń o deprecacji |  | ||||||
| 
 |  | ||||||
| ## Przykłady kolorów i wyników |  | ||||||
| 
 |  | ||||||
| | Kolor bazowy | Nazwa | Jasność | Wynik dla (white, black) | |  | ||||||
| |--------------|-------|---------|--------------------------| |  | ||||||
| | `#ffffff` | Biały | 100% | `black` | |  | ||||||
| | `#ffc107` | Żółty | ~75% | `black` | |  | ||||||
| | `#28a745` | Zielony | ~45% | `white` | |  | ||||||
| | `#007bff` | Niebieski | ~35% | `white` | |  | ||||||
| | `#dc3545` | Czerwony | ~30% | `white` | |  | ||||||
| | `#000000` | Czarny | 0% | `white` | |  | ||||||
| 
 |  | ||||||
| Funkcja zapewnia optymalny kontrast dla wszystkich kolorów w systemie motywów biblioteki UI. |  | ||||||
|  | @ -1,29 +1,12 @@ | ||||||
| /* Theme Integration Mixins for UI Library */ | /* Theme Integration Mixins for UI Library */ | ||||||
| 
 | 
 | ||||||
| @use 'sass:color'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Mixin that returns the best contrasting color based on lightness |  | ||||||
|  * If the base color is closer to white than black, returns the dark color |  | ||||||
|  * If the base color is closer to black than white, returns the light color |  | ||||||
|  * |  | ||||||
|  * @param $base-color - The color to check lightness for |  | ||||||
|  * @param $light-color - Color to return for dark base colors (usually text color in light theme or background in dark theme) |  | ||||||
|  * @param $dark-color - Color to return for light base colors (usually background color in light theme or text color in dark theme) |  | ||||||
|  * @return Color - The contrasting color |  | ||||||
|  */ |  | ||||||
| @function ui-contrast-color($base-color, $light-color, $dark-color) { |  | ||||||
|   $lightness: color.channel($base-color, "lightness", $space: hsl); |  | ||||||
|   @return if($lightness > 40%, $dark-color, $light-color); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Mixin that generates CSS variables for UI library components |  * Mixin that generates CSS variables for UI library components | ||||||
|  * This mixin should be called by the main application to provide colors for the UI library |  * This mixin should be called by the main application to provide colors for the UI library | ||||||
|  * The UI library uses only --ui-* variables with hardcoded fallbacks for portability |  * The UI library uses only --ui-* variables with hardcoded fallbacks for portability | ||||||
|  * |  *  | ||||||
|  * @param $primary - Primary color for the theme |  * @param $primary - Primary color for the theme | ||||||
|  * @param $secondary - Secondary color for the theme |  * @param $secondary - Secondary color for the theme   | ||||||
|  * @param $background - Background color for the theme |  * @param $background - Background color for the theme | ||||||
|  * @param $text - Text color for the theme |  * @param $text - Text color for the theme | ||||||
|  * @param $border - Border color for the theme |  * @param $border - Border color for the theme | ||||||
|  | @ -35,181 +18,29 @@ | ||||||
|   $background: #343a40, |   $background: #343a40, | ||||||
|   $text: #ffffff, |   $text: #ffffff, | ||||||
|   $border: #d0d0d0, |   $border: #d0d0d0, | ||||||
|   $hover: rgba(255, 255, 255, 0.1), |   $hover: rgba(255, 255, 255, 0.1) | ||||||
|   $success: #28a745, |  | ||||||
|   $warning: #ffc107, |  | ||||||
|   $danger: #dc3545, |  | ||||||
|   $info: #17a2b8 |  | ||||||
| ) { | ) { | ||||||
|   /* Assign SCSS variables for each color */ |   /* UI Library specific CSS variables - only these should be used in UI components */ | ||||||
|   $primary-color: $primary; |   --ui-color-primary: #{$primary}; | ||||||
|   $secondary-color: $secondary; |   --ui-color-secondary: #{$secondary}; | ||||||
|   $background-color: $background; |   --ui-color-background: #{$background}; | ||||||
|   $text-color: $text; |   --ui-color-text: #{$text}; | ||||||
|   $border-color: $border; |   --ui-color-border: #{$border}; | ||||||
|   $hover-color: $hover; |   --ui-color-hover: #{$hover}; | ||||||
|   $success-color: $success; |    | ||||||
|   $warning-color: $warning; |   /* Derived colors for specific UI components */ | ||||||
|   $danger-color: $danger; |   --ui-color-menu-bg: #{$background}; | ||||||
|   $info-color: $info; |   --ui-color-menu-text: #{$text}; | ||||||
| 
 |   --ui-color-menu-hover: #{$hover}; | ||||||
|   /* Derived colors as SCSS variables using SCSS functions */ |   --ui-color-menu-active: color-mix(in srgb, #{$background} 80%, black 20%); | ||||||
|   $menu-active-color: color.mix(black, $background-color, 20%); |   --ui-color-menu-border: #{$border}; | ||||||
|   $content-bg-color: color.mix(white, $background-color, 5%); |    | ||||||
|   $icon-muted-color: rgba($text-color, 0.6); |   --ui-color-content-bg: color-mix(in srgb, #{$background} 95%, white 5%); | ||||||
|   $card-bg-color: if($background-color == #343a40, #ffffff, color.mix(white, $background-color, 5%)); |   --ui-color-content-text: #{$text}; | ||||||
|   $card-text-color: if($text-color == #ffffff, #333333, $text-color); |    | ||||||
|   $card-footer-bg-color: if($background-color == #343a40, #f8f9fa, color.mix(white, $background-color, 10%)); |   --ui-color-icon-primary: #{$primary}; | ||||||
| 
 |   --ui-color-icon-secondary: #{$secondary}; | ||||||
|   /* UI Library specific CSS variables - HEX format */ |   --ui-color-icon-muted: color-mix(in srgb, #{$text} 60%, transparent 40%); | ||||||
|   --ui-color-primary: #{$primary-color}; |  | ||||||
|   --ui-color-secondary: #{$secondary-color}; |  | ||||||
|   --ui-color-background: #{$background-color}; |  | ||||||
|   --ui-color-text: #{$text-color}; |  | ||||||
|   --ui-color-border: #{$border-color}; |  | ||||||
|   --ui-color-hover: #{$hover-color}; |  | ||||||
| 
 |  | ||||||
|   /* Derived colors for specific UI components - HEX format */ |  | ||||||
|   --ui-color-menu-bg: #{$background-color}; |  | ||||||
|   --ui-color-menu-text: #{$text-color}; |  | ||||||
|   --ui-color-menu-hover: #{$hover-color}; |  | ||||||
|   --ui-color-menu-active: #{$menu-active-color}; |  | ||||||
|   --ui-color-menu-border: #{$border-color}; |  | ||||||
| 
 |  | ||||||
|   --ui-color-content-bg: #{$content-bg-color}; |  | ||||||
|   --ui-color-content-text: #{$text-color}; |  | ||||||
| 
 |  | ||||||
|   --ui-color-icon-primary: #{$primary-color}; |  | ||||||
|   --ui-color-icon-secondary: #{$secondary-color}; |  | ||||||
|   --ui-color-icon-muted: #{$icon-muted-color}; |  | ||||||
| 
 |  | ||||||
|   /* Card component variables - HEX format */ |  | ||||||
|   --ui-color-card-bg: #{$card-bg-color}; |  | ||||||
|   --ui-color-card-border: #{$border-color}; |  | ||||||
|   --ui-color-card-title: #{$primary-color}; |  | ||||||
|   --ui-color-card-text: #{$card-text-color}; |  | ||||||
|   --ui-color-card-footer-bg: #{$card-footer-bg-color}; |  | ||||||
| 
 |  | ||||||
|   /* Status colors - HEX format */ |  | ||||||
|   --ui-color-success: #{$success-color}; |  | ||||||
|   --ui-color-warning: #{$warning-color}; |  | ||||||
|   --ui-color-danger: #{$danger-color}; |  | ||||||
|   --ui-color-info: #{$info-color}; |  | ||||||
| 
 |  | ||||||
|   /* Contrast colors - automatically choose text or background color for best contrast */ |  | ||||||
|   --ui-color-primary-contrast: #{ui-contrast-color($primary-color, $text-color, $background-color)}; |  | ||||||
|   --ui-color-secondary-contrast: #{ui-contrast-color($secondary-color, $text-color, $background-color)}; |  | ||||||
|   --ui-color-success-contrast: #{ui-contrast-color($success-color, $text-color, $background-color)}; |  | ||||||
|   --ui-color-warning-contrast: #{ui-contrast-color($warning-color, $text-color, $background-color)}; |  | ||||||
|   --ui-color-danger-contrast: #{ui-contrast-color($danger-color, $text-color, $background-color)}; |  | ||||||
|   --ui-color-info-contrast: #{ui-contrast-color($info-color, $text-color, $background-color)}; |  | ||||||
| 
 |  | ||||||
|   /* Hard colors - darker in light themes, lighter in dark themes */ |  | ||||||
|   --ui-color-primary-hard: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $primary-color, 20%), color.mix(white, $primary-color, 20%))}; |  | ||||||
|   --ui-color-secondary-hard: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $secondary-color, 20%), color.mix(white, $secondary-color, 20%))}; |  | ||||||
|   --ui-color-success-hard: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $success-color, 20%), color.mix(white, $success-color, 20%))}; |  | ||||||
|   --ui-color-warning-hard: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $warning-color, 20%), color.mix(white, $warning-color, 20%))}; |  | ||||||
|   --ui-color-danger-hard: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $danger-color, 20%), color.mix(white, $danger-color, 20%))}; |  | ||||||
|   --ui-color-info-hard: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $info-color, 20%), color.mix(white, $info-color, 20%))}; |  | ||||||
| 
 |  | ||||||
|   /* Soft colors - lighter in light themes, darker in dark themes */ |  | ||||||
|   --ui-color-primary-soft: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $primary-color, 20%), color.mix(black, $primary-color, 20%))}; |  | ||||||
|   --ui-color-secondary-soft: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $secondary-color, 20%), color.mix(black, $secondary-color, 20%))}; |  | ||||||
|   --ui-color-success-soft: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $success-color, 20%), color.mix(black, $success-color, 20%))}; |  | ||||||
|   --ui-color-warning-soft: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $warning-color, 20%), color.mix(black, $warning-color, 20%))}; |  | ||||||
|   --ui-color-danger-soft: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $danger-color, 20%), color.mix(black, $danger-color, 20%))}; |  | ||||||
|   --ui-color-info-soft: #{if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $info-color, 20%), color.mix(black, $info-color, 20%))}; |  | ||||||
| 
 |  | ||||||
|   /* RGB versions for rgba() usage - Basic colors */ |  | ||||||
|   --ui-color-primary-rgb: #{color.channel($primary-color, "red")}, #{color.channel($primary-color, "green")}, #{color.channel($primary-color, "blue")}; |  | ||||||
|   --ui-color-secondary-rgb: #{color.channel($secondary-color, "red")}, #{color.channel($secondary-color, "green")}, #{color.channel($secondary-color, "blue")}; |  | ||||||
|   --ui-color-background-rgb: #{color.channel($background-color, "red")}, #{color.channel($background-color, "green")}, #{color.channel($background-color, "blue")}; |  | ||||||
|   --ui-color-text-rgb: #{color.channel($text-color, "red")}, #{color.channel($text-color, "green")}, #{color.channel($text-color, "blue")}; |  | ||||||
|   --ui-color-border-rgb: #{color.channel($border-color, "red")}, #{color.channel($border-color, "green")}, #{color.channel($border-color, "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Menu colors RGB versions */ |  | ||||||
|   --ui-color-menu-bg-rgb: #{color.channel($background-color, "red")}, #{color.channel($background-color, "green")}, #{color.channel($background-color, "blue")}; |  | ||||||
|   --ui-color-menu-text-rgb: #{color.channel($text-color, "red")}, #{color.channel($text-color, "green")}, #{color.channel($text-color, "blue")}; |  | ||||||
|   --ui-color-menu-border-rgb: #{color.channel($border-color, "red")}, #{color.channel($border-color, "green")}, #{color.channel($border-color, "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Content colors RGB versions */ |  | ||||||
|   --ui-color-content-text-rgb: #{color.channel($text-color, "red")}, #{color.channel($text-color, "green")}, #{color.channel($text-color, "blue")}; |  | ||||||
|   --ui-color-content-bg-rgb: #{color.channel($content-bg-color, "red")}, #{color.channel($content-bg-color, "green")}, #{color.channel($content-bg-color, "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Icon colors RGB versions */ |  | ||||||
|   --ui-color-icon-primary-rgb: #{color.channel($primary-color, "red")}, #{color.channel($primary-color, "green")}, #{color.channel($primary-color, "blue")}; |  | ||||||
|   --ui-color-icon-secondary-rgb: #{color.channel($secondary-color, "red")}, #{color.channel($secondary-color, "green")}, #{color.channel($secondary-color, "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Menu active RGB version */ |  | ||||||
|   --ui-color-menu-active-rgb: #{color.channel($menu-active-color, "red")}, #{color.channel($menu-active-color, "green")}, #{color.channel($menu-active-color, "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Card colors RGB versions */ |  | ||||||
|   --ui-color-card-border-rgb: #{color.channel($border-color, "red")}, #{color.channel($border-color, "green")}, #{color.channel($border-color, "blue")}; |  | ||||||
|   --ui-color-card-title-rgb: #{color.channel($primary-color, "red")}, #{color.channel($primary-color, "green")}, #{color.channel($primary-color, "blue")}; |  | ||||||
|   --ui-color-card-bg-rgb: #{color.channel($card-bg-color, "red")}, #{color.channel($card-bg-color, "green")}, #{color.channel($card-bg-color, "blue")}; |  | ||||||
|   --ui-color-card-text-rgb: #{color.channel($card-text-color, "red")}, #{color.channel($card-text-color, "green")}, #{color.channel($card-text-color, "blue")}; |  | ||||||
|   --ui-color-card-footer-bg-rgb: #{color.channel($card-footer-bg-color, "red")}, #{color.channel($card-footer-bg-color, "green")}, #{color.channel($card-footer-bg-color, "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Status colors RGB versions */ |  | ||||||
|   --ui-color-success-rgb: #{color.channel($success-color, "red")}, #{color.channel($success-color, "green")}, #{color.channel($success-color, "blue")}; |  | ||||||
|   --ui-color-warning-rgb: #{color.channel($warning-color, "red")}, #{color.channel($warning-color, "green")}, #{color.channel($warning-color, "blue")}; |  | ||||||
|   --ui-color-danger-rgb: #{color.channel($danger-color, "red")}, #{color.channel($danger-color, "green")}, #{color.channel($danger-color, "blue")}; |  | ||||||
|   --ui-color-info-rgb: #{color.channel($info-color, "red")}, #{color.channel($info-color, "green")}, #{color.channel($info-color, "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Contrast colors RGB versions */ |  | ||||||
|   --ui-color-primary-contrast-rgb: #{color.channel(ui-contrast-color($primary-color, $text-color, $background-color), "red")}, #{color.channel(ui-contrast-color($primary-color, $text-color, $background-color), "green")}, #{color.channel(ui-contrast-color($primary-color, $text-color, $background-color), "blue")}; |  | ||||||
|   --ui-color-secondary-contrast-rgb: #{color.channel(ui-contrast-color($secondary-color, $text-color, $background-color), "red")}, #{color.channel(ui-contrast-color($secondary-color, $text-color, $background-color), "green")}, #{color.channel(ui-contrast-color($secondary-color, $text-color, $background-color), "blue")}; |  | ||||||
|   --ui-color-success-contrast-rgb: #{color.channel(ui-contrast-color($success-color, $text-color, $background-color), "red")}, #{color.channel(ui-contrast-color($success-color, $text-color, $background-color), "green")}, #{color.channel(ui-contrast-color($success-color, $text-color, $background-color), "blue")}; |  | ||||||
|   --ui-color-warning-contrast-rgb: #{color.channel(ui-contrast-color($warning-color, $text-color, $background-color), "red")}, #{color.channel(ui-contrast-color($warning-color, $text-color, $background-color), "green")}, #{color.channel(ui-contrast-color($warning-color, $text-color, $background-color), "blue")}; |  | ||||||
|   --ui-color-danger-contrast-rgb: #{color.channel(ui-contrast-color($danger-color, $text-color, $background-color), "red")}, #{color.channel(ui-contrast-color($danger-color, $text-color, $background-color), "green")}, #{color.channel(ui-contrast-color($danger-color, $text-color, $background-color), "blue")}; |  | ||||||
|   --ui-color-info-contrast-rgb: #{color.channel(ui-contrast-color($info-color, $text-color, $background-color), "red")}, #{color.channel(ui-contrast-color($info-color, $text-color, $background-color), "green")}, #{color.channel(ui-contrast-color($info-color, $text-color, $background-color), "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Hard colors RGB versions */ |  | ||||||
|   --ui-color-primary-hard-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $primary-color, 20%), color.mix(white, $primary-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $primary-color, 20%), color.mix(white, $primary-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $primary-color, 20%), color.mix(white, $primary-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-secondary-hard-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $secondary-color, 20%), color.mix(white, $secondary-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $secondary-color, 20%), color.mix(white, $secondary-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $secondary-color, 20%), color.mix(white, $secondary-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-success-hard-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $success-color, 20%), color.mix(white, $success-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $success-color, 20%), color.mix(white, $success-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $success-color, 20%), color.mix(white, $success-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-warning-hard-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $warning-color, 20%), color.mix(white, $warning-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $warning-color, 20%), color.mix(white, $warning-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $warning-color, 20%), color.mix(white, $warning-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-danger-hard-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $danger-color, 20%), color.mix(white, $danger-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $danger-color, 20%), color.mix(white, $danger-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $danger-color, 20%), color.mix(white, $danger-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-info-hard-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $info-color, 20%), color.mix(white, $info-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $info-color, 20%), color.mix(white, $info-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(black, $info-color, 20%), color.mix(white, $info-color, 20%)), "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Soft colors RGB versions */ |  | ||||||
|   --ui-color-primary-soft-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $primary-color, 20%), color.mix(black, $primary-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $primary-color, 20%), color.mix(black, $primary-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $primary-color, 20%), color.mix(black, $primary-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-secondary-soft-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $secondary-color, 20%), color.mix(black, $secondary-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $secondary-color, 20%), color.mix(black, $secondary-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $secondary-color, 20%), color.mix(black, $secondary-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-success-soft-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $success-color, 20%), color.mix(black, $success-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $success-color, 20%), color.mix(black, $success-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $success-color, 20%), color.mix(black, $success-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-warning-soft-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $warning-color, 20%), color.mix(black, $warning-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $warning-color, 20%), color.mix(black, $warning-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $warning-color, 20%), color.mix(black, $warning-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-danger-soft-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $danger-color, 20%), color.mix(black, $danger-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $danger-color, 20%), color.mix(black, $danger-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $danger-color, 20%), color.mix(black, $danger-color, 20%)), "blue")}; |  | ||||||
|   --ui-color-info-soft-rgb: #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $info-color, 20%), color.mix(black, $info-color, 20%)), "red")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $info-color, 20%), color.mix(black, $info-color, 20%)), "green")}, #{color.channel(if(color.channel($background-color, "lightness", $space: hsl) > 50%, color.mix(white, $info-color, 20%), color.mix(black, $info-color, 20%)), "blue")}; |  | ||||||
| 
 |  | ||||||
|   /* Note: hover and icon-muted use rgba(), so they already have alpha transparency built-in */ |  | ||||||
|   /* For hover effects, use the HEX version: var(--ui-color-hover) */ |  | ||||||
|   /* For icon-muted, use the HEX version: var(--ui-color-icon-muted) */ |  | ||||||
| 
 |  | ||||||
|   /* Card spacing and layout variables */ |  | ||||||
|   --ui-spacing-xs: 4px; |  | ||||||
|   --ui-spacing-sm: 8px; |  | ||||||
|   --ui-spacing-md: 16px; |  | ||||||
|   --ui-spacing-lg: 24px; |  | ||||||
|   --ui-border-radius: 8px; |  | ||||||
|   --ui-font-size-lg: 18px; |  | ||||||
|   --ui-font-weight-semibold: 600; |  | ||||||
|   --ui-card-header-min-height: 40px; |  | ||||||
| 
 |  | ||||||
|   /* Card shadows */ |  | ||||||
|   --ui-shadow-card: 0 2px 4px rgba(0, 0, 0, 0.1); |  | ||||||
|   --ui-shadow-card-hover: 0 4px 8px rgba(0, 0, 0, 0.15); |  | ||||||
| 
 |  | ||||||
|   /* Input component variables */ |  | ||||||
|   --ui-color-input-bg: #{color-mix(in srgb, #{$background} 95%, white 5%)}; |  | ||||||
|   --ui-color-input-text: #{color-mix(in srgb, #{$text} 95%, white 5%)}; |  | ||||||
|   --ui-color-input-placeholder: #{color-mix(in srgb, #{$primary} 50%, transparent 50%)}; |  | ||||||
|   --ui-color-input-label-focus: #{color-mix(in srgb, #{$primary} 95%, white 5%)}; |  | ||||||
|   --ui-color-input-label-invalid: #dc3545; |  | ||||||
| 
 |  | ||||||
|   /* Input box-shadow borders and effects */ |  | ||||||
|   --ui-shadow-input-border: 0 0 0 0px #{$primary}, 0 0 0 0px #{if($background == #343a40, #ffffff, color-mix(in srgb, #{$background} 95%, white 5%))}, inset 0 0 0 1px #{$border}; |  | ||||||
|   --ui-shadow-input-focus: 0 0 0 0px #{$primary}, 0 0 0 0px #{if($background == #343a40, #ffffff, color-mix(in srgb, #{$background} 95%, white 5%))}, inset 0 0 0 2px #{$primary}; |  | ||||||
|   --ui-shadow-input-active: 0 0 0 10px #{$primary}, 0 0 0 9px #{if($background == #343a40, #ffffff, color-mix(in srgb, #{$background} 95%, white 5%))}; |  | ||||||
|   --ui-shadow-input-invalid: 0 0 0 0px #{$primary}, 0 0 0 0px #{if($background == #343a40, #ffffff, color-mix(in srgb, #{$background} 95%, white 5%))}, inset 0 0 0 2px #dc3545; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | @ -219,11 +50,11 @@ | ||||||
|   background: var(--ui-color-menu-bg); |   background: var(--ui-color-menu-bg); | ||||||
|   color: var(--ui-color-menu-text); |   color: var(--ui-color-menu-text); | ||||||
|   border-right: 1px solid var(--ui-color-menu-border); |   border-right: 1px solid var(--ui-color-menu-border); | ||||||
| 
 |    | ||||||
|   &.active { |   &.active { | ||||||
|     background: var(--ui-color-menu-active); |     background: var(--ui-color-menu-active); | ||||||
|   } |   } | ||||||
| 
 |    | ||||||
|   &.focus, |   &.focus, | ||||||
|   &:active, |   &:active, | ||||||
|   &:hover { |   &:hover { | ||||||
|  | @ -252,31 +83,4 @@ | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * Mixin that applies theme-aware styles to card components |  | ||||||
|  */ |  | ||||||
| @mixin ui-card-theme() { |  | ||||||
|   background: var(--ui-color-card-bg); |  | ||||||
|   border: 1px solid var(--ui-color-card-border); |  | ||||||
|   border-radius: var(--ui-border-radius); |  | ||||||
|   box-shadow: var(--ui-shadow-card); |  | ||||||
| 
 |  | ||||||
|   &:hover { |  | ||||||
|     box-shadow: var(--ui-shadow-card-hover); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   .ui-card-title { |  | ||||||
|     color: var(--ui-color-card-title); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   .ui-card-content { |  | ||||||
|     color: var(--ui-color-card-text); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   .ui-card-footer { |  | ||||||
|     background: var(--ui-color-card-footer-bg); |  | ||||||
|     border-top-color: var(--ui-color-card-border); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,150 +0,0 @@ | ||||||
| /* Examples of using ui-contrast-color function in UI Library */ |  | ||||||
| 
 |  | ||||||
| @use 'sass:color'; |  | ||||||
| @use 'theme-mixins' as theme; |  | ||||||
| 
 |  | ||||||
| /* Example 1: Basic usage with predefined colors */ |  | ||||||
| .example-button { |  | ||||||
|   $button-bg: #007bff; // Blue background |  | ||||||
|   $light-text: #ffffff; // White text for dark backgrounds |  | ||||||
|   $dark-text: #333333;  // Dark text for light backgrounds |  | ||||||
|    |  | ||||||
|   background-color: $button-bg; |  | ||||||
|   color: theme.ui-contrast-color($button-bg, $light-text, $dark-text); |  | ||||||
|   // Result: white text because blue is darker than 50% lightness |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Example 2: Using with theme variables */ |  | ||||||
| .example-card { |  | ||||||
|   $card-bg: var(--ui-color-primary); |  | ||||||
|    |  | ||||||
|   // In SCSS context, you need to use actual color values |  | ||||||
|   $primary-color: #2c3e50; // This would come from your theme |  | ||||||
|   $text-light: #ffffff; |  | ||||||
|   $text-dark: #333333; |  | ||||||
|    |  | ||||||
|   background-color: $primary-color; |  | ||||||
|   color: theme.ui-contrast-color($primary-color, $text-light, $text-dark); |  | ||||||
|   // Result: white text because #2c3e50 is dark |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Example 3: Status colors with automatic contrast */ |  | ||||||
| .status-examples { |  | ||||||
|   .success-badge { |  | ||||||
|     $success: #28a745; // Green |  | ||||||
|     $light: #ffffff; |  | ||||||
|     $dark: #000000; |  | ||||||
|      |  | ||||||
|     background-color: $success; |  | ||||||
|     color: theme.ui-contrast-color($success, $light, $dark); |  | ||||||
|     // Result: white text because green is relatively dark |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   .warning-badge { |  | ||||||
|     $warning: #ffc107; // Yellow |  | ||||||
|     $light: #ffffff; |  | ||||||
|     $dark: #000000; |  | ||||||
|      |  | ||||||
|     background-color: $warning; |  | ||||||
|     color: theme.ui-contrast-color($warning, $light, $dark); |  | ||||||
|     // Result: black text because yellow is light (>50% lightness) |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   .danger-badge { |  | ||||||
|     $danger: #dc3545; // Red |  | ||||||
|     $light: #ffffff; |  | ||||||
|     $dark: #000000; |  | ||||||
|      |  | ||||||
|     background-color: $danger; |  | ||||||
|     color: theme.ui-contrast-color($danger, $light, $dark); |  | ||||||
|     // Result: white text because red is dark |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   .info-badge { |  | ||||||
|     $info: #17a2b8; // Cyan |  | ||||||
|     $light: #ffffff; |  | ||||||
|     $dark: #000000; |  | ||||||
|      |  | ||||||
|     background-color: $info; |  | ||||||
|     color: theme.ui-contrast-color($info, $light, $dark); |  | ||||||
|     // Result: white text because cyan is dark |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Example 4: Using with different light/dark colors based on theme */ |  | ||||||
| .theme-aware-component { |  | ||||||
|   // For light theme |  | ||||||
|   $bg-light: #f8f9fa; |  | ||||||
|   $text-light: #333333; |  | ||||||
|   $bg-dark: #343a40; |  | ||||||
|   $text-dark: #ffffff; |  | ||||||
|    |  | ||||||
|   // Component background |  | ||||||
|   $component-bg: #007bff; |  | ||||||
|    |  | ||||||
|   // In light theme context |  | ||||||
|   &.light-theme { |  | ||||||
|     background-color: $component-bg; |  | ||||||
|     color: theme.ui-contrast-color($component-bg, $text-dark, $text-light); |  | ||||||
|     // For light theme: if bg is light, use dark text; if bg is dark, use light text |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   // In dark theme context |  | ||||||
|   &.dark-theme { |  | ||||||
|     background-color: $component-bg; |  | ||||||
|     color: theme.ui-contrast-color($component-bg, $text-dark, $bg-light); |  | ||||||
|     // For dark theme: if bg is light, use light bg color; if bg is dark, use dark text |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Example 5: Dynamic contrast with CSS variables (conceptual) */ |  | ||||||
| /* |  | ||||||
| Note: The ui-contrast-color function works at compile time with SCSS variables. |  | ||||||
| For runtime CSS variables, you would use the pre-computed contrast variables: |  | ||||||
| 
 |  | ||||||
| .dynamic-component { |  | ||||||
|   background-color: var(--ui-color-primary); |  | ||||||
|   color: var(--ui-color-primary-contrast); |  | ||||||
|    |  | ||||||
|   // Or with RGB for transparency: |  | ||||||
|   background-color: rgba(var(--ui-color-primary-rgb), 0.8); |  | ||||||
|   color: var(--ui-color-primary-contrast); |  | ||||||
| } |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /* Example 6: Complex usage with mixed colors */ |  | ||||||
| .complex-example { |  | ||||||
|   $base-colors: ( |  | ||||||
|     'primary': #2c3e50, |  | ||||||
|     'secondary': #6c757d, |  | ||||||
|     'light': #f8f9fa, |  | ||||||
|     'dark': #343a40 |  | ||||||
|   ); |  | ||||||
|    |  | ||||||
|   $text-light: #ffffff; |  | ||||||
|   $text-dark: #333333; |  | ||||||
|    |  | ||||||
|   @each $name, $color in $base-colors { |  | ||||||
|     .#{$name}-variant { |  | ||||||
|       background-color: $color; |  | ||||||
|       color: theme.ui-contrast-color($color, $text-light, $text-dark); |  | ||||||
|        |  | ||||||
|       // Border with semi-transparent contrast color |  | ||||||
|       $contrast: theme.ui-contrast-color($color, $text-light, $text-dark); |  | ||||||
|       border: 2px solid rgba($contrast, 0.3); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* How the function works: |  | ||||||
|  *  |  | ||||||
|  * ui-contrast-color($base-color, $light-color, $dark-color) |  | ||||||
|  *  |  | ||||||
|  * 1. Calculates lightness of $base-color using HSL color space |  | ||||||
|  * 2. If lightness > 50% (closer to white): returns $dark-color |  | ||||||
|  * 3. If lightness ≤ 50% (closer to black): returns $light-color |  | ||||||
|  *  |  | ||||||
|  * This ensures optimal contrast for readability: |  | ||||||
|  * - Light backgrounds get dark text |  | ||||||
|  * - Dark backgrounds get light text |  | ||||||
|  */ |  | ||||||
|  | @ -17,6 +17,3 @@ export * from './lib/modules/form/components/input/input.component'; | ||||||
| // Components
 | // Components
 | ||||||
| export * from './lib/components/button/button.component'; | export * from './lib/components/button/button.component'; | ||||||
| export * from './lib/components/card/card.component'; | export * from './lib/components/card/card.component'; | ||||||
| export * from './lib/components/card/card-title/card-title.component'; |  | ||||||
| export * from './lib/components/card/card-menu/card-menu.component'; |  | ||||||
| export * from './lib/components/card/card-footer/card-footer.component'; |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue