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);