סקירה כללית בסיסית של תהליך היצירה של רכיב מתג נגישות ורספונסיבי.
בפוסט הזה אני רוצה לשתף אתכם במחשבה על דרך לפיתוח רכיבים שונים. רוצים לנסות את ההדגמה?
אם אתם מעדיפים סרטון, הנה גרסה של YouTube לפוסט:
סקירה כללית
מתג פועל באופן דומה לתיבת סימון אלא מייצג במפורש מצבים בוליאניים של הפעלה וכיבוי.
ההדגמה הזו משתמשת ב-<input type="checkbox" role="switch">
ברוב
לפונקציונליות הזו, שלא צריך להשתמש ב-CSS או ב-JavaScript
פונקציונליות מלאה ונגישות. טעינת CSS מאפשרת תמיכה מימין לשמאל
שפות, אנכיות, אנימציה ועוד. טעינת JavaScript מבצעת את המעבר
מוחשי לגרירה.
מאפיינים מותאמים אישית
המשתנים הבאים מייצגים את החלקים השונים של המתג ואת
אפשרויות. כמחלקה ברמה העליונה, .gui-switch
מכיל מאפיינים מותאמים אישית שנמצאים בשימוש
לרכיבי הצאצאים של הרכיבים, ובנקודות הכניסה
בהתאמה אישית.
מעקב
האורך (--track-size
), המרווח הפנימי ושני צבעים:
.gui-switch {
--track-size: calc(var(--thumb-size) * 2);
--track-padding: 2px;
--track-inactive: hsl(80 0% 80%);
--track-active: hsl(80 60% 45%);
--track-color-inactive: var(--track-inactive);
--track-color-active: var(--track-active);
@media (prefers-color-scheme: dark) {
--track-inactive: hsl(80 0% 35%);
--track-active: hsl(80 60% 60%);
}
}
תמונות ממוזערות
הגודל, צבע הרקע וצבעי האינטראקציה מדגישים:
.gui-switch {
--thumb-size: 2rem;
--thumb: hsl(0 0% 100%);
--thumb-highlight: hsl(0 0% 0% / 25%);
--thumb-color: var(--thumb);
--thumb-color-highlight: var(--thumb-highlight);
@media (prefers-color-scheme: dark) {
--thumb: hsl(0 0% 5%);
--thumb-highlight: hsl(0 0% 100% / 25%);
}
}
תנועה מופחתת
כדי להוסיף כינוי ברור ולהפחית את חזרות, משתמש עם העדפת תנועה מופחתת אפשר להזין שאילתת מדיה בנכס מותאם אישית באמצעות PostCSS יישומי פלאגין שמבוססים על הטיוטה הזו מפרט בשאילתות מדיה 5:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Markup
בחרתי לעטוף את הרכיב <input type="checkbox" role="switch">
שלי עם
<label>
, קיבוץ הקשרים כדי למנוע שיוך של תיבות סימון ותוויות
אי בהירות, ובמקביל לתת למשתמש את היכולת לקיים אינטראקציה עם התווית
להחליף את מצב הקלט.
<label for="switch" class="gui-switch">
Label text
<input type="checkbox" role="switch" id="switch">
</label>
<input type="checkbox">
מגיע מראש עם
API
ומצב.
הדפדפן מנהל את
checked
מאפיין וקלט
אירועים
כגון oninput
ו-onchanged
.
פריסות
Flexbox, רשת ובהתאמה אישית הנכסים הם חיוניים בשמירה על הסגנונות של הרכיב הזה. הם מרכזים ערכים, נותנים שמות כדי ליצור חישובים או אזורים מעורפלים אחרים, ולאפשר נכס קטן מותאם אישית ממשק API להתאמה אישית קלה של רכיבים.
.gui-switch
הפריסה ברמה העליונה של המתג היא Flexbox. הכיתה .gui-switch
מכילה
את הנכסים המותאמים אישית הפרטיים והציבוריים שבהם הילדים משתמשים כדי לחשב
שונות.
.gui-switch {
display: flex;
align-items: center;
gap: 2ch;
justify-content: space-between;
}
הרחבה ושינוי של פריסת Flexbox הם כמו שינוי של כל פריסה של Flexbox.
לדוגמה, כדי להציב תוויות מעל או מתחת למתג, או כדי לשנות את
flex-direction
:
<label for="light-switch" class="gui-switch" style="flex-direction: column">
Default
<input type="checkbox" role="switch" id="light-switch">
</label>
מעקב
הקלט של תיבת הסימון מעוצב כרצועה של מתג על ידי הסרת הערך הרגיל
appearance: checkbox
ולציין גודל משלו במקום:
.gui-switch > input {
appearance: none;
inline-size: var(--track-size);
block-size: var(--thumb-size);
padding: var(--track-padding);
flex-shrink: 0;
display: grid;
align-items: center;
grid: [track] 1fr / [track] 1fr;
}
המסלול גם יוצר אזור של מסלולי רשת, אחד אחרי השני, לאגודל .
תמונות ממוזערות
הסגנון appearance: none
מסיר גם את סימן הווי החזותי שסופק על ידי
בדפדפן. רכיב זה משתמש
רכיב מדומה וה:checked
pseudo-class בקלט,
החלפת האינדיקטור החזותי הזה.
האגודל הוא צאצא של פסאודו-אלמנט שמחובר ל-input[type="checkbox"]
ול-
מופיע על גבי הטראק במקום מתחתיו, על ידי הצהרה על אזור הרשת
track
:
.gui-switch > input::before {
content: "";
grid-area: track;
inline-size: var(--thumb-size);
block-size: var(--thumb-size);
}
סגנונות
מאפיינים מותאמים אישית מאפשרים רכיב מתג רב-תכליתי שמתאים לצבעים סכמות, שפות מימין לשמאל והעדפות תנועה.
סגנונות אינטראקציה במגע
בנייד, דפדפנים מוסיפים לתוויות הדגשות מסוג הקשה ותכונות לבחירת טקסט
של קלטים. אלו השפיעו לרעה על הסגנון ועל המשוב החזותי של האינטראקציות
המתג הזה נדרש. עם כמה שורות של CSS אפשר להסיר את האפקטים האלה ולהוסיף אותם
סגנון cursor: pointer
משלי:
.gui-switch {
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
לא תמיד מומלץ להסיר את הסגנונות האלה, כי הם יכולים להיות בעלי ערך ויזואלי משוב על אינטראקציה. חשוב לספק חלופות בהתאמה אישית אם מסירים אותן.
מעקב
הסגנונות של הרכיב הזה מתמקדים בעיקר בצורה ובצבע שלו, שאליהם הוא ניגש
מההורה .gui-switch
דרך
מדורג.
.gui-switch > input {
appearance: none;
border: none;
outline-offset: 5px;
box-sizing: content-box;
padding: var(--track-padding);
background: var(--track-color-inactive);
inline-size: var(--track-size);
block-size: var(--thumb-size);
border-radius: var(--track-size);
}
מגוון רחב של אפשרויות להתאמה אישית במתג הנגישות
מאפיינים מותאמים אישית. border: none
התווסף כי appearance: none
לא
להסיר את הגבולות מתיבות הסימון בכל הדפדפנים.
תמונות ממוזערות
אלמנט האגודל כבר מופיע ב-track
השמאלי, אך יש צורך בסגנונות של עיגול:
.gui-switch > input::before {
background: var(--thumb-color);
border-radius: 50%;
}
אינטראקציה
משתמשים במאפיינים מותאמים אישית כדי להתכונן לאינטראקציות שיוצגו כשמעבירים את העכבר מעל הדגשה ושינויים במיקום הסמן. ההעדפה של המשתמש היא גם לפני ההעברה זזים או מעבירים את העכבר מעל סגנונות ההדגשה.
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
המיקום של האגודל
נכסים מותאמים אישית מספקים מנגנון מקור יחיד למיקום האגודל
את הטראק. לרשותנו נמצאים גודלי הרצועות והאגודל שבהם נשתמש
כדי לקזז את האגודל בצורה נכונה בין פריטים בתוך הטראק:
0%
וגם 100%
הרכיב input
הוא הבעלים של משתנה המיקום --thumb-position
והאגודל
רכיב פסאודו משתמש בו כמיקום translateX
:
.gui-switch > input {
--thumb-position: 0%;
}
.gui-switch > input::before {
transform: translateX(var(--thumb-position));
}
עכשיו אנחנו יכולים לשנות את --thumb-position
בהגדרות של שירות ה-CSS ושל המחלקות המדומה
סופקו באלמנטים של תיבות סימון. מכיוון שהגדרנו את transition: transform
var(--thumb-transition-duration) ease
בשלב מוקדם יותר של הרכיב הזה, השינויים האלה
עשוי להוסיף אנימציה כאשר משנים אותו:
/* positioned at the end of the track: track length - 100% (thumb width) */
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
}
/* positioned in the center of the track: half the track - half the thumb */
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
}
חשבתי שהתזמור הנפרד הזה עובד כמו שצריך. הרכיב הראשי הוא
רלוונטיים רק לסגנון אחד, מיקום של translateX
. הקלט יכול לנהל את כל
את המורכבות והחישובים.
לאורך
התמיכה בוצעה באמצעות תכונת שינוי של מחלקה -vertical
, שמוסיפה רוטציה עם
שירות CSS מבצע טרנספורמציה לרכיב input
.
עם זאת, רכיב מסובב בתלת ממד לא משנה את הגובה הכולל של הרכיב.
מה שעלול להשפיע על פריסת הבלוקים. חשבון זה באמצעות --track-size
ו
--track-padding
משתנים. חשבו את השטח המינימלי שנדרש
לחצן אנכי לזרימה בפריסה כמצופה:
.gui-switch.-vertical {
min-block-size: calc(var(--track-size) + calc(var(--track-padding) * 2));
& > input {
transform: rotate(-90deg);
}
}
(RTL) מימין לשמאל
חבר שירות CSS, אלד שכטר ואני יצרנו אב טיפוס יחד החלק בתפריט צדדי באמצעות התמרות ב-CSS המטפלות מימין לשמאל באמצעות היפוך מותאם אישית. עשינו את זה כי אין טרנספורמציות של מאפיינים לוגיים ב-CSS, ואולי אף פעם לא יהיו. לאלאד היה רעיון נהדר להשתמש בערך מותאם אישית של נכס להפוך אחוזים, כדי לאפשר ניהול מיקום יחיד של של טרנספורמציות לוגיות. השתמשתי באותה טכניקה במתג הזה נראה שזה עבד מצוין:
.gui-switch {
--isLTR: 1;
&:dir(rtl) {
--isLTR: -1;
}
}
מאפיין מותאם אישית שנקרא --isLTR
מכיל בהתחלה את הערך 1
, כלומר
true
מכיוון שהפריסה שלנו היא משמאל לימין כברירת מחדל. לאחר מכן, באמצעות שירות ה-CSS
פסאודו class :dir()
,
הערך מוגדר ל--1
כשהרכיב נמצא בפריסה מימין לשמאל.
כדי להחיל את --isLTR
בתוך טרנספורמציה, צריך להשתמש בו בתוך calc()
:
.gui-switch.-vertical > input {
transform: rotate(-90deg);
transform: rotate(calc(90deg * var(--isLTR) * -1));
}
עכשיו הסיבוב של המתג האנכי קובע את המיקום הנגדי. שנדרשת על ידי הפריסה מימין לשמאל.
צריך לעדכן גם את הטרנספורמציות translateX
ברכיב לדוגמה
חשבון לדרישה ההפוך:
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
--thumb-position: calc(
((var(--track-size) / 2) - (var(--thumb-size) / 2))
* var(--isLTR)
);
}
הגישה הזו לא תצליח לתת מענה לכל הצרכים של קונספטים כמו שירות CSS לוגי משתנה, הוא מציע עקרונות DRY במקרים שונים.
מדינות
השימוש בפלטפורמה input[type="checkbox"]
לא יושלם בלי
טיפול במצבים הבאים: :checked
, :disabled
,
:indeterminate
וגם :hover
. :focus
נשארה לבדה בכוונה, עם
התאמה שבוצעה לקיזוז שלה בלבד; טבעת המיקוד נראתה מעולה ב-Firefox
Safari:
מסומן
<label for="switch-checked" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-checked" checked="true">
</label>
המצב הזה מייצג את המצב on
. במצב הזה, הקלט "track"
הרקע מוגדר לצבע הפעיל ומיקום האגודל מוגדר
סוף".
.gui-switch > input:checked {
background: var(--track-color-active);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
מושבת
<label for="switch-disabled" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-disabled" disabled="true">
</label>
לחצן :disabled
לא רק נראה שונה מבחינה חזותית, אלא גם צריך לגרום
אלמנט לא ניתן לשינוי.לא ניתנים לשינוי של אינטראקציה מהדפדפן, אבל
מצבים ויזואליים צריכים סגנונות בגלל השימוש ב-appearance: none
.
.gui-switch > input:disabled {
cursor: not-allowed;
--thumb-color: transparent;
&::before {
cursor: not-allowed;
box-shadow: inset 0 0 0 2px hsl(0 0% 100% / 50%);
@media (prefers-color-scheme: dark) { & {
box-shadow: inset 0 0 0 2px hsl(0 0% 0% / 50%);
}}
}
}
המצב הזה לא פשוט כי יש צורך בעיצוב בהיר ועיצוב כהים, כשהאפשרות 'מושבתת' וגם את המצבים המסומנים בכוכב. בחרתי סגנונות מינימליים למצבים האלה כדי שיהיה קל יותר נטל התחזוקה של שילובי הסגנונות.
לא קבוע
מצב שנשכח לעיתים קרובות הוא :indeterminate
, שבו תיבת סימון היא לא מצב
מסומנת או לא מסומנת. זהו מצב כיפי, מזמין וקליל. טובה
תזכורת שמצבים בוליאניים עלולים להיות "מטעים" בין מדינות.
קשה להגדיר תיבת סימון כדי לקבוע מועד, רק JavaScript יכול להגדיר אותה:
<label for="switch-indeterminate" class="gui-switch">
Indeterminate
<input type="checkbox" role="switch" id="switch-indeterminate">
<script>document.getElementById('switch-indeterminate').indeterminate = true</script>
</label>
מאחר שהמדינה, מבחינתי, צנועה ומזמינה, הרגשתי מקובל להציג מיקום אגודל המתג באמצע:
.gui-switch > input:indeterminate {
--thumb-position: calc(
calc(calc(var(--track-size) / 2) - calc(var(--thumb-size) / 2))
* var(--isLTR)
);
}
העברת העכבר מלמעלה
האינטראקציות של העברת העכבר צריכות לספק תמיכה חזותית בממשק המשתמש המקושר, וגם לספק כיוון בממשק משתמש אינטראקטיבי. המתג הזה מדגיש את האגודל באמצעות טבעת שקופה למחצה כשהתווית או הקלט מעבירים את העכבר מעליה. העברת העכבר לאחר מכן מספקת כיוון ביחס לאלמנט האצבע האינטראקטיבי.
ה'הדגשה' האפקט מסתיים ב-box-shadow
. כשמעבירים את העכבר מעל קלט שאינו מושבת, מגדילים את הערך של --highlight-size
. אם התנועה מקובלת על המשתמש, אנחנו מחליפים את box-shadow
ונראה שהוא גדל. אם התנועה לא מקובלת עליו, ההדגשה תופיע מיד:
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
.gui-switch > input:not(:disabled):hover::before {
--highlight-size: .5rem;
}
JavaScript
בעיניי, ממשק מתג יכול להיראות מוזר בניסיון לחקות מודל פיזי במיוחד מהסוג הזה, כשיש עיגול בתוך מסלול. פתרת את הבעיה ב-iOS עם המתג שלו, אפשר לגרור אותם מצד לצד, יש אפשרות. לעומת זאת, רכיב בממשק המשתמש יכול להיראות לא פעיל אם תנועת גרירה וכלום לא קורה.
סימוני 'אהבתי' שניתן לגרור
הרכיב המדומה מקבל את המיקום שלו מ-.gui-switch > input
בהיקף var(--thumb-position)
, JavaScript יכול לספק ערך סגנון מוטבע
את הקלט כדי לעדכן באופן דינמי את מיקום האגודל, כך שייראה כאילו הוא
תנועת הסמן. לאחר שחרור הסמן, מסירים את הסגנונות המוטבעים ואז
לקבוע אם הגרירה הייתה קרובה יותר למצב כבוי או יותר באמצעות המאפיין המותאם אישית
--thumb-position
זה עמוד התווך של הפתרון; אירועי תנועה
מעקב מותנה אחר מיקומי הסמן כדי לשנות מאפיינים מותאמים אישית של CSS.
הרכיב כבר היה 100% פונקציונליות לפני שהסקריפט הזה הוצג נדרש לא מעט עבודה כדי לשמור על ההתנהגות הקיימת, כמו לחיצה על תווית כדי להחליף את מצב הקלט. קוד ה-JavaScript שלנו לא אמור להוסיף תכונות על חשבון התכונות הקיימות.
touch-action
גרירה היא תנועה מותאמת אישית, שהופכת אותה למועמדת נהדרת
הטבות של touch-action
. במקרה של המתג הזה, תנועה אופקית צריכה
מטופל באמצעות התסריט שלנו, או תנועה אנכית שתועדה עבור המתג האנכי
הווריאנט. בעזרת touch-action
אנחנו יכולים להגדיר לדפדפן באילו תנועות להשתמש
של הרכיב הזה, כך שהסקריפט יכול להתמודד עם תנועה ללא תחרות.
קוד ה-CSS הבא מורה לדפדפן שכאשר תנועת מצביע מתחילה מ- בתוך הטראק הזה, טיפול בתנועות אנכיות, לא לעשות כלום עם כיוון אופקי after:
.gui-switch > input {
touch-action: pan-y;
}
התוצאה הרצויה היא תנועה אופקית שלא הזזה או גלילה של הדף הזה. מצביע יכול לגלול אנכית להתחיל מתוך הקלט ולגלול אבל עמודות אופקיות מטופלות בהתאמה אישית.
כלי עזר לסגנון של ערך Pixel
בתהליך ההגדרה ובמהלך הגרירה, יהיה צורך לשלוף ערכים שונים של מספרים שמחושבים
מאלמנטים. פונקציות ה-JavaScript הבאות מחזירות ערכי פיקסלים מחושבים
שניתנו במאפיין CSS. הוא משמש בסקריפט ההגדרה כך
getStyle(checkbox, 'padding-left')
const getStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element).getPropertyValue(prop));
}
const getPseudoStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element, ':before').getPropertyValue(prop));
}
export {
getStyle,
getPseudoStyle,
}
שימו לב איך window.getComputedStyle()
מקבל ארגומנט שני, רכיב פסאודו של יעד. די מדליק ש-JavaScript יכול לקרוא כל כך הרבה ערכים מאלמנטים, אפילו מאלמנטים של פסאודו.
dragging
זהו רגע מרכזי בלוגיקת הגרירה, ויש כמה דברים שחשוב לשים לב אליהם מגורם המטפל באירועים של הפונקציה:
const dragging = event => {
if (!state.activethumb) return
let {thumbsize, bounds, padding} = switches.get(state.activethumb.parentElement)
let directionality = getStyle(state.activethumb, '--isLTR')
let track = (directionality === -1)
? (state.activethumb.clientWidth * -1) + thumbsize + padding
: 0
let pos = Math.round(event.offsetX - thumbsize / 2)
if (pos < bounds.lower) pos = 0
if (pos > bounds.upper) pos = bounds.upper
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
}
הגיבור של התסריט הוא state.activethumb
, העיגול הקטן הזה שהסקריפט הזה
את המיקום יחד עם מצביע. האובייקט switches
הוא Map()
שבו
המפתחות הם של .gui-switch
והערכים הם גבולות וגדלים שנשמרו במטמון
ביעילות התסריט. מתבצע עיבוד מימין לשמאל באמצעות אותו מאפיין מותאם אישית
ששירות ה-CSS הוא --isLTR
, ויכול להשתמש בו כדי להפוך לוגיקה ולהמשיך
שתומך ב-RTL. גם הערך של event.offsetX
חשוב, כי הוא מכיל דלתא
שימושי למיקום האגודל.
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
השורה האחרונה של ה-CSS מגדירה את המאפיין המותאם אישית שבו משתמש הרכיב הראשי. הזה
אחרת, הקצאת הערכים תשתנה עם הזמן, אבל מצביע קודם
האירוע הגדיר באופן זמני את הערך --thumb-transition-duration
לערך 0s
, והמערכת מסירה את מה
האינטראקציה הייתה איטית.
dragEnd
כדי לאפשר למשתמש לגרור רחוק מחוץ למתג ולהרפות, אירוע חלון גלובלי נדרש לצורך רישום:
window.addEventListener('pointerup', event => {
if (!state.activethumb) return
dragEnd(event)
})
אני חושב שחשוב מאוד למשתמש תהיה חופש לגרור באופן משוחרר יהיה חכם מספיק כדי להביא בחשבון את זה. לא נדרש הרבה טיפול עם מתג זה, אך היה צורך להפעיל שיקול דעת בעת הפיתוח תהליך האימות.
const dragEnd = event => {
if (!state.activethumb) return
state.activethumb.checked = determineChecked()
if (state.activethumb.indeterminate)
state.activethumb.indeterminate = false
state.activethumb.style.removeProperty('--thumb-transition-duration')
state.activethumb.style.removeProperty('--thumb-position')
state.activethumb.removeEventListener('pointermove', dragging)
state.activethumb = null
padRelease()
}
האינטראקציה עם האלמנט הסתיימה, הגיע הזמן להגדיר את הקלט שנבדק
מאפיין ולהסיר את כל אירועי התנועה. תיבת הסימון תשתנה עם
state.activethumb.checked = determineChecked()
determineChecked()
הפונקציה הזו, שנקראת על ידי dragEnd
, קובעת את המיקום של האגודל
בתוך גבולות הטראק, ומחזירה את הערך true אם הוא שווה ל- או מעל
באמצע המסלול:
const determineChecked = () => {
let {bounds} = switches.get(state.activethumb.parentElement)
let curpos =
Math.abs(
parseInt(
state.activethumb.style.getPropertyValue('--thumb-position')))
if (!curpos) {
curpos = state.activethumb.checked
? bounds.lower
: bounds.upper
}
return curpos >= bounds.middle
}
מחשבות נוספות
תנועת הגרירה גרמה למעט חוב בקוד בגלל מבנה ה-HTML הראשוני
נבחר, בעיקר ועוטף את הקלט בתווית. את התווית, כהורה
יקבל אינטראקציות של קליקים אחרי הקלט. בסוף המשימה
אירוע מסוג dragEnd
, יכול להיות שהבחנת ב-padRelease()
כאירוע מוזר
מותאמת אישית.
const padRelease = () => {
state.recentlyDragged = true
setTimeout(_ => {
state.recentlyDragged = false
}, 300)
}
זאת כדי להביא בחשבון את התווית שמקבלת את הקליק הזה מאוחר יותר, שכן היא תבטל את הסימון של או לבדוק, את האינטראקציה שמשתמש ביצע.
אם אעשה זאת שוב, אולי אשקול לשנות את ה-DOM באמצעות JavaScript במהלך השדרוג של חוויית המשתמש, וכך ליצור רכיב שמטפל בקליקים על תוויות ולא נאבק בהתנהגות מובנית.
סוג ה-JavaScript הזה הוא הכי פחות אהוב עליי, אני לא רוצה לנהל מבעבוע של אירוע מותנה:
const preventBubbles = event => {
if (state.recentlyDragged)
event.preventDefault() && event.stopPropagation()
}
סיכום
רכיב ההחלפה הזה הוא בסופו של דבר היצירה הקשה ביותר מכל אתגרי GUI עד עכשיו! עכשיו, אחרי שהסברתי איך עשיתי את זה, איך היית? 🙂
בואו לגוון את הגישות שלנו ונלמד את כל הדרכים לבניית אתרים באינטרנט. אפשר ליצור הדגמה, לשלוח לי קישורים של שלחו לי ציוץ ואני אוסיף אותם לקטע 'רמיקסים' של הקהילה שבהמשך.
רמיקסים קהילתיים
- @KonstantinRouda עם רכיב מותאם אישית: demo וקוד.
- @jhvanderschee עם לחצן: Codepen.
משאבים
איתור קוד המקור של .gui-switch
באתר
מ-GitHub.