primer_view_components 0.0.60 → 0.0.64

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +155 -1
  3. data/app/components/primer/alpha/border_box/header.rb +1 -2
  4. data/app/components/primer/alpha/button_marketing.rb +4 -4
  5. data/app/components/primer/alpha/layout.html.erb +5 -0
  6. data/app/components/primer/alpha/layout.rb +276 -0
  7. data/app/components/primer/alpha/tab_nav.rb +1 -1
  8. data/app/components/primer/alpha/tab_panels.rb +2 -2
  9. data/app/components/primer/alpha/underline_nav.rb +2 -1
  10. data/app/components/primer/alpha/underline_panels.rb +2 -2
  11. data/app/components/primer/base_button.rb +1 -5
  12. data/app/components/primer/base_component.rb +14 -37
  13. data/app/components/primer/beta/auto_complete/item.rb +1 -1
  14. data/app/components/primer/beta/auto_complete.rb +4 -2
  15. data/app/components/primer/beta/avatar.rb +1 -1
  16. data/app/components/primer/beta/blankslate.html.erb +15 -0
  17. data/app/components/primer/beta/blankslate.rb +241 -0
  18. data/app/components/primer/beta/breadcrumbs.rb +2 -2
  19. data/app/components/primer/beta/text.rb +1 -1
  20. data/app/components/primer/blankslate_component.rb +1 -1
  21. data/app/components/primer/border_box_component.rb +1 -1
  22. data/app/components/primer/box_component.rb +3 -2
  23. data/app/components/primer/button_component.html.erb +3 -9
  24. data/app/components/primer/button_component.rb +50 -19
  25. data/app/components/primer/button_group.rb +1 -8
  26. data/app/components/primer/clipboard_copy.rb +1 -1
  27. data/app/components/primer/close_button.rb +1 -1
  28. data/app/components/primer/component.rb +79 -2
  29. data/app/components/primer/counter_component.rb +1 -1
  30. data/app/components/primer/details_component.rb +1 -1
  31. data/app/components/primer/dropdown/menu.rb +1 -1
  32. data/app/components/primer/dropdown.html.erb +0 -1
  33. data/app/components/primer/dropdown.rb +1 -0
  34. data/app/components/primer/dropdown_menu_component.rb +1 -1
  35. data/app/components/primer/flash_component.rb +2 -1
  36. data/app/components/primer/flex_component.rb +16 -16
  37. data/app/components/primer/flex_item_component.rb +1 -1
  38. data/app/components/primer/hellip_button.rb +39 -0
  39. data/app/components/primer/hidden_text_expander.rb +19 -7
  40. data/app/components/primer/image.rb +1 -1
  41. data/app/components/primer/image_crop.rb +2 -1
  42. data/app/components/primer/layout_component.rb +1 -0
  43. data/app/components/primer/local_time.rb +1 -1
  44. data/app/components/primer/markdown.rb +1 -1
  45. data/app/components/primer/menu_component.rb +2 -1
  46. data/app/components/primer/navigation/tab_component.rb +1 -0
  47. data/app/components/primer/octicon_component.rb +4 -2
  48. data/app/components/primer/octicon_symbols_component.rb +2 -2
  49. data/app/components/primer/popover_component.rb +3 -3
  50. data/app/components/primer/progress_bar_component.rb +7 -6
  51. data/app/components/primer/spinner_component.html.erb +11 -3
  52. data/app/components/primer/spinner_component.rb +6 -7
  53. data/app/components/primer/subhead_component.rb +4 -2
  54. data/app/components/primer/tab_container_component.rb +1 -1
  55. data/app/components/primer/time_ago_component.rb +1 -1
  56. data/app/components/primer/timeline_item_component.rb +4 -3
  57. data/app/components/primer/tooltip.rb +1 -0
  58. data/app/lib/primer/octicon/cache.rb +4 -10
  59. data/lib/primer/classify/utilities.rb +26 -23
  60. data/lib/primer/classify/utilities.yml +298 -68
  61. data/lib/primer/classify.rb +94 -180
  62. data/lib/primer/view_components/engine.rb +2 -1
  63. data/lib/primer/view_components/linters/base_linter.rb +3 -52
  64. data/lib/primer/view_components/linters/blankslate_api_migration.rb +152 -0
  65. data/lib/primer/view_components/linters/blankslate_component_migration_counter.rb +1 -1
  66. data/lib/primer/view_components/linters/close_button_component_migration_counter.rb +2 -4
  67. data/lib/primer/view_components/linters/helpers/rubocop_helpers.rb +14 -0
  68. data/lib/primer/view_components/linters/tag_tree_helpers.rb +61 -0
  69. data/lib/primer/view_components/linters/two_column_layout_migration_counter.rb +158 -0
  70. data/lib/primer/view_components/version.rb +1 -1
  71. data/lib/rubocop/cop/primer/deprecated_layout_component.rb +30 -0
  72. data/lib/rubocop/cop/primer/primer_octicon.rb +1 -3
  73. data/lib/tasks/custom_utilities.yml +298 -0
  74. data/lib/tasks/docs.rake +50 -1
  75. data/lib/tasks/utilities.rake +6 -2
  76. data/static/arguments.yml +56 -71
  77. data/static/audited_at.json +5 -0
  78. data/static/classes.yml +35 -17
  79. data/static/constants.json +108 -7
  80. data/static/statuses.json +6 -1
  81. metadata +18 -13
  82. data/app/components/primer/auto_complete/auto_complete.d.ts +0 -1
  83. data/app/components/primer/auto_complete/auto_complete.js +0 -1
  84. data/app/components/primer/auto_complete/auto_component.d.ts +0 -1
  85. data/app/components/primer/auto_complete/auto_component.js +0 -1
  86. data/lib/primer/classify/cache.rb +0 -109
  87. data/lib/primer/classify/flex.rb +0 -111
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb6606f92936041aed71037f2590bdd1ea29778b963a5396f19dcf8d57b70dc5
4
- data.tar.gz: 2f0525e24ddb1e5fa304220caaec413b52e4543c81196e2401a33ca4fb13fdbc
3
+ metadata.gz: 293526832927614dca06b1e03788d2db4f94fef8a5572a20304bd85e5498bd53
4
+ data.tar.gz: 419cd1ea3365120b4a3bb4429a1b9da105b2dc3c8474015a661b6e44d319f359
5
5
  SHA512:
