<chunky-control-panel>
  <chunky-button text="" type="white"></chunky-button>
  <chunky-button text="hold" type="blue"></chunky-button>
  <chunky-button text="buzzer" type="yellow"></chunky-button>
  <chunky-button text="ring" type="green"></chunky-button>
  <chunky-button text="release" type="red"></chunky-button>
  <chunky-button text="sim coord" type="white"></chunky-button>
  <chunky-button text="" type="yellow"></chunky-button>
  <chunky-button text="FD 2" type="yellow"></chunky-button>
  <chunky-button text="a/g 2" type="yellow"></chunky-button>
  <chunky-button text="" type="white"></chunky-button>
  <chunky-button text="ops planner" type="blue"></chunky-button>
  <chunky-button text="" type="green"></chunky-button>
</chunky-control-panel>
class ChunkyButton extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: "open" })
    this.render()
    this.handleClicks()
  }

  render() {
    this.shadowRoot.innerHTML = `
      <style>
        .btn {
            background:
                linear-gradient(rgb(255, 255, 255, .8), 4%, rgb(0, 0, 0, 0)),
                linear-gradient(rgb(255, 255, 255, 0) 97%, rgb(0, 0, 0, .4) 99%, rgb(120, 120, 120, 0.4)),
                linear-gradient(30deg, #d7d0c8, #b1aaa4, #e4dbd0, #f0ede9),
                #d7d0c8;
            width: 208px;
            height: 128px;
            border-radius: 2px;
            box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.6);
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .btn .button-well {
            width: 90%;
            height: 85%;
            background: #222;
            border-radius: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
        }

        .btn .the-button {
            height: 96%;
            width: 99%;
            border-radius: 2px;
            position: relative;
            left: -1px;
            top: -2px;
            box-shadow: -1px 2px 3px rgba(0, 0, 0, 0.6);
            display: flex;
            align-items: center;
            justify-content: center;
            background: linear-gradient(rgba(255, 255, 255, 0.58), 1%, rgba(98, 98, 98, 0.35) 2%, 15%, rgba(217, 217, 214, 0.53) 18%, rgba(255, 255, 255, 0.81)),
                        #ddd149;
        }

        .btn .the-button.pushed {
          left: 1px;
          top: 3px;
          box-shadow: inset 2px 0px 6px rgba(0, 0, 0, 0.8);
        }

        .btn .the-button.yellow {
          background: linear-gradient(rgba(255, 255, 255, 0.58), 1%, rgba(98, 98, 98, 0.35) 2%, 15%, rgba(217, 217, 214, 0.53) 18%, rgba(255, 255, 255, 0.81)),
                      #f7ff00;
        }

        .btn .the-button.yellow.pushed {
          background: linear-gradient(rgba(98, 98, 98, 0.35) 80%, rgba(255, 255, 255, 0.40)),
                      #f7ff00;
        }

        .btn .the-button.blue {
          background: linear-gradient(rgba(255, 255, 255, 0.58), 1%, rgba(98, 98, 98, 0.35) 2%, 15%, rgba(217, 217, 214, 0.53) 18%, rgba(255, 255, 255, 0.81)),
                      #1061df;
        }

        .btn .the-button.blue.pushed {
          background: linear-gradient(rgba(98, 98, 98, 0.35) 80%, rgba(255, 255, 255, 0.40)),
                      #1061df;
        }

        .btn .the-button.red {
          background: linear-gradient(rgba(255, 255, 255, 0.58), 1%, rgba(98, 98, 98, 0.35) 2%, 15%, rgba(217, 217, 214, 0.53) 18%, rgba(255, 255, 255, 0.81)),
                      #bf0000;
        }

        .btn .the-button.red.pushed {
          background: linear-gradient(rgba(98, 98, 98, 0.35) 80%, rgba(255, 255, 255, 0.40)),
                      #bf0000;
        }

        .btn .the-button.white {
          background: linear-gradient(rgba(255, 255, 255, 0.58), 1%, rgba(98, 98, 98, 0.35) 2%, 15%, rgba(217, 217, 214, 0.53) 18%, rgba(255, 255, 255, 0.81)),
                      #eee;
        }

        .btn .the-button.white.pushed {
          background: linear-gradient(rgba(98, 98, 98, 0.35) 80%, rgba(255, 255, 255, 0.40)),
                      #eee;
        }

        .btn .the-button.green {
          background: linear-gradient(rgba(255, 255, 255, 0.58), 1%, rgba(98, 98, 98, 0.35) 2%, 15%, rgba(217, 217, 214, 0.53) 18%, rgba(255, 255, 255, 0.81)),
                      #057e45;
        }

        .btn .the-button.green.pushed {
          background: linear-gradient(rgba(98, 98, 98, 0.35) 80%, rgba(255, 255, 255, 0.40)),
                      #057e45;
        }

        .btn .button-content {
            font-family: monospace;
            text-transform: uppercase;
            font-size: 20px;
            letter-spacing: 0.1em;
        }
      </style>

      <div class="btn">
        <div class="button-well">
          <div class="the-button">
            <div class="button-content">Push it</div>
          </div>
        </div>
      </div>
    `
  }

  static get observedAttributes() {
    return ['text', 'type']
  }

  attributeChangedCallback(attr, oldVal, newVal) {
    if (attr === 'text') {
      this.shadowRoot.querySelector('.button-content').innerText = newVal
    }

    if (attr === 'type') {
      let btn = this.shadowRoot.querySelector('.the-button')
      const colors = ['yellow', 'blue', 'red', 'white', 'green']

      if (colors.includes(newVal)) {
        btn.classList.remove(...colors)
        btn.classList.add(newVal)
      }
    }
  }

  handleClicks() {
    let btn_el = this.shadowRoot.querySelector('.the-button')
    btn_el.addEventListener('mousedown', (e) => {
      e.preventDefault()
      btn_el.classList.add('pushed')
    })
    document.addEventListener('mouseup', (e) => {
      if (btn_el.classList.contains('pushed')) {
        btn_el.classList.remove('pushed')
        const event = new Event("custom-click")
        this.dispatchEvent(event)
      }
    })
  }
}

customElements.define('chunky-button', ChunkyButton)


class ChunkyControlPanel extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.render()
  }

  render() {
    this.shadowRoot.innerHTML = `
       <style>
         .buttons-container {
            display: flex;
            flex-direction: row;
            justify-content: center;
            gap: 1px 5px;
            background:
                linear-gradient(-30deg, #d7d0c8, #b1aaa4, #e4dbd0, #f0ede9),
                #d7d0c8;
            padding: 30px 10px;
            flex-wrap: wrap;
            box-shadow: 1px 2px 3px 1px #888;
            max-width: 850px;
          }
       </style>
       <div class="buttons-container">
         <slot></slot>
       </div>
    `
  }
}

customElements.define('chunky-control-panel', ChunkyControlPanel)

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.