<h1 class="page-title">CATS 🐈</h1>
<img src="https://cataas.com/cat?width=400&height=300" alt="" height="300" width="400" />
<button type="button" class="js-new-cat new-cat-button">New cat!</button>

<footer>Big thanks to <a href="https://cataas.com">Cat as a service</a></footer>
*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin-bottom: 0;
}

* + * {
  margin-top: 2rem;
}

:focus {
  outline: 0.25rem solid tomato;
  outline-offset: 0.2rem;
}

button,
input,
textarea {
  font-family: inherit;
  font-size: inherit;
}

:root {
  font-size: calc(1rem + 0.5vw);
}

body {
  align-items: center;
  background-color: paleturquoise;
  display: flex;
  flex-direction: column;
  font-family: monospace;
  justify-content: center;
  margin: 0;
  min-height: 100vh;
  padding: 0 0 4rem;
}

.page-title {
  background-color: white;
  font-size: 2rem;
  font-style: italic;
  padding: 0.25em;
  text-align: center;
}

.new-cat-button,
.confirm-dialog-button {
  background-color: white;
  border: 0.35em solid;
  border-bottom-color: steelblue;
  border-left-color: cadetblue;
  border-right-color: steelblue;
  border-top-color: cadetblue;
  cursor: pointer;
  font-size: 1.25rem;
  padding: 0.75em 1em;
}

img {
  border-radius: 0.75rem;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
  max-width: 100%;
  object-fit: cover;
}

.confirm-dialog {
  max-width: 45em;
  padding: 2rem;
  width: 90vw;

  &::backdrop {
    background-color: rgba(0, 0, 0, 0.3);
  }
}

.confirm-dialog-question {
  font-size: 1.5em;
  font-style: italic;
  font-weight: 600;
}

.confirm-dialog-button-group {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin: 1rem -1rem -1rem;
  
  > * {
    margin: 1rem;
  }
}

.confirm-dialog-button {
  font-size: 1rem;
}

footer {
  margin-top: 5rem;
  padding: 0 1rem;
}
View Compiled
const image = document.querySelector("img");
const newCatButton = document.querySelector(".js-new-cat");

newCatButton.addEventListener("click", async () => {
  const dialog = new ConfirmDialog({
    trueButtonText: "Yes!",
    falseButtonText: "Noo",
    questionText: "Are you sure you want to see yet another picture of a cat?"
  });

  const shouldFetchNewImage = await dialog.confirm();
  if (shouldFetchNewImage) {
    image.src = `https://cataas.com/cat?width=400&height=300&timestamp=${Date.now()}`;
  }
});

class ConfirmDialog {
  constructor({ questionText, trueButtonText, falseButtonText, parent }) {
    this.questionText = questionText || "Are you sure?";
    this.trueButtonText = trueButtonText || "Yes";
    this.falseButtonText = falseButtonText || "No";
    this.parent = parent || document.body;

    this.dialog = undefined;
    this.trueButton = undefined;
    this.falseButton = undefined;

    this._createDialog();
    this._appendDialog();
  }

  confirm() {
    return new Promise((resolve, reject) => {
      const somethingWentWrongUponCreation =
        !this.dialog || !this.trueButton || !this.falseButton;
      if (somethingWentWrongUponCreation) {
        reject('Someting went wrong when creating the modal');
        return;
      }
      
      this.dialog.showModal();
      this.trueButton.focus();

      this.trueButton.addEventListener("click", () => {
        resolve(true);
        this._destroy();
      });

      this.falseButton.addEventListener("click", () => {
        resolve(false);
        this._destroy();
      });
    });
  }

  _createDialog() {
    this.dialog = document.createElement("dialog");
    this.dialog.classList.add("confirm-dialog");

    const question = document.createElement("div");
    question.textContent = this.questionText;
    question.classList.add("confirm-dialog-question");
    this.dialog.appendChild(question);

    const buttonGroup = document.createElement("div");
    buttonGroup.classList.add("confirm-dialog-button-group");
    this.dialog.appendChild(buttonGroup);

    this.falseButton = document.createElement("button");
    this.falseButton.classList.add(
      "confirm-dialog-button",
      "confirm-dialog-button--false"
    );
    this.falseButton.type = "button";
    this.falseButton.textContent = this.falseButtonText;
    buttonGroup.appendChild(this.falseButton);

    this.trueButton = document.createElement("button");
    this.trueButton.classList.add(
      "confirm-dialog-button",
      "confirm-dialog-button--true"
    );
    this.trueButton.type = "button";
    this.trueButton.textContent = this.trueButtonText;
    buttonGroup.appendChild(this.trueButton);
  }

  _appendDialog() {
    this.parent.appendChild(this.dialog);
  }

  _destroy() {
    this.parent.removeChild(this.dialog);
    delete this;
  }
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.