6
- metadata.gz: 525f0e51074bc3490763836ce5060180d6222048333b53a768ae4cb287e6cff234ef69a5b570b760328fc4a26da165bf586694b3a0ecdf8287d750426c258541
7
- data.tar.gz: ba7fd3fbb1ab40e214fa6be6ceda52b84875d48c49f7aa75c790d3d594049b0a183e4a94959f36a82ccafa47acdc4ee9c1e0d065f33659ceb710adabbd50e933
6
+ metadata.gz: 2da4816e43ed7a7b7a13436d83d767bb5d6ee100748c7058f8a2f201e41132f34a17df862bf0f798b216f4b2b2cb6249b2bd61a3d620fbc401ce6fa06a16ce43
7
+ data.tar.gz: ca7bbc94ecdc2a39b57892f881b9be545b4af17456ac14094880a5154ebd6a2d6e69fe1e1b219f9ec1bbddac607a4c25b6f12c7117a32dd06366c3125f521f1b
data/CHANGELOG.md CHANGED
@@ -30,6 +30,160 @@ The category for changes related to documentation, testing and tooling. Also, fo
30
30
 
31
31
  ## main
32
32
 
33
+ ## 0.0.64
34
+
35
+ ### New
36
+
37
+ * Add `raise_on_invalid_aria` config option to silence `aria-label` errors.
38
+
39
+ *Manuel Puyol*
40
+
41
+ ### Bug Fixes
42
+
43
+ * Add missing `border: 0`, `font_size: 0` and responsive `flex` system arguments.
44
+
45
+ *Manuel Puyol*
46
+
47
+ ## 0.0.63
48
+
49
+ ### Breaking Changes
50
+
51
+ * Rename `caret` argument to `dropdown` in `ButtonComponent`.
52
+
53
+ *Manuel Puyol*
54
+
55
+ * Remove `:large` variant from `ButtonComponent`.
56
+
57
+ *Manuel Puyol*
58
+
59
+ * Update `Spinner` to add system arguments to outermost element
60
+
61
+ *Charlotte Dann*
62
+
63
+ ### Deprecations
64
+
65
+ * Deprecate `icon` and `counter` slots in `ButtonComponent` in favor of `leading_visual` and `trailing_visual`.
66
+
67
+ *Manuel Puyol*
68
+
69
+ ### Bug Fixes
70
+
71
+ * Fix `PopoverComponent`, allowing to reset `left` and `right` positioning.
72
+
73
+ *Manuel Puyol*
74
+
75
+ ## 0.0.62
76
+
77
+ ### New
78
+
79
+ * Add linter for tracking deprecated `LayoutComponent` callsites
80
+
81
+ *Josh Klina*
82
+
83
+ ### Updates
84
+
85
+ * Update `Button` to add `8px` spacing between icon, text and counter.
86
+
87
+ *Manuel Puyol*
88
+
89
+ * Update `BlankslateApiMigration` linter to support interpolations.
90
+
91
+ *Manuel Puyol*
92
+
93
+ * Change spacing in `Blankslate`:
94
+ * Between `description` and `primary_action` to `32px`.
95
+ * Between `primary_action` and `secondary_action` to `16px`.
96
+
97
+ *Manuel Puyol*
98
+
99
+ * Improve performance of `Classify#call`.
100
+
101
+ *Cameron Dutro*
102
+
103
+ ### Breaking Changes
104
+
105
+ * Add a warning to users if they try to use `tag:` parameters on a component where the tag is fixed.
106
+
107
+ *Owen Niblock*
108
+
109
+ * Updating to @primer/css@19.0.0 and @primer/primitives@7.1.0. Which removes support for deprecated system color arguments.
110
+
111
+ *Jon Rohan*
112
+
113
+ * Prevent `aria-label` to be used with `:div, :span, :p` tags without an explicit `role`.
114
+
115
+ *Manuel Puyol*
116
+
117
+ ## 0.0.61
118
+
119
+ ### New
120
+
121
+ * Adding new Alpha component: `Layout` with `main` and `sidebar` slots
122
+
123
+ *Cameron Dutro*
124
+
125
+ * Add a two-column layout linter.
126
+
127
+ *Cameron Dutro*
128
+
129
+ * Add the `HellipButton` component
130
+
131
+ *Amélia Chavot*, *Owen Niblock*
132
+
133
+ ### Updates
134
+
135
+ * Bump Storybook version to include Skip to Content links for keyboard auditors.
136
+
137
+ *Katie Foster @inkblotty*
138
+
139
+ * Update the `HiddenTextExpander` component to use the `HellipButton`.
140
+
141
+ *Amélia Chavot*, *Owen Niblock*
142
+
143
+ ### Misc
144
+
145
+ * Fix components not rendering in Storybook because of kebab case arguments.
146
+
147
+ *Amélia Chavot*, *Manuel Puyol*, *Owen Niblock*
148
+
149
+ * Fix a typo on a command on the contribution page.
150
+
151
+ *Amélia Chavot*, *Owen Niblock*
152
+
153
+ ### Bug Fixes
154
+
155
+ * Fix issue where tags were not self-closing when they are void elements.
156
+
157
+ *Owen Niblock*
158
+
159
+ ### Deprecations
160
+
161
+ * Deprecate `Primer::BlankslateComponent` in favor of `Primer::Beta::Blankslate`.
162
+
163
+ *Manuel Puyol*
164
+
165
+ ### Breaking Changes
166
+
167
+ * Require an `aria-label` to be provided for the `HiddenTextExpander` component.
168
+
169
+ *Amélia Chavot*, *Owen Niblock*
170
+
171
+ * Rename `force_system_arguments` to `raise_on_invalid_options` to better reflect its functionality
172
+
173
+ *Owen Niblock*
174
+
175
+ * Renamed `Blankslate` `title` slot to `heading`.
176
+
177
+ *Manuel Puyol*
178
+
179
+ * Removed `Blankslate` `large` variant.
180
+
181
+ *Manuel Puyol*
182
+
183
+ * Renamed `Blankslate` `graphic` slot to `visual`.
184
+
185
+ *Manuel Puyol*
186
+
33
187
  ## 0.0.60
