Skip to content

Commit 35c30b2

Browse files
authored
Add tmp- prefix to margin and padding utility classes (#3997)
1 parent ea593aa commit 35c30b2

5 files changed

Lines changed: 57 additions & 30 deletions

File tree

.changeset/clever-spaces-dance.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/view-components": patch
3+
---
4+
5+
Add `tmp-` prefixed duplicate classes for margin and padding utilities. System arguments like `mb: 3` now output both `mb-3` and `tmp-mb-3` classes to support CSS namespace migration.

lib/primer/classify.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ class Classify
2424

2525
LOOKUP = Primer::Classify::Utilities::UTILITIES
2626

27+
# Keys that should have tmp- prefixed duplicates for CSS namespace migration
28+
SPACING_KEYS = Set.new(%i[m mt mb ml mr mx my p pt pb pl pr px py]).freeze
29+
30+
# Pre-computed tmp- prefixed strings to avoid runtime allocation
31+
TMP_PREFIX_CACHE = SPACING_KEYS.each_with_object({}) do |key, cache|
32+
next unless LOOKUP[key]
33+
34+
LOOKUP[key].each_value do |classnames|
35+
classnames.each do |cls|
36+
cache[cls] = -"tmp-#{cls}" if cls
37+
end
38+
end
39+
end.freeze
40+
2741
class << self
2842
# Utility for mapping component configuration into Primer CSS class names.
2943
#
@@ -75,7 +89,10 @@ def call(args = {})
7589
# in the lookup table.
7690
found = (LOOKUP[key][item][brk] rescue nil) || validate(key, item, brk)
7791
# rubocop:enable Style/RescueModifier
78-
result << found if found
92+
if found
93+
result << found
94+
result << TMP_PREFIX_CACHE[found] if TMP_PREFIX_CACHE.key?(found)
95+
end
7996
brk += 1
8097
end
8198
else
@@ -84,7 +101,10 @@ def call(args = {})
84101
# rubocop:disable Style/RescueModifier
85102
found = (LOOKUP[key][val][0] rescue nil) || validate(key, val, 0)
86103
# rubocop:enable Style/RescueModifier
87-
result << found if found
104+
if found
105+
result << found
106+
result << TMP_PREFIX_CACHE[found] if TMP_PREFIX_CACHE.key?(found)
107+
end
88108
end
89109
end
90110
end.join(" ")

test/components/base_component_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ def test_does_not_render_class_attribute_if_none_is_set
7676
def test_renders_system_argument_class_with_no_whitespace
7777
render_inline(Primer::BaseComponent.new(tag: :div, ml: 3))
7878

79-
assert_selector("div[class='ml-3']")
79+
# Asserts exact class attribute value with no leading/trailing/extra whitespace
80+
assert_selector("div[class='ml-3 tmp-ml-3']")
8081
end
8182

8283
def test_does_not_render_primer_layout_classes_as_attributes

test/lib/classify_test.rb

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class PrimerClassifyTest < Minitest::Test
66
include Primer::ComponentTestHelpers
77

88
def test_multiple_params
9-
assert_generated_class("m-4 py-2", { m: 4, py: 2 })
9+
assert_generated_class("m-4 tmp-m-4 py-2 tmp-py-2", { m: 4, py: 2 })
1010
end
1111

1212
def test_container
@@ -42,19 +42,19 @@ def test_font_size
4242
end
4343

4444
def test_m
45-
assert_generated_class("m-4", { m: 4 })
46-
assert_generated_class("mx-4", { mx: 4 })
47-
assert_generated_class("my-4", { my: 4 })
48-
assert_generated_class("mt-4", { mt: 4 })
49-
assert_generated_class("ml-4", { ml: 4 })
50-
assert_generated_class("mb-4", { mb: 4 })
51-
assert_generated_class("mr-4", { mr: 4 })
52-
assert_generated_class("mt-n4", { mt: -4 })
53-
assert_generated_class("ml-n4", { ml: -4 })
54-
assert_generated_class("mb-n4", { mb: -4 })
55-
assert_generated_class("mr-n4", { mr: -4 })
56-
assert_generated_class("mx-auto", { mx: :auto })
57-
assert_generated_class("mr-1 mr-sm-2 mr-md-3 mr-lg-4 mr-xl-5", { mr: [1, 2, 3, 4, 5] })
45+
assert_generated_class("m-4 tmp-m-4", { m: 4 })
46+
assert_generated_class("mx-4 tmp-mx-4", { mx: 4 })
47+
assert_generated_class("my-4 tmp-my-4", { my: 4 })
48+
assert_generated_class("mt-4 tmp-mt-4", { mt: 4 })
49+
assert_generated_class("ml-4 tmp-ml-4", { ml: 4 })
50+
assert_generated_class("mb-4 tmp-mb-4", { mb: 4 })
51+
assert_generated_class("mr-4 tmp-mr-4", { mr: 4 })
52+
assert_generated_class("mt-n4 tmp-mt-n4", { mt: -4 })
53+
assert_generated_class("ml-n4 tmp-ml-n4", { ml: -4 })
54+
assert_generated_class("mb-n4 tmp-mb-n4", { mb: -4 })
55+
assert_generated_class("mr-n4 tmp-mr-n4", { mr: -4 })
56+
assert_generated_class("mx-auto tmp-mx-auto", { mx: :auto })
57+
assert_generated_class("mr-1 tmp-mr-1 mr-sm-2 tmp-mr-sm-2 mr-md-3 tmp-mr-md-3 mr-lg-4 tmp-mr-lg-4 mr-xl-5 tmp-mr-xl-5", { mr: [1, 2, 3, 4, 5] })
5858

5959
assert_raises ArgumentError do
6060
Primer::Classify.call(m: -1)
@@ -78,15 +78,15 @@ def test_m
7878
end
7979

8080
def test_p
81-
assert_generated_class("p-4", { p: 4 })
82-
assert_generated_class("px-4", { px: 4 })
83-
assert_generated_class("py-4", { py: 4 })
84-
assert_generated_class("pt-4", { pt: 4 })
85-
assert_generated_class("pl-4", { pl: 4 })
86-
assert_generated_class("pb-4", { pb: 4 })
87-
assert_generated_class("pr-4", { pr: 4 })
88-
assert_generated_class("p-responsive", { p: :responsive })
89-
assert_generated_class("pr-1 pr-sm-2 pr-md-3 pr-lg-4 pr-xl-5", { pr: [1, 2, 3, 4, 5] })
81+
assert_generated_class("p-4 tmp-p-4", { p: 4 })
82+
assert_generated_class("px-4 tmp-px-4", { px: 4 })
83+
assert_generated_class("py-4 tmp-py-4", { py: 4 })
84+
assert_generated_class("pt-4 tmp-pt-4", { pt: 4 })
85+
assert_generated_class("pl-4 tmp-pl-4", { pl: 4 })
86+
assert_generated_class("pb-4 tmp-pb-4", { pb: 4 })
87+
assert_generated_class("pr-4 tmp-pr-4", { pr: 4 })
88+
assert_generated_class("p-responsive tmp-p-responsive", { p: :responsive })
89+
assert_generated_class("pr-1 tmp-pr-1 pr-sm-2 tmp-pr-sm-2 pr-md-3 tmp-pr-md-3 pr-lg-4 tmp-pr-lg-4 pr-xl-5 tmp-pr-xl-5", { pr: [1, 2, 3, 4, 5] })
9090

9191
assert_raises ArgumentError do
9292
Primer::Classify.call(p: -1)
@@ -337,16 +337,16 @@ def test_word_break
337337
end
338338

339339
def test_responsive
340-
assert_generated_class("p-4", { p: [4] })
341-
assert_generated_class("p-4 p-sm-3", { p: [4, 3] })
340+
assert_generated_class("p-4 tmp-p-4", { p: [4] })
341+
assert_generated_class("p-4 tmp-p-4 p-sm-3 tmp-p-sm-3", { p: [4, 3] })
342342
assert_generated_class("float-left float-md-right", { float: [:left, nil, :right] })
343343
assert_generated_class("d-flex d-sm-block", { display: %i[flex block] })
344344
assert_generated_class("d-flex d-md-block", { display: [:flex, nil, :block] })
345345
assert_generated_class("d-lg-block", { display: [nil, nil, nil, :block] })
346346
assert_generated_class("flex-row flex-sm-column", { direction: %i[row column] })
347347
assert_generated_class("col-1 col-sm-2", { col: [1, 2] })
348348
assert_generated_class("col-12 col-lg-9", { col: [12, nil, nil, 9] })
349-
assert_generated_class("p-4 p-sm-3 p-md-3 p-lg-3 p-xl-2", { p: [4, 3, 3, 3, 2] })
349+
assert_generated_class("p-4 tmp-p-4 p-sm-3 tmp-p-sm-3 p-md-3 tmp-p-md-3 p-lg-3 tmp-p-lg-3 p-xl-2 tmp-p-xl-2", { p: [4, 3, 3, 3, 2] })
350350
assert_generated_class("border-bottom border-sm-right border-lg-left", { border: [:bottom, :right, nil, :left, nil] })
351351
assert_generated_class("rounded-0 rounded-sm-1 rounded-md-2 rounded-lg-2 rounded-xl-3", { border_radius: [0, 1, 2, 2, 3] })
352352
end

test/performance/bench_classify.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ def setup
4040
end
4141

4242
def bench_allocations
43-
assert_allocations "4.0" => 7, "3.4" => 7, "3.3" => 7, "3.2" => 6, "3.1" => 6, "3.0" => 6, "2.7" => 4 do
43+
# +1 allocation from tmp- prefixed spacing utilities (pre-computed cache lookup)
44+
assert_allocations "4.0" => 8, "3.4" => 8, "3.3" => 8, "3.2" => 7, "3.1" => 7, "3.0" => 7, "2.7" => 5 do
4445
Primer::Classify.call(**@values)
4546
end
4647
end

0 commit comments

Comments
 (0)