openproject-primer_view_components 0.30.0 → 0.30.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/banner.rb +13 -13
- data/app/components/primer/alpha/tab_nav.css +1 -1
- data/app/components/primer/alpha/tab_nav.css.json +0 -2
- data/app/components/primer/alpha/tab_nav.css.map +1 -1
- data/app/components/primer/alpha/tab_nav.pcss +0 -10
- data/app/components/primer/alpha/tab_panels.html.erb +9 -5
- data/app/components/primer/alpha/tab_panels.rb +13 -4
- data/app/components/primer/alpha/underline_nav.css +1 -1
- data/app/components/primer/alpha/underline_nav.css.json +0 -2
- data/app/components/primer/alpha/underline_nav.css.map +1 -1
- data/app/components/primer/alpha/underline_nav.pcss +1 -7
- data/app/components/primer/alpha/underline_panels.html.erb +8 -6
- data/app/components/primer/alpha/underline_panels.rb +14 -6
- data/app/components/primer/primer.pcss +0 -1
- data/lib/primer/view_components/version.rb +1 -1
- data/static/arguments.json +12 -0
- data/static/info_arch.json +13 -1
- metadata +4 -8
- data/app/components/primer/alpha/underline_panels.css +0 -1
- data/app/components/primer/alpha/underline_panels.css.json +0 -6
- data/app/components/primer/alpha/underline_panels.css.map +0 -1
- data/app/components/primer/alpha/underline_panels.pcss +0 -4
@@ -5,25 +5,25 @@ module Primer
|
|
5
5
|
# Use `Banner` to highlight important information.
|
6
6
|
#
|
7
7
|
# @accessibility
|
8
|
-
#
|
8
|
+
# ### Improve discoverability with a heading and landmark
|
9
|
+
# Banners are made visually prominent with icons and colors to immediately draw attention.
|
9
10
|
#
|
10
|
-
#
|
11
|
+
# To ensure the Banner is also easily discoverable for assistive technology users, consider:
|
12
|
+
# 1. Providing a heading inside of the Banner that describes the purpose of the Banner.
|
13
|
+
# 2. Designating the Banner as a `region` landmark. This can be achieved by rendering the Banner as a `section` with an `aria-labelledby` pointing to the heading.
|
11
14
|
#
|
12
|
-
#
|
13
|
-
#
|
15
|
+
# ### Communicating feedback
|
16
|
+
# When a Banner is used to communicate feedback, a live region or focus management technique should be in place to ensure that assistive technology users are aware of the feedback, especially when the Banner is shown client-side. Visit the [Banner's Accessibility section](https://primer.style/components/banner#accessibility), or defer to the accessibility team.
|
14
17
|
#
|
15
|
-
#
|
18
|
+
# #### Approach 1: Announcing a Banner
|
19
|
+
# A live region announcement can be used to communicate non-critical feedback, such as a success message.
|
16
20
|
#
|
17
|
-
#
|
21
|
+
# To successfully trigger a live region announcement for a Banner that is un-`hidden` or dynamically injected onto the page, **do not** set the live region attribute/role on the Banner itself. Instead, it's important to rely on a live region that is already guaranteed to be on the page. Learn more about specific techniques at: [Staff only: Challenges with live regions](https://github.com/github/accessibility/blob/main/docs/coaching-recommendations/toast-flash-banner/accessible-banner-prototype.md#challenges-with-dynamically-inserted-live-region).
|
18
22
|
#
|
19
|
-
#
|
23
|
+
# #### Approach 2: Focusing a Banner
|
24
|
+
# Focusing the Banner can be appropriate for critical feedback scenarios, such as a [form validation error summary](https://primer.style/ui-patterns/forms/overview#interactive-summary-of-errors) where the Banner contains actions to help unblock the user.
|
20
25
|
#
|
21
|
-
#
|
22
|
-
# Focusing a Banner when it appears helps to maximize discoverability of the message, especially in critical scenarios.
|
23
|
-
#
|
24
|
-
# To properly focus a banner, add a `tabindex="-1"` to the Banner container, and focus that container (one way is using the [`focus()` API](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)).
|
25
|
-
#
|
26
|
-
# For more information about the focus management technique, visit the [Staff only: Accessible Banner Prototype docs](https://github.com/github/accessibility/blob/main/docs/coaching-recommendations/toast-flash-banner/accessible-banner-prototype.md#consideration). This guidance is subject to change.
|
26
|
+
# To properly focus a Banner, add a `tabindex="-1"` place focus with JavaScript (using the [`focus()` API](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)).
|
27
27
|
class Banner < Primer::Component
|
28
28
|
status :alpha
|
29
29
|
|
@@ -1 +1 @@
|
|
1
|
-
.tabnav{border-bottom:var(--borderWidth-thin) solid var(--borderColor-default);margin-bottom:var(--stack-gap-normal);margin-top:0}.tabnav-tabs{display:flex;margin-bottom:calc(var(--borderWidth-thin)*-1);overflow:auto}.tabnav
|
1
|
+
.tabnav{border-bottom:var(--borderWidth-thin) solid var(--borderColor-default);margin-bottom:var(--stack-gap-normal);margin-top:0}.tabnav-tabs{display:flex;margin-bottom:calc(var(--borderWidth-thin)*-1);overflow:auto}.tabnav-tab{background-color:initial;border:var(--borderWidth-thin) solid #0000;border-bottom:0;color:var(--fgColor-muted);display:inline-block;flex-shrink:0;font-size:var(--text-body-size-medium);line-height:23px;padding:var(--base-size-8) var(--control-medium-paddingInline-spacious);-webkit-text-decoration:none;text-decoration:none;transition:color .2s cubic-bezier(.3,0,.5,1)}.tabnav-tab.selected,.tabnav-tab[aria-current]:not([aria-current=false]),.tabnav-tab[aria-selected=true]{background-color:var(--bgColor-default);border-color:var(--borderColor-default);border-radius:var(--borderRadius-medium) var(--borderRadius-medium) 0 0;color:var(--fgColor-default)}.tabnav-tab.selected .octicon,.tabnav-tab[aria-current]:not([aria-current=false]) .octicon,.tabnav-tab[aria-selected=true] .octicon{color:inherit}.tabnav-tab:hover{color:var(--fgColor-default);-webkit-text-decoration:none;text-decoration:none;transition-duration:.1s}.tabnav-tab:focus,.tabnav-tab:focus-visible{border-radius:var(--borderRadius-medium) var(--borderRadius-medium) 0 0!important;outline-offset:-6px}.tabnav-tab .octicon,.tabnav-tab:active{color:var(--fgColor-muted)}.tabnav-tab .octicon{margin-right:var(--control-small-gap)}.tabnav-tab .Counter{color:inherit;margin-left:var(--control-small-gap)}.tabnav-extra{color:var(--fgColor-muted);display:inline-block;font-size:var(--text-body-size-small);margin-left:10px;padding-top:10px}.tabnav-extra>.octicon{margin-right:2px}a.tabnav-extra:hover{color:var(--fgColor-accent);-webkit-text-decoration:none;text-decoration:none}.tabnav-btn{margin-left:var(--controlStack-medium-gap-condensed)}
|
@@ -3,7 +3,6 @@
|
|
3
3
|
"selectors": [
|
4
4
|
".tabnav",
|
5
5
|
".tabnav-tabs",
|
6
|
-
".tabnav::part(tablist-wrapper)",
|
7
6
|
".tabnav-tab",
|
8
7
|
".tabnav-tab.selected",
|
9
8
|
".tabnav-tab[aria-current]:not([aria-current=false])",
|
@@ -17,7 +16,6 @@
|
|
17
16
|
".tabnav-tab .octicon",
|
18
17
|
".tabnav-tab:active",
|
19
18
|
".tabnav-tab .Counter",
|
20
|
-
"tab-container .tabnav-tab",
|
21
19
|
".tabnav-extra",
|
22
20
|
".tabnav-extra>.octicon",
|
23
21
|
"a.tabnav-extra:hover",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["tab_nav.pcss"],"names":[],"mappings":"AAGA,QAGE,sEAAuE,CADvE,qCAAsC,CADtC,YAGF,CAEA,aACE,YAAa,CACb,8CAAiD,CACjD,aACF,CAEA
|
1
|
+
{"version":3,"sources":["tab_nav.pcss"],"names":[],"mappings":"AAGA,QAGE,sEAAuE,CADvE,qCAAsC,CADtC,YAGF,CAEA,aACE,YAAa,CACb,8CAAiD,CACjD,aACF,CAEA,YAQE,wBAA6B,CAE7B,0CAAgB,CAAhB,eAAgB,CAJhB,0BAA2B,CAL3B,oBAAqB,CACrB,aAAc,CAEd,sCAAuC,CACvC,gBAAiB,CAFjB,uEAAwE,CAIxE,4BAAqB,CAArB,oBAAqB,CAIrB,4CAwCF,CAtCE,yGAIE,uCAAwC,CACxC,uCAAwC,CACxC,uEAAwE,CAHxE,4BAQF,CAHE,oIACE,aACF,CAGF,kBACE,4BAA6B,CAC7B,4BAAqB,CAArB,oBAAqB,CACrB,uBACF,CAEA,4CAEE,iFAAmF,CACnF,mBACF,CAMA,wCAHE,0BAMF,CAHA,qBACE,qCAEF,CAEA,qBAEE,aAAc,CADd,oCAEF,CAQF,cAKE,0BAA2B,CAJ3B,oBAAqB,CAGrB,qCAAsC,CADtC,gBAAiB,CADjB,gBAQF,CAHE,uBACE,gBACF,CAKF,qBACE,2BAA4B,CAC5B,4BAAqB,CAArB,oBACF,CAOA,YACE,oDACF","file":"tab_nav.css","sourcesContent":["/* tabnav */\n\n/* Outer wrapper */\n.tabnav {\n margin-top: 0;\n margin-bottom: var(--stack-gap-normal);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-default);\n}\n\n.tabnav-tabs {\n display: flex;\n margin-bottom: calc(var(--borderWidth-thin) * -1);\n overflow: auto;\n}\n\n.tabnav-tab {\n display: inline-block;\n flex-shrink: 0;\n padding: var(--base-size-8) var(--control-medium-paddingInline-spacious);\n font-size: var(--text-body-size-medium);\n line-height: 23px;\n color: var(--fgColor-muted);\n text-decoration: none;\n background-color: transparent;\n border: var(--borderWidth-thin) solid transparent;\n border-bottom: 0;\n transition: color 0.2s cubic-bezier(0.3, 0, 0.5, 1);\n\n &.selected,\n &[aria-selected='true'],\n &[aria-current]:not([aria-current='false']) {\n color: var(--fgColor-default);\n background-color: var(--bgColor-default); /* cover bottom border */\n border-color: var(--borderColor-default);\n border-radius: var(--borderRadius-medium) var(--borderRadius-medium) 0 0;\n\n & .octicon {\n color: inherit;\n }\n }\n\n &:hover {\n color: var(--fgColor-default);\n text-decoration: none;\n transition-duration: 0.1s;\n }\n\n &:focus,\n &:focus-visible {\n border-radius: var(--borderRadius-medium) var(--borderRadius-medium) 0 0 !important;\n outline-offset: -6px;\n }\n\n &:active {\n color: var(--fgColor-muted);\n }\n\n & .octicon {\n margin-right: var(--control-small-gap);\n color: var(--fgColor-muted);\n }\n\n & .Counter {\n margin-left: var(--control-small-gap);\n color: inherit;\n }\n}\n\n/* Tabnav extras\n**\n** Tabnav extras are non-tab elements that sit in the tabnav. Usually they're\n** inline text or links. */\n\n.tabnav-extra {\n display: inline-block;\n padding-top: 10px;\n margin-left: 10px;\n font-size: var(--text-body-size-small);\n color: var(--fgColor-muted);\n\n & > .octicon {\n margin-right: 2px;\n }\n}\n\n/* When tabnav-extra are anchors\n** stylelint-disable-next-line selector-no-qualifying-type */\na.tabnav-extra:hover {\n color: var(--fgColor-accent);\n text-decoration: none;\n}\n\n/* Tabnav buttons\n**\n** For when there are multiple buttons, space them out appropriately. Requires\n** the buttons to be floated or inline-block. */\n\n.tabnav-btn {\n margin-left: var(--controlStack-medium-gap-condensed);\n}\n"]}
|
@@ -13,11 +13,6 @@
|
|
13
13
|
overflow: auto;
|
14
14
|
}
|
15
15
|
|
16
|
-
.tabnav::part(tablist-wrapper) {
|
17
|
-
margin-bottom: var(--stack-gap-normal);
|
18
|
-
border-bottom: var(--borderWidth-thin) solid var(--borderColor-default);
|
19
|
-
}
|
20
|
-
|
21
16
|
.tabnav-tab {
|
22
17
|
display: inline-block;
|
23
18
|
flex-shrink: 0;
|
@@ -71,11 +66,6 @@
|
|
71
66
|
}
|
72
67
|
}
|
73
68
|
|
74
|
-
tab-container .tabnav-tab {
|
75
|
-
margin-bottom: -1px;
|
76
|
-
}
|
77
|
-
|
78
|
-
|
79
69
|
/* Tabnav extras
|
80
70
|
**
|
81
71
|
** Tabnav extras are non-tab elements that sit in the tabnav. Usually they're
|
@@ -1,9 +1,13 @@
|
|
1
|
-
<%=
|
2
|
-
<%=
|
3
|
-
|
4
|
-
<%=
|
1
|
+
<%= tab_container_wrapper(with_panel: true, **@wrapper_arguments) do %>
|
2
|
+
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
|
3
|
+
<%= extra if @align == :left %>
|
4
|
+
<%= render Primer::BaseComponent.new(**@body_arguments) do %>
|
5
|
+
<% tabs.each do |tab| %>
|
6
|
+
<%= tab %>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
9
|
+
<%= extra if @align == :right %>
|
5
10
|
<% end %>
|
6
|
-
<%= extra if @align == :right %>
|
7
11
|
<% tabs.each do |tab| %>
|
8
12
|
<%= tab.panel %>
|
9
13
|
<% end %>
|
@@ -26,7 +26,7 @@ module Primer
|
|
26
26
|
Primer::Alpha::Navigation::Tab.new(
|
27
27
|
selected: selected,
|
28
28
|
with_panel: true,
|
29
|
-
list:
|
29
|
+
list: true,
|
30
30
|
panel_id: "panel-#{id}",
|
31
31
|
**system_arguments
|
32
32
|
)
|
@@ -43,14 +43,23 @@ module Primer
|
|
43
43
|
|
44
44
|
# @param label [String] Sets an `aria-label` that helps assistive technology users understand the purpose of the tabs.
|
45
45
|
# @param align [Symbol] <%= one_of(Primer::TabNavHelper::EXTRA_ALIGN_OPTIONS) %> - Defaults to <%= Primer::TabNavHelper::EXTRA_ALIGN_DEFAULT %>
|
46
|
+
# @param body_arguments [Hash] <%= link_to_system_arguments_docs %> for the body wrapper.
|
47
|
+
# @param wrapper_arguments [Hash] <%= link_to_system_arguments_docs %> for the `TabContainer` wrapper.
|
46
48
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
47
49
|
def initialize(label:, body_arguments: {}, wrapper_arguments: {}, **system_arguments)
|
48
50
|
@align = EXTRA_ALIGN_DEFAULT
|
51
|
+
@wrapper_arguments = wrapper_arguments
|
49
52
|
|
50
|
-
@system_arguments =
|
51
|
-
@system_arguments[:tag] = :
|
53
|
+
@system_arguments = deny_tag_argument(**system_arguments)
|
54
|
+
@system_arguments[:tag] = :div
|
52
55
|
@system_arguments[:classes] = tab_nav_classes(@system_arguments[:classes])
|
53
|
-
|
56
|
+
|
57
|
+
@body_arguments = deny_tag_argument(**body_arguments)
|
58
|
+
@body_arguments[:tag] = :ul
|
59
|
+
@body_arguments[:classes] = tab_nav_body_classes(@body_arguments[:classes])
|
60
|
+
|
61
|
+
@body_arguments[:role] = :tablist
|
62
|
+
@body_arguments[:"aria-label"] = label
|
54
63
|
end
|
55
64
|
|
56
65
|
def before_render
|
@@ -1 +1 @@
|
|
1
|
-
.UnderlineNav{box-shadow:inset 0 -1px 0 var(--borderColor-muted);display:flex;min-height:var(--base-size-48);overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:auto;justify-content:space-between}.UnderlineNav .Counter{background-color:var(--bgColor-neutral-muted,var(--color-neutral-muted));color:var(--fgColor-default);margin-left:var(--control-medium-gap)}.UnderlineNav .Counter--primary{background-color:var(--bgColor-neutral-emphasis);color:var(--fgColor-onEmphasis)}.UnderlineNav
|
1
|
+
.UnderlineNav{box-shadow:inset 0 -1px 0 var(--borderColor-muted);display:flex;min-height:var(--base-size-48);overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:auto;justify-content:space-between}.UnderlineNav .Counter{background-color:var(--bgColor-neutral-muted,var(--color-neutral-muted));color:var(--fgColor-default);margin-left:var(--control-medium-gap)}.UnderlineNav .Counter--primary{background-color:var(--bgColor-neutral-emphasis);color:var(--fgColor-onEmphasis)}.UnderlineNav-body{align-items:center;display:flex;gap:var(--control-medium-gap);list-style:none}.UnderlineNav-item{align-items:center;background-color:initial;border:0;border-radius:var(--borderRadius-medium);color:var(--fgColor-default);cursor:pointer;display:flex;font-size:var(--text-body-size-medium);line-height:30px;padding:0 var(--control-medium-paddingInline-condensed);position:relative;text-align:center;white-space:nowrap}.UnderlineNav-item:focus,.UnderlineNav-item:focus-visible,.UnderlineNav-item:hover{border-bottom-color:var(--borderColor-neutral-muted);color:var(--fgColor-default);outline-offset:-2px;-webkit-text-decoration:none;text-decoration:none;transition:border-bottom-color .12s ease-out}.UnderlineNav-item [data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold);height:0;visibility:hidden}.UnderlineNav-item:before{content:"";height:100%;left:50%;min-height:48px;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}@media (pointer:fine){.UnderlineNav-item:hover{background:var(--control-transparent-bgColor-hover);color:var(--fgColor-default);-webkit-text-decoration:none;text-decoration:none;transition:background .12s ease-out}}.UnderlineNav-item.selected,.UnderlineNav-item[aria-current]:not([aria-current=false]),.UnderlineNav-item[role=tab][aria-selected=true]{border-bottom-color:var(--underlineNav-borderColor-active);color:var(--fgColor-default);font-weight:var(--base-text-weight-semibold)}.UnderlineNav-item.selected:after,.UnderlineNav-item[aria-current]:not([aria-current=false]):after,.UnderlineNav-item[role=tab][aria-selected=true]:after{background:var(--underlineNav-borderColor-active);border-radius:var(--borderRadius-medium);bottom:calc(50% - 25px);content:"";height:2px;position:absolute;right:50%;transform:translate(50%,-50%);width:100%;z-index:1}.UnderlineNav--right{justify-content:flex-end}.UnderlineNav--right .UnderlineNav-actions{flex:1 1 auto}.UnderlineNav-actions{align-self:center}.UnderlineNav--full{display:block}.UnderlineNav--full .UnderlineNav-body{min-height:var(--base-size-48)}.UnderlineNav-octicon{color:var(--fgColor-muted);display:inline!important;margin-right:var(--control-medium-gap);fill:var(--fgColor-muted)}.UnderlineNav-container{display:flex;justify-content:space-between}
|
@@ -4,9 +4,7 @@
|
|
4
4
|
".UnderlineNav",
|
5
5
|
".UnderlineNav .Counter",
|
6
6
|
".UnderlineNav .Counter--primary",
|
7
|
-
".UnderlineNav::part(tablist-wrapper)",
|
8
7
|
".UnderlineNav-body",
|
9
|
-
".UnderlineNav::part(tablist)",
|
10
8
|
".UnderlineNav-item",
|
11
9
|
".UnderlineNav-item:focus",
|
12
10
|
".UnderlineNav-item:focus-visible",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["underline_nav.pcss","<no source>"],"names":[],"mappings":"AAEA,cAKE,kDAAmD,CAJnD,YAAa,CACb,8BAA+B,CAC/B,eAAgB,CAChB,iBAAkB,CAElB,+BAAgC,CAChC,6BAYF,CAVE,uBAGE,wEAA0E,CAD1E,4BAA6B,CAD7B,qCAGF,CAEA,gCAEE,gDAAiD,CADjD,+BAEF,CAGF,
|
1
|
+
{"version":3,"sources":["underline_nav.pcss","<no source>"],"names":[],"mappings":"AAEA,cAKE,kDAAmD,CAJnD,YAAa,CACb,8BAA+B,CAC/B,eAAgB,CAChB,iBAAkB,CAElB,+BAAgC,CAChC,6BAYF,CAVE,uBAGE,wEAA0E,CAD1E,4BAA6B,CAD7B,qCAGF,CAEA,gCAEE,gDAAiD,CADjD,+BAEF,CAGF,mBAEE,kBAAmB,CADnB,YAAa,CAEb,6BAA8B,CAC9B,eACF,CAEA,mBAaE,kBAAmB,CAHnB,wBAA6B,CAC7B,QAAS,CACT,wCAAyC,CANzC,4BAA6B,CAG7B,cAAe,CAPf,YAAa,CAEb,sCAAuC,CACvC,gBAAiB,CAFjB,uDAAwD,CAFxD,iBAAkB,CAMlB,iBAAkB,CAClB,kBA8DF,CAvDE,mFAKE,oDAAqD,CAFrD,4BAA6B,CAG7B,mBAAoB,CAFpB,4BAAqB,CAArB,oBAAqB,CAGrB,4CACF,CAGA,yCAKE,0BAA2B,CAJ3B,aAAc,CAEd,4CAA6C,CAD7C,QAAS,CAET,iBAEF,CAIE,0BClEJ,WAAA,YAAA,SAAA,gBAAA,kBAAA,QAAA,4CAAA,UDkE8B,CAI5B,sBACE,yBAGE,mDAAoD,CAFpD,4BAA6B,CAC7B,4BAAqB,CAArB,oBAAqB,CAErB,mCACF,CACF,CAEA,wIAKE,0DAA2D,CAD3D,4BAA6B,CAD7B,4CAiBF,CAZE,0JAQE,iDAAkD,CAClD,wCAAyC,CALzC,uBAAwB,CAGxB,UAAW,CADX,UAAW,CALX,iBAAkB,CAElB,SAAU,CAOV,6BAA+B,CAL/B,UAAW,CAHX,SASF,CAIJ,qBACE,wBAKF,CAHE,2CACE,aACF,CAGF,sBACE,iBACF,CAEA,oBACE,aAMF,CAHE,uCACE,8BACF,CAGF,sBAGE,0BAA2B,CAF3B,wBAA0B,CAC1B,sCAAuC,CAEvC,yBACF,CAEA,wBACE,YAAa,CACb,6BACF","file":"underline_nav.css","sourcesContent":["/* UnderlineNav */\n\n.UnderlineNav {\n display: flex;\n min-height: var(--base-size-48);\n overflow-x: auto;\n overflow-y: hidden;\n box-shadow: inset 0 -1px 0 var(--borderColor-muted);\n -webkit-overflow-scrolling: auto;\n justify-content: space-between;\n\n & .Counter {\n margin-left: var(--control-medium-gap);\n color: var(--fgColor-default);\n background-color: var(--bgColor-neutral-muted, var(--color-neutral-muted));\n }\n\n & .Counter--primary {\n color: var(--fgColor-onEmphasis);\n background-color: var(--bgColor-neutral-emphasis);\n }\n}\n\n.UnderlineNav-body {\n display: flex;\n align-items: center;\n gap: var(--control-medium-gap);\n list-style: none;\n}\n\n.UnderlineNav-item {\n position: relative;\n display: flex;\n padding: 0 var(--control-medium-paddingInline-condensed);\n font-size: var(--text-body-size-medium);\n line-height: 30px;\n color: var(--fgColor-default);\n text-align: center;\n white-space: nowrap;\n cursor: pointer;\n background-color: transparent;\n border: 0;\n border-radius: var(--borderRadius-medium);\n align-items: center;\n\n &:hover,\n &:focus,\n &:focus-visible {\n color: var(--fgColor-default);\n text-decoration: none;\n border-bottom-color: var(--borderColor-neutral-muted);\n outline-offset: -2px;\n transition: border-bottom-color 0.12s ease-out;\n }\n\n /* renders a visibly hidden \"copy\" of the label in bold, reserving box space for when label becomes bold on selected */\n & [data-content]::before {\n display: block;\n height: 0;\n font-weight: var(--base-text-weight-semibold);\n visibility: hidden;\n content: attr(data-content);\n }\n\n /* increase touch target area */\n &::before {\n @mixin minTouchTarget 48px;\n }\n\n /* hover state was \"sticking\" on mobile after click */\n @media (pointer: fine) {\n &:hover {\n color: var(--fgColor-default);\n text-decoration: none;\n background: var(--control-transparent-bgColor-hover);\n transition: background 0.12s ease-out;\n }\n }\n\n &.selected,\n &[role='tab'][aria-selected='true'],\n &[aria-current]:not([aria-current='false']) {\n font-weight: var(--base-text-weight-semibold);\n color: var(--fgColor-default);\n border-bottom-color: var(--underlineNav-borderColor-active);\n\n /* current/selected underline */\n &::after {\n position: absolute;\n z-index: 1; /* raise above full-width flash banner */\n right: 50%;\n bottom: calc(50% - 25px); /* 48px total height / 2 (24px) + 1px */\n width: 100%;\n height: 2px;\n content: '';\n background: var(--underlineNav-borderColor-active);\n border-radius: var(--borderRadius-medium);\n transform: translate(50%, -50%);\n }\n }\n}\n\n.UnderlineNav--right {\n justify-content: flex-end;\n\n & .UnderlineNav-actions {\n flex: 1 1 auto;\n }\n}\n\n.UnderlineNav-actions {\n align-self: center;\n}\n\n.UnderlineNav--full {\n display: block;\n\n /* required for underline to align with additional wrapper element */\n & .UnderlineNav-body {\n min-height: var(--base-size-48);\n }\n}\n\n.UnderlineNav-octicon {\n display: inline !important;\n margin-right: var(--control-medium-gap);\n color: var(--fgColor-muted);\n fill: var(--fgColor-muted);\n}\n\n.UnderlineNav-container {\n display: flex;\n justify-content: space-between;\n}\n",null]}
|
@@ -21,13 +21,7 @@
|
|
21
21
|
}
|
22
22
|
}
|
23
23
|
|
24
|
-
.UnderlineNav
|
25
|
-
width: 100%;
|
26
|
-
box-shadow: inset 0 -1px 0 var(--borderColor-muted);
|
27
|
-
padding: var(--control-medium-gap) 0;
|
28
|
-
}
|
29
|
-
|
30
|
-
.UnderlineNav-body,.UnderlineNav::part(tablist) {
|
24
|
+
.UnderlineNav-body {
|
31
25
|
display: flex;
|
32
26
|
align-items: center;
|
33
27
|
gap: var(--control-medium-gap);
|
@@ -1,16 +1,18 @@
|
|
1
|
-
<%=
|
1
|
+
<%= tab_container_wrapper(with_panel: true, **@wrapper_arguments) do %>
|
2
2
|
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
|
3
3
|
<% if @align == :right %>
|
4
4
|
<%= actions %>
|
5
5
|
<% end %>
|
6
|
-
|
7
|
-
|
6
|
+
<%= render body do %>
|
7
|
+
<% tabs.each do |tab| %>
|
8
|
+
<%= tab %>
|
9
|
+
<% end %>
|
8
10
|
<% end %>
|
9
11
|
<% if @align == :left %>
|
10
12
|
<%= actions %>
|
11
13
|
<% end %>
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
<% end %>
|
15
|
+
<% tabs.each do |tab| %>
|
16
|
+
<%= tab.panel %>
|
15
17
|
<% end %>
|
16
18
|
<% end %>
|
@@ -18,7 +18,7 @@ module Primer
|
|
18
18
|
Primer::Alpha::Navigation::Tab.new(
|
19
19
|
selected: selected,
|
20
20
|
with_panel: true,
|
21
|
-
list:
|
21
|
+
list: true,
|
22
22
|
icon_classes: "UnderlineNav-octicon",
|
23
23
|
panel_id: "panel-#{id}",
|
24
24
|
**system_arguments
|
@@ -43,16 +43,24 @@ module Primer
|
|
43
43
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
44
44
|
def initialize(label:, align: ALIGN_DEFAULT, body_arguments: {}, wrapper_arguments: {}, **system_arguments)
|
45
45
|
@align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
|
46
|
-
@wrapper_arguments =
|
47
|
-
@wrapper_arguments[:tag] = :div
|
46
|
+
@wrapper_arguments = wrapper_arguments
|
48
47
|
|
49
48
|
@system_arguments = deny_tag_argument(**system_arguments)
|
50
|
-
@system_arguments[:tag] = :
|
49
|
+
@system_arguments[:tag] = :div
|
51
50
|
@system_arguments[:classes] = underline_nav_classes(@system_arguments[:classes], @align)
|
52
|
-
@system_arguments[:"aria-label"] = label
|
53
51
|
|
54
52
|
@body_arguments = deny_tag_argument(**body_arguments)
|
55
|
-
@body_arguments[:tag] = :
|
53
|
+
@body_arguments[:tag] = :ul
|
54
|
+
@body_arguments[:classes] = underline_nav_body_classes(@body_arguments[:classes])
|
55
|
+
|
56
|
+
@body_arguments[:role] = :tablist
|
57
|
+
@body_arguments[:"aria-label"] = label
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def body
|
63
|
+
Primer::BaseComponent.new(**@body_arguments)
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
data/static/arguments.json
CHANGED
@@ -2462,6 +2462,18 @@
|
|
2462
2462
|
"default": "N/A",
|
2463
2463
|
"description": "One of `:left` or `:right`. - Defaults to left"
|
2464
2464
|
},
|
2465
|
+
{
|
2466
|
+
"name": "body_arguments",
|
2467
|
+
"type": "Hash",
|
2468
|
+
"default": "`{}`",
|
2469
|
+
"description": "[System arguments](/system-arguments) for the body wrapper."
|
2470
|
+
},
|
2471
|
+
{
|
2472
|
+
"name": "wrapper_arguments",
|
2473
|
+
"type": "Hash",
|
2474
|
+
"default": "`{}`",
|
2475
|
+
"description": "[System arguments](/system-arguments) for the `TabContainer` wrapper."
|
2476
|
+
},
|
2465
2477
|
{
|
2466
2478
|
"name": "system_arguments",
|
2467
2479
|
"type": "Hash",
|
data/static/info_arch.json
CHANGED
@@ -2284,7 +2284,7 @@
|
|
2284
2284
|
{
|
2285
2285
|
"fully_qualified_name": "Primer::Alpha::Banner",
|
2286
2286
|
"description": "Use `Banner` to highlight important information.",
|
2287
|
-
"accessibility_docs": "
|
2287
|
+
"accessibility_docs": "### Improve discoverability with a heading and landmark\nBanners are made visually prominent with icons and colors to immediately draw attention.\n\nTo ensure the Banner is also easily discoverable for assistive technology users, consider:\n1. Providing a heading inside of the Banner that describes the purpose of the Banner.\n2. Designating the Banner as a `region` landmark. This can be achieved by rendering the Banner as a `section` with an `aria-labelledby` pointing to the heading.\n\n### Communicating feedback\nWhen a Banner is used to communicate feedback, a live region or focus management technique should be in place to ensure that assistive technology users are aware of the feedback, especially when the Banner is shown client-side. Visit the [Banner's Accessibility section](https://primer.style/components/banner#accessibility), or defer to the accessibility team.\n\n#### Approach 1: Announcing a Banner\nA live region announcement can be used to communicate non-critical feedback, such as a success message.\n\nTo successfully trigger a live region announcement for a Banner that is un-`hidden` or dynamically injected onto the page, **do not** set the live region attribute/role on the Banner itself. Instead, it's important to rely on a live region that is already guaranteed to be on the page. Learn more about specific techniques at: [Staff only: Challenges with live regions](https://github.com/github/accessibility/blob/main/docs/coaching-recommendations/toast-flash-banner/accessible-banner-prototype.md#challenges-with-dynamically-inserted-live-region).\n\n#### Approach 2: Focusing a Banner\nFocusing the Banner can be appropriate for critical feedback scenarios, such as a [form validation error summary](https://primer.style/ui-patterns/forms/overview#interactive-summary-of-errors) where the Banner contains actions to help unblock the user.\n\nTo properly focus a Banner, add a `tabindex=\"-1\"` place focus with JavaScript (using the [`focus()` API](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)).",
|
2288
2288
|
"is_form_component": false,
|
2289
2289
|
"is_published": true,
|
2290
2290
|
"requires_js": true,
|
@@ -7628,6 +7628,18 @@
|
|
7628
7628
|
"default": "N/A",
|
7629
7629
|
"description": "One of `:left` or `:right`. - Defaults to left"
|
7630
7630
|
},
|
7631
|
+
{
|
7632
|
+
"name": "body_arguments",
|
7633
|
+
"type": "Hash",
|
7634
|
+
"default": "`{}`",
|
7635
|
+
"description": "{{link_to_system_arguments_docs}} for the body wrapper."
|
7636
|
+
},
|
7637
|
+
{
|
7638
|
+
"name": "wrapper_arguments",
|
7639
|
+
"type": "Hash",
|
7640
|
+
"default": "`{}`",
|
7641
|
+
"description": "{{link_to_system_arguments_docs}} for the `TabContainer` wrapper."
|
7642
|
+
},
|
7631
7643
|
{
|
7632
7644
|
"name": "system_arguments",
|
7633
7645
|
"type": "Hash",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openproject-primer_view_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.30.
|
4
|
+
version: 0.30.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-05-
|
12
|
+
date: 2024-05-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionview
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 19.
|
48
|
+
version: 19.12.0
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 19.
|
55
|
+
version: 19.12.0
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: view_component
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -292,11 +292,7 @@ files:
|
|
292
292
|
- app/components/primer/alpha/underline_nav.html.erb
|
293
293
|
- app/components/primer/alpha/underline_nav.pcss
|
294
294
|
- app/components/primer/alpha/underline_nav.rb
|
295
|
-
- app/components/primer/alpha/underline_panels.css
|
296
|
-
- app/components/primer/alpha/underline_panels.css.json
|
297
|
-
- app/components/primer/alpha/underline_panels.css.map
|
298
295
|
- app/components/primer/alpha/underline_panels.html.erb
|
299
|
-
- app/components/primer/alpha/underline_panels.pcss
|
300
296
|
- app/components/primer/alpha/underline_panels.rb
|
301
297
|
- app/components/primer/alpha/x_banner.d.ts
|
302
298
|
- app/components/primer/alpha/x_banner.js
|
@@ -1 +0,0 @@
|
|
1
|
-
tab-container.UnderlineNav{box-shadow:none;flex-direction:column}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"sources":["underline_panels.pcss"],"names":[],"mappings":"AAAA,2BACE,eAAgB,CAChB,qBACF","file":"underline_panels.css","sourcesContent":["tab-container.UnderlineNav {\n box-shadow: none;\n flex-direction: column;\n}\n"]}
|