34
188
 
35
189
  ### Updates
@@ -535,7 +689,7 @@ The category for changes related to documentation, testing and tooling. Also, fo
535
689
 
536
690
  *Manuel Puyol*
537
691
 
538
- * Added a changelog authoring guide to `CHANGELOG.md`.
692
+ * Add a changelog authoring guide to `CHANGELOG.md`.
539
693
 
540
694
  *Amélia Chavot*
541
695
 
@@ -3,8 +3,7 @@
3
3
  module Primer
4
4
  module Alpha
5
5
  module BorderBox
6
- # BorderBox::Header: used inside the BorderBoxComponent to render its header slot
7
- # Optional title slot
6
+ # `BorderBox::Header` is used inside `BorderBox` to render its header slot.
8
7
  #
9
8
  # @accessibility When using `header.title`, set `tag` to one of `h1`, `h2`, `h3`, etc. based on what is appropriate for the page context. <%= link_to_heading_practices %>
10
9
  class Header < Primer::Component
@@ -7,9 +7,9 @@ module Primer
7
7
  DEFAULT_SCHEME = :default
8
8
  SCHEME_MAPPINGS = {
9
9
  DEFAULT_SCHEME => "",
10
- :primary => "btn-primary-mktg",
11
- :outline => "btn-outline-mktg",
12
- :transparent => "btn-transparent"
10
+ :primary => "btn-signup-mktg",
11
+ :outline => "btn-muted-mktg",
12
+ :transparent => "btn-subtle-mktg"
13
13
  }.freeze
14
14
  SCHEME_OPTIONS = SCHEME_MAPPINGS.keys
15
15
 
@@ -30,7 +30,7 @@ module Primer
30
30
  # <%= render(Primer::Alpha::ButtonMarketing.new(mr: 2)) { "Default" } %>
31
31
  # <%= render(Primer::Alpha::ButtonMarketing.new(scheme: :primary, mr: 2)) { "Primary" } %>
32
32
  # <%= render(Primer::Alpha::ButtonMarketing.new(scheme: :outline)) { "Outline" } %>
33
- # <div class="color-bg-canvas-inverse">
33
+ # <div class="color-bg-emphasis">
34
34
  # <%= render(Primer::Alpha::ButtonMarketing.new(scheme: :transparent)) { "Transparent" } %>
35
35
  # </div>
36
36
  #
