Skip to content

Commit c6afc95

Browse files
committed
Fixes DataTable empty-state heading order
Axe flagged a heading-order violation on the empty_state preview: the table title renders as an h2 while the Blankslate heading was hard-coded to h4, skipping a level. Defaults the empty-state heading to h3 and exposes a heading_tag parameter on the slot so callers embedding the table under deeper heading structures can adjust the level.
1 parent 1545766 commit c6afc95

6 files changed

Lines changed: 37 additions & 5 deletions

File tree

app/components/primer/open_project/data_table.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ def sort_data
9090
# rows. Without this slot, an empty table renders a default
9191
# <%= link_to_component(Primer::OpenProject::DataTable::EmptyState) %>.
9292
# Ignored while rows are present.
93-
renders_one :empty_state, ->(title:, description: nil, icon: nil, interactive: false, **system_arguments) {
93+
renders_one :empty_state, ->(title:, heading_tag: EmptyState::HEADING_TAG_DEFAULT, description: nil, icon: nil, interactive: false, **system_arguments) {
9494
EmptyState.new(
9595
title: title,
96+
heading_tag: heading_tag,
9697
description: description,
9798
icon: icon,
9899
interactive: interactive,

app/components/primer/open_project/data_table/empty_state.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ class DataTable
1212
class EmptyState < Primer::Component
1313
status :open_project
1414

15+
HEADING_TAG_DEFAULT = :h3
16+
1517
# @param title [String] Empty-state heading
18+
# @param heading_tag [Symbol] Heading level of the empty-state title.
19+
# Defaults to `:h3` so it nests under the table's `:h2` title without
20+
# skipping a level.
1621
# @param description [String, nil] Optional supporting text
1722
# @param icon [Symbol, nil] Optional Primer icon
1823
# @param interactive [Boolean] Whether empty-state updates should be
@@ -21,12 +26,14 @@ class EmptyState < Primer::Component
2126
# System arguments passed to the underlying `Primer::Beta::Blankslate`
2227
def initialize(
2328
title:,
29+
heading_tag: HEADING_TAG_DEFAULT,
2430
description: nil,
2531
icon: nil,
2632
interactive: false,
2733
**system_arguments
2834
)
2935
@title = title
36+
@heading_tag = heading_tag
3037
@description = description
3138
@icon = icon
3239

@@ -50,7 +57,9 @@ def call
5057

5158
def blankslate
5259
blankslate = Primer::Beta::Blankslate.new(**@system_arguments)
53-
blankslate.with_heading(tag: :h4).with_content(@title)
60+
# `Primer::Beta::Blankslate` validates the tag against its own
61+
# heading options.
62+
blankslate.with_heading(tag: @heading_tag).with_content(@title)
5463
blankslate.with_description_content(@description) if @description
5564
blankslate.with_visual_icon(icon: @icon) if @icon
5665

static/arguments.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6238,6 +6238,12 @@
62386238
"default": "N/A",
62396239
"description": "Empty-state heading"
62406240
},
6241+
{
6242+
"name": "heading_tag",
6243+
"type": "Symbol",
6244+
"default": "`:h3`",
6245+
"description": "Heading level of the empty-state title. Defaults to `:h3` so it nests under the table's `:h2` title without skipping a level."
6246+
},
62416247
{
62426248
"name": "description",
62436249
"type": "String, nil",

static/constants.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1807,7 +1807,8 @@
18071807
"GeneratedSlotMethods": "Primer::OpenProject::DataTable::Column::GeneratedSlotMethods"
18081808
},
18091809
"Primer::OpenProject::DataTable::EmptyState": {
1810-
"GeneratedSlotMethods": "Primer::OpenProject::DataTable::EmptyState::GeneratedSlotMethods"
1810+
"GeneratedSlotMethods": "Primer::OpenProject::DataTable::EmptyState::GeneratedSlotMethods",
1811+
"HEADING_TAG_DEFAULT": "h3"
18111812
},
18121813
"Primer::OpenProject::DataTable::PaginationFooter": {
18131814
"GeneratedSlotMethods": "Primer::OpenProject::DataTable::PaginationFooter::GeneratedSlotMethods"

static/info_arch.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20420,6 +20420,12 @@
2042020420
"default": "N/A",
2042120421
"description": "Empty-state heading"
2042220422
},
20423+
{
20424+
"name": "heading_tag",
20425+
"type": "Symbol",
20426+
"default": "`:h3`",
20427+
"description": "Heading level of the empty-state title. Defaults to `:h3` so it nests under the table's `:h2` title without skipping a level."
20428+
},
2042320429
{
2042420430
"name": "description",
2042520431
"type": "String, nil",

test/components/primer/open_project/data_table/data_table_test.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ def test_renders_default_empty_state_without_rows
592592
data_table.with_title { "Projects" }
593593
end
594594

595-
assert_selector(".TableContainer .TableEmptyState .blankslate h4", text: "No data available")
595+
assert_selector(".TableContainer .TableEmptyState .blankslate h3", text: "No data available")
596596
assert_no_selector("table")
597597
assert_no_selector("[aria-labelledby]")
598598
end
@@ -607,11 +607,20 @@ def test_renders_custom_empty_state_without_rows
607607
)
608608
end
609609

610-
assert_selector(".TableEmptyState h4", text: "Nothing here")
610+
assert_selector(".TableEmptyState h3", text: "Nothing here")
611611
assert_selector(".TableEmptyState p", text: "Create a project to get started.")
612612
assert_selector(".TableEmptyState .octicon-book")
613613
end
614614

615+
def test_renders_empty_state_with_custom_heading_tag
616+
render_component([]) do |data_table|
617+
data_table.with_column(field: :subject, header: "Subject")
618+
data_table.with_empty_state(title: "Nothing here", heading_tag: :h4)
619+
end
620+
621+
assert_selector(".TableEmptyState h4", text: "Nothing here")
622+
end
623+
615624
def test_interactive_empty_state_announces_politely
616625
render_component([]) do |data_table|
617626
data_table.with_column(field: :subject, header: "Subject")

0 commit comments

Comments
 (0)