StatusBadge Implementation

Pretty cool; just had to inherit Button and add stylesheets
Area

class StatusBadge(Button):
    """
    A customizable badge component that can show different statuses with visual effects.
    """

    status = param.Selector(
        default="pending", objects=["pending", "running", "success", "failed"]
    )

    _base_stylesheet = """
    :host {
        position: relative;
    }

    /* Base badge styles */
    .bk-btn {
        border-radius: 16px !important;
        padding: 6px 10px !important;
        transition: all 0.3s ease;
        cursor: not-allowed;
        pointer-events: none !important;
    }

    .bk-btn .bk-TablerIcon {
        display: inline-flex;
        border-radius: 50%;
        margin-right: 5px;
        margin-bottom: 2px;
    }

    .bk-btn .bk-TablerIcon path {
        stroke: inherit;
        fill: inherit;
    }
    """

    # Status-specific stylesheets
    _status_stylesheets = {
        "pending": """
            /* Badge pending state */
            .bk-btn {
                background-color: #f0f0f0 !important;
                border-color: #d0d0d0 !important;
                color: #606060 !important;
            }

            .bk-btn .bk-TablerIcon {
                color: #808080 !important;
            }

            .bk-btn .bk-TablerIcon path {
                stroke: #808080;
                fill: #808080;
            }
        """,
        "running": """
            /* Badge running state */
            .bk-btn {
                background-color: #fffceb !important;
                border-color: #ffe066 !important;
                color: #997a00 !important;
            }

            .bk-btn .bk-TablerIcon {
                color: #FFD700 !important;
                animation: pulse-gold 2.5s infinite;
            }

            .bk-btn .bk-TablerIcon path {
                stroke: #FFD700;
                fill: #FFD700;
            }

            @keyframes pulse-gold {
                0% {
                    box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.7);
                }
                70% {
                    box-shadow: 0 0 0 7px rgba(255, 215, 0, 0);
                }
                100% {
                    box-shadow: 0 0 0 0 rgba(255, 215, 0, 0);
                }
            }
        """,
        "success": """
            /* Badge success state */
            .bk-btn {
                background-color: #e8f5e9 !important;
                border-color: #a5d6a7 !important;
                color: #2e7d32 !important;
            }

            .bk-btn .bk-TablerIcon {
                color: #4CAF50 !important;
            }

            .bk-btn .bk-TablerIcon path {
                stroke: #4CAF50;
                fill: #4CAF50;
            }
        """,
        "failed": """
            /* Badge failed state */
            .bk-btn {
                background-color: #ffebee !important;
                border-color: #ef9a9a !important;
                color: #c62828 !important;
            }

            .bk-btn .bk-TablerIcon {
                color: #f44336 !important;
            }

            .bk-btn .bk-TablerIcon path {
                stroke: #f44336;
                fill: #f44336;
            }
        """,
    }

    # Status mapping for other properties
    _status_mapping = {
        "pending": {
            "icon": "circle",
        },
        "running": {
            "icon": "circle-filled",
        },
        "success": {
            "icon": "circle-check",
        },
        "failed": {
            "icon": "circle-x",
        },
    }

    _rename = {
        "status": None,
        **Button._rename,
    }

    def __init__(self, **params):
        super().__init__(**params)
        self.param.update(
            icon=self.param.status.rx().rx.pipe(
                lambda status: self._status_mapping[status]["icon"]
            ),
            stylesheets=self.param.status.rx().rx.pipe(
                lambda status: [self._base_stylesheet, self._status_stylesheets[status]]
            ),
        )