@@ -0,0 +1,5 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <% if @first_in_source == :main %><%= main %><% end %>
3
+ <%= sidebar %>
4
+ <% if @first_in_source == :sidebar %><%= main %><% end %>
5
+ <% end %>
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ # `Layout` provides foundational patterns for responsive pages.
6
+ # `Layout` can be used for simple two-column pages, or it can be nested to provide flexible 3-column experiences.
7
+ # On smaller screens, `Layout` uses vertically stacked rows to display content.
8
+ #
9
+ # `Layout` flows as both column, when there's enough horizontal space to render both `Main` and `Sidebar`side-by-side (on a desktop of tablet device, per instance);
10
+ # or it flows as a row, when `Main` and `Sidebar` are stacked vertically (e.g. on a mobile device).
11
+ # `Layout` should always work in any screen size.
12
+ #
13
+ # @accessibility
14
+ # Keyboard navigation follows the markup order. Decide carefully how the focus order should be be by deciding whether
15
+ # `main` or `sidebar` comes first in code. The code order won’t affect the visual position.
16
+ class Layout < Primer::Component
17
+ FIRST_IN_SOURCE_DEFAULT = :sidebar
18
+ FIRST_IN_SOURCE_OPTIONS = [FIRST_IN_SOURCE_DEFAULT, :main].freeze
19
+
20
+ SIDEBAR_COL_PLACEMENT_DEFAULT = :start
21
+ SIDEBAR_COL_PLACEMENT_OPTIONS = [SIDEBAR_COL_PLACEMENT_DEFAULT, :end].freeze
22
+
23
+ GUTTER_DEFAULT = :default
24
+ GUTTER_MAPPINGS = {
25
+ :none => "Layout--gutter-none",
26
+ :condensed => "Layout--gutter-condensed",
27
+ :spacious => "Layout--gutter-spacious",
28
+ GUTTER_DEFAULT => ""
29
+ }.freeze
30
+ GUTTER_OPTIONS = GUTTER_MAPPINGS.keys.freeze
31
+
32
+ STACKING_BREAKPOINT_DEFAULT = :md
33
+ STACKING_BREAKPOINT_MAPPINGS = {
34
+ :sm => "",
35
+ STACKING_BREAKPOINT_DEFAULT => "Layout--flowRow-until-md",
36
+ :lg => "Layout--flowRow-until-lg"
37
+ }.freeze
38
+ STACKING_BREAKPOINT_OPTIONS = STACKING_BREAKPOINT_MAPPINGS.keys.freeze
39
+
40
+ SIDEBAR_ROW_PLACEMENT_DEFAULT = :start
41
+ SIDEBAR_ROW_PLACEMENT_OPTIONS = [SIDEBAR_ROW_PLACEMENT_DEFAULT, :end, :none].freeze
42
+
43
+ SIDEBAR_WIDTH_DEFAULT = :default
44
+ SIDEBAR_WIDTH_MAPPINGS = {
45
+ SIDEBAR_WIDTH_DEFAULT => "",
46
+ :narrow => "Layout--sidebar-narrow",
47
+ :wide => "Layout--sidebar-wide"
48
+ }.freeze
49
+ SIDEBAR_WIDTH_OPTIONS = SIDEBAR_WIDTH_MAPPINGS.keys.freeze
50
+
51
+ # The layout's main content.
52
+ #
53
+ # @param width [Symbol] <%= one_of(Primer::Alpha::Layout::Main::WIDTH_OPTIONS) %>
54
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
55
+ renders_one :main, "Primer::Alpha::Layout::Main"
56
+
57
+ # The layout's sidebar.
58
+ #
59
+ # @param width [Symbol] <%= one_of(Primer::Alpha::Layout::SIDEBAR_WIDTH_OPTIONS) %>
60
+ # @param col_placement [Symbol] Sidebar placement when `Layout` is in column modes. <%= one_of(Primer::Alpha::Layout::SIDEBAR_COL_PLACEMENT_OPTIONS) %>
61
+ # @param row_placement [Symbol] Sidebar placement when `Layout` is in row mode. <%= one_of(Primer::Alpha::Layout::SIDEBAR_ROW_PLACEMENT_OPTIONS) %>
62
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
63
+ renders_one :sidebar, lambda { |
64
+ width: SIDEBAR_WIDTH_DEFAULT,
65
+ col_placement: SIDEBAR_COL_PLACEMENT_DEFAULT,
66
+ row_placement: SIDEBAR_ROW_PLACEMENT_DEFAULT,
67
+ **system_arguments
68
+ |
69
+ # These classes have to be set in the parent `Layout` element, so we modify its system arguments.
70
+ @system_arguments[:classes] = class_names(
71
+ @system_arguments[:classes],
72
+ "Layout--sidebarPosition-#{fetch_or_fallback(SIDEBAR_COL_PLACEMENT_OPTIONS, col_placement, SIDEBAR_COL_PLACEMENT_DEFAULT)}",
73
+ "Layout--sidebarPosition-flowRow-#{fetch_or_fallback(SIDEBAR_ROW_PLACEMENT_OPTIONS, row_placement, SIDEBAR_ROW_PLACEMENT_DEFAULT)}",
74
+ SIDEBAR_WIDTH_MAPPINGS[fetch_or_fallback(SIDEBAR_WIDTH_OPTIONS, width, SIDEBAR_WIDTH_DEFAULT)]
75
+ )
76
+
77
+ Primer::Alpha::Layout::Sidebar.new(**system_arguments)
78
+ }
79
+
80
+ # @example Default
81
+ #
82
+ # <%= render(Primer::Alpha::Layout.new) do |c| %>
83
+ # <% c.main(border: true) { "Main" } %>
84
+ # <% c.sidebar(border: true) { "Sidebar" } %>
85
+ # <% end %>
86
+ #
87
+ # @example Main widths
88
+ #
89
+ # @description
90
+ # When `full`, the main column will stretch to cover all the available width.
91
+ # Otherwise, the main column will try to be centered in the screen; it may appear aligned to the left when there isn't enough space.
92
+ #
93
+ # Use smaller maximum widths in the main column to facilitate interface scanning and reading.
94
+ #
95
+ # When flowing as a row, `Main` takes the full width.
96
+ #
97
+ # @code
98
+ # <%= render(Primer::Alpha::Layout.new) do |c| %>
99
+ # <% c.main(width: :full, border: true) { "Main" } %>
100
+ # <% c.sidebar(border: true) { "Sidebar" } %>
101
+ # <% end %>
102
+ # <%= render(Primer::Alpha::Layout.new(mt: 5)) do |c| %>
103
+ # <% c.main(width: :md, border: true) { "Main" } %>
104
+ # <% c.sidebar(border: true) { "Sidebar" } %>
105
+ # <% end %>
106
+ # <%= render(Primer::Alpha::Layout.new(mt: 5)) do |c| %>
107
+ # <% c.main(width: :lg, border: true) { "Main" } %>
108
+ # <% c.sidebar(border: true) { "Sidebar" } %>
109
+ # <% end %>
110
+ # <%= render(Primer::Alpha::Layout.new(mt: 5)) do |c| %>
111
+ # <% c.main(width: :xl, border: true) { "Main" } %>
112
+ # <% c.sidebar(border: true) { "Sidebar" } %>
113
+ # <% end %>
114
+ #
115
+ # @example Sidebar widths
116
+ #
117
+ # @description
118
+ # Sets the sidebar width. The width is predetermined according to the breakpoint instead of it being percentage-based.
119
+ #
120
+ # - `default`: [md: 256px, lg: 296px, xl: 320px]
121
+ # - `narrow`: [md: 240px, lg: 256px, xl: 296px]
122
+ # - `wide`: [md: 296px, lg: 320px, xl: 344px]
123
+ #
124
+ # When flowing as a row, `Sidebar` takes the full width.
125
+ #
126
+ # @code
127
+ # <%= render(Primer::Alpha::Layout.new) do |c| %>
128
+ # <% c.main(border: true) { "Main" } %>
129
+ # <% c.sidebar(width: :default, border: true) { "Sidebar" } %>
130
+ # <% end %>
131
+ # <%= render(Primer::Alpha::Layout.new(mt: 5)) do |c| %>
132
+ # <% c.main(border: true) { "Main" } %>
133
+ # <% c.sidebar(width: :narrow, border: true) { "Sidebar" } %>
134
+ # <% end %>
135
+ # <%= render(Primer::Alpha::Layout.new(mt: 5)) do |c| %>
136
+ # <% c.main(border: true) { "Main" } %>
137
+ # <% c.sidebar(width: :wide, border: true) { "Sidebar" } %>
138
+ # <% end %>
139
+ #
140
+ # @example Sidebar placement
141
+ #
142
+ # @description
143
+ # Use `start` for sidebars that manipulate local navigation, while right-aligned `end` is useful for metadata and other auxiliary information.
144
+ #
145
+ # @code
146
+ # <%= render(Primer::Alpha::Layout.new) do |c| %>
147
+ # <% c.main(border: true) { "Main" } %>
148
+ # <% c.sidebar(col_placement: :start, border: true) { "Sidebar" } %>
149
+ # <% end %>
150
+ # <%= render(Primer::Alpha::Layout.new( mt: 5)) do |c| %>
151
+ # <% c.main(border: true) { "Main" } %>
152
+ # <% c.sidebar(col_placement: :end, border: true) { "Sidebar" } %>
153
+ # <% end %>
154
+ #
155
+ # @example Sidebar placement as row
156
+ #
157
+ # @description
158
+ # When flowing as a row, whether the sidebar is rendered first or last in the layout, or, if it's entirely hidden from the user.
159
+ #
160
+ # When `hidden`, make sure the experience is not degraded on smaller screens, and the user can still access the sidebar content somehow.
161
+ # For instance, the user may not see a Settings navigation sidebar when drilled down on a page, but they can still navigate to the Settings
162
+ # landing page to interact with the local navigation.
163
+ #
164
+ # @code
165
+ # <%= render(Primer::Alpha::Layout.new) do |c| %>
166
+ # <% c.main(border: true) { "Main" } %>
167
+ # <% c.sidebar(row_placement: :start, border: true) { "Sidebar" } %>
168
+ # <% end %>
169
+ # <%= render(Primer::Alpha::Layout.new(mt: 5)) do |c| %>
170
+ # <% c.main(border: true) { "Main" } %>
171
+ # <% c.sidebar(row_placement: :end, border: true) { "Sidebar" } %>
172
+ # <% end %>
173
+ # <%= render(Primer::Alpha::Layout.new(mt: 5)) do |c| %>
174
+ # <% c.main(border: true) { "Main" } %>
175
+ # <% c.sidebar(row_placement: :none, border: true) { "Sidebar" } %>
176
+ # <% end %>
177
+ #
178
+ # @example Changing when to render `Layout` as columns
179
+ #
180
+ # @description
181
+ # You can specify when the `Layout` should change from rows into columns.
182
+ # Any screen size before this breakpoint will render the `Layout` in stacked rows.
183
+ #
184
+ # @code
185
+ # <%= render(Primer::Alpha::Layout.new(stacking_breakpoint: :sm)) do |c| %>
186
+ # <% c.main(border: true) { "Main" } %>
187
+ # <% c.sidebar(border: true) { "Sidebar" } %>
188
+ # <% end %>
189
+ # <%= render(Primer::Alpha::Layout.new(stacking_breakpoint: :md, mt: 5)) do |c| %>
190
+ # <% c.main(border: true) { "Main" } %>
191
+ # <% c.sidebar(border: true) { "Sidebar" } %>
192
+ # <% end %>
193
+ # <%= render(Primer::Alpha::Layout.new(stacking_breakpoint: :lg, mt: 5)) do |c| %>
194
+ # <% c.main(border: true) { "Main" } %>
195
+ # <% c.sidebar(border: true) { "Sidebar" } %>
196
+ # <% end %>
197
+ #
198
+ # @param stacking_breakpoint [Symbol] When the `Layout` should change from rows into columns. <%= one_of(Primer::Alpha::Layout::STACKING_BREAKPOINT_OPTIONS) %>
199
+ # @param first_in_source [Symbol] Which element to render first in the HTML. This will change the keyboard navigation order. <%= one_of(Primer::Alpha::Layout::FIRST_IN_SOURCE_OPTIONS) %>
200
+ # @param gutter [Symbol] The amount of space between the main section and the sidebar. <%= one_of(Primer::Alpha::Layout::GUTTER_OPTIONS) %>
201
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
202
+ def initialize(stacking_breakpoint: STACKING_BREAKPOINT_DEFAULT, first_in_source: FIRST_IN_SOURCE_DEFAULT, gutter: :default, **system_arguments)
203
+ @first_in_source = fetch_or_fallback(FIRST_IN_SOURCE_OPTIONS, first_in_source, FIRST_IN_SOURCE_OPTIONS)
204
+
205
+ @system_arguments = system_arguments
206
+ @system_arguments[:tag] = :div
207
+ @system_arguments[:classes] = class_names(
208
+ "Layout",
209
+ STACKING_BREAKPOINT_MAPPINGS[fetch_or_fallback(STACKING_BREAKPOINT_OPTIONS, stacking_breakpoint, STACKING_BREAKPOINT_DEFAULT)],
210
+ GUTTER_MAPPINGS[fetch_or_fallback(GUTTER_OPTIONS, gutter, GUTTER_DEFAULT)],
211
+ system_arguments[:classes]
212
+ )
213
+ end
214
+
215
+ def render?
216
+ main.present? && sidebar.present?
217
+ end
218
+
219
+ # The layout's main content.
220
+ class Main < Primer::Component
221
+ WIDTH_DEFAULT = :full
222
+ WIDTH_OPTIONS = [WIDTH_DEFAULT, :md, :lg, :xl].freeze
223
+
224
+ TAG_DEFAULT = :div
225
+ TAG_OPTIONS = [TAG_DEFAULT, :main].freeze
226
+
227
+ # @param width [Symbol] <%= one_of(Primer::Alpha::Layout::Main::WIDTH_OPTIONS) %>
228
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
229
+ def initialize(tag: TAG_DEFAULT, width: WIDTH_DEFAULT, **system_arguments)
230
+ @width = fetch_or_fallback(WIDTH_OPTIONS, width, WIDTH_DEFAULT)
231
+
232
+ @system_arguments = system_arguments
233
+ @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
234
+ @system_arguments[:classes] = class_names(
235
+ "Layout-main",
236
+ system_arguments[:classes]
237
+ )
238
+ end
239
+
240
+ def call
241
+ render(Primer::BaseComponent.new(**@system_arguments)) do
242
+ if @width == :full
243
+ content
244
+ else
245
+ render(Primer::BaseComponent.new(tag: :div, classes: "Layout-main-centered-#{@width}")) do
246
+ render(Primer::BaseComponent.new(tag: :div, container: @width)) do
247
+ content
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+
255
+ # The layout's sidebar content.
256
+ class Sidebar < Primer::Component
257
+ TAG_DEFAULT = :div
258
+ TAG_OPTIONS = [TAG_DEFAULT, :aside, :nav, :section].freeze
259
+
260
+ def initialize(tag: TAG_DEFAULT, **system_arguments)
261
+ @system_arguments = system_arguments
262
+
263
+ @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
264
+ @system_arguments[:classes] = class_names(
265
+ "Layout-sidebar",
266
+ @system_arguments[:classes]
267
+ )
268
+ end
269
+
270
+ def call
271
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
@@ -101,7 +101,7 @@ module Primer
101
101
  # <% end %>
