• HTML

    input-button.html html

    <input-button>
    	<button type="button">
    		<span class="label">🛒 Shopping Cart</span>
    		<span class="badge">5</span>
    	</button>
    </input-button>
    
    <input-button disabled>
    	<button type="submit" class="primary" disabled>Submit</button>
    </input-button>
    CSS

    input-button.css css

    input-button {
    	position: relative;
    	display: inline-block;
    	flex: 0;
    
    	& button {
    		height: var(--input-height);
    		min-width: var(--input-height);
    		border: 1px solid var(--color-border);
    		border-radius: var(--space-xs);
    		background-color: var(--color-secondary);
    		color: var(--color-text);
    		padding: 0 var(--space-s);
    		font-size: var(--font-size-s);
    		line-height: var(--line-height-s);
    		white-space: nowrap;
    		opacity: var(--opacity-dimmed);
    		transition: all var(--transition-shorter) var(--easing-inout);
    
    		&:disabled {
    			opacity: var(--opacity-translucent);
    		}
    
    		&:not(:disabled) {
    			cursor: pointer;
    			opacity: var(--opacity-solid);
    
    			&:hover {
    				background-color: var(--color-secondary-hover);
    			}
    
    			&:active {
    				background-color: var(--color-secondary-active);
    			}
    		}
    
    		&.primary {
    			color: var(--color-text-inverted);
    			background-color: var(--color-primary);
    			border-color: var(--color-primary-active);
    			
    			&:not(:disabled) {
    				opacity: var(--opacity-solid);
    
    				&:hover {
    					background-color: var(--color-primary-hover);
    				}
    
    				&:active {
    					background-color: var(--color-primary-active);
    				}
    			}
    		}
    
    		&.destructive {
    			color: var(--color-text-inverted);
    			background-color: var(--color-error);
    			border-color: var(--color-error-active);
    			
    			&:not(:disabled) {
    				opacity: var(--opacity-solid);
    				
    				&:hover {
    					background-color: var(--color-error-hover);
    				}
    
    				&:active {
    					background-color: var(--color-error-active);
    				}
    			}
    		}
    
    		&.constructive {
    			color: var(--color-text-inverted);
    			background-color: var(--color-success);
    			border-color: var(--color-success-active);
    			
    			&:not(:disabled) {
    				opacity: var(--opacity-solid);
    				
    				&:hover {
    					background-color: var(--color-success-hover);
    				}
    
    				&:active {
    					background-color: var(--color-success-active);
    				}
    			}
    		}
    
    		&.small {
    			--input-height: var(--space-l);
    			font-size: var(--font-size-xs);
    			padding-inline: var(--space-xs);
    		}
    
    		&.large {
    			--input-height: var(--space-xl);
    			font-size: var(--font-size-m);
    			padding-inline: var(--space-m);
    		}
    	}
    
    	.badge {
    		position: absolute;
    		box-sizing: border-box;
    		top: calc(-1* var(--space-s));
    		right: calc(-1* var(--space-s));
    		font-size: var(--font-size-xs);
    		line-height: var(--line-height-xs);
    		background-color: var(--color-primary);
    		color: var(--color-white);
    		padding: var(--space-xxs) var(--space-xs);
    		height: calc(2* var(--space-s));
    		min-width: calc(2* var(--space-s));
    		border-radius: var(--space-s);
    
    		&:empty {
    			display: none;
    		}
    	}
    }
    
    TS

    input-button.ts ts

    import { UIElement, asBoolean, setProperty, setText } from "../../../"
    
    export class InputButton extends UIElement<{ disabled: boolean }> {
    	static localName = 'input-button'
    	static observedAttributes = ['disabled']
    
    	init = {
            disabled: asBoolean,
        }
    
    	connectedCallback() {
            super.connectedCallback()
    
    		this.first<HTMLButtonElement>('button').sync(setProperty('disabled'))
    		this.first('.label').sync(setText('label'))
    		this.first('.badge').sync(setText('badge'))
        }
    }
    InputButton.define()