2.1 #Components.Accordion Accordion
Rozwijane sekcje FAQ. Gładka animacja max-height, rotacja ikony chevron.
JS: src/js/modules/accordion.js. Requires data-accordion on container.
Deep-link: strona.html#id-itemu → scroll + auto-open.
Markup: accordion.html
<div style="max-width: 1260px; margin: 0 auto; padding: 40px 0;">
<div class="accordion" data-accordion>
<div class="accordion__item">
<button class="accordion__header" type="button">
<span class="accordion__title">Kto może korzystać ze strony?</span>
<svg class="accordion__icon" xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.00863 20.2932C3.62384 20.6851 3.62337 21.321 4.00757 21.7136C4.38568 22.0999 4.99545 22.1065 5.38147 21.733L5.39997 21.7146L15.5144 11.4124L25.5992 21.6939C25.9777 22.0798 26.5874 22.0858 26.9731 21.7119L26.9916 21.6935C27.3698 21.3074 27.3757 20.6853 27.0092 20.292L26.9911 20.2731L16.2108 9.28225C15.8325 8.89664 15.2233 8.89038 14.8376 9.26357L14.8191 9.28192L4.00863 20.2932Z" fill="currentColor"/>
</svg>
</button>
<div class="accordion__body">
<div class="accordion__content">
Strona <strong>winston.pl</strong> jest przeznaczona wyłącznie dla osób pełnoletnich (18+). Podczas rejestracji weryfikujemy wiek za pomocą bankowości elektronicznej.
</div>
</div>
</div>
<div class="accordion__item">
<button class="accordion__header" type="button">
<span class="accordion__title">Jak mogę zmienić hasło?</span>
<svg class="accordion__icon" xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.00863 20.2932C3.62384 20.6851 3.62337 21.321 4.00757 21.7136C4.38568 22.0999 4.99545 22.1065 5.38147 21.733L5.39997 21.7146L15.5144 11.4124L25.5992 21.6939C25.9777 22.0798 26.5874 22.0858 26.9731 21.7119L26.9916 21.6935C27.3698 21.3074 27.3757 20.6853 27.0092 20.292L26.9911 20.2731L16.2108 9.28225C15.8325 8.89664 15.2233 8.89038 14.8376 9.26357L14.8191 9.28192L4.00863 20.2932Z" fill="currentColor"/>
</svg>
</button>
<div class="accordion__body">
<div class="accordion__content">
Hasło zresetujesz w <a href="#">ustawieniach profilu</a>. Możesz to zrobić również na stronie logowania – kliknij „<strong>Nie pamiętasz hasła?</strong>" i podaj swój adres e-mail.
</div>
</div>
</div>
<div class="accordion__item">
<button class="accordion__header" type="button">
<span class="accordion__title">Jak mogę zaktualizować dane w profilu?</span>
<svg class="accordion__icon" xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.00863 20.2932C3.62384 20.6851 3.62337 21.321 4.00757 21.7136C4.38568 22.0999 4.99545 22.1065 5.38147 21.733L5.39997 21.7146L15.5144 11.4124L25.5992 21.6939C25.9777 22.0798 26.5874 22.0858 26.9731 21.7119L26.9916 21.6935C27.3698 21.3074 27.3757 20.6853 27.0092 20.292L26.9911 20.2731L16.2108 9.28225C15.8325 8.89664 15.2233 8.89038 14.8376 9.26357L14.8191 9.28192L4.00863 20.2932Z" fill="currentColor"/>
</svg>
</button>
<div class="accordion__body">
<div class="accordion__content">
W każdej chwili możesz zmienić swoje dane osobowe. Aby to zrobić, ponownie zweryfikuj swoją tożsamość poprzez bankowość elektroniczną lub w razie potrzeby skontaktuj się z nami.
</div>
</div>
</div>
</div>
</div>
src/scss/components/_accordion.scss, line 1
2.1.1 #Components.Accordion.Single Accordion — Tryb single
Dodaj data-accordion-single na kontenerze — tylko jeden otwarty na raz.
Markup: accordion--single.html
<div style="max-width: 1260px; margin: 0 auto; padding: 40px 0;">
<div class="accordion" data-accordion data-accordion-single>
<div class="accordion__item">
<button class="accordion__header" type="button">
<span class="accordion__title">Jak usunąć konto?</span>
<svg class="accordion__icon" xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.00863 20.2932C3.62384 20.6851 3.62337 21.321 4.00757 21.7136C4.38568 22.0999 4.99545 22.1065 5.38147 21.733L5.39997 21.7146L15.5144 11.4124L25.5992 21.6939C25.9777 22.0798 26.5874 22.0858 26.9731 21.7119L26.9916 21.6935C27.3698 21.3074 27.3757 20.6853 27.0092 20.292L26.9911 20.2731L16.2108 9.28225C15.8325 8.89664 15.2233 8.89038 14.8376 9.26357L14.8191 9.28192L4.00863 20.2932Z" fill="currentColor"/>
</svg>
</button>
<div class="accordion__body">
<div class="accordion__content">
Konto usuniesz w <a href="#">ustawieniach profilu</a>. <strong>Pamiętaj: usunięcie konta jest nieodwracalne</strong>. Stracisz dostęp do serwisu, zgromadzonych punktów i nagród.
</div>
</div>
</div>
<div class="accordion__item">
<button class="accordion__header" type="button">
<span class="accordion__title">Czy mogę mieć więcej niż jedno konto?</span>
<svg class="accordion__icon" xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.00863 20.2932C3.62384 20.6851 3.62337 21.321 4.00757 21.7136C4.38568 22.0999 4.99545 22.1065 5.38147 21.733L5.39997 21.7146L15.5144 11.4124L25.5992 21.6939C25.9777 22.0798 26.5874 22.0858 26.9731 21.7119L26.9916 21.6935C27.3698 21.3074 27.3757 20.6853 27.0092 20.292L26.9911 20.2731L16.2108 9.28225C15.8325 8.89664 15.2233 8.89038 14.8376 9.26357L14.8191 9.28192L4.00863 20.2932Z" fill="currentColor"/>
</svg>
</button>
<div class="accordion__body">
<div class="accordion__content">
Nie. Każde konto jest przypisane do danych osobowych konkretnego użytkownika.
</div>
</div>
</div>
</div>
</div>
src/scss/components/_accordion.scss, line 11
2.5 #Components.CardFull Card Full
Full-width karta promocyjna z tłem (image/video), overlay gradient, tytuł + opis + CTA. Warianty: --video, --game. Hover: zoom na obrazie (desktop).
Komponent card-full wymaga pełnego layoutu z obrazami/wideo. Podgląd w kontekście strony: nowosci.html
Komponent card-full wymaga pełnego layoutu z obrazami/wideo. Podgląd w kontekście strony: nowosci.html
Markup: card-full.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent card-full wymaga pełnego layoutu z obrazami/wideo. Podgląd w kontekście strony: <a href="../nowosci.html">nowosci.html</a></p>
src/scss/components/_card-full.scss, line 1
2.6 #Components.Cards Cards
Bazowa karta z obrazem, tytułem i opisem. Border-radius, hover shadow + translateY.
Card Title
Opis karty z przykładowym tekstem.
Card Title 2
Kolejna karta w gridzie.
Markup: cards.html
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px; max-width: 900px;">
<div class="card">
<div class="card-body">
<h4 class="card-title">Card Title</h4>
<p class="card-text">Opis karty z przykładowym tekstem.</p>
</div>
</div>
<div class="card">
<div class="card-body">
<h4 class="card-title">Card Title 2</h4>
<p class="card-text">Kolejna karta w gridzie.</p>
</div>
</div>
</div>
src/scss/components/_cards.scss, line 1
2.7 #Components.Checkbox Checkbox
Niestandardowy checkbox z ukrytym natywnym inputem i wizualnym indicatorem. CSS-only checkmark (pseudo-element). Stany: checked, disabled, error, blocked, focus.
Markup: checkbox.html
<div style="display: flex; gap: 24px; flex-wrap: wrap;">
<!-- Default -->
<label class="checkbox">
<input type="checkbox" class="checkbox__control" />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Default</span>
</label>
<!-- Disabled -->
<label class="checkbox">
<input type="checkbox" class="checkbox__control" disabled />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Disabled</span>
</label>
<!-- Error -->
<label class="checkbox checkbox--error">
<input type="checkbox" class="checkbox__control" />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Error</span>
</label>
<!-- Selected -->
<label class="checkbox">
<input type="checkbox" class="checkbox__control" checked />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Selected</span>
</label>
<!-- Blocked -->
<label class="checkbox checkbox--blocked">
<input type="checkbox" class="checkbox__control" checked />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Blocked</span>
</label>
<!-- Focus -->
<label class="checkbox">
<input type="checkbox" class="checkbox__control" />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Focus (Tab)</span>
</label>
</div>
src/scss/components/_checkbox.scss, line 1
2.7.1 #Components.Checkbox.Group Checkbox — Grupa
Przykład użycia wielu checkboxów w formularzu.
Markup: checkbox--group.html
<div style="display: flex; flex-direction: column; align-items: flex-start; gap: 12px;">
<label class="checkbox">
<input type="checkbox" class="checkbox__control" checked />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Regulamin serwisu</span>
</label>
<label class="checkbox">
<input type="checkbox" class="checkbox__control" />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Newsletter</span>
</label>
<label class="checkbox">
<input type="checkbox" class="checkbox__control" />
<span class="checkbox__indicator"></span>
<span class="checkbox__label">Powiadomienia SMS</span>
</label>
</div>
src/scss/components/_checkbox.scss, line 13
2.8 #Components.CodeInput Code Input
CTA sekcja "Wprowadź kod z paczki" z tłem (image), overlay gradient, tytuł + opis + formularz (text-input + button).
Komponent code-input wymaga pełnego layoutu z tłem. Podgląd: win-club-dodawaj-kody.html
Markup: code-input.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent code-input wymaga pełnego layoutu z tłem. Podgląd: <a href="../win-club-dodawaj-kody.html">win-club-dodawaj-kody.html</a></p>
src/scss/components/_code-input.scss, line 1
2.9 #Components.Configurator Configurator
Multi-step quiz dopasowania produktu. 3 kroki: Format → Smak → Zdjęcia,
loader (spinner), wynik z rekomendacją. JS: src/js/modules/configurator.js.
Zawiera progress bar, tile grid (3- i 4-kolumnowy), checkboxy na kafelkach,
counter (Wybrano: 0/3), loader ze spinnerem i krok wynikowy z CTA.
Komponent interaktywny z wieloma krokami. Podgląd na żywo: dopasuj-produkt.html
Markup: configurator.html
<!-- Configurator: Informacja -->
<p style="color:#666;font-size:14px;">
Komponent interaktywny z wieloma krokami.
Podgląd na żywo: <a href="/dopasuj-produkt.html" target="_blank">dopasuj-produkt.html</a>
</p>
src/scss/components/_configurator.scss, line 1
2.10 #Components.Dialog Dialog
Okno modalne (formularz edycji) z backdrop, przyciskiem zamknięcia (X),
treścią formularza (body) i przyciskami akcji (submit).
Trigger: data-dialog-open="dialog-xyz". JS: src/js/modules/dialog.js.
Stany: .is-active, .is-dismissing. Scroll lock: .dialog-open na body.
Markup: dialog.html
<!-- Dialog: statyczny podgląd (bez backdrop) -->
<div style="position:relative; background:#f5f5f1; padding:20px; border-radius:8px; max-width:400px;">
<div class="dialog" style="position:relative; transform:none; opacity:1; max-width:100%;">
<button class="dialog__close" aria-label="Zamknij"></button>
<div class="dialog__body">
<label class="text-input__label">Imię</label>
<div class="text-input__body">
<input class="text-input__field" value="Jan" placeholder="Wpisz imię" />
</div>
</div>
<div class="dialog__actions">
<button class="btn btn-positive">Zapisz</button>
</div>
</div>
</div>
src/scss/components/_dialog.scss, line 1
2.11 #Components.DropdownProfile Dropdown Profile
Panel profilu użytkownika rozwijany z navbara. Zawiera nagłówek z tytułem,
kartę punktów (wartość + obrazek + data wygaśnięcia + CTA), menu linków
i przycisk wylogowania. Animacja stagger (slideIn). Responsywne skalowanie
na desktop < 2xl. JS: trigger .navbar__profile-toggle, stan .is-open.
Markup: dropdown-profile.html
<!-- Dropdown Profile: statyczny podgląd -->
<div style="position:relative; max-width:320px; background:#f5f5f1; border-radius:8px; padding:20px;">
<div class="dropdown-profile__header" style="opacity:1; width:100%;">
<div class="dropdown-profile__spacer"></div>
<span class="dropdown-profile__title">Mój profil</span>
<button class="dropdown-profile__close">✕</button>
</div>
<div class="dropdown-profile__card" style="opacity:1; width:100%;">
<div class="dropdown-profile__points-row">
<div class="dropdown-profile__points-info">
<span class="dropdown-profile__points-value">1250</span>
<span class="dropdown-profile__points-label">PUNKTY</span>
</div>
</div>
<div class="dropdown-profile__divider"></div>
<p class="dropdown-profile__expiry">Ważne do: <strong>31.12.2026</strong></p>
<a href="#" class="dropdown-profile__card-cta">Zobacz szczegóły</a>
</div>
<div class="dropdown-profile__menu" style="opacity:1; width:100%;">
<a href="#" class="dropdown-profile__menu-item">Moje dane</a>
<a href="#" class="dropdown-profile__menu-item">Historia zamówień</a>
</div>
<button class="dropdown-profile__logout" style="opacity:1;">
Wyloguj się
</button>
</div>
src/scss/components/_dropdown-profile.scss, line 1
2.12 #Components.EarningPointItem Earning Point Item
Element grida "Dodatkowe sposoby zdobywania punktów".
Ikona + separator + body (tytuł + punkty + opis).
Grid: .earning-point-grid — 1 kolumna mobile, 2 kolumny desktop.
Bierz udział w konkursach i zdobywaj dodatkowe punkty Win.
Markup: earning-point-item.html
<div class="earning-point-grid" style="max-width: 900px;">
<div class="earning-point-item">
<div class="earning-point-item__icon">
<img src="assets/images/app-icon-winston.png" alt="" style="width:45px; height:45px; background:#eee; border-radius:8px;">
</div>
<div class="earning-point-item__separator"></div>
<div class="earning-point-item__body">
<div class="earning-point-item__header">
<span class="earning-point-item__title">Konkursy</span>
<span class="earning-point-item__points">50–200 Win</span>
</div>
<p class="earning-point-item__desc">Bierz udział w konkursach i zdobywaj dodatkowe punkty Win.</p>
</div>
</div>
</div>
src/scss/components/_earning-point-item.scss, line 1
2.13 #Components.FeatureCards Feature Cards
Karty na stronach produktowych. 6 typów: image, video, info (SVG+tekst),
packshot-title, packshot, image-title. Obsługa flip-card (3D), animacje
reveal (slide-in), slow pan & zoom tła, like-button, vertical text.
CSS custom properties: --fc-accent-color, --fc-text-color.
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Złożony komponent z 6 typami kart. Podgląd na żywo: product-legend-blue.html
Info Card
z ikoną SVG i tekstem
Packshot Card
Markup: feature-cards.html
<!-- Feature Cards: Informacja -->
<p style="color:#666;font-size:14px;">
Złożony komponent z 6 typami kart. Podgląd na żywo:
<a href="/product-legend-blue.html" target="_blank">product-legend-blue.html</a>
</p>
<div style="display:flex; gap:16px; flex-wrap:wrap;">
<!-- Info Card -->
<div class="feature-card feature-card--info" style="width:200px; aspect-ratio:165/262; border:1px solid rgba(0,0,0,0.08); --fc-accent-color:#1c51a0; --fc-text-color:#333;">
<p class="feature-card__text">Info Card<br>z ikoną SVG i tekstem</p>
</div>
<!-- Packshot Card -->
<div class="feature-card feature-card--packshot" style="width:200px; aspect-ratio:165/262;">
<p style="color:#999;font-size:12px;text-align:center;">Packshot Card</p>
</div>
</div>
src/scss/components/_feature-cards.scss, line 1
2.14 #Components.FormSelect Form Select
Custom dropdown select stylizowany jak text-input. Ukryty natywny <select>
(accessibility + form submit), widoczny trigger, rozwijana lista opcji.
JS: src/js/modules/form-select.js.
Markup: form-select.html
<!-- Form Select: Default -->
<div class="form-select [modifier class]" style="max-width:400px;">
<label class="form-select__label">Kategoria</label>
<div class="form-select__wrapper">
<div class="form-select__trigger" tabindex="0">
<span class="form-select__value">Wybierz z listy</span>
<span class="form-select__arrow"></span>
</div>
</div>
</div>
src/scss/components/_form-select.scss, line 1
2.15 #Components.HeroSlider Hero Slider
Fullscreen slider na stronę główną z image/video backgrounds, animowanym
contentem (stagger slide-down) i page indicators. JS: src/js/modules/hero-slider.js.
Stany slajdu: .is-active, .is-animated. Pager: .is-active na item.
Komponent fullscreen – podgląd na żywo na stronie głównej: index.html
Markup: hero-slider.html
<!-- Hero Slider: Informacja -->
<p style="color:#666;font-size:14px;">
Komponent fullscreen – podgląd na żywo na stronie głównej:
<a href="/index.html" target="_blank">index.html</a>
</p>
src/scss/components/_hero-slider.scss, line 1
2.16 #Components.HomeCard Home Card
Karta z tłem (image/video), overlay gradient, tytuł + tekst + CTA. Grid: .home-cards__grid — 1 kolumna mobile, row desktop. Hover (desktop): CTA wjeżdża, tekst przesuwa się w górę, image zoom.
Komponent home-card wymaga obrazów/wideo tła. Podgląd: home.html
Markup: home-card.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent home-card wymaga obrazów/wideo tła. Podgląd: <a href="../home.html">home.html</a></p>
src/scss/components/_home-card.scss, line 1
2.17 #Components.Icon Icon
Ikony SVG renderowane przez sprite (<use>). Kolor dziedziczy currentColor.
Rozmiary: sm (15px) → default (20px) → lg (24px) → xl (38px)
Rozmiary: sm (15px) → default (20px) → lg (24px) → xl (38px)
Rozmiary: sm (15px) → default (20px) → lg (24px) → xl (38px)
Rozmiary: sm (15px) → default (20px) → lg (24px) → xl (38px)
Markup: icon.html
<div style="display: flex; gap: 24px; align-items: center;">
<svg class="icon icon--sm" style="color: #1c51a0;"><use href="assets/images/sprite.svg#heart"></use></svg>
<svg class="icon" style="color: #1c51a0;"><use href="assets/images/sprite.svg#heart"></use></svg>
<svg class="icon icon--lg" style="color: #1c51a0;"><use href="assets/images/sprite.svg#heart"></use></svg>
<svg class="icon icon--xl" style="color: #1c51a0;"><use href="assets/images/sprite.svg#heart"></use></svg>
</div>
<p style="margin-top:12px; font-size:13px; color:#999;">Rozmiary: sm (15px) → default (20px) → lg (24px) → xl (38px)</p>
src/scss/components/_icon.scss, line 1
2.19 #Components.MemoryGame Memory Game
Plansza gry memory z gradient blue background, stats bar (czas + ruchy),
siatką 4×4 kart z animacją flip i shake.
JS: src/js/modules/memory-game.js.
BEM: .memory-board__*.
Komponent interaktywny (gra). Podgląd: gra-memory.html
Markup: memory-game.html
<!-- Memory Game: Informacja -->
<p style="color:#666;font-size:14px;">
Komponent interaktywny (gra). Podgląd:
<a href="/gra-memory.html" target="_blank">gra-memory.html</a>
</p>
src/scss/components/_memory-game.scss, line 1
2.20 #Components.Modal Modal
Okno modalne z backdrop, grafiką (opcjonalną), tytułem, tekstem, wartością
i przyciskami (confirm/cancel). Wariant modal--points z dużą liczbą
- labelem. JS:
Modal.show({...}). Stany:.is-active,.is-dismissing. Desktop: two-column layout (grafika + body). Scroll lock:.modal-open.
Czy na pewno chcesz odebrać ten voucher?
Z Twojego konta zostanie pobrane:
500 punktów
Markup: modal.html
<!-- Modal: statyczny podgląd (bez backdrop) -->
<div style="position:relative; background:#f5f5f1; padding:20px; border-radius:8px; max-width:500px;">
<div class="modal" style="position:relative; transform:none; opacity:1; max-width:100%; border-radius:8px;">
<button class="modal__close" aria-label="Zamknij"></button>
<div class="modal__body" style="order:1;">
<h2 class="modal__title">Czy na pewno chcesz odebrać ten voucher?</h2>
<div class="modal__separator"></div>
<p class="modal__text">Z Twojego konta zostanie pobrane:</p>
<p class="modal__value">500 punktów</p>
<div class="modal__actions">
<button class="btn btn-primary">Odbierz</button>
<button class="btn btn-secondary-positive">Anuluj</button>
</div>
</div>
</div>
</div>
<button class="btn btn-primary"
onclick="Modal.show({ image: '../assets/images/vouchers/voucher-decathlon.jpg', title: 'Czy na pewno chcesz odebrać ten voucher?', text: 'Z Twojego konta zostanie pobrane:', value: '500 punktów', confirmLabel: 'Odbierz', cancelLabel: 'Anuluj', onConfirm: function() { Toast.show({ title: 'Sukces!', text: 'Voucher odebrany.' }); } })">
Otwórz Modal (pełny)
</button>
<button class="btn btn-primary"
onclick="Modal.show({ image: '../assets/images/vouchers/voucher-decathlon.jpg', title: 'Gratulacje!', text: 'Twój voucher został aktywowany.', confirmLabel: 'OK' })">
Otwórz Modal (1 button)
</button>
<button class="btn btn-primary"
onclick="Modal.show({ title: 'Czy na pewno?', text: 'Tej operacji nie można cofnąć.', confirmLabel: 'Potwierdź', cancelLabel: 'Anuluj' })">
Otwórz Modal (bez grafiki)
</button>
<button class="btn btn-primary"
onclick="Modal.show({ variant: 'points', image: '../assets/images/own-it-card-big.jpg', pointsNumber: '235', pointsLabel: 'Punktów', text: 'Jan, kod został wprowadzony poprawnie!', value: '+ 15 PUNKTÓW', confirmLabel: 'Zamknij' })">
Kod poprawny
</button>
<button class="btn btn-primary"
onclick="Modal.show({ variant: 'points', image: '../assets/images/own-it-card-big.jpg', pointsNumber: '235', pointsLabel: 'Punktów', text: '<strong>Brawo!</strong><br/> Dodatkowe punkty wpadły na Twoje konto!', value: '+ 10 PUNKTÓW', confirmLabel: 'Zamknij' })">
Brawo (dodatkowe)
</button>
<button class="btn btn-primary"
onclick="Modal.show({ variant: 'points', image: '../assets/images/own-it-card-big.jpg', pointsNumber: '335', pointsLabel: 'Punktów', text: '<strong>Gratulacje!</strong><br/><br/> Twój znajomy pomyślnie zarejestrował się z&nbsp;linku polecającego, otrzymujesz punkty lojalnościowe:', value: '+ 100 PUNKTÓW', confirmLabel: 'Wyślij kolejne zaproszenie', cancelLabel: 'Zamknij' })">
Zaproszenie
</button>
<button class="btn btn-primary"
onclick="Modal.show({ image: '../assets/images/vouchers/voucher-decathlon.jpg', title: 'Gratulacje, voucher jest Twój!', text: 'Nagroda została wysłana na Twoją skrzynkę e-mail.', confirmLabel: 'Zobacz voucher' })">
Gratulacje
</button>
<button class="btn btn-primary"
onclick="Modal.show({ image: '../assets/images/vouchers/voucher-decathlon.jpg', title: 'Wykorzystałeś swój limit miesięczny', text: 'Pamiętaj, że możesz wymienić punkty na <strong>1 voucher w ciągu miesiąca</strong>.', confirmLabel: 'Zamknij' })">
Limit miesięczny
</button>
<button class="btn btn-primary"
onclick="Modal.show({ image: '../assets/images/vouchers/voucher-decathlon.jpg', title: 'Wykorzystałeś swój limit roczny', text: 'Pamiętaj, że możesz odebrać do <strong>6 voucherów w ciągu roku</strong>.', confirmLabel: 'Zamknij' })">
Limit roczny
</button>
<button class="btn btn-primary"
onclick="Modal.show({ image: '../assets/images/vouchers/voucher-decathlon.jpg', title: 'Nie masz wystarczającej ilości punktów', text: 'Rejestruj kody z paczek i zdobądź punkty, aby odebrać ten voucher.', confirmLabel: 'Dodaj nowy kod', cancelLabel: 'Anuluj' })">
Brak punktów
</button>
src/scss/components/_modal.scss, line 1
2.21 #Components.ModelViewer Model Viewer
Sekcja 3D model viewer z kontenerami, hotspotami i kontrolkami. Wymaga biblioteki model-viewer. Placeholder image fallback.
Komponent model-viewer wymaga biblioteki 3D. Podgląd: strony produktowe.
Markup: model-viewer.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent model-viewer wymaga biblioteki 3D. Podgląd: strony produktowe.</p>
src/scss/components/_model-viewer.scss, line 1
2.23 #Components.Onboarding Onboarding
Wieloekranowy modal onboardingowy (fullscreen mobile / panel desktop).
Background crossfade, gradient overlay, close button, kroki z opisami,
kartami info, SVG animated text, progress bar, CTA.
JS: Onboarding.show(). Stany: .is-active, .is-dismissing.
Scroll lock: .onboarding-open.
Komponent interaktywny (wieloekranowy wizard).
Triggered via JS: Onboarding.show().
Markup: onboarding.html
<!-- Onboarding: Informacja -->
<p style="color:#666;font-size:14px;">
Komponent interaktywny (wieloekranowy wizard).
Triggered via JS: <code>Onboarding.show()</code>.
</p>
src/scss/components/_onboarding.scss, line 1
2.25 #Components.ProductCard Product Card
Karta produktowa z packshotem (absolute), nazwą, opisem i CTA. Hover (desktop): packshot zoom out, button fade-in. Kolory per produkt: --red, --green, --pink.
Komponent product-card wymaga packshotów produktowych. Podgląd: products.html
Komponent product-card wymaga packshotów produktowych. Podgląd: products.html
Komponent product-card wymaga packshotów produktowych. Podgląd: products.html
Komponent product-card wymaga packshotów produktowych. Podgląd: products.html
Komponent product-card wymaga packshotów produktowych. Podgląd: products.html
Markup: product-card.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent product-card wymaga packshotów produktowych. Podgląd: <a href="../products.html">products.html</a></p>
src/scss/components/_product-card.scss, line 1
2.26 #Components.ProductFilter Product Filter
Filtrowanie produktów: desktop – chip grid w grupach; mobile – przycisk
trigger z badge, aktywne tagi, modal z listą chipów. JS: src/js/modules/product-filter.js.
Komponent filtrowania z chipami, tagami i modalem mobile. Podgląd: swiat-zapachow.html
Markup: product-filter.html
<!-- Product Filter: Informacja -->
<p style="color:#666;font-size:14px;">
Komponent filtrowania z chipami, tagami i modalem mobile.
Podgląd: <a href="/swiat-zapachow.html" target="_blank">swiat-zapachow.html</a>
</p>
src/scss/components/_product-filter.scss, line 1
2.28 #Components.ProfilPointsCard Profil Points Card
Karta punktów profilowych z opisem, monetą i licznikiem (wartość + separator + info).
Wariant: .profil-card--points. Używany na: moj-profil, zdobyte-punkty.
Komponent profil-points-card wymaga kontekstu profilu. Podgląd: moj-profil.html
Markup: profil-points-card.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent profil-points-card wymaga kontekstu profilu. Podgląd: <a href="../moj-profil.html">moj-profil.html</a></p>
src/scss/components/_profil-points-card.scss, line 1
2.29 #Components.ProgressBar Progress Bar
Pasek postępu z animacją fill, tytułem, podtytułem i opisem.
JS: src/js/modules/progress-bar.js — viewport animation, auto-text.
Markup: progress-bar.html
<div style="display: flex; flex-direction: column; gap: 24px; max-width: 600px;">
<div class="progress-bar progress-bar--animated" style="--progress: 50%;">
<p class="progress-bar__title">Postęp odblokowania nagrody</p>
<p class="progress-bar__subtitle">3 / 6 odebranych voucherów</p>
<div class="progress-bar__track">
<div class="progress-bar__fill" style="width: 50%;"></div>
</div>
<p class="progress-bar__desc">Odbierz 6 voucherów, aby odblokować nagrodę specjalną.</p>
</div>
<div class="progress-bar progress-bar--success progress-bar--animated" style="--progress: 100%;">
<p class="progress-bar__title">Nagroda specjalna odblokowana!</p>
<p class="progress-bar__subtitle">6 / 6 odebranych voucherów</p>
<div class="progress-bar__track">
<div class="progress-bar__fill" style="width: 100%;"></div>
</div>
<p class="progress-bar__desc">Gratulacje!</p>
</div>
</div>
src/scss/components/_progress-bar.scss, line 1
2.30 #Components.ProgressCounter Progress Counter
Licznik postępu z etykietą i wartością (np. "0/6"). Używany na: vouchers, odebrane-nagrody.
Markup: progress-counter.html
<div class="progress-counter">
<div class="progress-counter__row">
<span class="progress-counter__label">Odebrane vouchery</span>
<div class="progress-counter__value"><span>3/6</span></div>
</div>
<div class="progress-counter__row">
<span class="progress-counter__label">Nagroda specjalna</span>
<div class="progress-counter__value"><span>0/1</span></div>
</div>
</div>
src/scss/components/_progress-counter.scss, line 1
2.31 #Components.RadioInput Radio Input
Niestandardowy radio z ukrytym natywnym inputem i okrągłym indicatorem. Stany: checked, disabled, error, blocked, focus.
Markup: radio-input.html
<div style="display: flex; gap: 24px; flex-wrap: wrap;">
<label class="radio-input">
<input type="radio" class="radio-input__control" name="demo" />
<span class="radio-input__indicator"></span>
<span class="radio-input__label">Default</span>
</label>
<label class="radio-input">
<input type="radio" class="radio-input__control" name="demo" checked />
<span class="radio-input__indicator"></span>
<span class="radio-input__label">Selected</span>
</label>
<label class="radio-input">
<input type="radio" class="radio-input__control" name="demo2" disabled />
<span class="radio-input__indicator"></span>
<span class="radio-input__label">Disabled</span>
</label>
<label class="radio-input radio-input--error">
<input type="radio" class="radio-input__control" name="demo3" />
<span class="radio-input__indicator"></span>
<span class="radio-input__label">Error</span>
</label>
<label class="radio-input radio-input--blocked">
<input type="radio" class="radio-input__control" name="demo4" checked />
<span class="radio-input__indicator"></span>
<span class="radio-input__label">Blocked</span>
</label>
</div>
src/scss/components/_radio-input.scss, line 1
2.32 #Components.ReferralLink Referral Link
CTA sekcja "Twój link polecający" z tłem (image), overlay gradient, odznaki nagród, tytuł + opis + formularz (text-input + button).
Komponent referral-link wymaga obrazów tła i badge. Podgląd: win-club-polecaj-znajomym.html
Markup: referral-link.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent referral-link wymaga obrazów tła i badge. Podgląd: <a href="../win-club-polecaj-znajomym.html">win-club-polecaj-znajomym.html</a></p>
src/scss/components/_referral-link.scss, line 1
2.33 #Components.SliderHistory Slider History
Slider historii z osią czasu lat, zdjęciami i opisami. Desktop: paginacja
lat (tabs) + slide (zdjęcie z gradient overlay i tekstem). Mobile: kolumna
(data + opis nad zdjęciem), kropkowa paginacja, strzałki nawigacji.
JS: src/js/modules/slider-history.js.
Komponent interaktywny – slider historii marki. Podgląd: historia-winston.html
Markup: slider-history.html
<!-- Slider History: Informacja -->
<p style="color:#666;font-size:14px;">
Komponent interaktywny – slider historii marki.
Podgląd: <a href="/historia-winston.html" target="_blank">historia-winston.html</a>
</p>
src/scss/components/_slider-history.scss, line 1
2.34 #Components.TextInput Text Input
Pole tekstowe z label, helper text, ikony (left/right). Stany: empty, disabled, locked, locked-edit, error. Wariant textarea.
Markup: text-input.html
<div style="display: flex; flex-direction: column; gap: 24px; max-width: 460px;">
<div class="text-input">
<label class="text-input__label">Default</label>
<div class="text-input__body">
<input class="text-input__field" placeholder="Wpisz tekst..." />
</div>
</div>
<div class="text-input text-input--error">
<label class="text-input__label">Error</label>
<div class="text-input__body">
<input class="text-input__field" value="Błędna wartość" />
</div>
<div class="text-input__helper">
<span class="text-input__helper-text">Pole jest wymagane</span>
</div>
</div>
<div class="text-input text-input--disabled">
<label class="text-input__label">Disabled</label>
<div class="text-input__body">
<input class="text-input__field" value="Wyłączony" disabled />
</div>
</div>
<div class="text-input text-input--locked">
<label class="text-input__label">Locked</label>
<div class="text-input__body">
<input class="text-input__field" value="jan.kowalski@email.com" readonly />
</div>
</div>
</div>
src/scss/components/_text-input.scss, line 1
2.35 #Components.Toast Toast
Powiadomienie fixed na dole ekranu (mobile) / prawy dół (desktop).
JS: Toast.show({ title, text, duration }). Animacja slide-in/out.
Markup: toast.html
<div style="position: relative; height: 120px; background: #f5f5f1; border-radius: 8px; overflow: hidden;">
<div class="toast" style="position: absolute; display: block; pointer-events: auto; bottom: 12px; left: 10px; right: 10px; transform: none;">
<div class="toast__inner">
<span class="toast__icon"></span>
<div class="toast__content">
<p class="toast__title">+2 Punkty Win</p>
<p class="toast__text">Brawo! Zdobywasz <strong>2 Punkty Win</strong>!</p>
</div>
</div>
</div>
</div>
src/scss/components/_toast.scss, line 1
2.36 #Components.Tutorial Tutorial
Guided tour (samouczek). Backdrop + spotlight na element docelowy +
dialog (intro / step / centered). Strzałki nawigacji, counter „1/3",
CTA na ostatnim kroku. JS: Tutorial.start({…}).
Komponent interaktywny – guided tour z podświetleniem elementów.
JS: Tutorial.start({…}).
Markup: tutorial.html
<!-- Tutorial: Informacja -->
<p style="color:#666;font-size:14px;">
Komponent interaktywny – guided tour z podświetleniem elementów.
JS: <code>Tutorial.start({…})</code>.
</p>
src/scss/components/_tutorial.scss, line 1
2.37 #Components.VoucherCard Voucher Card
Karta vouchera z obrazkiem, tytułem, punktami i CTA. Hover (desktop): bg ciemnieje, tytuł zmniejsza się, btn fade-in. Mobile: CTA zawsze widoczny, stała pozycja.
Komponent voucher-card wymaga obrazków voucherów. Podgląd: vouchers.html
Komponent voucher-card wymaga obrazków voucherów. Podgląd: vouchers.html
Komponent voucher-card wymaga obrazków voucherów. Podgląd: vouchers.html
Markup: voucher-card.html
<p style="color:#999; font-style:italic; padding: 20px;">Komponent voucher-card wymaga obrazków voucherów. Podgląd: <a href="../vouchers.html">vouchers.html</a></p>
src/scss/components/_voucher-card.scss, line 1