102
102
  #
103
103
  # @example Customizing the body
104
- # <%= render(Primer::Alpha::TabNav.new(label: "Default", body_arguments: { classes: "custom-class", border: true, border_color: :info })) do |c| %>
104
+ # <%= render(Primer::Alpha::TabNav.new(label: "Default", body_arguments: { classes: "custom-class", border: true, border_color: :accent_emphasis })) do |c| %>
105
105
  # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
106
106
  # <% c.tab(href: "#") { "Tab 2" } %>
107
107
  # <% c.tab(href: "#") { "Tab 3" } %>
@@ -66,11 +66,11 @@ module Primer
66
66
  @align = EXTRA_ALIGN_DEFAULT
67
67
  @wrapper_arguments = wrapper_arguments
68
68
 
69
- @system_arguments = system_arguments
69
+ @system_arguments = deny_tag_argument(**system_arguments)
70
70
  @system_arguments[:tag] = :div
71
71
  @system_arguments[:classes] = tab_nav_classes(@system_arguments[:classes])
72
72
 
73
- @body_arguments = body_arguments
73
+ @body_arguments = deny_tag_argument(**body_arguments)
74
74
  @body_arguments[:tag] = :ul
75
75
  @body_arguments[:classes] = tab_nav_body_classes(@body_arguments[:classes])
