TriStateCheckbox add a new state to a checkbox value.
<div class="card">
    <h:form>
        <p:growl id="growl" showDetail="true"/>
        <h5 class="mt-0">Basic</h5>
        <p:triStateCheckbox value="#{triStateCheckboxView.value1}"/>
        <h5>Remote</h5>
        <p:triStateCheckbox id="ajaxTriState" value="#{triStateCheckboxView.value2}">
            <p:ajax event="change" update="growl" listener="#{triStateCheckboxView.addMessage}"/>
        </p:triStateCheckbox>
        <h5>Custom Icons and Label</h5>
        <p:triStateCheckbox value="#{triStateCheckboxView.value3}" stateTwoIcon="pi pi-plus" stateThreeIcon="pi pi-minus" itemLabel="Custom Icons"/>
    </h:form>
</div>
package org.primefaces.showcase.view.input;
import java.io.Serializable;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
@Named("triStateCheckboxView")
@ViewScoped
public class TriStateCheckboxView implements Serializable {
    private Boolean value1;
    private Boolean value2;
    private Boolean value3;
    @PostConstruct
    public void init() {
        value1 = Boolean.FALSE;
        value2 = Boolean.TRUE;
    }
    public Boolean getValue1() {
        return value1;
    }
    public void setValue1(Boolean value1) {
        this.value1 = value1;
    }
    public Boolean getValue2() {
        return value2;
    }
    public void setValue2(Boolean value2) {
        this.value2 = value2;
    }
    public Boolean getValue3() {
        return value3;
    }
    public void setValue3(Boolean value3) {
        this.value3 = value3;
    }
    public void addMessage() {
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
                "State has been changed", "State is = " + value2);
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
}