From 762ca1b3abafc273ac999652e6a7d5a88c7f8a9f Mon Sep 17 00:00:00 2001 From: Ayo Date: Fri, 8 May 2026 14:01:27 +0200 Subject: [PATCH] feat: use slot & constructable stylesheet --- index.html | 2 +- src/status-indicator.ts | 5 +- src/stylesheets.ts | 113 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 src/stylesheets.ts diff --git a/index.html b/index.html index c8741f2..090fa15 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,6 @@ - + All systems operational \ No newline at end of file diff --git a/src/status-indicator.ts b/src/status-indicator.ts index c16e098..5cdfc5b 100644 --- a/src/status-indicator.ts +++ b/src/status-indicator.ts @@ -1,9 +1,12 @@ import { WebComponent, html } from 'web-component-base' +import stylesheet from './stylesheets' + +console.log(stylesheet.cssRules) class StatusIndicator extends WebComponent { get template(): any { return html` -

Hello, World!

+ ` } } diff --git a/src/stylesheets.ts b/src/stylesheets.ts new file mode 100644 index 0000000..d9b4d4a --- /dev/null +++ b/src/stylesheets.ts @@ -0,0 +1,113 @@ +const sheet = new CSSStyleSheet() + +sheet.replaceSync(` + :root { + --status-indicator-size: 0.5rem; + --status-indicator-animation-duration: 2s; + + --status-indicator-color: rgb(216, 226, 233); + --status-indicator-color-semi: rgba(216, 226, 233, .5); + --status-indicator-color-transparent: rgba(216, 226, 233, 0); + + --status-indicator-color-active: rgb(0, 149, 255); + --status-indicator-color-active-semi: rgba(0, 149, 255, .5); + --status-indicator-color-active-transparent: rgba(0, 149, 255, 0); + + --status-indicator-color-positive: rgb(75, 210, 143); + --status-indicator-color-positive-semi: rgba(75, 210, 143, .5); + --status-indicator-color-positive-transparent: rgba(75, 210, 143, 0); + + --status-indicator-color-intermediary: rgb(255, 170, 0); + --status-indicator-color-intermediary-semi: rgba(255, 170, 0, .5); + --status-indicator-color-intermediary-transparent: rgba(255, 170, 0, 0); + + --status-indicator-color-negative: rgb(255, 77, 77); + --status-indicator-color-negative-semi: rgba(255, 77, 77, .5); + --status-indicator-color-negative-transparent: rgba(255, 77, 77, 0); +} + +@keyframes status-indicator-pulse { + 0% { box-shadow: 0 0 0 0 var(--status-indicator-color-semi); } + 70% { box-shadow: 0 0 0 var(--status-indicator-size) var(--status-indicator-color-transparent); } + 100% { box-shadow: 0 0 0 0 var(--status-indicator-color-transparent); } +} + +@keyframes status-indicator-pulse-active { + 0% { box-shadow: 0 0 0 0 var(--status-indicator-color-active-semi); } + 70% { box-shadow: 0 0 0 var(--status-indicator-size) var(--status-indicator-color-active-transparent); } + 100% { box-shadow: 0 0 0 0 var(--status-indicator-color-active-transparent); } +} + +@keyframes status-indicator-pulse-positive { + 0% { box-shadow: 0 0 0 0 var(--status-indicator-color-positive-semi); } + 70% { box-shadow: 0 0 0 var(--status-indicator-size) var(--status-indicator-color-positive-transparent); } + 100% { box-shadow: 0 0 0 0 var(--status-indicator-color-positive-transparent); } +} + +@keyframes status-indicator-pulse-intermediary { + 0% { box-shadow: 0 0 0 0 var(--status-indicator-color-intermediary-semi); } + 70% { box-shadow: 0 0 0 var(--status-indicator-size) var(--status-indicator-color-intermediary-transparent); } + 100% { box-shadow: 0 0 0 0 var(--status-indicator-color-intermediary-transparent); } +} + +@keyframes status-indicator-pulse-negative { + 0% { box-shadow: 0 0 0 0 var(--status-indicator-color-negative-semi); } + 70% { box-shadow: 0 0 0 var(--status-indicator-size) var(--status-indicator-color-negative-transparent); } + 100% { box-shadow: 0 0 0 0 var(--status-indicator-color-negative-transparent); } +} + +status-indicator { + display: inline-block; + border-radius: 50%; + cursor: pointer; + width: var(--status-indicator-size); + height: var(--status-indicator-size); + background-color: var(--status-indicator-color); +} + +status-indicator[pulse] { + animation-name: status-indicator-pulse; + animation-duration: var(--status-indicator-animation-duration); + animation-timing-function: ease-in-out; + animation-iteration-count: infinite; + animation-direction: normal; + animation-delay: 0; + animation-fill-mode: none; +} + +status-indicator[active] { + background-color: var(--status-indicator-color-active); +} + +status-indicator[active][pulse] { + animation-name: status-indicator-pulse-active; +} + +status-indicator[positive] { + background-color: var(--status-indicator-color-positive); + animation-name: status-indicator-pulse-positive; +} + +status-indicator[positive][pulse] { + animation-name: status-indicator-pulse-positive; +} + +status-indicator[intermediary] { + background-color: var(--status-indicator-color-intermediary); +} + +status-indicator[intermediary][pulse] { + animation-name: status-indicator-pulse-intermediary; +} + +status-indicator[negative] { + background-color: var(--status-indicator-color-negative); + animation-name: status-indicator-pulse-negative; +} + +status-indicator[negative][pulse] { + animation-name: status-indicator-pulse-negative; +} +`) + +export default sheet \ No newline at end of file