Close menu

Pattern Library

Button Group

Window sizes

Button Group

A container for grouping related buttons. Supports a standard stacked layout and a segmented (toolbar) layout where buttons share borders. Follows USWDS button group patterns.

Props

c-button-group

Prop Default Description
segemented Set to "true" to render buttons as a connected segmented group

c-button-group.button-group-item

The c-button-group.button-group-item component is a wrapper <li> item. It accepts no props; place a c-button inside it.

Example Usage

Default Button Group

Buttons are stacked and styled independently.

<c-button-group>
    <c-button-group.button-group-item>
        <c-button text="Back" variant="outline" />
    </c-button-group.button-group-item>
    <c-button-group.button-group-item>
        <c-button text="Continue" />
    </c-button-group.button-group-item>
</c-button-group>

Segmented Button Group

Buttons share borders and appear as a connected unit, useful for toggle controls.

<c-button-group segemented="true">
    <c-button-group.button-group-item>
        <c-button text="Map" />
    </c-button-group.button-group-item>
    <c-button-group.button-group-item>
        <c-button text="Hybrid" variant="outline" />
    </c-button-group.button-group-item>
    <c-button-group.button-group-item>
        <c-button text="Satellite" variant="outline" />
    </c-button-group.button-group-item>
</c-button-group>

Segmented Group with Accent Cool

<c-button-group segemented="true">
    <c-button-group.button-group-item>
        <c-button text="Map" variant="accent-cool" />
    </c-button-group.button-group-item>
    <c-button-group.button-group-item>
        <c-button text="Hybrid" variant="accent-cool" />
    </c-button-group.button-group-item>
    <c-button-group.button-group-item>
        <c-button text="Satellite" variant="accent-cool" />
    </c-button-group.button-group-item>
</c-button-group>

Segmented Group with Outline Inverse

Use on dark backgrounds.

<c-button-group segemented="true">
    <c-button-group.button-group-item>
        <c-button text="Map" variant="outline-inverse" />
    </c-button-group.button-group-item>
    <c-button-group.button-group-item>
        <c-button text="Hybrid" variant="outline-inverse" />
    </c-button-group.button-group-item>
    <c-button-group.button-group-item>
        <c-button text="Satellite" variant="outline-inverse" />
    </c-button-group.button-group-item>
</c-button-group>

Usage Notes

  • Note: the segemented prop name preserves the original USWDS Cotton component spelling
  • In a segmented group, all buttons should use the same variant for visual consistency
  • Each button must be wrapped in a c-button-group.button-group-item element
  • The default layout is suitable for form navigation (e.g., Back / Continue); the segmented layout is better for view-toggle controls
{% load cotton %}

<div class="component-variants">
    <h1>Button Group Component</h1>
    
    {% for variant in default_variant %}
    <div class="component-variant">
        <h2 class="variant-title">{{ variant.title }}</h2>

        {% cotton button-group %}
            {% cotton button-group.button-group-item %}
                {% cotton button text="Back" variant="outline" %}{% endcotton %}
            {% endcotton %}
            {% cotton button-group.button-group-item %}
                {% cotton button text="Continue" %}{% endcotton %}
            {% endcotton %}
        {% endcotton %}
    </div>
    {% endfor %}
    {% for variant in segemented_variant %}
    <div class="component-variant">
        <h2 class="variant-title">{{ variant.title }}</h2>

        {% cotton button-group segemented="{{ variant.segemented }}" %}
            {% for options in variant.options %}
            {% cotton button-group.button-group-item %}
                {% cotton button text="{{ options.text }}" variant="{{ options.variant }}" %}{% endcotton %}
            {% endcotton %}
            {% endfor %}
        {% endcotton %}
    </div>
    {% endfor %}
    {% for variant in segemented_inverse_variant %}
    <div class="component-variant">
        <h2 class="variant-title">{{ variant.title }}</h2>
        <div class="bg-base-darkest padding-1" style="max-width: fit-content">
            {% cotton button-group segemented="{{ variant.segemented }}" %}
                {% for options in variant.options %}
                {% cotton button-group.button-group-item %}
                    {% cotton button text="{{ options.text }}" variant="{{ options.variant }}" %}{% endcotton %}
                {% endcotton %}
                {% endfor %}
            {% endcotton %}
        </div>
    </div>
    {% endfor %}
</div>
name: Button Group
context:
  default_variant:            
    - title: "Button Group Default"
      control_id: "button-group-1"
      label_title: "This is a button group"
  segemented_variant:            
    - title: "Button Group Segemented Hybrid"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: ""
      - text: "Hybrid"
        state: ""
        variant: "outline"
      - text: "Satellite"
        state: ""
        variant: "outline"
    - title: "Button Group Segemented Default"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: ""
      - text: "Hybrid"
        state: ""
        variant: ""
      - text: "Satellite"
        state: ""
        variant: ""
    - title: "Button Group Segemented Accent Cool"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: "accent-cool"
      - text: "Hybrid"
        state: ""
        variant: "accent-cool"
      - text: "Satellite"
        state: ""
        variant: "accent-cool"
    - title: "Button Group Segemented Accent Warm"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: "accent-warm"
      - text: "Hybrid"
        state: ""
        variant: "accent-warm"
      - text: "Satellite"
        state: ""
        variant: "accent-warm"
    - title: "Button Group Segemented Base"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: "base"
      - text: "Hybrid"
        state: ""
        variant: "base"
      - text: "Satellite"
        state: ""
        variant: "base"
    - title: "Button Group Segemented Big"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: "big"
      - text: "Hybrid"
        state: ""
        variant: "big"
      - text: "Satellite"
        state: ""
        variant: "big"
    - title: "Button Group Segemented Outline"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: "outline"
      - text: "Hybrid"
        state: ""
        variant: "outline"
      - text: "Satellite"
        state: ""
        variant: "outline"
    - title: "Button Group Segemented Secondary"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: "secondary"
      - text: "Hybrid"
        state: ""
        variant: "secondary"
      - text: "Satellite"
        state: ""
        variant: "secondary"
  segemented_inverse_variant:            
    - title: "Button Group Segemented Hybrid"
      segemented: "true"
      options:
      - text: "Map"
        state: ""
        variant: "outline-inverse"
      - text: "Hybrid"
        state: ""
        variant: "outline-inverse"
      - text: "Satellite"
        state: ""
        variant: "outline-inverse"