Podstawowe omówienie tworzenia komponentu ustawień z suwakami i polami wyboru.
W tym poście przedstawię sposoby tworzenia komponentu ustawień dla jest elastyczny, obsługuje wiele urządzeń wejściowych i działa przeglądarki. Zobacz prezentację.
.Jeśli wolisz obejrzeć filmy lub zobaczyć podgląd UI/UX tego, co tworzymy, tutaj znajdziesz w YouTube:
Omówienie
Najważniejsze aspekty tego komponentu zostały podzielone na następujące sekcje:
- Układy
- Kolor
- Pole do wpisania zakresu niestandardowego
- Wprowadzanie niestandardowych pól wyboru
- Uwagi na temat ułatwień dostępu
- JavaScript
Układy
To jest pierwsza wersja demonstracyjna GUI Challenge, w której dostępna jest cała siatka CSS. Oto każda siatka są wyróżnione za pomocą Narzędzi deweloperskich w Chrome dla siatki:
Tylko dla przerwy
Najpopularniejszy układ:
foo {
display: grid;
gap: var(--something);
}
Nazywam go „tylko dla luki” ponieważ używa siatki tylko do dodawania przerw między bryłami.
Z tej strategii korzysta 5 układów. Oto wszystkie z nich:
Element fieldset
, który zawiera każdą grupę wejściową (.fieldset-item
), używa parametru gap: 1px
do
tworzą linie graniczne między elementami. Nie ma skomplikowanego rozwiązania obramowania!
.grid { display: grid; gap: 1px; background: var(--bg-surface-1); & > .fieldset-item { background: var(--bg-surface-2); } }
.grid { display: grid; & > .fieldset-item { background: var(--bg-surface-2); &:not(:last-child) { border-bottom: 1px solid var(--bg-surface-1); } } }
Naturalne zawijanie siatki
Najbardziej złożony układ okazał się
układem makro, logicznym układem,
system między <main>
a <form>
.
Środkowe zawijanie treści
Zarówno Flexbox, jak i siatka dają możliwości: align-items
oraz
align-content
, a w przypadku elementów paczki – układ content
wyrównania rozdzielają odstępy między elementy podrzędne w grupie.
main {
display: grid;
gap: var(--space-xl);
place-content: center;
}
Główny element jest wyrównany place-content: center
skrót, więc
aby elementy podrzędne były wyśrodkowane w pionie i w poziomie w układach jedno- i dwóch kolumnowych.
Zobacz na filmie powyżej, jak „treść” pozostaje wyśrodkowany, mimo że zawijanie miało miejsce.
Powtórz autodopasowanie min.
<form>
korzysta z adaptacyjnego układu siatki w przypadku każdej sekcji.
Ten układ przełącza się między 1 a 2 kolumnami w zależności od dostępnego miejsca.
form {
display: grid;
gap: var(--space-xl) var(--space-xxl);
grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
align-items: flex-start;
max-width: 89vw;
}
Ta siatka ma inną wartość dla funkcji row-gap
(--space-xl) niż column-gap
(--space-xxl)
aby nadać
taki niestandardowy wygląd w układzie elastycznym. Gdy kolumny się układają,
ale nie tak duży, jak na szerokim ekranie.
Właściwość grid-template-columns
korzysta z 3 funkcji CSS: repeat()
, minmax()
i
min()
Una Kravets prowadzi bloga o doskonałym układzie
na ten temat,
Pamięć RAM.
Nasz układ ma 3 specjalne dodatki, jeśli porównamy go z układem Uny:
- Przekazujemy dodatkową funkcję
min()
. - Określamy wartość
align-items: flex-start
. - Obowiązuje styl:
max-width: 89vw
.
Dodatkową funkcję min()
dobrze opisuje Evan Minto na swoim blogu w
post właściwie elastyczna siatka CSS z właściwością minmax() i
min().
Warto się z tym zapoznać. Korekta wyrównania flex-start
to
usuń domyślny efekt rozciągania, aby elementy podrzędne tego układu nie były
muszą mieć jednakową wysokość, mogą mieć naturalne, wrodzone wysokości.
W filmie w YouTube znajdziesz krótkie omówienie tego dodanego wyrównania.
W tym poście pokrótce omówimy max-width: 89vw
.
Pokażę układ z zastosowanym stylem i bez niego:
Co się dzieje? Gdy jest określony max-width
, podaje kontekst,
jednoznaczny rozmiar lub określony rozmiar
rozmiar auto-fit
algorytm układu, by dowiedzieć się,
odpowiednią liczbę powtórzeń. Choć wydaje się oczywiste,
oznacza „pełną szerokość”, zgodnie ze specyfikacją siatki CSS określony rozmiar lub maksymalny rozmiar
należy podać. Podano maksymalny rozmiar.
Dlaczego więc 89vw
? Bo „to zadziałało” dla mojego układu.
Wraz z innymi użytkownikami Chrome zastanawiamy się, dlaczego ta wartość jest bardziej uzasadniona,
jak 100vw
nie jest wystarczające, a jeśli to rzeczywiście błąd.
Odstępy
Harmonia w tym układzie zależy w większości od ograniczonej palety odstępów. bardzo dokładne.
:root {
--space-xxs: .25rem;
--space-xs: .5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
--space-xxl: 6rem;
}
Świetnie Ci idzie korzystanie z tych przepływów dzięki składni siatki, CSS @nest i poziomu 5.
z @media. Oto przykład całego zestawu stylów układu <main>
.
main {
display: grid;
gap: var(--space-xl);
place-content: center;
padding: var(--space-sm);
@media (width >= 540px) {
& {
padding: var(--space-lg);
}
}
@media (width >= 800px) {
& {
padding: var(--space-xl);
}
}
}
Siatka z wyśrodkowanymi treściami, domyślnie dopełniona umiarkowanie (jak na urządzeniach mobilnych). Ale w miarę zwiększania dostępnego obszaru widoczny obszar będzie się rozciągał, zwiększając dopełnienie. Usługa porównywania cen na rok 2021 wygląda całkiem nieźle
Pamiętasz poprzedni układ, „tylko dla luki”? Oto pełniejsza wersja jak wyglądają w tym komponencie:
header {
display: grid;
gap: var(--space-xxs);
}
section {
display: grid;
gap: var(--space-md);
}
Kolor
Kontrolowane użycie kolorów sprawiło, że ten projekt wyróżniał się tak ekspresyjnym, ale bardziej wyrazistym charakterem. jest minimalna. Robię to w ten sposób:
:root {
--surface1: lch(10 0 0);
--surface2: lch(15 0 0);
--surface3: lch(20 0 0);
--surface4: lch(25 0 0);
--text1: lch(95 0 0);
--text2: lch(75 0 0);
}
Nazywam kolory powierzchni i tekstu liczbami, a nie nazwami takimi jak
surface-dark
i surface-darker
, ponieważ w zapytaniu o multimedia zostaną odwrócone
więc nie będą miały znaczenia światło i ciemne.
Odwracam je w takim zapytaniu o multimedia:
:root {
...
@media (prefers-color-scheme: light) {
& {
--surface1: lch(90 0 0);
--surface2: lch(100 0 0);
--surface3: lch(98 0 0);
--surface4: lch(85 0 0);
--text1: lch(20 0 0);
--text2: lch(40 0 0);
}
}
}
Warto szybko przyjrzeć się ogólnemu obrazowi i strategii, zanim zagłębiamy się w szczegóły składni kolorów. Ale ponieważ wybiegłam trochę przed siebie, cofnijmy się trochę.
LCH?
Bez wgłębiania się w teorię kolorów, LCH to składnia ukierunkowana na człowieka, który pozwala nam postrzegać kolory, a nie jak mierzymy je za pomocą matematyki (np. 255). To daje charakterystyczną zaletę, ponieważ człowiek może to pisać łatwiej, a inne a ludzie dostosują się do tych zmian.
W tej prezentacji skupmy się dziś na składni i odwracanych wartościach. aby uzyskać światło i ciemność. Przyjrzyjmy się jednej powierzchni i 1 kolorowi tekstu:
:root {
--surface1: lch(10 0 0);
--text1: lch(95 0 0);
@media (prefers-color-scheme: light) {
& {
--surface1: lch(90 0 0);
--text1: lch(40 0 0);
}
}
}
--surface1: lch(10 0 0)
oznacza jasność 10%
, 0 chroma i 0 odcienie:
bardzo ciemny bezbarwny szary. Następnie w zapytaniu o multimedia dla trybu jasnego
jest zwracana na 90%
z --surface1: lch(90 0 0);
. To sedno
strategii ustalania stawek. Zacznij od zmiany jasności w obu 2 motywach, utrzymując
współczynniki kontrastu, jakich wymaga projekt lub co może zapewnić dostępność.
Zaletą w usłudze lch()
jest to, że lekkość jest zorientowana na człowieka i możemy poczuć
dobrze jest wprowadzić zmianę %
, że będzie ona widoczna w sposób zauważalny i spójny
co się zmieniło o %
. hsl()
na przykład nie jest tak
wiarygodne.
To więcej...
więcej informacji o
przestrzeni kolorów i funkcji lch()
. Już wkrótce!
Usługa porównywania cen obecnie w ogóle nie ma dostępu do tych kolorów. Powtórzę: w nowoczesnych kolorach nie mamy dostępu do jednej trzeciej i monitory. Są to nie tylko kolory, ale najbardziej żywe kolory, co może być widoczne na ekranie. Nasze strony internetowe są wyłaniane z powodu zmian na sprzęcie do monitorowania szybciej niż w przypadku specyfikacji CSS i implementacji w przeglądarkach.
Lea Verou (w języku angielskim)
Adaptacyjne elementy sterujące formularza z schematem kolorów
Wiele przeglądarek wysyła ustawienia ciemnego motywu (obecnie Safari i Chromium), musisz określić w kodzie CSS lub HTML, że będą one używane w projekcie.
Powyżej pokazano efekt właściwości z panelu Style Narzędzia deweloperskie. W wersji demonstracyjnej użyto tagu HTML, który moim zdaniem jest ogólnie lepszą lokalizację:
<meta name="color-scheme" content="dark light">
Więcej informacji na ten temat znajdziesz tutaj: color-scheme
artykuł autorstwa Thomasa
Steiner. Możesz zyskać jeszcze więcej możliwości
niż ciemne pola wyboru.
Usługa porównywania cen: accent-color
Wprowadzono niedawne
aktywność w okolicy
accent-color
w elementach formularza. To pojedynczy styl CSS, który może zmieniać
odcień użyty w elemencie wprowadzania danych przeglądarki. Więcej informacji na ten temat można znaleźć tutaj w witrynie
GitHub. Umieściłem to na swoim
stylów dla tego komponentu. Ponieważ przeglądarki obsługują tę funkcję, moje pola wyboru będą
z wyostrzeniami w różowych i fioletowych kolorach.
input[type="checkbox"] {
accent-color: var(--brand);
}
Wyostrzenie kolorów ze stałymi gradientami i ostrością w środku
Kolory wyostrzają najczęściej, gdy są używane oszczędnie. czyli kolorowych interakcji z interfejsem.
W tym filmie jest wiele warstw opinii i interakcji z interfejsem, które nadają mu osobisty charakter, ponieważ:
- Wyróżnianie kontekstu
- W interfejsie użytkownika z informacją o pełnym napełnieniu wartość znajduje się w zakresie.
- Przekazywanie informacji w interfejsie użytkownika, że pole przyjmuje dane wejściowe.
Aby przesłać opinię, gdy użytkownik wchodzi w interakcję z elementem, CSS korzysta z metody
:focus-within
pseudoklasy, aby zmienić wygląd różnych elementów. Przeanalizujmy klasę
.fieldset-item
, to bardzo interesujące:
.fieldset-item {
...
&:focus-within {
background: var(--surface2);
& svg {
fill: white;
}
& picture {
clip-path: circle(50%);
background: var(--brand-bg-gradient) fixed;
}
}
}
Gdy jedno z elementów podrzędnych tego elementu ma zaznaczenie w:
- Do tła
.fieldset-item
przypisano wyższy kontrast powierzchni. - Zagnieżdżony element
svg
jest wypełniany na biało w celu zwiększenia kontrastu. - Zagnieżdżona funkcja
<picture>
clip-path
rozwija się do pełnego okręgu, a element tło jest wypełnione jasnym, stałym gradientem.
Zakres niestandardowy
Na podstawie poniższego elementu wejściowego kodu HTML pokażę, Wygląd:
<input type="range">
Ten element wymaga dostosowania w 3 częściach:
Style elementów zakresu
input[type="range"] {
/* style setting variables */
--track-height: .5ex;
--track-fill: 0%;
--thumb-size: 3ex;
--thumb-offset: -1.25ex;
--thumb-highlight-size: 0px;
appearance: none; /* clear styles, make way for mine */
display: block;
inline-size: 100%; /* fill container */
margin: 1ex 0; /* ensure thumb isn't colliding with sibling content */
background: transparent; /* bg is in the track */
outline-offset: 5px; /* focus styles have space */
}
Pierwszych kilka wierszy CSS to niestandardowe części stylów. Mam nadzieję, pomaga im wyraźne oznaczenie ich etykietami. Pozostałe style to głównie style zresetowane, co zapewnia spójną podstawę do tworzenia skomplikowanych części komponentu.
Style torów
input[type="range"]::-webkit-slider-runnable-track {
appearance: none; /* clear styles, make way for mine */
block-size: var(--track-height);
border-radius: 5ex;
background:
/* hard stop gradient:
- half transparent (where colorful fill we be)
- half dark track fill
- 1st background image is on top
*/
linear-gradient(
to right,
transparent var(--track-fill),
var(--surface1) 0%
),
/* colorful fill effect, behind track surface fill */
var(--brand-bg-gradient) fixed;
}
Kluczem do sukcesu jest „ujawnienie” żywy kolor wypełnienia. Odbywa się to za pomocą zatrzymuje gradient. Gradient jest przezroczysty do procentu wypełnienia, a po nim z niewypełnionym kolorem powierzchni ścieżki. Za tą niewypełnioną powierzchnią znajduje się kolor o pełnej szerokości, czekając na odkrycie przezroczystości.
Śledź styl wypełnienia
Mój projekt wymaga JavaScriptu do zachowania stylu wypełnienia. OK to strategie oparte wyłącznie na CSS, ale muszą mieć tę samą wysokość jako ścieżkę dźwiękową i nie znalazłem w tych granicach harmonii.
/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')
/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
const max = slider.getAttribute('max') || 10;
const percent = slider.value / max * 100;
return `${parseInt(percent)}%`;
};
/* on page load, set the fill amount */
sliders.forEach(slider => {
slider.style.setProperty('--track-fill', rangeToPercent(slider));
/* when a slider changes, update the fill prop */
slider.addEventListener('input', e => {
e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
})
})
Myślę, że stanowi to ładną ulepszoną wizualną wersję interfejsu. Suwak działa świetnie bez
JavaScript, właściwość --track-fill
nie jest wymagana, po prostu nie będzie miała
stylu wypełnienia, jeśli go nie ma. Jeśli JavaScript jest dostępny, wypełnij pole niestandardowe
oraz obserwując zmiany wprowadzone przez użytkowników, synchronizując usługę niestandardową z
wartość.
Oto świetna
opublikuj na
CSS-Tricks, autorka: Ana
Tudor, która prezentuje jedyne w swoim rodzaju CSS
aby śledzić wypełnienie. Też znalazłam to
range
element bardzo inspirujący.
Style kciuków
input[type="range"]::-webkit-slider-thumb {
appearance: none; /* clear styles, make way for mine */
cursor: ew-resize; /* cursor style to support drag direction */
border: 3px solid var(--surface3);
block-size: var(--thumb-size);
inline-size: var(--thumb-size);
margin-top: var(--thumb-offset);
border-radius: 50%;
background: var(--brand-bg-gradient) fixed;
}
Większość z tych stylów służy do tworzenia ładnego okręgu.
Widać tu stały gradient tła, który ujednolica
dynamiczne kolory kciuków, ścieżek i powiązanych elementów SVG.
Style dla interakcji zostały rozdzielone, aby pomóc w wyodrębnieniu elementu box-shadow
metoda użyta do podświetlenia elementów po najechaniu kursorem:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
::-webkit-slider-thumb {
…
/* shadow spread is initally 0 */
box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
/* if motion is OK, transition the box-shadow change */
@media (--motionOK) {
& {
transition: box-shadow .1s ease;
}
}
/* on hover/active state of parent, increase size prop */
@nest input[type="range"]:is(:hover,:active) & {
--thumb-highlight-size: 10px;
}
}
Celem była łatwa w zarządzaniu animowana wizualizacja z informacjami dla użytkowników. Używając cienia ramki, mogę uniknąć uruchamiania układ z efektem. Ja to robię tworząc cień, który nie jest rozmyty i pasuje do okrągłego kształtu kciuka. Potem zmieniam i przenoszę rozmiar rozłożonego po najechaniu kursorem.
Gdyby tylko efekt zaznaczenia był tak łatwy w polach wyboru...
Selektory w różnych przeglądarkach
Widzę, że do wyświetlania w różnych przeglądarkach potrzebuję tych selektorów -webkit-
i -moz-
spójność:
input[type="range"] {
&::-webkit-slider-runnable-track {}
&::-moz-range-track {}
&::-webkit-slider-thumb {}
&::-moz-range-thumb {}
}
Niestandardowe pole wyboru
Na podstawie poniższego elementu wejściowego kodu HTML pokażę, Wygląd:
<input type="checkbox">
Ten element wymaga dostosowania w 3 częściach:
Element pola wyboru
input[type="checkbox"] {
inline-size: var(--space-sm); /* increase width */
block-size: var(--space-sm); /* increase height */
outline-offset: 5px; /* focus style enhancement */
accent-color: var(--brand); /* tint the input */
position: relative; /* prepare for an absolute pseudo element */
transform-style: preserve-3d; /* create a 3d z-space stacking context */
margin: 0;
cursor: pointer;
}
Style transform-style
i position
są przygotowane na wprowadzenie pseudoelementu, który omówimy później
aby zmienić styl zaznaczenia. W przeciwnym razie jest to przeważnie
ode mnie tylko zdania na temat stylu mniejszości. Kursor jest wskaźnikiem.
obrysu konturu, domyślne pola wyboru są za małe, a jeśli accent-color
ma
supported, wstaw te
ze schematem kolorów marki.
Etykiety pól wyboru
Etykiety pól wyboru należy podać z 2 powodów. Po pierwsze, wskazują, do czego służy wartość pola wyboru, aby odpowiedzieć „w jakim celu?” Po drugie, jeśli chodzi o wygodę użytkowników, użytkownicy przyzwyczajają się za pomocą powiązanych etykiet.
<input type="checkbox" id="text-notifications" name="text-notifications" >
<label for="text-notifications"> <h3>Text Messages</h3> <small>Get notified about all text messages sent to your device</small> </label>
Na etykiecie umieść atrybut for
wskazujący pole wyboru o identyfikatorze: <label for="text-notifications">
. W polu wyboru podwój nazwę i identyfikator, by
aby ją znaleźć, korzystając z różnych narzędzi i technologii, takich jak mysz czy czytnik ekranu.
<input type="checkbox" id="text-notifications" name="text-notifications">
:hover
, :active
i inne usługi są bezpłatne dzięki połączeniu, co zwiększa
sposobów interakcji z formularzem.
Wyróżnienie pola wyboru
Chcę zachować spójność interfejsów, a suwak ma ładny wygląd
miniaturę miniatury, której chcę użyć z polem wyboru. Miniatura była
może używać właściwości box-shadow
i spread
do skalowania cienia w górę,
w dół. Taki efekt nie działa jednak w tym przypadku, ponieważ nasze pola wyboru są i powinny
be, kwadrat.
Taki sam efekt wizualny udało mi się uzyskać dzięki pseudoelementowi, i mnóstwo trudnych problemów z kodem CSS:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
input[type="checkbox"]::before {
--thumb-scale: .01; /* initial scale of highlight */
--thumb-highlight-size: var(--space-xl);
content: "";
inline-size: var(--thumb-highlight-size);
block-size: var(--thumb-highlight-size);
clip-path: circle(50%); /* circle shape */
position: absolute; /* this is why position relative on parent */
top: 50%; /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
left: 50%;
background: var(--thumb-highlight-color);
transform-origin: center center; /* goal is a centered scaling circle */
transform: /* order here matters!! */
translateX(-50%) /* counter balances left: 50% */
translateY(-50%) /* counter balances top: 50% */
translateZ(-1px) /* PUTS IT BEHIND THE CHECKBOX */
scale(var(--thumb-scale)) /* value we toggle for animation */
;
will-change: transform;
@media (--motionOK) { /* transition only if motion is OK */
& {
transition: transform .2s ease;
}
}
}
/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
--thumb-scale: 1;
}
Utworzenie pseudoelementu okręgu nie jest trudne, ale umieszczenie go elementu, z którym jest połączony, było trudniejsze. Oto przed i po naprawieniu tego błędu:
To oczywiście mikrointerakcja,
ale zależy mi na tym,
i zapewniać spójność. Metoda skalowania animacji jest taka sama jak
w innych miejscach. Ustawiamy właściwość niestandardową na nową wartość i pozwólmy CSS przenieść ją
na podstawie preferencji ruchu. Kluczową funkcją jest translateZ(-1px)
.
element nadrzędny utworzył przestrzeń 3D, a ten pseudoelementowy element podrzędny skorzystał z niej przez
umiejscowienie się nieco z powrotem w przestrzeni Z.
Ułatwienia dostępu
Film w YouTube wspaniale eksponuje mysz, klawiaturę i dla interakcji z czytnikiem ekranu. Będę przywołać kilka tutaj.
Wybór elementu HTML
<form>
<header>
<fieldset>
<picture>
<label>
<input>
Każda z nich zawiera wskazówki i wskazówki dla narzędzia przeglądania. Niektóre elementy zawiera wskazówki dotyczące interakcji, umożliwia interaktywność, drzewo ułatwień dostępu, z którego korzysta czytnik ekranu.
Atrybuty HTML
Możemy ukryć elementy, które nie są potrzebne czytnikom ekranu, w tym przypadku ikona obok suwaka:
<picture aria-hidden="true">
Powyższy film pokazuje działanie czytnika ekranu w systemie Mac OS. Zwróć uwagę na sposób wprowadzania zaznaczenie przesuwa się prosto z jednego suwaka na drugi. To dlatego, że ukryliśmy ikonę, która mogła stanowić przystanek na drodze do następnego suwaka. Bez tego użytkownik musiałby zatrzymać się, posłuchać i przejść dalej niż obraz, który których mogą nie widzieć.
Format SVG to typ matematyki, dodajmy element <title>
umożliwiający swobodne najechanie kursorem myszy.
tytuł i zrozumiały dla człowieka komentarz na temat tego, co matematyka:
<svg viewBox="0 0 24 24">
<title>A note icon</title>
<path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>
Poza tym w formularzu zastosowaliśmy wystarczająco dużo wyraźnie oznaczonego kodu HTML, z myszy, klawiatury, kontrolerów do gier i czytników ekranu.
JavaScript
Omówiliśmy już sposób zarządzania kolorem wypełnienia ścieżki za pomocą JavaScriptu.
przyjrzyjmy się teraz powiązanemu skryptowi JavaScript <form>
:
const form = document.querySelector('form');
form.addEventListener('input', event => {
const formData = Object.fromEntries(new FormData(form));
console.table(formData);
})
Za każdym razem, gdy nastąpi interakcja z formularzem i jego zmiana, konsola zarejestruje formularz jako obiektu w tabeli w celu łatwego sprawdzenia przed przesłaniem na serwer.
Podsumowanie
Skoro już wiesz, jak to robię, jak Ty?! To będzie dobra zabawa architekturę komponentów. Kto stworzy pierwszą wersję z miejscami ulubiony schemat? 🙂
Stosujmy różne podejścia i poznajmy sposoby budowania obecności w internecie. Utwórz wersję demonstracyjną, a potem dodaj linki do funkcji tweetuj mi. znajdziesz w sekcji Remiksy społeczności poniżej.