2025-01-17 19:45:32 +00:00
( ( ) => { "use strict" ; var _ _webpack _modules _ _ = { 946 : ( e , t , n ) => { function o ( e , t = 40 ) { if ( Array . isArray ( e ) && 3 === e . length ) { for ( let t = 0 ; t < 3 ; t ++ ) if ( e [ t ] < 0 || e [ t ] > 255 ) return ; return e . every ( ( e => Math . abs ( e - 255 ) <= t ) ) } } let a ; function i ( e , t , n = 1 ) { if ( e . startsWith ( "#" ) ) if ( 4 === e . length ) { let o = Math . min ( 255 , parseInt ( e . charAt ( 1 ) . repeat ( 2 ) , 16 ) * n ) , i = Math . min ( 255 , parseInt ( e . charAt ( 2 ) . repeat ( 2 ) , 16 ) * n ) , r = Math . min ( 255 , parseInt ( e . charAt ( 3 ) . repeat ( 2 ) , 16 ) * n ) ; a = "rgba(" + o + ", " + i + ", " + r + ", " + t + ")" } else { let o = Math . min ( 255 , parseInt ( e . slice ( 1 , 3 ) , 16 ) * n ) , i = Math . min ( 255 , parseInt ( e . slice ( 3 , 5 ) , 16 ) * n ) , r = Math . min ( 255 , parseInt ( e . slice ( 5 , 7 ) , 16 ) * n ) ; a = "rgba(" + o + ", " + i + ", " + r + ", " + t + ")" } else if ( e . startsWith ( "rgb" ) ) { let o = e . match ( /\d+/g ) ; a = "rgba(" + Math . min ( 255 , o [ 0 ] * n ) + ", " + Math . min ( 255 , o [ 1 ] * n ) + ", " + Math . min ( 255 , o [ 2 ] * n ) + ", " + t + ")" } else if ( e . startsWith ( "var(--" ) ) { let o = e . slice ( 4 , - 1 ) , r = window . getComputedStyle ( document . documentElement ) . getPropertyValue ( o ) ; ( r . startsWith ( "#" ) || r . startsWith ( "rgb" ) ) && ( a = i ( r , t , n ) ) } return a } n . d ( t , { _k : ( ) => i , wW : ( ) => o } ) } , 191 : ( _ _unused _webpack _module , _ _webpack _exports _ _ , _ _webpack _require _ _ ) => { _ _webpack _require _ _ . d ( _ _webpack _exports _ _ , { BX : ( ) => fireEvent , GP : ( ) => applyScrollingEffect , IL : ( ) => getAttribute , Jn : ( ) => tapFeedback , OC : ( ) => isEntityType , P2 : ( ) => throttle , Vv : ( ) => isColorLight , X : ( ) => getWeatherIcon , az : ( ) => createElement , gJ : ( ) => getImage , jk : ( ) => forwardHaptic , jx : ( ) => setLayout , mk : ( ) => getIconColor , o0 : ( ) => formatDateTime , oY : ( ) => getName , pr : ( ) => isStateOn , q7 : ( ) => getIcon , y0 : ( ) => getState } ) ; var _style _ts _ _WEBPACK _IMPORTED _MODULE _0 _ _ = _ _webpack _require _ _ ( 946 ) ; const fireEvent = ( e , t , n , o ) => { o = o || { } , n = null == n ? { } : n ; const a = new Event ( t , { bubbles : void 0 === o . bubbles || o . bubbles , cancelable : Boolean ( o . cancelable ) , composed : void 0 === o . composed || o . composed } ) ; return a . detail = n , e . dispatchEvent ( a ) , a } , forwardHaptic = e => { fireEvent ( window , "haptic" , e ) } , navigate = ( e , t , n = ! 1 ) => { n ? history . replaceState ( null , "" , t ) : history . pushState ( null , "" , t ) , fireEvent ( window , "location-changed" , { replace : n } ) } ; function tapFeedback ( e ) { void 0 !== e && ( e . style . display = "" , e . style . animation = "tap-feedback .3s" , setTimeout ( ( ( ) => { e . style . animation = "none" , e . style . display = "none" } ) , 500 ) ) } function getIcon ( e , t = e . config . entity , n = e . config . icon ) { const o = t ? . split ( "." ) [ 0 ] , a = getAttribute ( e , "device_class" , t ) , i = getAttribute ( e , "icon" , t ) , r = n , s = getState ( e , t ) , l = { alarm _control _panel : "mdi:shield" , alert : "mdi:alert" , automation : "mdi:playlist-play" , binary _sensor : function ( ) { const n = "off" === s ; switch ( getAttribute ( e , "device_class" , t ) ) { case "battery" : return n ? "mdi:battery" : "mdi:battery-outline" ; case "battery_charging" : return n ? "mdi:battery" : "mdi:battery-charging" ; case "cold" : return n ? "mdi:thermometer" : "mdi:snowflake" ; case "connectivity" : return n ? "mdi:server-network-off" : "mdi:server-network" ; case "door" : return n ? "mdi:door-closed" : "mdi:door-open" ; case "garage_door" : return n ? "mdi:garage" : "mdi:garage-open" ; case "heat" : return n ? "mdi:thermometer" : "mdi:fire" ; case "light" : return n ? "mdi:brightness-5" : "mdi:brightness-7" ; case "lock" : return n ? "mdi:lock" : "mdi:lock-open" ; case "moisture" : return n ? "mdi:water-off" : "mdi:water" ; case "motion" : return n ? "mdi:motion-sensor-off" : "mdi:motion-sensor" ; case "occupancy" : case "presence" : return n ? "mdi:home-outline" : "mdi:home" ; case "opening" : return n ? "mdi:square" : "mdi:square-outline" ; case "plug" : case "power" : return n ? "mdi:power-plug-off" : "mdi:power-plug" ; case "running" : return n ? "mdi:stop" : "mdi:play" ; case "safety" : case "tamper" : return n ? "mdi:check-circle" : "mdi:alert-circle" ; case "smoke" : return n ? "mdi:check-circle" : "mdi:smoke" ; case "sound" : return n ? "mdi:music-note-off" : "mdi:music-note" ; case "update" : return n ? "mdi:package" : "mdi:package-up" ; case "vibration" : return n ? "mdi:crop-portrait" : "mdi:vibrate" ; case "window" : return n ? "mdi:window-closed" : "mdi:window-open" ; default : return n ? "mdi:radiobox-blank" : "mdi:checkbox-marked-circle" } } ( ) , calendar : "mdi:calendar" , camera : "mdi:video" , climate : "mdi:thermostat" , configurator : "mdi:settings" , conversation : "mdi:text-to-speech" , cover : function ( ) { const n = "closed" !== s ; switch ( getAttribute ( e , "device_class" , t ) ) { case "awning" : return n ? "mdi:awning-outline" : "mdi:awning" ; case "blind" : return n ? "mdi:blinds-open" : "mdi:blinds" ; case "curtain" : return n ? " mdi : curtai
2024-12-17 17:05:10 +00:00
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
< ha - textfield
label = "Hash (e.g. #kitchen)"
. value = "${this._hash}"
. configValue = "${" hash "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:dock-top" > < / h a - i c o n >
Header settings
< / h 4 >
< div class = "content" >
< ha - formfield . label = "Optional - Show header" >
< ha - switch
aria - label = "Optional - Show header"
. checked = $ { this . _show _header }
. configValue = "${" show _header "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show header < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - alert alert - type = "info" > You can completely hide the pop - up header , including the close button . To close it when hidden , either make a long swipe within the pop - up or click outside of it . < / h a - a l e r t >
< div style = "${this._show_header?" ":" display : none ; "}" >
< hr / >
$ { this . makeDropdown ( "Button type" , "button_type" , i ) }
$ { this . makeDropdown ( "Optional - Entity" , "entity" , n , r ) }
< ha - textfield
label = "Optional - Name"
. value = "${this._name}"
. configValue = "${" name "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
$ { this . makeDropdown ( "Optional - Icon" , "icon" ) }
$ { this . makeShowState ( ) }
< hr / >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on icon
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" ) }
$ { this . makeActionPanel ( "Double tap action" ) }
$ { this . makeActionPanel ( "Hold action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined style = "display: ${" slider "===this._config.button_type?" none ":" "}" >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on button
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" , this . _button _action , "name" !== this . _config . button _type ? "state" === this . _config . button _type ? "more-info" : "toggle" : "none" , "button_action" ) }
$ { this . makeActionPanel ( "Double tap action" , this . _button _action , "name" !== this . _config . button _type ? "state" === this . _config . button _type ? "more-info" : "toggle" : "none" , "button_action" ) }
$ { this . makeActionPanel ( "Hold action" , this . _button _action , "name" !== this . _config . button _type ? "more-info" : "none" , "button_action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeSubButtonPanel ( ) }
< / d i v >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:cog" > < / h a - i c o n >
Pop - up settings
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Auto close in milliseconds (e.g. 15000)"
type = "number"
inputMode = "numeric"
min = "0"
step = "1000"
. value = "${this._auto_close}"
. configValue = "${" auto _close "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Slide to close distance (default to 400)"
type = "number"
inputMode = "numeric"
min = "0"
step = "10"
. value = "${this._slide_to_close_distance}"
. configValue = "${" slide _to _close _distance "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - formfield . label = "Optional - Close the pop-up by clicking outside of it (a refresh is needed)" >
< ha - switch
aria - label = "Optional - Close the pop-up by clicking outside of it (a refresh is needed)"
. checked = $ { this . _close _by _clicking _outside }
. configValue = "${" close _by _clicking _outside "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Close the pop - up by clicking outside of it ( a refresh is needed ) < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Close the pop-up after any click or tap" >
< ha - switch
aria - label = "Optional - Close the pop-up after any click or tap"
. checked = $ { this . _close _on _click }
. configValue = "${" close _on _click "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Close the pop - up after any click or tap < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Update cards in background (not recommended)" >
< ha - switch
aria - label = "Optional - Update cards in background (not recommended)"
. checked = $ { this . _background _update }
. configValue = "${" background _update "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Update cards in background ( not recommended ) < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - alert alert - type = "info" > Background updates are only recommended if you encounter issues with certain cards within your pop - up . < / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:bell" > < / h a - i c o n >
Pop - up trigger
< / h 4 >
< div class = "content" >
< ha - card - conditions - editor
. hass = $ { this . hass }
. conditions = $ { l }
@ value - changed = $ { e => this . _conditionChanged ( e ) }
>
< / h a - c a r d - c o n d i t i o n s - e d i t o r >
< ha - alert alert - type = "info" >
The pop - up will be opened when ALL conditions are fulfilled . For example you can open a "Security" pop - up with a camera when a person is in front of your house . You can also create a toggle helper ( < code > input _boolean < / c o d e > ) a n d t r i g g e r i t s o p e n i n g / c l o s i n g i n a n a u t o m a t i o n .
< / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Pop - up open / close action
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Open action" , this . _config , "none" ) }
$ { this . makeActionPanel ( "Close action" , this . _config , "none" ) }
2024-12-17 17:05:10 +00:00
< ha - alert alert - type = "info" > This allows you to trigger an action on pop - up open / close . < / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Pop - up styling
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Margin (fix centering on some themes) (e.g. 13px)"
. value = "${this._margin}"
. configValue = "${" margin "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Top margin on mobile (e.g. -56px if your header is hidden)"
. value = "${this._margin_top_mobile}"
. configValue = "${" margin _top _mobile "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Top margin on desktop (e.g. 50vh for an half sized pop-up)"
. value = "${this._margin_top_desktop}"
. configValue = "${" margin _top _desktop "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Width on desktop (100% by default on mobile)"
. value = "${this._width_desktop}"
. configValue = "${" width _desktop "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Background color (any var, hex, rgb or rgba value)"
. value = "${this._bg_color}"
. configValue = "${" bg _color "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Background opacity (0-100 range)"
type = "number"
inputMode = "numeric"
min = "0"
max = "100"
. value = "${this._bg_opacity}"
. configValue = "${" bg _opacity "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Background blur (0-100 range)"
type = "number"
inputMode = "numeric"
min = "0"
max = "100"
. value = "${this._bg_blur}"
. configValue = "${" bg _blur "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Backdrop blur (0-100 range)"
type = "number"
inputMode = "numeric"
min = "0"
max = "100"
. value = "${this._backdrop_blur}"
. configValue = "${" backdrop _blur "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Shadow opacity (0-100 range)"
type = "number"
inputMode = "numeric"
min = "0"
max = "100"
. configValue = "${" shadow _opacity "}"
. value = "${this._shadow_opacity}" "
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - formfield . label = "Optional - Hide pop-up backdrop (a refresh is needed)" >
< ha - switch
aria - label = "Optional - Hide pop-up backdrop (a refresh is needed)"
. checked = $ { this . _hide _backdrop }
. configValue = "${" hide _backdrop "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide pop - up backdrop ( a refresh is needed ) < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - alert alert - type = "warning" > Set this toggle to true on the first pop - up of your main dashboard to hide the darker backdrop behind all pop - ups . < b > You can add a blurred effect to it by changing < code > Optional - Backdrop blur < / c o d e > j u s t b e l o w , b u t b e a w a r e t h a t t h i s c a n s l o w d o w n y o u r d a s h b o a r d w h e n o p e n i n g p o p - u p s . I t i s n o w s e t t o 0 f o r t h a t r e a s o n . < / b > < / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - alert alert - type = "info" >
This card allows you to convert any vertical stack into a pop - up . Each pop - up is hidden by default and can be opened by targeting its link ( e . g . , '#pop-up-name' ) , with < a style = "color: var(--text-primary-color)" href = "https://github.com/Clooos/Bubble-Card#example" > any card < / a > t h a t s u p p o r t s t h e < c o d e > n a v i g a t e < / c o d e > a c t i o n , o r w i t h t h e < a s t y l e = " c o l o r : v a r ( - - t e x t - p r i m a r y - c o l o r ) " h r e f = " h t t p s : / / g i t h u b . c o m / C l o o o s / B u b b l e - C a r d # h o r i z o n t a l - b u t t o n s - s t a c k " > h o r i z o n t a l b u t t o n s s t a c k < / a > t h a t i s i n c l u d e d .
< br > < br > < b > Important : < /b> This card must be placed within a <a style="color: var(--text-primary-color)" href="https:/ / www . home - assistant . io / dashboards / vertical - stack / " > vertical stack < / a > c a r d a t t h e t o p m o s t p o s i t i o n t o f u n c t i o n p r o p e r l y . T o a v o i d m i s a l i g n m e n t w i t h y o u r v i e w , p l a c e v e r t i c a l s t a c k s / p o p - u p s a f t e r a l l o t h e r d a s h b o a r d c a r d s . I t s h o u l d b e c a l l e d f r o m t h e s a m e v i e w t o w o r k .
< br > < br > < b > You can also watch this < a style = "color: var(--text-primary-color)" href = "https://www.youtube.com/watch?v=7mOV7BfWoFc" > video < / a > t h a t e x p l a i n s h o w t o c r e a t e y o u r f i r s t p o p - u p . < / b >
< / h a - a l e r t >
< ha - alert alert - type = "warning" > Since v1 . 7.0 , the optimized mode has been removed to ensure stability and to simplify updates for everyone . However , if your pop - up content still appears on the screen during page loading , < a style = "color: var(--text-primary-color)" href = "https://github.com/Clooos/Bubble-Card#pop-up-initialization-fix" > you can install this similar fix . < / a > < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` }if("button"===this._config?.card_type)return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
$ { this . makeDropdown ( "Button type" , "button_type" , i ) }
$ { this . makeDropdown ( "slider" !== this . _button _type ? "Entity (toggle)" : "Entity (light, media_player, cover or input_number)" , "entity" , n , r ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:cog" > < / h a - i c o n >
Button settings
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Name"
. value = "${this._name}"
. configValue = "${" name "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
$ { this . makeDropdown ( "Optional - Icon" , "icon" ) }
$ { this . makeShowState ( ) }
< ha - formfield . label = "Optional - Slider live update" style = "display: ${" slider "!==this._button_type?" none ":" "}" >
< ha - switch
aria - label = "Optional - Slider live update"
. checked = $ { this . _slider _live _update }
. configValue = "${" slider _live _update "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Slider live update < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - alert style = "display: ${" slider "!==this._button_type?" none ":" "}" alert - type = "info" > By default , sliders are updated only on release . You can toggle this option to enable live updates while sliding . < / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on icon
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" ) }
$ { this . makeActionPanel ( "Double tap action" ) }
$ { this . makeActionPanel ( "Hold action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined style = "display: ${" slider "===this._config.button_type?" none ":" "}" >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on button
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" , this . _button _action , "name" !== this . _config . button _type ? "state" === this . _config . button _type ? "more-info" : "toggle" : "none" , "button_action" ) }
$ { this . makeActionPanel ( "Double tap action" , this . _button _action , "name" !== this . _config . button _type ? "state" === this . _config . button _type ? "more-info" : "toggle" : "none" , "button_action" ) }
$ { this . makeActionPanel ( "Hold action" , this . _button _action , "name" !== this . _config . button _type ? "more-info" : "none" , "button_action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeSubButtonPanel ( ) }
< ha - alert alert - type = "info" > This card allows you to control your entities . $ { "slider" === this . _config . button _type ? "Supported entities: Light (brightness), media player (volume), cover (position), fan (percentage), climate (temperature), input number and number (value). To access color / control of an entity, simply tap on the icon." : "" } < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` ;if("separator"===this._config?.card_type)return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
< ha - textfield
label = "Name"
. value = "${this._name}"
. configValue = "${" name "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
$ { this . makeDropdown ( "Icon" , "icon" ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeSubButtonPanel ( ) }
< ha - alert alert - type = "info" > This card is a simple separator for dividing your pop - up into categories / sections . e . g . Lights , Devices , Covers , Settings , Automations ... < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` ;if("horizontal-buttons-stack"===this._config?.card_type){if(!this.buttonAdded)for(this.buttonAdded=!0,this.buttonIndex=0;this._config[this.buttonIndex+1+"_link"];)this.buttonIndex++;function c(){this.buttonIndex++,this.requestUpdate()}return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
< div id = "buttons-container" >
$ { this . makeButton ( ) }
< / d i v >
< button class = "icon-button" @ click = "${c}" >
< ha - icon icon = "mdi:plus" > < / h a - i c o n >
New button
< / b u t t o n >
< ha - formfield . label = "Auto order" >
< ha - switch
aria - label = "Toggle auto order"
. checked = $ { this . _auto _order }
. configValue = "${" auto _order "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Auto order ( Presence / occupancy sensors needed ) < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Horizontal buttons stack styling
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Margin (fix centering on some themes) (e.g. 13px)"
. value = "${this._margin}"
. configValue = "${" margin "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Width on desktop (100% by default on mobile)"
. value = "${this._width_desktop}"
. configValue = "${" width _desktop "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - formfield . label = "Optional - Rise animation (Displays an animation once the page has loaded)" >
< ha - switch
aria - label = "Optional - Rise animation (Displays an animation once the page has loaded)"
. checked = $ { this . _rise _animation }
. configValue = "${" rise _animation "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Rise animation ( Displays an animation once the page has loaded ) < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Highlight current hash / view" >
< ha - switch
aria - label = "Optional - Highlight current hash / view"
. checked = $ { this . _highlight _current _view }
. configValue = "${" highlight _current _view "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Highlight current hash / view < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Hide gradient" >
< ha - switch
aria - label = "Optional - Hide gradient"
. checked = $ { this . _hide _gradient }
. configValue = "${" hide _gradient "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide gradient < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - alert alert - type = "info" > This card is the companion to the pop - up card , allowing you to open the corresponding pop - ups . It also allows you to open any page of your dashboard . In addition , you can add your motion sensors so that the order of the buttons adapts according to the room you just entered . This card is scrollable , remains visible and acts as a footer . < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` }if("cover"===this._config?.card_type)return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
$ { this . makeDropdown ( "Entity" , "entity" , o ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:cog" > < / h a - i c o n >
Cover settings
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Name"
. value = "${this._name||" "}"
. configValue = "${" name "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
$ { this . makeDropdown ( "Optional - Open icon" , "icon_open" ) }
$ { this . makeDropdown ( "Optional - Closed icon" , "icon_close" ) }
$ { this . makeShowState ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:window-shutter-cog" > < / h a - i c o n >
Custom services
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Open service (cover.open_cover by default)"
. value = "${this._open_service}"
. configValue = "${" open _service "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Stop service (cover.stop_cover by default)"
. value = "${this._stop_service}"
. configValue = "${" stop _service "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Close service (cover.close_cover by default)"
. value = "${this._close_service}"
. configValue = "${" close _service "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on icon
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" ) }
$ { this . makeActionPanel ( "Double tap action" ) }
$ { this . makeActionPanel ( "Hold action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Cover styling
< / h 4 >
< div class = "content" >
$ { this . makeDropdown ( "Optional - Arrow down icon" , "icon_down" ) }
$ { this . makeDropdown ( "Optional - Arrow up icon" , "icon_up" ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeSubButtonPanel ( ) }
< ha - alert alert - type = "info" > This card allows you to control your covers . < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` ;if("media-player"===this._config?.card_type)return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
$ { this . makeDropdown ( "Entity" , "entity" , this . mediaPlayerList ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:cog" > < / h a - i c o n >
Media player settings
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Name"
. value = "${this._name||" "}"
. configValue = "${" name "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
$ { this . makeDropdown ( "Optional - Icon" , "icon" ) }
$ { this . makeShowState ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:eye-off" > < / h a - i c o n >
Display / hide buttons
< / h 4 >
< div class = "content" >
< ha - formfield . label = "Optional - Hide play/pause button" >
< ha - switch
aria - label = "Optional - Hide play/pause button"
. checked = $ { this . _hide _play _pause _button }
. configValue = "${" hide . play _pause _button "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide play / pause button < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Hide volume button" >
< ha - switch
aria - label = "Optional - Hide volume button"
. checked = $ { this . _hide _volume _button }
. configValue = "${" hide . volume _button "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide volume button < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Hide next button" >
< ha - switch
aria - label = "Optional - Hide next button"
. checked = $ { this . _hide _next _button }
. configValue = "${" hide . next _button "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide next button < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Hide previous button" >
< ha - switch
aria - label = "Optional - Hide previous button"
. checked = $ { this . _hide _previous _button }
. configValue = "${" hide . previous _button "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide previous button < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Hide power button" >
< ha - switch
aria - label = "Optional - Hide power button"
. checked = $ { this . _hide _power _button }
. configValue = "${" hide . power _button "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide power button < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on icon
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" ) }
$ { this . makeActionPanel ( "Double tap action" ) }
$ { this . makeActionPanel ( "Hold action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Media player styling
< / h 4 >
< div class = "content" >
< ha - formfield . label = "Optional - Blurred media cover in background" >
< ha - switch
aria - label = "Optional - Blurred media cover in background"
. checked = $ { this . _cover _background }
. configValue = "${" cover _background "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Blurred media cover in background < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeSubButtonPanel ( ) }
< ha - alert alert - type = "info" > This card allows you to control a media player . You can tap on the icon to get more control . < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` ;if("empty-column"===this._config?.card_type)return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - alert alert - type = "info" > Just an empty card to fill any empty column . < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` ;if("select"===this._config?.card_type){const d=this._config.entity,u=(d?.startsWith("input_select")||d?.startsWith("select")||this._config.select_attribute,this.hass.states[d]?.attributes),b=this._selectable_attributes.some((e=>u?.[e])),p=Object.keys(this.hass.states[d]?.attributes||{}).map((e=>{let t=this.hass.states[d];return{label:this.hass.formatEntityAttributeName(t,e),value:e}})).filter((e=>this._selectable_attributes.includes(e.value)));return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
$ { this . makeDropdown ( "Entity" , "entity" , this . inputSelectList ) }
$ { b ? ce `
< div class = "ha-combo-box" >
< ha - combo - box
label = "Select menu (from attributes)"
. value = "${this._config.select_attribute}"
. items = "${p}"
. configValue = "${" select _attribute "}"
@ value - changed = "${this._valueChanged}"
> < / h a - c o m b o - b o x >
< / d i v >
` :""}
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:cog" > < / h a - i c o n >
Button settings
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Name"
. value = "${this._name}"
. configValue = "${" name "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
$ { this . makeDropdown ( "Optional - Icon" , "icon" ) }
$ { this . makeShowState ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on icon
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" ) }
$ { this . makeActionPanel ( "Double tap action" ) }
$ { this . makeActionPanel ( "Hold action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeSubButtonPanel ( ) }
< ha - alert alert - type = "info" >
This card allows you to have a select menu for your
< code > input _select < / c o d e > , < c o d e > s e l e c t < / c o d e > e n t i t i e s , a n d
any other entities that have attribute lists like
< code > source _list < / c o d e > , < c o d e > s o u n d _ m o d e _ l i s t < / c o d e > ,
< code > hvac _modes < / c o d e > , < c o d e > f a n _ m o d e s < / c o d e > ,
< code > swing _modes < / c o d e > , < c o d e > p r e s e t _ m o d e s < / c o d e > , o r
< code > effect _list < / c o d e > .
< / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` }if("climate"===this._config?.card_type){if("climate"===this._config.card_type&&!this.climateSubButtonsAdded&&this._config.entity){const h=this.hass.states[this._config.entity]?.attributes?.hvac_modes;this._config.sub_button&&0!==this._config.sub_button.length||(this._config.sub_button=[h?{name:"HVAC modes menu",select_attribute:"hvac_modes",state_background:!1,show_arrow:!1}:null].filter(Boolean)),this.climateSubButtonsAdded=!0}return ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
$ { this . makeDropdown ( "Entity" , "entity" , this . climateList ) }
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:cog" > < / h a - i c o n >
Climate settings
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Optional - Name"
. value = "${this._name}"
. configValue = "${" name "}"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
$ { this . makeDropdown ( "Optional - Icon" , "icon" ) }
$ { this . makeShowState ( ) }
$ { this . hass . states [ this . _config . entity ] ? . attributes ? . target _temp _low ? ce `
< ha - formfield . label = "Optional - Hide target temp low" >
< ha - switch
aria - label = "Optional - Hide target temp low"
. checked = $ { this . _config . hide _target _temp _low }
. configValue = "${" hide _target _temp _low "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide target temp low < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
$ { this . hass . states [ this . _config . entity ] ? . attributes ? . target _temp _high ? ce `
< ha - formfield . label = "Optional - Hide target temp high" >
< ha - switch
aria - label = "Optional - Hide target temp high"
. checked = $ { this . _config . hide _target _temp _high }
. configValue = "${" hide _target _temp _high "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Hide target temp high < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
< ha - formfield . label = "Optional - Constant background color when ON" >
< ha - switch
aria - label = "Optional - Constant background color when ON"
. checked = $ { ! 0 === this . _config . state _color }
. configValue = "${" state _color "}"
@ change = $ { this . _valueChanged }
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Constant background color when ON < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on icon
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" ) }
$ { this . makeActionPanel ( "Double tap action" ) }
$ { this . makeActionPanel ( "Hold action" ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:palette" > < / h a - i c o n >
Styling options
< / h 4 >
< div class = "content" >
$ { this . makeLayoutOptions ( ) }
$ { this . makeStyleEditor ( ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
$ { this . makeSubButtonPanel ( ) }
< ha - alert alert - type = "info" > This card allows you to control your climate entities . You can also add a sub - button that display a select menu for your climate modes ( check if you have "Select menu" available when you create a new sub - button ) . < / h a - a l e r t >
$ { this . makeVersion ( ) }
< / d i v >
` }return this._config?.card_type?void 0:ce `
< div class = "card-config" >
$ { this . makeDropdown ( "Card type" , "card_type" , a ) }
< ha - alert alert - type = "info" > You need to add a card type first . Please note that in some cases , a page refresh might be needed after exiting the editor . < / h a - a l e r t >
< img style = "width: 100%; height: auto; border-radius: 24px;" src = "https://raw.githubusercontent.com/Clooos/Bubble-Card/main/.github/bubble-card.gif" >
< p > The < b > Bubble Card $ { e } < /b> changelog is available <a href="https:/ / github . com / Clooos / Bubble - Card / releases / tag / $ { e } " > < b > here < / b > < / a > . < / p >
< hr / >
< p > If you have an issue or a question you can find more details in the GitHub documentation . You can also find useful resources and help in these links . < / p >
< div style = "display: inline-block;" >
< a href = "https://github.com/Clooos/Bubble-Card" > < img src = "https://img.shields.io/badge/GitHub-Documentation-blue?logo=github" > < / a >
< a href = "https://www.youtube.com/@cloooos" > < img src = "https://img.shields.io/badge/YouTube-My%20channel-red?logo=youtube" > < / a >
< a href = "https://www.reddit.com/r/BubbleCard/" > < img src = "https://img.shields.io/badge/Reddit-r/BubbleCard-orange?logo=reddit" > < / a >
< a href = "https://community.home-assistant.io/t/bubble-card-a-minimalist-card-collection-for-home-assistant-with-a-nice-pop-up-touch/609678" > < img src = "https://img.shields.io/badge/Home%20Assistant-Community%20Forum-blue?logo=home-assistant" > < / a >
< / d i v >
< hr / >
< p > I dedicate most of my spare time to making this project the best it can be . So if you appreciate my work , any donation would be a great way to show your support . < / p >
< div style = "display: inline-block;" >
< a href = "https://www.buymeacoffee.com/clooos" > < img src = "https://img.shields.io/badge/Donate-Buy%20me%20a%20beer-yellow?logo=buy-me-a-coffee" > < / a >
< a href = "https://www.paypal.com/donate/?business=MRVBV9PLT9ZPL&no_recurring=0&item_name=Hi%2C+I%27m+Clooos+the+creator+of+Bubble+Card.+Thank+you+for+supporting+me+and+my+passion.+You+are+awesome%21+%F0%9F%8D%BB¤cy_code=EUR" > < img src = "https://img.shields.io/badge/Donate-PayPal-blue?logo=paypal" > < / i m g > < / a >
< / d i v >
< p > Looking for more advanced examples ? Check out my < a href = "https://www.patreon.com/Clooos" > < b > Patreon < / b > < / a > f o r e x c l u s i v e c u s t o m s t y l e s a n d t e m p l a t e s ! < / p >
< a href = "https://www.patreon.com/Clooos" > < img src = "https://img.shields.io/badge/Patreon-Clooos-orange?logo=patreon" > < / a >
< p style = "margin-top: 0;" > Thank you ! 🍻 < / p >
$ { this . makeVersion ( ) }
< / d i v >
` }makeLayoutOptions(){return ce `
< ha - combo - box
label = "${" pop - up "===this._config.card_type?" Header card layout ":" Card layout "}"
. value = "${this._config.card_layout||" normal "}"
. configValue = "${" card _layout "}"
. items = "${[{label:" Normal ",value:" normal "},{label:" Large ( Optimized for sections ) ",value:" large "},{label:" Large with 2 sub - buttons rows ( Optimized for sections ) ",value:" large - 2 - rows "}]}"
@ value - changed = "${this._valueChanged}"
> < / h a - c o m b o - b o x >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:table" > < / h a - i c o n >
Layout options for sections
< / h 4 >
< div class = "content" >
< ha - combo - box
label = "Columns"
. value = "${this._config.columns}"
. configValue = "${" columns "}"
. items = "${[{label:" Auto ",value:null},{label:" 1 / 4 ",value:1},{label:" 2 / 4 ",value:2},{label:" 3 / 4 ",value:3},{label:" 4 / 4 ",value:4}]}"
@ value - changed = "${this._valueChanged}"
> < / h a - c o m b o - b o x >
< ha - combo - box
label = "Rows"
. value = "${this._config.rows}"
. configValue = "${" rows "}"
. items = "${[{label:" Auto ",value:null},{label:" 1 / 4 ",value:1},{label:" 2 / 4 ",value:2},{label:" 3 / 4 ",value:3},{label:" 4 / 4 ",value:4}]}"
@ value - changed = "${this._valueChanged}"
> < / h a - c o m b o - b o x >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
` }makeShowState(e=this._config,t="",n=!1,o){const a=e?.entity??this._config.entity??"",i="name"===this._config.button_type,r=a?.startsWith("input_select")||a?.startsWith("select")||e.select_attribute,s=Object.keys(this.hass.states[a]?.attributes||{}).map((e=>{let t=this.hass.states[a];return{label:this.hass.formatEntityAttributeName(t,e),value:e}}));return ce `
$ { "sub_button" !== n ? ce `
< ha - formfield . label = "Optional - Text scrolling effect" >
< ha - switch
aria - label = "Optional - Text scrolling effect"
. checked = $ { e ? . scrolling _effect ? ? ! 0 }
. configValue = "${t+" scrolling _effect "}"
@ change = "${n?e=>this._arrayValueChange(o,{scrolling_effect:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Text scrolling effect < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
$ { "sub_button" === n ? ce `
< ha - formfield . label = "Optional - Show background" >
< ha - switch
aria - label = "Optional - Show background when entity is on"
. checked = $ { e ? . show _background ? ? ! 0 }
@ change = "${e=>this._arrayValueChange(o,{show_background:e.target.checked},n)}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show background when entity is on < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
$ { "sub_button" === n && ( e ? . show _background ? ? 1 ) ? ce `
< ha - formfield . label = "Optional - Background color based on state" >
< ha - switch
aria - label = "Optional - Background color based on state"
. checked = $ { e ? . state _background ? ? ! 0 }
@ change = "${e=>this._arrayValueChange(o,{state_background:e.target.checked},n)}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Background color based on state < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
$ { "sub_button" === n && ( e ? . state _background ? ? 1 ) && a . startsWith ( "light" ) ? ce `
< ha - formfield . label = "Optional - Background color based on light color" >
< ha - switch
aria - label = "Optional - Background color based on light color"
. checked = $ { e ? . light _background ? ? ! 0 }
@ change = "${e=>this._arrayValueChange(o,{light_background:e.target.checked},n)}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Background color based on light color < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
$ { "sub_button" !== n && a . startsWith ( "light" ) ? ce `
< ha - formfield . label = "Optional - Use accent color instead of light color" >
< ha - switch
aria - label = "Optional - Use accent color instead of light color"
. checked = $ { e ? . use _accent _color ? ? ! 1 }
. configValue = "${t+" use _accent _color "}"
@ change = "${this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Use accent color instead of light color < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
< ha - formfield . label = "Optional - Show icon" >
< ha - switch
aria - label = "Optional - Show icon"
. checked = $ { e ? . show _icon ? ? ! 0 }
. configValue = "${t+" show _icon "}"
@ change = "${n?e=>this._arrayValueChange(o,{show_icon:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show icon < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
$ { "sub_button" !== n ? ce `
< ha - formfield . label = "Optional - Prioritize icon over entity picture" >
< ha - switch
aria - label = "Optional - Prioritize icon over entity picture"
. checked = $ { e ? . force _icon ? ? ! 1 }
. configValue = "${t+" force _icon "}"
. disabled = "${i}"
@ change = "${n?e=>this._arrayValueChange(o,{force_icon:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Prioritize icon over entity picture < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
< ha - formfield . label = "Optional - Show name" >
< ha - switch
aria - label = "Optional - Show name"
. checked = $ { ! ! ( e ? . show _name ? ? "sub_button" !== n ) }
. configValue = "${t+" show _name "}"
@ change = "${n?e=>this._arrayValueChange(o,{show_name:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show name < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Show entity state" >
< ha - switch
aria - label = "Optional - Show entity state"
. checked = "${e?.show_state??" state "===e.button_type}"
. configValue = "${t+" show _state "}"
. disabled = "${i&&" sub _button "!==n}"
@ change = "${n?e=>this._arrayValueChange(o,{show_state:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show entity state < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Show last changed" >
< ha - switch
aria - label = "Optional - Show last changed"
. checked = $ { e ? . show _last _changed }
. configValue = "${t+" show _last _changed "}"
. disabled = "${i&&" sub _button "!==n}"
@ change = "${n?e=>this._arrayValueChange(o,{show_last_changed:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show last changed < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
< ha - formfield . label = "Optional - Show attribute" >
< ha - switch
aria - label = "Optional - Show attribute"
. checked = $ { e ? . show _attribute }
. configValue = "${t+" show _attribute "}"
. disabled = "${i&&" sub _button "!==n}"
@ change = "${n?e=>this._arrayValueChange(o,{show_attribute:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show attribute < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
$ { e ? . show _attribute ? ce `
< div class = "ha-combo-box" >
< ha - combo - box
label = "Optional - Attribute to show"
. value = "${e?.attribute}"
. configValue = "${t+" attribute "}"
. items = "${s}"
. disabled = "${i}"
@ value - changed = "${n?e=>this._arrayValueChange(o,{attribute:e.detail.value},n):this._valueChanged}"
> < / h a - c o m b o - b o x >
< / d i v >
` :""}
$ { "sub_button" === n && r ? ce `
< ha - formfield . label = "Optional - Show arrow (Select entities only)" >
< ha - switch
aria - label = "Optional - Show arrow (Select entities only)"
. checked = $ { e ? . show _arrow ? ? ! 0 }
. configValue = "${t+" show _arrow "}"
@ change = "${n?e=>this._arrayValueChange(o,{show_arrow:e.target.checked},n):this._valueChanged}"
> < / h a - s w i t c h >
< div class = "mdc-form-field" >
< label class = "mdc-label" > Optional - Show arrow ( Select menu only ) < / l a b e l >
< / d i v >
< / h a - f o r m f i e l d >
` :""}
` }makeDropdown(e,t,n,o){return e.includes("icon")||e.includes("Icon")?ce `
< div class = "ha-icon-picker" >
< ha - icon - picker
label = "${e}"
. value = "${this[" _ "+t]}"
. configValue = "${t}"
item - value - path = "icon"
item - label - path = "icon"
@ value - changed = "${this._valueChanged}"
> < / h a - i c o n - p i c k e r >
< / d i v >
` :ce `
< div class = "ha-combo-box" >
< ha - combo - box
label = "${e}"
. value = "${this[" _ "+t]}"
. configValue = "${t}"
. items = "${n}"
. disabled = "${o}"
@ value - changed = "${this._valueChanged}"
> < / h a - c o m b o - b o x >
< / d i v >
2025-01-17 19:45:32 +00:00
` }makeActionPanel(e,t=this._config,n,o,a=this._config){const i="Tap action"===e?"mdi:gesture-tap":"Double tap action"===e?"mdi:gesture-double-tap":"Hold action"===e?"mdi:gesture-tap-hold":"mdi:gesture-tap",r="Tap action"===e?"tap_action":"Double tap action"===e?"double_tap_action":"Hold action"===e?"hold_action":"Open action"===e?"open_action":"close_action",s=t===this._config;return n||(n=s&&"Tap action"===e?"name"!==this._config.button_type?"more-info":"none":s?"name"!==this._config.button_type?"toggle":"none":""),ce `
2024-12-17 17:05:10 +00:00
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "${i}" > < / h a - i c o n >
$ { e }
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
< ha - form
. hass = $ { this . hass }
. data = $ { t }
. schema = $ { [ { name : r , selector : { ui _action : { default _action : n } } } ] }
. computeLabel = $ { this . _computeLabelCallback }
@ value - changed = $ { e => this . _ActionChanged ( e , o , a ) }
> < / h a - f o r m >
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
` }makeSubButtonPanel(){const e=this._config?.sub_button?.map(((e,t)=>{if(!e)return;const n="sub_button."+t+".",o=e.entity??this._config.entity,a=o?.startsWith("input_select")||o?.startsWith("select")||e.select_attribute,i=this.hass.states[o]?.attributes,r=this._selectable_attributes.some((e=>i?.[e])),s=Object.keys(this.hass.states[o]?.attributes||{}).map((e=>{let t=this.hass.states[o];return{label:this.hass.formatEntityAttributeName(t,e),value:e}})).filter((e=>this._selectable_attributes.includes(e.value))),l=e.visibility??[];return ce `
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:border-radius" > < / h a - i c o n >
$ { this . _config . sub _button [ t ] ? "Button " + ( t + 1 ) + ( e . name ? " - " + e . name : "" ) : "New button" }
< button class = "icon-button header" @ click = "${n=>{n.stopPropagation();let o=[...this._config.sub_button];o.splice(t,1),this._config.sub_button=o,this._valueChanged({target:{configValue:" sub _button . "+(t-1),value:e}}),this.requestUpdate()}}" >
< ha - icon icon = "mdi:delete" > < / h a - i c o n >
< / b u t t o n >
$ { t > 0 ? ce ` <button class="icon-button header" @click=" ${ e => { if ( e . stopPropagation ( ) , t > 0 ) { let e = [ ... this . _config . sub _button ] ; [ e [ t ] , e [ t - 1 ] ] = [ e [ t - 1 ] , e [ t ] ] , this . _config . sub _button = e , this . _valueChanged ( { target : { configValue : "sub_button." + t , value : this . _config . sub _button [ t ] } })}this.requestUpdate()}}">
< ha - icon icon = "mdi:arrow-left" > < / h a - i c o n >
< / b u t t o n > ` : " " }
$ { t < this . _config . sub _button . length - 1 ? ce ` <button class="icon-button header" @click=" ${ e => { if ( e . stopPropagation ( ) , t < this . _config . sub _button . length - 1 ) { let e = [ ... this . _config . sub _button ] ; [ e [ t ] , e [ t + 1 ] ] = [ e [ t + 1 ] , e [ t ] ] , this . _config . sub _button = e , this . _valueChanged ( { target : { configValue : "sub_button." + t , value : this . _config . sub _button [ t ] } })}this.requestUpdate()}}">
< ha - icon icon = "mdi:arrow-right" > < / h a - i c o n >
< / b u t t o n > ` : " " }
< / h 4 >
< div class = "content" >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:cog" > < / h a - i c o n >
Button settings
< / h 4 >
< div class = "content" >
< div class = "ha-combo-box" >
< ha - combo - box
label = "${" Optional - Entity ( default to card entity ) "}"
. value = "${o}"
. items = "${this.allEntitiesList}"
@ value - changed = "${e=>this._arrayValueChange(t,{entity:e.detail.value}," sub _button ")}"
> < / h a - c o m b o - b o x >
< / d i v >
$ { r ? ce `
< div class = "ha-combo-box" >
< ha - combo - box
label = "Optional - Select menu (from attributes)"
. value = "${e.select_attribute}"
. items = "${s}"
@ value - changed = "${e=>this._arrayValueChange(t,{select_attribute:e.detail.value}," sub _button ")}"
> < / h a - c o m b o - b o x >
< / d i v >
` :""}
< div class = "ha-textfield" >
< ha - textfield
label = "Optional - Name"
. value = "${e.name??" "}"
@ input = "${e=>this._arrayValueChange(t,{name:e.target.value}," sub _button ")}"
> < / h a - t e x t f i e l d >
< / d i v >
< div class = "ha-icon-picker" >
< ha - icon - picker
label = "Optional - Icon"
. value = "${e.icon}"
item - label - path = "label"
item - value - path = "value"
@ value - changed = "${e=>this._arrayValueChange(t,{icon:e.detail.value}," sub _button ")}"
> < / h a - i c o n - p i c k e r >
< / d i v >
$ { this . makeShowState ( e , n , "sub_button" , t ) }
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined style = "${a?" opacity : 0.5 ; pointer - events : none ; ":" "}" >
< h4 slot = "header" >
< ha - icon icon = "mdi:gesture-tap" > < / h a - i c o n >
Tap action on button
< / h 4 >
< div class = "content" >
2025-01-17 19:45:32 +00:00
$ { this . makeActionPanel ( "Tap action" , e , "more-info" , "sub_button" , t ) }
$ { this . makeActionPanel ( "Double tap action" , e , "none" , "sub_button" , t ) }
$ { this . makeActionPanel ( "Hold action" , e , "none" , "sub_button" , t ) }
2024-12-17 17:05:10 +00:00
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:eye" > < / h a - i c o n >
Visibility
< / h 4 >
< div class = "content" >
< ha - card - conditions - editor
. hass = $ { this . hass }
. conditions = $ { l }
@ value - changed = $ { e => this . _conditionChanged ( e , t , "sub_button" ) }
>
< / h a - c a r d - c o n d i t i o n s - e d i t o r >
< ha - alert alert - type = "info" >
The sub - button will be shown when ALL conditions are fulfilled . If no conditions are set , the sub - button will always be shown .
< / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
` }));return ce `
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:shape-square-rounded-plus" > < / h a - i c o n >
Sub - buttons editor
< / h 4 >
< div class = "content" >
$ { e }
< button class = "icon-button" @ click = "${()=>{this._config.sub_button||(this._config.sub_button=[]);let e={entity:this._config.entity};this._config.sub_button=[...this._config.sub_button],this._config.sub_button.push(e),(0,n.BX)(this," config - changed ",{config:this._config}),this.requestUpdate()}}" >
< ha - icon icon = "mdi:plus" > < / h a - i c o n >
New sub - button
< / b u t t o n >
< ha - alert alert - type = "info" >
Add new customized buttons fixed to the right .
These buttons can also display a select menu for your
< code > input _select < / c o d e > , < c o d e > s e l e c t < / c o d e > e n t i t i e s , a n d
any other entities that have attribute lists like
< code > source _list < / c o d e > , < c o d e > s o u n d _ m o d e _ l i s t < / c o d e > ,
< code > hvac _modes < / c o d e > , < c o d e > f a n _ m o d e s < / c o d e > ,
< code > swing _modes < / c o d e > , < c o d e > p r e s e t _ m o d e s < / c o d e > , o r
< code > effect _list < / c o d e > .
< / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
` }makeButton(){let e=[];for(let t=1;t<=this.buttonIndex;t++)e.push(ce `
< div class = "${t}_button" >
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:border-radius" > < / h a - i c o n >
Button $ { t } $ { this . _config [ t + "_name" ] ? "- " + this . _config [ t + "_name" ] : "" }
< button class = "icon-button header" @ click = "${()=>this.removeButton(t)}" >
< ha - icon icon = "mdi:delete" > < / h a - i c o n >
< / b u t t o n >
< / h 4 >
< div class = "content" >
< ha - textfield
label = "Link / Hash to pop-up (e.g. #kitchen)"
. value = "${this._config[t+" _link "]||" "}"
. configValue = "${t}_link"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - textfield
label = "Optional - Name"
. value = "${this._config[t+" _name "]||" "}"
. configValue = "${t}_name"
@ input = "${this._valueChanged}"
> < / h a - t e x t f i e l d >
< ha - icon - picker
label = "Optional - Icon"
. value = "${this._config[t+" _icon "]||" "}"
. configValue = "${t}_icon"
item - label - path = "label"
item - value - path = "value"
@ value - changed = "${this._valueChanged}"
> < / h a - i c o n - p i c k e r >
< ha - combo - box
label = "Optional - Light / Light group (For background color)"
. value = "${this._config[t+" _entity "]||" "}"
. configValue = "${t}_entity"
. items = "${this.allEntitiesList}"
@ value - changed = "${this._valueChanged}"
> < / h a - c o m b o - b o x >
< ha - combo - box
label = "Optional - Presence / Occupancy sensor (For button auto order)"
. value = "${this._config[t+" _pir _sensor "]||" "}"
. configValue = "${t}_pir_sensor"
. disabled = $ { ! this . _config . auto _order }
. items = "${this.allEntitiesList}"
@ value - changed = "${this._valueChanged}"
> < / h a - c o m b o - b o x >
< ha - alert alert - type = "info" > In fact you can also get the auto order with any entity type , for example you can add light groups to these fields and the order will change based on the last changed states . < / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
< / d i v >
` );return e}makeVersion(){return ce `
< h4 style = "
font - size : 12 px ! important ;
color : # fff ;
background : rgba ( 0 , 0 , 0 , 0.1 ) ;
padding : 8 px 16 px ;
border - radius : 32 px ;
" >
Bubble Card
< span style = "
font - size : 10 px ;
background : rgba ( 0 , 120 , 180 , 1 ) ;
padding : 0 px 8 px ;
border - radius : 12 px ;
margin - right : - 6 px ;
float : right ;
color : white ;
" >
$ { e }
< / s p a n >
< / h 4 >
` }removeButton(e){delete this._config[e+"_name"],delete this._config[e+"_icon"],delete this._config[e+"_link"],delete this._config[e+"_entity"],delete this._config[e+"_pir_sensor"];for(let t=e;t<this.buttonIndex;t++)this._config[t+"_name"]=this._config[t+1+"_name"],this._config[t+"_icon"]=this._config[t+1+"_icon"],this._config[t+"_link"]=this._config[t+1+"_link"],this._config[t+"_entity"]=this._config[t+1+"_entity"],this._config[t+"_pir_sensor"]=this._config[t+1+"_pir_sensor"];delete this._config[this.buttonIndex+"_name"],delete this._config[this.buttonIndex+"_icon"],delete this._config[this.buttonIndex+"_link"],delete this._config[this.buttonIndex+"_entity"],delete this._config[this.buttonIndex+"_pir_sensor"],this.buttonIndex--,(0,n.BX)(this,"config-changed",{config:this._config})}makeStyleEditor(){return ce `
< ha - expansion - panel outlined >
< h4 slot = "header" >
< ha - icon icon = "mdi:code-braces" > < / h a - i c o n >
Custom styles / Templates
< / h 4 >
< div class = "content" >
< div class = "code-editor" >
< ha - code - editor
mode = "yaml"
autofocus
autocomplete - entities
autocomplete - icons
. hass = $ { this . hass }
. value = $ { this . _config . styles }
. configValue = "${" styles "}"
@ value - changed = $ { this . _valueChanged }
> < / h a - c o d e - e d i t o r >
< / d i v >
< ha - alert alert - type = "info" >
For advanced users , you can edit the CSS style of this card in this editor . More information < a href = "https://github.com/Clooos/Bubble-Card#styling" > here < / a > . Y o u d o n ' t n e e d t o a d d < c o d e > s t y l e s : | < / c o d e > , i t w i l l b e a d d e d a u t o m a t i c a l l y . Y o u c a n a l s o a d d < a h r e f = " h t t p s : / / g i t h u b . c o m / C l o o o s / B u b b l e - C a r d # t e m p l a t e s " > t e m p l a t e s < / a > .
< br > < br > < b > Looking for more advanced examples ? < /b> Check out my <a href="https:/ / www . patreon . com / Clooos " > Patreon < / a > f o r e x c l u s i v e c u s t o m s t y l e s a n d a d v a n c e d t e m p l a t e s , t h i s i s a l s o t h e b e s t w a y t o s h o w y o u r s u p p o r t t o m y p r o j e c t !
< / h a - a l e r t >
< / d i v >
< / h a - e x p a n s i o n - p a n e l >
2025-01-17 19:45:32 +00:00
` }_valueChanged(e){const t=e.target,o=e.detail;let a;if("HA-SWITCH"===t.tagName?a=t.checked:void 0!==t.value&&(a="string"==typeof t.value?t.value.replace(",","."):t.value),"string"==typeof a&&(a.endsWith(".")||"-"===a))return;const{configValue:i,checked:r}=t;if(i){const n=i.split(".");let r=this._config;for(let e=0;e<n.length-1;e++)r[n[e]]=r[n[e]]||{},r=r[n[e]];"input"===e.type?r[n[n.length-1]]=a:o&&r[n[n.length-1]]!==o.value?r[n[n.length-1]]=o.value:"HA-SWITCH"===t.tagName&&(r[n[n.length-1]]=a)}(0,n.BX)(this,"config-changed",{config:this._config}),this.requestUpdate()}_arrayValueChange(e,t,o){if(this._config.sub_button&&!this.subButtonJustAdded)return this.subButtonJustAdded=!0,void setTimeout((()=>this._arrayValueChange(e,t,o)),10);this._config[o]=this._config[o]||[];let a=[...this._config[o]];a[e]=a[e]||{},a[e]={...a[e],...t},this._config[o]=a,(0,n.BX)(this,"config-changed",{config:this._config}),this.requestUpdate()}_ActionChanged(e,t,o){if(e.stopPropagation(),"button_action"===t){var a=!!this._config[t],i=null!=e.detail.value[e.currentTarget.__schema[0].name];(a||i)&&(this._config[t]=e.detail.value)}else if(t){this._config[t]=this._config[t]||[];let n=[...this._config[t]];n[o]=e.detail.value,this._config[t]=n}else this._config=e.detail.value;(0,n.BX)(this,"config-changed",{config:this._config})}_computeLabelCallback=e=>{switch(e.name){case"theme":return"Theme";case"hold_action":return"Hold Action";case"double_tap_action":return"Double tap action";case"open_action":return"Open action";case"close_action":return"Close action";default:return"Tap action"}};_conditionChanged(e,t,o){if(e.stopPropagation(),o){this._config[o]=this._config[o]||[];let n=[...this._config[o]];n[t]=n[t]||{};const a=e.detail.value;n[t]={...n[t],visibility:a},this._config[o]=n}else if("pop-up"===this._config.card_type){const t=e.detail.value;this._config={...this._config,trigger:t}}(0,n.BX)(this,"config-changed",{config:this._config}),this.requestUpdate()}static get styles(){return de `
2024-12-17 17:05:10 +00:00
div {
display : grid ;
grid - gap : 12 px ;
}
ha - combo - box [ label = "Card type" ] : : after {
content : "" ;
position : relative ;
background - color : var ( -- background - color , var ( -- secondary - background - color ) ) ;
display : block ;
width : 100 % ;
height : 1 px ;
top : 12 px ;
margin - bottom : 12 px ! important ;
opacity : 0.6 ;
}
# add - button {
margin : 0 0 14 px 0 ;
color : var ( -- text - primary - color ) ;
width : 100 % ;
height : 32 px ;
border - radius : 16 px ;
border : none ;
background - color : var ( -- accent - color ) ;
cursor : pointer ;
}
p {
margin - bottom : 4 px ;
}
ha - icon , a , p , button , h4 {
color : var ( -- primary - text - color ) ! important ;
}
hr {
display : inline - block ;
width : 100 % ;
border : 1 px solid var ( -- background - color , var ( -- secondary - background - color ) ) ;
opacity : 0.6 ;
margin : 8 px 0 0 0 ;
}
code {
background : var ( -- accent - color ) ;
background - blend - mode : darken ;
padding : 2 px 4 px ;
border - radius : 6 px ;
}
. button - header {
height : auto ;
width : 100 % ;
display : inline - flex ;
align - items : center ;
margin : 0 8 px ;
}
. button - number {
display : inline - flex ;
width : auto ;
}
. remove - button {
display : inline - flex ;
border - radius : 50 % ;
width : 24 px ;
height : 24 px ;
text - align : center ;
line - height : 24 px ;
vertical - align : middle ;
cursor : pointer ;
}
. content {
margin : 12 px 4 px 14 px 4 px ;
}
h4 > ha - icon {
margin : 8 px ;
}
ha - textfield {
width : 100 % ;
}
h3 {
margin : 4 px 0 ;
}
. code - editor {
overflow : scroll ;
}
. icon - button {
background : var ( -- accent - color ) ;
border : none ;
cursor : pointer ;
padding : 8 px ;
margin : 0 ;
border - radius : 32 px ;
font - weight : bold ;
}
. icon - button . header {
background : none ;
float : right ;
padding : 0 ;
margin : 0 8 px ;
}
ha - card - conditions - editor {
margin - top : - 12 px ;
}
` }})}(),document.createElement("bubble-card-editor")}getLayoutOptions(){let e=1;"pop-up"===this.config.card_type?e=0:"horizontal-buttons-stack"===this.config.card_type?e=1:["cover"].includes(this.config.card_type)&&(e=2);let t=4;return"pop-up"===this.config.card_type?t=0:"horizontal-buttons-stack"===this.config.card_type&&(t=4),{grid_columns:this.config.columns??t,grid_rows:this.config.rows??e}}}customElements.define("bubble-card",ue),window.customCards=window.customCards||[],window.customCards.push({type:"bubble-card",name:"Bubble Card",preview:!1,description:"A minimalist card collection with a nice pop-up touch.",documentationURL:"https://github.com/Clooos/Bubble-Card/"}),console.info( ` % c Bubble Card % c $ { e } ` ,"background-color: #555;color: #fff;padding: 3px 2px 3px 3px;border-radius: 14px 0 0 14px;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)","background-color: #506eac;color: #fff;padding: 3px 3px 3px 2px;border-radius: 0 14px 14px 0;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)")})()})();