76
76
 
@@ -5,6 +5,7 @@ module Primer
5
5
  # Use `UnderlineNav` to style navigation links with a minimal
6
6
  # underlined selected state, typically placed at the top
7
7
  # of the page.
8
+ #
8
9
  # For panel navigation, use <%= link_to_component(Primer::Alpha::UnderlinePanels) %> instead.
9
10
  #
10
11
  # @accessibility
@@ -102,7 +103,7 @@ module Primer
102
103
  # <% end %>
103
104
  #
104
105
  # @example Customizing the body
105
- # <%= render(Primer::Alpha::UnderlineNav.new(label: "Default", body_arguments: { classes: "custom-class", border: true, border_color: :info })) do |c| %>
106
+ # <%= render(Primer::Alpha::UnderlineNav.new(label: "Default", body_arguments: { classes: "custom-class", border: true, border_color: :accent_emphasis })) do |c| %>
106
107
  # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
107
108
  # <% c.tab(href: "#") { "Tab 2" } %>
108
109
  # <% c.tab(href: "#") { "Tab 3" } %>
@@ -64,11 +64,11 @@ module Primer
64
64
  @align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
65
65
  @wrapper_arguments = wrapper_arguments
66
66
 
67
- @system_arguments = system_arguments
67
+ @system_arguments = deny_tag_argument(**system_arguments)
68
68
  @system_arguments[:tag] = :div
