<table class="bux-table" aria-describedby="summary-default">
    <caption>Default Table</caption>
    <thead>
        <tr>
            <th scope="col">Column 1</th>
            <th scope="col">Column 2</th>
            <th scope="col">Column 3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Cell data A1</td>
            <td>Cell data B1</td>
            <td>Cell data C1</td>
        </tr>
        <tr>
            <td>Cell data B1</td>
            <td>Cell data B2</td>
            <td>Cell data B3</td>
        </tr>
        <tr>
            <td>Cell data C1</td>
            <td>Cell data C2</td>
            <td>Cell data C3</td>
        </tr>
    </tbody>
</table>
<div class="bux-table bux-table--announcement-region" aria-live="polite"></div>

<p id="summary-default" class="visually-hidden"> Some info about this default table.</p>
{# 

Table

Available variables:

- striped:          Set to true for a striped table.
- compact:          Set to true for a compact table.
- sortable:         Set to true for a sortable table.
- summary:          Content of the table summary. Optional.
- summaryId:        Unique ID for the summary.
- caption:          Content of the table's caption.
- header_columns:   Array of column headers.
- row_header:       Set to true for row headers as well as column headers.
- rows:             Array of table rows.
- rows.cells:       Array of row cells.

#}

{% set classes_array = ["bux-table"] %}
{% if striped is defined %}
	{% set classes_array = classes_array|merge(["bux-table--striped"]) %}
{% endif %}
{% if compact is defined %}
	{% set classes_array = classes_array|merge(["bux-table--compact"]) %}
{% endif %}
{% if sortable is defined %}
	{% set classes_array = classes_array|merge(["bux-table--sortable"]) %}
{% endif %}


{% set table_classes = classes_array|join(" ") %}

<table class="{{ table_classes }}" {% if summary %} aria-describedby="{{ summaryId }}" {% endif %}>
	<caption>{{ caption }}</caption>
	<thead>
		<tr>
			{% for col in header_columns %}
				{% if sortable %}
					<th scope="col" class="sort-by"><button aria-pressed="false">{{ col }}</button></th>
				{% else %}
					<th scope="col">{{ col }}</th>
				{% endif %}
			{% endfor %}
		</tr>
	</thead>
	<tbody>
		{% for row in rows %}
			<tr>
				{% for cell in row.cells %}
					{% if row_header and loop.first %}
						<th scope="row">{{ cell }}</th>
					{% else %}
						<td>{{ cell }}</td>
					{% endif %}
				{% endfor %}
			</tr>
		{% endfor %}
	</tbody>
</table>
<div class="{{ table_classes }} bux-table--announcement-region" aria-live="polite"></div>

{% if summary %}
	<p id="{{ summaryId }}" class="visually-hidden"> {{ summary }}</p>
{% endif %}
site_name_prefix: Office of
site_name: Learning Relations Excellence
site_slogan: Additional text or site slogan
address_1: 100 Building Name
address_2: 1 Oval Mall
city: Columbus
state: OH
zip: '43210'
contact_email: email@osu.edu
contact_phone: 614-292-OHIO
contact_tty: 614-688-8605
header_columns:
  '1': Column 1
  '2': Column 2
  '3': Column 3
rows:
  - cells:
      '1': Cell data A1
      '2': Cell data B1
      '3': Cell data C1
  - cells:
      '1': Cell data B1
      '2': Cell data B2
      '3': Cell data B3
  - cells:
      '1': Cell data C1
      '2': Cell data C2
      '3': Cell data C3
caption: Default Table
summary: Some info about this default table.
summaryId: summary-default
  • Content:
    .bux-table {
    	width: 100%;
    	display: table;
        overflow-x: auto;
    
    	caption {
    		font-size: $ts-22;
    		font-weight: 700;
    		line-height: calc(#{$ts-22} * 1.125);
    		margin-bottom: $sp-16;
    		text-align: left;
    		@include breakpoint(md) {
    			font-size: $ts-md;
    			line-height: calc(#{$ts-md} * 1.125);
    		}
    		p {
    			font-family: inherit;
    		}
    	}
    	th {
    		font-size: $ts-base;
    		padding: $sp-8 $sp-16;
    		border-bottom: 2px solid $gray-dark-40;
    		background-color: $white;
    		text-align: left;
    		font-weight: 700;
    
    	}
    	tbody th {
    			font-weight: 700;
    			border-bottom: none;
    			border-right: 2px solid $gray-dark-40;
    		}
    	tr {
    		border-bottom: 2px solid $gray-light-80;
    	}
    	td {
    		font-size: $ts-base;
    		padding: $sp-16;
    		font-weight: 400;
    	}
    }
    
    // Striped variant.
    .bux-table--striped {
    	tr:nth-child(even) {
    		background-color: $gray-light-90;
    	}
    }
    
    // Compact variant.
    .bux-table--compact {
    	th,
    	td {
    		font-size: $ts-sm;
    		padding: $sp-8;
    	}
    }
    
    .bux-table--sortable {
    	.sort-by {
    		cursor: pointer;
    
        button {
          color: $gray-dark-80;
          margin: 0;
          padding: 0;
          background-color: transparent;
          border: none;
          &:after {
            content: "\f00f";
            font-family: $icon;
            color: $gray-dark-80;
            margin-left: $sp-4;
          }
        }
    	}
    	.th-sort-asc,
    	.th-sort-desc {
    		background-color: $gray-light-90;
    		margin-left: $sp-4;
    	}
    	.th-sort-asc {
        button::after	{
    		  content: "\f011";
    		  font-family: $icon;
        }
    	}
    	.th-sort-desc {
        button::after	{
    		  content: "\f010";
    		  font-family: $icon;
        }
    	}
      &.bux-table--announcement-region {
        @include visually-hidden();
      }
    }
    
  • URL: /components/raw/table/_table.scss
  • Filesystem Path: src/components/table/_table.scss
  • Size: 1.6 KB
  • Content:
    function sortTable(table, column, asc = true) {
        const dirModifier = asc ? 1 : -1;
        const tBody = table.tBodies[0];
        const rows = Array.from(tBody.querySelectorAll("tr"));
    
        // Sort each row
        const sortedRows = rows.sort((a, b) => {
            const aColText = a.querySelector(`td:nth-child(${column + 1})`).textContent.trim();
            const bColText = b.querySelector(`td:nth-child(${column + 1})`).textContent.trim();
    
            return aColText > bColText ? (1 * dirModifier) : (-1 * dirModifier);
        });
    
        // Remove all existing TRs
        while (tBody.firstChild) {
            tBody.removeChild(tBody.firstChild);
        }
    
        // Add sorted TRs
        tBody.append(...sortedRows);
    
        // Record sort direction
        table.querySelectorAll("th").forEach(th => th.classList.remove("th-sort-asc", "th-sort-desc"));
        table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-asc", asc);
        table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-desc", !asc);
    
        // Add/Move aria-sort attribute to sorted column
        table.querySelectorAll("th").forEach(th => th.removeAttribute("aria-sort"));
        let ariaSort = (asc) ? "ascending" : "descending";
        table.querySelector(`th:nth-child(${column + 1})`).setAttribute("aria-sort", ariaSort);
    
        // Modify aria-pressed values on buttons
        table.querySelectorAll("th button").forEach(button => button.setAttribute("aria-pressed", "false"));
        table.querySelector(`th:nth-child(${column + 1}) button`).setAttribute("aria-pressed", "true");
    
        // Update aria-live region
        let caption = table.querySelector("caption").textContent;
        let columnName = table.querySelector(`th:nth-child(${ column + 1}) button`).textContent;
        let announcement = `${ columnName } is now sorted in ${ ariaSort } order.`;
        table.parentElement.querySelector(".bux-table--announcement-region").textContent = announcement;
    }
    
    // Query for tables with Sortable property and add Click event
    document.querySelectorAll(".bux-table--sortable th button").forEach(button => {
        button.addEventListener("click", () => {
            const headerCell = button.parentElement;
            const tableElement = headerCell.parentElement.parentElement.parentElement;
            const headerIndex = Array.prototype.indexOf.call(headerCell.parentElement.children, headerCell);
            const currentIsAscending = headerCell.classList.contains("th-sort-asc");
    
            sortTable(tableElement, headerIndex, !currentIsAscending);
        });
    });
    
  • URL: /components/raw/table/table.js
  • Filesystem Path: src/components/table/table.js
  • Size: 2.5 KB

No notes defined.