JSFiddle - React, Tailwind, and code Playground
by Artem
HTML
<div class="sticky-widget">
<ul class="sticky-widget__list">
<li class="sticky-widget__list-item">
<i class="sticky-widget__icon">S3</i>
<p class="sticky-widget__title">Simple Storage Service (S3)</p>
</li>
<li class="sticky-widget__list-item">
<i class="sticky-widget__icon">DF</i>
<p class="sticky-widget__title">Data Fusion</p>
</li>
<li class="sticky-widget__list-item">
<i class="sticky-widget__icon">H</i>
<p class="sticky-widget__title">Hadoop (EMR)</p>
</li>
<li class="sticky-widget__list-item">
<i class="sticky-widget__icon">P</i>
<p class="sticky-widget__title">PostgreSQL</p>
</li>
<li class="sticky-widget__list-item sticky-widget__list-item--no-border">
<i class="sticky-widget__icon">M</i>
<p class="sticky-widget__title">MySQL</p>
</li>
</ul>
</div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
<li>21</li>
<li>22</li>
<li>23</li>
<li>24</li>
<li>25</li>
<li>26</li>
<li>27</li>
<li>28</li>
<li>29</li>
<li>30</li>
<li>31</li>
<li>32</li>
<li>33</li>
<li>34</li>
<li>35</li>
<li>36</li>
<li>37</li>
<li>38</li>
<li>39</li>
<li>40</li>
<li>41</li>
<li>42</li>
<li>43</li>
<li>44</li>
<li>45</li>
<li>46</li>
<li>47</li>
<li>48</li>
<li>49</li>
<li>50</li>
<li>51</li>
<li>52</li>
<li>53</li>
<li>54</li>
<li>55</li>
<li>56</li>
<li>57</li>
<li>58</li>
<li>59</li>
<li>60</li>
<li>61</li>
<li>62</li>
<li>63</li>
<li>64</li>
<li>65</li>
<li>66</li>
<li>67</li>
<li>68</li>
<li>69</li>
<li>70</li>
<li>71</li>
<li>72</li>
<li>73</li>
<li>74</li>
<li data-service-id="s3">Simple Storage Service (S3)</li>
<li>76</li>
<li>77</li>
...
CSS
html,
body {
margin: 0;
padding: 0;
}
.sticky-widget {
position: fixed;
right: 0;
bottom: 200px;
width: 80px;
/* 69 260*/
height: 180px;
overflow-y: auto;
font-size: 14px;
border: 1px solid #ccc;
background-color: #fff;
box-sizing: border-box;
transition: width 600ms;
}
.sticky-widget:hover {
width: 260px;
}
.sticky-widget__list {
box-sizing: inherit;
margin: 0;
padding: 0;
list-style-type: none;
}
.sticky-widget__list-item {
padding: 10px 12px;
box-sizing: inherit;
height: 45px;
border-bottom: 1px solid #ccc;
border-left: 3px solid transparent;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
}
.sticky-widget__list-item:hover {
border-left: 3px solid #ff8000;
}
.sticky-widget__list-item--no-border {
border-bottom: none;
}
.sticky-widget__list-item::after {
content: '';
display: table;
clear: both;
}
.sticky-widget__icon {
display: inline-block;
width: 25px;
height: 25px;
border-radius: 50%;
line-height: 25px;
margin-right: 10px;
text-align: center;
background-color: rgb(64, 191, 174);
}
.sticky-widget__list-item--active .sticky-widget__icon {
background-color: #ff8000;
}
.sticky-widget__title {
display: inline-block;
margin: 0;
padding: 0;
opacity: 0;
vertical-align: middle;
transition: opacity 1s;
}
.sticky-widget:hover .sticky-widget__title {
opacity: 1;
display: inline-block;
}
JavaScript
'use strict';
var li = document.getElementsByClassName('sticky-widget__list-item')[0];
var s3 = document.querySelector('[data-service-id=s3]');
var activeClass = 'sticky-widget__list-item--active';
li.onclick = () => {
s3.scrollIntoView({
block: 'start',
behavior: 'smooth'
});
li.classList.add(activeClass);
};
var observer = new IntersectionObserver(function(entries, observer) {
console.log('observed');
entries.forEach(entry => {
if (entry.isIntersecting) {
li.classList.add(activeClass);
} else {
li.classList.remove(activeClass);
}
});
});
observer.observe(s3);