69
69
  @system_arguments[:classes] = underline_nav_classes(@system_arguments[:classes], @align)
70
70
 
71
- @body_arguments = body_arguments
71
+ @body_arguments = deny_tag_argument(**body_arguments)
72
72
  @body_arguments[:tag] = :ul
73
73
  @body_arguments[:classes] = underline_nav_body_classes(@body_arguments[:classes])
74
74
 
@@ -28,11 +28,7 @@ module Primer
28
28
  @system_arguments = system_arguments
29
29
  @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, DEFAULT_TAG)
30
30
 
31
- if @system_arguments[:tag] == :button
32
- @system_arguments[:type] = fetch_or_fallback(TYPE_OPTIONS, type, DEFAULT_TYPE)
33
- else
34
- @system_arguments[:role] = :button
35
- end
31
+ @system_arguments[:type] = fetch_or_fallback(TYPE_OPTIONS, type, DEFAULT_TYPE) if @system_arguments[:tag] == :button
36
32
 
37
33
  @system_arguments[:classes] = class_names(
38
34
  system_arguments[:classes],
@@ -27,6 +27,7 @@ module Primer
27
27
  class BaseComponent < Primer::Component
28
28
  status :beta
29
29
 
30
+ SELF_CLOSING_TAGS = [:area, :base, :br, :col, :embed, :hr, :img, :input, :link, :meta, :param, :source, :track, :wbr].freeze
30
31
  # ## HTML attributes
31
32
  #
32
33
  # System arguments include most HTML attributes. For example:
@@ -71,14 +72,14 @@ module Primer
71
72
  #
72
73
  # | Name | Type | Description |
73
74
  # | :- | :- | :- |
74
- # | `align_items` | Symbol | <%= one_of(Primer::Classify::Flex::ALIGN_ITEMS_VALUES) %> |
75
- # | `align_self` | Symbol | <%= one_of(Primer::Classify::Flex::ALIGN_SELF_VALUES) %> |
76
- # | `direction` | Symbol | <%= one_of(Primer::Classify::Flex::DIRECTION_VALUES) %> |
77
- # | `flex` | Integer, Symbol | <%= one_of(Primer::Classify::Flex::FLEX_VALUES) %> |
75
+ # | `align_items` | Symbol | <%= one_of(Primer::Classify::FLEX_ALIGN_ITEMS_VALUES) %> |
76
+ # | `align_self` | Symbol | <%= one_of(Primer::Classify::FLEX_ALIGN_SELF_VALUES) %> |
77
+ # | `direction` | Symbol | <%= one_of(Primer::Classify::FLEX_DIRECTION_VALUES) %> |
78
+ # | `flex` | Integer, Symbol | <%= one_of(Primer::Classify::FLEX_VALUES) %> |
78
79
  # | `flex_grow` | Integer | To enable, set to `0`. |
79
80
  # | `flex_shrink` | Integer | To enable, set to `0`. |
80
- # | `flex_wrap` | Symbol | <%= one_of(Primer::Classify::Flex::WRAP_MAPPINGS.keys) %> |
81
- # | `justify_content` | Symbol | <%= one_of(Primer::Classify::Flex::JUSTIFY_CONTENT_VALUES) %> |
81
+ # | `flex_wrap` | Symbol | <%= one_of(Primer::Classify::FLEX_WRAP_MAPPINGS.keys) %> |
82
+ # | `justify_content` | Symbol | <%= one_of(Primer::Classify::FLEX_JUSTIFY_CONTENT_VALUES) %> |
82
83
  #
83
84
  # ## Grid
84
85
  #
@@ -150,46 +151,22 @@ module Primer
150
151
  # | test_selector | String | Adds `data-test-selector='given value'` in non-Production environments for testing purposes. |
151
152
  def initialize(tag:, classes: nil, **system_arguments)
152
153
  @tag = tag
153
- @system_arguments = system_arguments
154
154
 
155
- raise ArgumentError, "`class` is an invalid argument. Use `classes` instead." if system_arguments.key?(:class) && !Rails.env.production?
156
-
157
- if (denylist = system_arguments[:system_arguments_denylist])
158
- if force_system_arguments? && !ENV["PRIMER_WARNINGS_DISABLED"]
159
- # Convert denylist from:
160
- # { [:p, :pt] => "message" } to:
161
- # { p: "message", pt: "message" }
162
- unpacked_denylist =
163
- denylist.each_with_object({}) do |(keys, value), memo|
164
- keys.each { |key| memo[key] = value }
165
- end
166
-
167
- violations = unpacked_denylist.keys & @system_arguments.keys
168
-
169
- if violations.any?
170
- message = "Found #{violations.count} #{'violation'.pluralize(violations)}:"
171
- violations.each do |violation|
172
- message += "\n The #{violation} system argument is not allowed here. #{unpacked_denylist[violation]}"
173
- end
174
-
175
- raise(ArgumentError, message)
176
- end
177
- end
178
-
179
- # Remove :system_arguments_denylist key and any denied keys from system arguments
180
- @system_arguments.except!(:system_arguments_denylist)
181
- @system_arguments.except!(*denylist.keys.flatten)
182
- end
155
+ @system_arguments = validate_arguments(tag: tag, **system_arguments)
183
156
 
184
157
  @result = Primer::Classify.call(**@system_arguments.merge(classes: classes))
185
158
 
186
159
  @system_arguments[:"data-view-component"] = true
187
160
  # Filter out Primer keys so they don't get assigned as HTML attributes
188
- @content_tag_args = add_test_selector(@system_arguments).except(*Primer::Classify::VALID_KEYS)
161
+ @content_tag_args = add_test_selector(@system_arguments).except(*Primer::Classify::Utilities::UTILITIES.keys)
189
162
  end
190
163
 
191
164
  def call
192
- content_tag(@tag, content, @content_tag_args.merge(@result))
165
+ if SELF_CLOSING_TAGS.include?(@tag)
166
+ tag(@tag, @content_tag_args.merge(@result))
167
+ else
168
+ content_tag(@tag, content, @content_tag_args.merge(@result))
169
+ end
193
170
  end
194
171
  end
195
172
  end
@@ -20,7 +20,7 @@ module Primer
20
20
  # @param disabled [Boolean] Whether the item is disabled.
21
21
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
22
22
  def initialize(value:, selected: false, disabled: false, **system_arguments)
23
- @system_arguments = system_arguments
23
+ @system_arguments = deny_tag_argument(**system_arguments)
24
24
  @system_arguments[:tag] = :li
25
25
  @system_arguments[:role] = :option
26
26
  @system_arguments[:"data-autocomplete-value"] = value