Filters

Details

The slider moves through the letters of the alpahbet. Animals whose names contain the letter get highlighted. The rest of them get crossed out.

I'm using bitty to wire things up. The rest of the code is here

The HTML

<bitty-2-0 
  data-connect="/components/weird.js" 
  data-send="init">
  <div class="filter-line">
    <label
      >Find animals with the letter: <span data-receive="letter">-</span><br />
      <input
        type="range"
        value="0"
        min="0"
        max="26"
        step="1"
        data-send="letter|animal"
      />
    </label>
  </div>
  <div class="animals" data-receive="init"></div>
</bitty-2-0>

The JavaScript

/components/weird.js
const template = `<div
  class="animal"
  data-receive="animal" 
  data-animal="ANIMAL">
  ANIMAL
</div>`;

export default class {
  async bittyInit() {
    const data = await this.api.getJSON("/animals.json");
    this.animals = data.list;
  }

  init(_event, el) {
    this.animals.forEach((animal) => {
      const subs = [["ANIMAL", animal]];
      const animalEl = this.api.useHTML(template, subs);
      el.appendChild(animalEl);
    });
  }

  animal(event, el) {
    const index = parseInt(event.target.value, 10);
    const letters = el.dataset.animal.split("");
    if (index === 0) {
      el.dataset.status = "none";
    } else {
      const checkLetter = String.fromCharCode(index + 96);
      if (letters.includes(checkLetter)) {
        el.dataset.status = "in";
      } else {
        el.dataset.status = "out";
      }
    }
  }

  letter(event, el) {
    const index = parseInt(event.target.value, 10);
    el.innerHTML = index === 0
      ? "-"
      : String.fromCharCode(index + 96);
  }
}

The CSS

[data-status=in] {
  font-weight: 900;
}

[data-status=out] {
  text-decoration: line-through;
  color: var(--default-faded);
}

.animal {
  width: 10rem;
}

.animals {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.filter-line {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

input {
  width: 100%;
}