Refactor inline styles to semantic CSS classes

- Removed all inline style assignments from RatingWidget.ts
- Added semantic CSS classes for symbol states (rated, unrated, normal)
- Implemented clean CSS class management with applySymbolState() method
- Updated styles.css with proper semantic class definitions
This commit is contained in:
Filip Noetzel 2025-06-10 09:17:41 +02:00
parent f163bf7e60
commit cc7ea8ead9
2 changed files with 55 additions and 26 deletions

View file

@ -49,8 +49,7 @@ export class RatingWidget extends WidgetType {
for (let i = 0; i < displaySymbolCount; i++) {
const span = document.createElement('span');
span.textContent = this.symbolSet.full;
span.style.cursor = 'pointer';
span.style.position = 'relative';
span.className = 'interactive-rating-symbol';
span.setAttribute('data-symbol-index', i.toString());
// Add click handler with full-only validation
@ -156,6 +155,17 @@ export class RatingWidget extends WidgetType {
}
}
/**
* Apply the appropriate CSS class to a symbol based on its state
*/
private applySymbolState(span: HTMLElement, state: 'rated' | 'unrated' | 'normal'): void {
// Remove all state classes
span.classList.remove('interactive-rating-symbol--rated', 'interactive-rating-symbol--unrated', 'interactive-rating-symbol--normal');
// Add the appropriate state class
span.classList.add(`interactive-rating-symbol--${state}`);
}
/**
* Preview rating with proper half-symbol rendering and full-only symbol support
*/
@ -175,29 +185,24 @@ export class RatingWidget extends WidgetType {
// For full-only symbols: show full symbol for rated, grey for unrated
span.textContent = this.symbolSet.full;
if (symbolRating <= newRating) {
span.style.opacity = '1';
span.style.filter = 'none';
this.applySymbolState(span, 'rated');
} else {
span.style.opacity = '0.5';
span.style.filter = 'grayscale(100%)';
this.applySymbolState(span, 'unrated');
}
} else {
// Regular symbol behavior
if (symbolRating <= newRating) {
// Full symbol
span.textContent = this.symbolSet.full;
span.style.opacity = '1';
span.style.filter = 'none';
this.applySymbolState(span, 'normal');
} else if (this.symbolSet.half && halfRating <= newRating && halfRating > newRating - 0.5) {
// Half symbol
span.textContent = this.symbolSet.half;
span.style.opacity = '1';
span.style.filter = 'none';
this.applySymbolState(span, 'normal');
} else {
// Empty symbol
span.textContent = this.symbolSet.empty;
span.style.opacity = '1';
span.style.filter = 'none';
this.applySymbolState(span, 'normal');
}
}
});
@ -250,11 +255,9 @@ export class RatingWidget extends WidgetType {
// For full-only symbols: show full symbol for rated, grey for unrated
span.textContent = this.symbolSet.full;
if (symbolRating <= rating) {
span.style.opacity = '1';
span.style.filter = 'none';
this.applySymbolState(span, 'rated');
} else {
span.style.opacity = '0.5';
span.style.filter = 'grayscale(100%)';
this.applySymbolState(span, 'unrated');
}
} else {
// Regular symbol behavior
@ -268,9 +271,8 @@ export class RatingWidget extends WidgetType {
// Empty symbol
span.textContent = this.symbolSet.empty;
}
// Reset any styling for regular symbols
span.style.opacity = '1';
span.style.filter = 'none';
// Apply normal state for regular symbols
this.applySymbolState(span, 'normal');
}
});

View file

@ -38,6 +38,32 @@
color: inherit;
}
/* Base symbol styling */
.interactive-rating-symbol {
position: relative;
cursor: pointer;
display: inline-block;
transition: opacity 0.2s ease, filter 0.2s ease;
}
/* Active/rated symbol state */
.interactive-rating-symbol--rated {
opacity: 1;
filter: none;
}
/* Inactive/unrated symbol state (for full-only symbols) */
.interactive-rating-symbol--unrated {
opacity: 0.5;
filter: grayscale(100%);
}
/* Normal symbol state (for regular symbols) */
.interactive-rating-symbol--normal {
opacity: 1;
filter: none;
}
/* Individual symbol spans in editor widget with half-symbol support */
.interactive-rating-editor-widget .interactive-rating-symbols span {
position: relative;
@ -80,14 +106,14 @@
transition: opacity 0.2s ease, filter 0.2s ease;
}
/* Ensure full-only unrated symbols are properly grayed out */
.interactive-rating-editor-widget[data-full-only="true"] .interactive-rating-symbols span[style*="opacity: 0.5"] {
/* Ensure full-only unrated symbols are properly grayed out - using class-based approach */
.interactive-rating-editor-widget[data-full-only="true"] .interactive-rating-symbol--unrated {
opacity: 0.5 !important;
filter: grayscale(100%) !important;
}
/* Ensure full-only rated symbols are fully visible */
.interactive-rating-editor-widget[data-full-only="true"] .interactive-rating-symbols span[style*="opacity: 1"] {
/* Ensure full-only rated symbols are fully visible - using class-based approach */
.interactive-rating-editor-widget[data-full-only="true"] .interactive-rating-symbol--rated {
opacity: 1 !important;
filter: none !important;
}
@ -120,8 +146,8 @@
/* No visual elements */
}
/* Enhanced contrast for full-only symbols */
.interactive-rating-editor-widget[data-full-only="true"] .interactive-rating-symbols span[style*="opacity: 0.5"] {
/* Enhanced contrast for full-only symbols using class-based approach */
.interactive-rating-editor-widget[data-full-only="true"] .interactive-rating-symbol--unrated {
opacity: 0.3 !important;
filter: grayscale(100%) contrast(0.7) !important;
}
@ -132,7 +158,8 @@
.interactive-rating-editor-widget,
.interactive-rating-editor-widget .interactive-rating-symbols span,
.interactive-rating-editor-widget .interactive-rating-symbols span::before,
.interactive-rating-editor-widget .interactive-rating-symbols span::after {
.interactive-rating-editor-widget .interactive-rating-symbols span::after,
.interactive-rating-symbol {
transition: none;
}
}