openproject-primer_view_components 0.78.0 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view.d.ts +1 -0
  4. data/app/assets/javascripts/components/primer/open_project/avatar_fallback.d.ts +7 -0
  5. data/app/assets/javascripts/components/primer/primer.d.ts +1 -0
  6. data/app/assets/javascripts/primer_view_components.js +1 -1
  7. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  8. data/app/assets/styles/primer_view_components.css +1 -1
  9. data/app/assets/styles/primer_view_components.css.map +1 -1
  10. data/app/components/primer/alpha/action_list.css +1 -1
  11. data/app/components/primer/alpha/action_list.css.map +1 -1
  12. data/app/components/primer/alpha/text_field.css +1 -1
  13. data/app/components/primer/alpha/text_field.css.map +1 -1
  14. data/app/components/primer/alpha/tree_view/tree_view.d.ts +1 -0
  15. data/app/components/primer/alpha/tree_view/tree_view.js +23 -16
  16. data/app/components/primer/alpha/tree_view/tree_view.ts +29 -20
  17. data/app/components/primer/alpha/underline_nav.css +1 -1
  18. data/app/components/primer/alpha/underline_nav.css.map +1 -1
  19. data/app/components/primer/beta/avatar.rb +6 -2
  20. data/app/components/primer/beta/avatar_stack.css +1 -1
  21. data/app/components/primer/beta/avatar_stack.css.json +7 -4
  22. data/app/components/primer/beta/avatar_stack.css.map +1 -1
  23. data/app/components/primer/beta/avatar_stack.pcss +22 -2
  24. data/app/components/primer/beta/avatar_stack.rb +4 -1
  25. data/app/components/primer/beta/button.css +1 -1
  26. data/app/components/primer/beta/button.css.map +1 -1
  27. data/app/components/primer/open_project/avatar_fallback.d.ts +7 -0
  28. data/app/components/primer/open_project/avatar_fallback.js +62 -0
  29. data/app/components/primer/open_project/avatar_fallback.ts +49 -0
  30. data/app/components/primer/open_project/avatar_stack.css +1 -0
  31. data/app/components/primer/open_project/avatar_stack.css.json +10 -0
  32. data/app/components/primer/open_project/avatar_stack.css.map +1 -0
  33. data/app/components/primer/open_project/avatar_stack.pcss +40 -0
  34. data/app/components/primer/open_project/avatar_stack.rb +23 -0
  35. data/app/components/primer/open_project/avatar_with_fallback.rb +114 -0
  36. data/app/components/primer/open_project/page_header.css +1 -1
  37. data/app/components/primer/open_project/page_header.css.json +2 -1
  38. data/app/components/primer/open_project/page_header.css.map +1 -1
  39. data/app/components/primer/open_project/page_header.pcss +9 -3
  40. data/app/components/primer/primer.d.ts +1 -0
  41. data/app/components/primer/primer.js +1 -0
  42. data/app/components/primer/primer.pcss +1 -0
  43. data/app/components/primer/primer.ts +1 -0
  44. data/lib/primer/view_components/version.rb +1 -1
  45. data/previews/primer/alpha/tree_view_preview/form_input.html.erb +1 -1
  46. data/previews/primer/beta/avatar_stack_preview.rb +23 -2
  47. data/previews/primer/open_project/avatar_stack_preview.rb +70 -0
  48. data/previews/primer/open_project/avatar_with_fallback_preview/fallback_multiple.html.erb +7 -0
  49. data/previews/primer/open_project/avatar_with_fallback_preview/fallback_sizes.html.erb +34 -0
  50. data/previews/primer/open_project/avatar_with_fallback_preview.rb +71 -0
  51. data/previews/primer/open_project/filterable_tree_view_preview/form_input.html.erb +1 -1
  52. data/static/arguments.json +110 -0
  53. data/static/audited_at.json +2 -0
  54. data/static/classes.json +2 -1
  55. data/static/constants.json +7 -0
  56. data/static/info_arch.json +373 -0
  57. data/static/previews.json +237 -0
  58. data/static/statuses.json +2 -0
  59. metadata +16 -2
@@ -1 +1 @@
1
- .PageHeader{border-bottom:var(--borderWidth-thin) solid var(--borderColor-muted);display:flex;flex-flow:column;margin-bottom:var(--base-size-16);padding-bottom:var(--base-size-8)}.PageHeader--withTabNav{border-bottom:none;margin-bottom:0;padding-bottom:0}.PageHeader-contextBar{height:var(--control-small-size)}.PageHeader-contextBar,.PageHeader-titleBar{align-items:center;display:flex;flex-flow:row;justify-content:flex-end;margin-bottom:var(--base-size-8)}.PageHeader-title{flex:1 1 auto;font-size:var(--text-title-size-medium)}.PageHeader-title--large{font-size:var(--text-title-size-large)}.PageHeader-description{color:var(--fgColor-muted);flex:1 auto;font-size:var(--text-body-size-medium)}.PageHeader-description--underlined-links a{-webkit-text-decoration:underline;text-decoration:underline}.PageHeader-tabNavBar{overflow:auto}.PageHeader-tabNavBar .PageHeader-tabNav{min-width:max-content}.PageHeader--withTabNav .PageHeader-description{margin-bottom:var(--base-size-16)}.PageHeader-actions{align-items:center;display:flex;justify-content:flex-end}.PageHeader-breadcrumbs{display:block;width:100%}.PageHeader-leadingAction{margin-right:var(--base-size-4);margin-top:var(--base-size-2)}.PageHeader-parentLink{flex:1 1 auto}@media screen and (min-width:543.98px){.PageHeader--noBreadcrumb .PageHeader-contextBar{display:none}}.PageHeader--noBreadcrumb .PageHeader-titleBar{line-height:var(--control-small-size)}
1
+ .PageHeader{border-bottom:var(--borderWidth-thin) solid var(--borderColor-muted);display:flex;flex-flow:column;margin-bottom:var(--base-size-16);padding-bottom:var(--base-size-8)}.PageHeader--withTabNav{border-bottom:none;margin-bottom:0;padding-bottom:0}.PageHeader-contextBar{height:var(--control-small-size)}.PageHeader-contextBar,.PageHeader-titleBar{align-items:center;display:flex;flex-flow:row;justify-content:flex-end;margin-bottom:var(--base-size-8)}.PageHeader-title{flex:1 1 auto;font-size:var(--text-title-size-medium)}.PageHeader-title--large{font-size:var(--text-title-size-large)}.PageHeader-description{color:var(--fgColor-muted);flex:1 auto;font-size:var(--text-body-size-medium)}.PageHeader-description--underlined-links a{-webkit-text-decoration:underline;text-decoration:underline}.PageHeader-tabNavBar{overflow:auto}.PageHeader-tabNavBar .PageHeader-tabNav{min-width:max-content}.PageHeader--withTabNav .PageHeader-description{margin-bottom:var(--base-size-16)}.PageHeader-actions{align-items:center;display:flex;justify-content:flex-end}.PageHeader-breadcrumbs{display:block;width:100%}.PageHeader-leadingAction{margin-right:var(--base-size-4);margin-top:var(--base-size-2)}.PageHeader-parentLink{flex:1 1 auto}@media screen and (min-width:543.98px){.PageHeader--noBreadcrumb .PageHeader-contextBar{display:none}}.PageHeader--noBreadcrumb .PageHeader-titleBar{line-height:var(--control-small-size)}.PageHeader--noBreadcrumb .PageHeader-actions{height:var(--control-small-size)}
@@ -17,6 +17,7 @@
17
17
  ".PageHeader-leadingAction",
18
18
  ".PageHeader-parentLink",
19
19
  ".PageHeader--noBreadcrumb .PageHeader-contextBar",
20
- ".PageHeader--noBreadcrumb .PageHeader-titleBar"
20
+ ".PageHeader--noBreadcrumb .PageHeader-titleBar",
21
+ ".PageHeader--noBreadcrumb .PageHeader-actions"
21
22
  ]
22
23
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,oEAAqE,CAHrE,YAAa,CAIb,gBAAiB,CAFjB,iCAAkC,CADlC,iCAIF,CAEA,wBACE,kBAAmB,CAEnB,eAAgB,CADhB,gBAEF,CAEA,uBAME,gCACF,CAEA,4CALE,kBAAmB,CAHnB,YAAa,CACb,aAAc,CACd,wBAAyB,CAEzB,gCAUF,CAEA,kBAEE,aAAc,CADd,uCAEF,CAEA,yBACE,sCACF,CAGA,wBAEE,0BAA2B,CAC3B,WAAY,CAFZ,sCAGF,CAEA,4CAEE,iCAA0B,CAA1B,yBACF,CAEA,sBACE,aACF,CAEA,yCACE,qBACF,CAEA,gDACE,iCACF,CAEA,oBAGE,kBAAmB,CADnB,YAAa,CADb,wBAGF,CAEA,wBACE,aAAc,CACd,UACF,CAEA,0BAEE,+BAAgC,CADhC,6BAEF,CAEA,uBACE,aACF,CAGA,uCACE,iDACE,YACF,CACF,CAGA,+CACE,qCACF","file":"page_header.css","sourcesContent":["/* OP PageHeader */\n\n.PageHeader {\n display: flex;\n padding-bottom: var(--base-size-8);\n margin-bottom: var(--base-size-16);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-muted);\n flex-flow: column;\n}\n\n.PageHeader--withTabNav {\n border-bottom: none;\n padding-bottom: 0;\n margin-bottom: 0;\n}\n\n.PageHeader-contextBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center;\n margin-bottom: var(--base-size-8);\n height: var(--control-small-size);\n}\n\n.PageHeader-titleBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center; /* Keep back button vertically aligned. */\n margin-bottom: var(--base-size-8);\n}\n\n.PageHeader-title {\n font-size: var(--text-title-size-medium);\n flex: 1 1 auto;\n}\n\n.PageHeader-title--large {\n font-size: var(--text-title-size-large);\n}\n\n/* One-liner of supporting text */\n.PageHeader-description {\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-muted);\n flex: 1 auto;\n}\n\n.PageHeader-description--underlined-links a {\n /* Ensure the accessibility is met, given that the description is written in light grey */\n text-decoration: underline;\n}\n\n.PageHeader-tabNavBar {\n overflow: auto;\n}\n\n.PageHeader-tabNavBar .PageHeader-tabNav {\n min-width: max-content;\n}\n\n.PageHeader--withTabNav .PageHeader-description {\n margin-bottom: var(--base-size-16);\n}\n\n.PageHeader-actions {\n justify-content: flex-end;\n display: flex;\n align-items: center;\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n}\n\n.PageHeader-leadingAction {\n margin-top: var(--base-size-2); /* to center align with label */\n margin-right: var(--base-size-4);\n}\n\n.PageHeader-parentLink {\n flex: 1 1 auto;\n}\n\n/* Hide the context bar on desktop when no breadcrumb is visible */\n@media screen and (min-width: 543.98px) {\n .PageHeader--noBreadcrumb .PageHeader-contextBar {\n display: none;\n }\n}\n\n/* Match the title bar height with the toggle menu button for proper vertical alignment */\n.PageHeader--noBreadcrumb .PageHeader-titleBar {\n line-height: var(--control-small-size);\n}"]}
1
+ {"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,oEAAqE,CAHrE,YAAa,CAIb,gBAAiB,CAFjB,iCAAkC,CADlC,iCAIF,CAEA,wBACE,kBAAmB,CAEnB,eAAgB,CADhB,gBAEF,CAEA,uBAME,gCACF,CAEA,4CALE,kBAAmB,CAHnB,YAAa,CACb,aAAc,CACd,wBAAyB,CAEzB,gCAUF,CAEA,kBAEE,aAAc,CADd,uCAEF,CAEA,yBACE,sCACF,CAGA,wBAEE,0BAA2B,CAC3B,WAAY,CAFZ,sCAGF,CAEA,4CAEE,iCAA0B,CAA1B,yBACF,CAEA,sBACE,aACF,CAEA,yCACE,qBACF,CAEA,gDACE,iCACF,CAEA,oBAGE,kBAAmB,CADnB,YAAa,CADb,wBAGF,CAEA,wBACE,aAAc,CACd,UACF,CAEA,0BAEE,+BAAgC,CADhC,6BAEF,CAEA,uBACE,aACF,CAGA,uCACE,iDACE,YACF,CACF,CAIE,+CACE,qCACF,CAEA,8CACE,gCACF","file":"page_header.css","sourcesContent":["/* OP PageHeader */\n\n.PageHeader {\n display: flex;\n padding-bottom: var(--base-size-8);\n margin-bottom: var(--base-size-16);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-muted);\n flex-flow: column;\n}\n\n.PageHeader--withTabNav {\n border-bottom: none;\n padding-bottom: 0;\n margin-bottom: 0;\n}\n\n.PageHeader-contextBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center;\n margin-bottom: var(--base-size-8);\n height: var(--control-small-size);\n}\n\n.PageHeader-titleBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center; /* Keep back button vertically aligned. */\n margin-bottom: var(--base-size-8);\n}\n\n.PageHeader-title {\n font-size: var(--text-title-size-medium);\n flex: 1 1 auto;\n}\n\n.PageHeader-title--large {\n font-size: var(--text-title-size-large);\n}\n\n/* One-liner of supporting text */\n.PageHeader-description {\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-muted);\n flex: 1 auto;\n}\n\n.PageHeader-description--underlined-links a {\n /* Ensure the accessibility is met, given that the description is written in light grey */\n text-decoration: underline;\n}\n\n.PageHeader-tabNavBar {\n overflow: auto;\n}\n\n.PageHeader-tabNavBar .PageHeader-tabNav {\n min-width: max-content;\n}\n\n.PageHeader--withTabNav .PageHeader-description {\n margin-bottom: var(--base-size-16);\n}\n\n.PageHeader-actions {\n justify-content: flex-end;\n display: flex;\n align-items: center;\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n}\n\n.PageHeader-leadingAction {\n margin-top: var(--base-size-2); /* to center align with label */\n margin-right: var(--base-size-4);\n}\n\n.PageHeader-parentLink {\n flex: 1 1 auto;\n}\n\n/* Hide the context bar on desktop when no breadcrumb is visible */\n@media screen and (min-width: 543.98px) {\n .PageHeader--noBreadcrumb .PageHeader-contextBar {\n display: none;\n }\n}\n\n/* Match the title bar and actions height with the toggle menu button for proper vertical alignment */\n.PageHeader--noBreadcrumb {\n & .PageHeader-titleBar {\n line-height: var(--control-small-size);\n }\n\n & .PageHeader-actions {\n height: var(--control-small-size);\n }\n}"]}
@@ -91,7 +91,13 @@
91
91
  }
92
92
  }
93
93
 
94
- /* Match the title bar height with the toggle menu button for proper vertical alignment */
95
- .PageHeader--noBreadcrumb .PageHeader-titleBar {
96
- line-height: var(--control-small-size);
94
+ /* Match the title bar and actions height with the toggle menu button for proper vertical alignment */
95
+ .PageHeader--noBreadcrumb {
96
+ & .PageHeader-titleBar {
97
+ line-height: var(--control-small-size);
98
+ }
99
+
100
+ & .PageHeader-actions {
101
+ height: var(--control-small-size);
102
+ }
97
103
  }
@@ -30,6 +30,7 @@ import './alpha/tree_view/tree_view';
30
30
  import './alpha/tree_view/tree_view_icon_pair_element';
31
31
  import './alpha/tree_view/tree_view_sub_tree_node_element';
32
32
  import './alpha/tree_view/tree_view_include_fragment_element';
33
+ import './open_project/avatar_fallback';
33
34
  import './open_project/page_header_element';
34
35
  import './open_project/zen_mode_button';
35
36
  import './open_project/sub_header_element';
@@ -30,6 +30,7 @@ import './alpha/tree_view/tree_view';
30
30
  import './alpha/tree_view/tree_view_icon_pair_element';
31
31
  import './alpha/tree_view/tree_view_sub_tree_node_element';
32
32
  import './alpha/tree_view/tree_view_include_fragment_element';
33
+ import './open_project/avatar_fallback';
33
34
  import './open_project/page_header_element';
34
35
  import './open_project/zen_mode_button';
35
36
  import './open_project/sub_header_element';
@@ -45,6 +45,7 @@
45
45
  @import "./alpha/action_bar.pcss";
46
46
 
47
47
  /* OP specifics */
48
+ @import "./open_project/avatar_stack.pcss";
48
49
  @import "./open_project/page_header.pcss";
49
50
  @import "./open_project/drag_handle.pcss";
50
51
  @import "./open_project/border_grid.pcss";
@@ -30,6 +30,7 @@ import './alpha/tree_view/tree_view'
30
30
  import './alpha/tree_view/tree_view_icon_pair_element'
31
31
  import './alpha/tree_view/tree_view_sub_tree_node_element'
32
32
  import './alpha/tree_view/tree_view_include_fragment_element'
33
+ import './open_project/avatar_fallback'
33
34
  import './open_project/page_header_element'
34
35
  import './open_project/zen_mode_button'
35
36
  import './open_project/sub_header_element'
@@ -5,7 +5,7 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 78
8
+ MINOR = 79
9
9
  PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
@@ -2,7 +2,7 @@
2
2
  <%= render(Primer::Alpha::Stack.new) do %>
3
3
  <%= render(Primer::Alpha::TreeView.new(form_arguments: { builder: f, name: "folder_structure" })) do |tree| %>
4
4
  <% tree.with_sub_tree(label: "src", expanded: expanded, select_variant: select_variant, value: 0) do |sub_tree| %>
5
- <% sub_tree.with_leaf(label: "button.rb", select_variant: select_variant, value: 1) %>
5
+ <% sub_tree.with_leaf(label: "button.rb", select_variant: select_variant, value: 1, checked: true) %>
6
6
  <% sub_tree.with_leaf(label: "icon_button.rb", current: true, select_variant: select_variant, value: 2) %>
7
7
  <% end %>
8
8
 
@@ -11,8 +11,9 @@ module Primer
11
11
  # @param align select [["Left", left], ["Right", right]]
12
12
  # @param tooltipped toggle
13
13
  # @param tooltip_label text
14
- def playground(number_of_avatars: 1, tag: :div, align: :left, tooltipped: false, tooltip_label: "This is a tooltip!")
15
- render(Primer::Beta::AvatarStack.new(tag: tag, align: align, tooltipped: tooltipped, body_arguments: { label: tooltip_label })) do |component|
14
+ # @param disable_expand toggle
15
+ def playground(number_of_avatars: 1, tag: :div, align: :left, tooltipped: false, tooltip_label: "This is a tooltip!", disable_expand: false)
16
+ render(Primer::Beta::AvatarStack.new(tag: tag, align: align, tooltipped: tooltipped, disable_expand: disable_expand, body_arguments: { label: tooltip_label })) do |component|
16
17
  Array.new(number_of_avatars&.to_i || 1) do
17
18
  component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
18
19
  end
@@ -97,6 +98,26 @@ module Primer
97
98
  component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser", href: "primer.style")
98
99
  end
99
100
  end
101
+
102
+ # @label With individual avatar tooltips
103
+ def with_individual_tooltips
104
+ render(Primer::Beta::AvatarStack.new) do |component|
105
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser", href: "https://github.com/user1", tooltip: "User 1")
106
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser", href: "https://github.com/user2", tooltip: "User 2")
107
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser", href: "https://github.com/user3", tooltip: "User 3")
108
+ end
109
+ end
110
+
111
+ # @label With disabled expand
112
+ def with_disabled_expand
113
+ render(Primer::Beta::AvatarStack.new(disable_expand: true)) do |component|
114
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
115
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
116
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
117
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
118
+ component.with_avatar(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
119
+ end
120
+ end
100
121
  #
101
122
  # @!endgroup
102
123
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
5
+ # @label OpenProject AvatarStack
6
+ class AvatarStackPreview < ViewComponent::Preview
7
+ # @label Playground
8
+ #
9
+ # @param number_of_avatars [Integer] number
10
+ # @param with_fallbacks toggle
11
+ # @param align select [["Left", left], ["Right", right]]
12
+ def playground(number_of_avatars: 3, with_fallbacks: true, align: :left)
13
+ render(Primer::OpenProject::AvatarStack.new(align: align)) do |component|
14
+ Array.new(number_of_avatars&.to_i || 1) do |i|
15
+ if with_fallbacks
16
+ component.with_avatar_with_fallback(src: nil, alt: "User #{i + 1}", unique_id: i + 1)
17
+ else
18
+ component.with_avatar_with_fallback(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # @label Default
25
+ # @snapshot
26
+ def default
27
+ render(Primer::OpenProject::AvatarStack.new) do |component|
28
+ component.with_avatar_with_fallback(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
29
+ end
30
+ end
31
+
32
+ # @label With fallback avatars
33
+ # @snapshot
34
+ def with_fallback_avatars
35
+ render(Primer::OpenProject::AvatarStack.new) do |component|
36
+ component.with_avatar_with_fallback(src: nil, alt: "Alice Johnson", unique_id: 1)
37
+ component.with_avatar_with_fallback(src: nil, alt: "Bob Smith", unique_id: 2)
38
+ component.with_avatar_with_fallback(src: nil, alt: "Charlie Brown", unique_id: 3)
39
+ end
40
+ end
41
+
42
+ # @label Mixed (image and fallback)
43
+ def mixed_avatars
44
+ render(Primer::OpenProject::AvatarStack.new) do |component|
45
+ component.with_avatar_with_fallback(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser")
46
+ component.with_avatar_with_fallback(src: nil, alt: "Alice Johnson", unique_id: 10)
47
+ component.with_avatar_with_fallback(src: nil, alt: "Bob Smith", unique_id: 20)
48
+ end
49
+ end
50
+
51
+ # @label Align right with fallbacks
52
+ def align_right_with_fallbacks
53
+ render(Primer::OpenProject::AvatarStack.new(align: :right)) do |component|
54
+ component.with_avatar_with_fallback(src: nil, alt: "Alice Johnson", unique_id: 1)
55
+ component.with_avatar_with_fallback(src: nil, alt: "Bob Smith", unique_id: 2)
56
+ component.with_avatar_with_fallback(src: nil, alt: "Charlie Brown", unique_id: 3)
57
+ end
58
+ end
59
+
60
+ # @label With tooltip and fallbacks
61
+ def with_tooltip_and_fallbacks
62
+ render(Primer::OpenProject::AvatarStack.new(tooltipped: true, body_arguments: { label: "Team members" })) do |component|
63
+ component.with_avatar_with_fallback(src: nil, alt: "Alice Johnson", unique_id: 1)
64
+ component.with_avatar_with_fallback(src: nil, alt: "Bob Smith", unique_id: 2)
65
+ component.with_avatar_with_fallback(src: nil, alt: "Charlie Brown", unique_id: 3)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,7 @@
1
+ <div class="d-flex gap-3 flex-items-center">
2
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Alice Johnson", unique_id: 10)) %>
3
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Bob Smith", unique_id: 20)) %>
4
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Charlie Brown", unique_id: 30)) %>
5
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Diana Prince", unique_id: 40)) %>
6
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Eve Anderson", unique_id: 50)) %>
7
+ </div>
@@ -0,0 +1,34 @@
1
+ <div class="d-flex gap-3 flex-items-center flex-wrap">
2
+ <div class="d-flex flex-column flex-items-center gap-2">
3
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 16)) %>
4
+ <span class="text-small">16px</span>
5
+ </div>
6
+ <div class="d-flex flex-column flex-items-center gap-2">
7
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 20)) %>
8
+ <span class="text-small">20px</span>
9
+ </div>
10
+ <div class="d-flex flex-column flex-items-center gap-2">
11
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 24)) %>
12
+ <span class="text-small">24px</span>
13
+ </div>
14
+ <div class="d-flex flex-column flex-items-center gap-2">
15
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 32)) %>
16
+ <span class="text-small">32px</span>
17
+ </div>
18
+ <div class="d-flex flex-column flex-items-center gap-2">
19
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 40)) %>
20
+ <span class="text-small">40px</span>
21
+ </div>
22
+ <div class="d-flex flex-column flex-items-center gap-2">
23
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 48)) %>
24
+ <span class="text-small">48px</span>
25
+ </div>
26
+ <div class="d-flex flex-column flex-items-center gap-2">
27
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 64)) %>
28
+ <span class="text-small">64px</span>
29
+ </div>
30
+ <div class="d-flex flex-column flex-items-center gap-2">
31
+ <%= render(Primer::OpenProject::AvatarWithFallback.new(src: nil, alt: "Test User", unique_id: 100, size: 80)) %>
32
+ <span class="text-small">80px</span>
33
+ </div>
34
+ </div>
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module OpenProject
5
+ # @label AvatarWithFallback
6
+ class AvatarWithFallbackPreview < ViewComponent::Preview
7
+ # @label Playground
8
+ #
9
+ # @param size [Integer] select [16, 20, 24, 32, 40, 48, 64, 80]
10
+ # @param shape [Symbol] select [circle, square]
11
+ # @param href [String] text
12
+ # @param with_src [Boolean] toggle
13
+ def playground(size: 24, shape: :circle, href: nil, with_src: false)
14
+ if with_src
15
+ render(Primer::OpenProject::AvatarWithFallback.new(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser", size: size, shape: shape, href: href))
16
+ else
17
+ render(Primer::OpenProject::AvatarWithFallback.new(alt: "OpenProject Admin", unique_id: 4, size: size, shape: shape, href: href))
18
+ end
19
+ end
20
+
21
+ # @label Default
22
+ # @snapshot
23
+ def default
24
+ render(Primer::OpenProject::AvatarWithFallback.new(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser"))
25
+ end
26
+
27
+ # @label With image src
28
+ # @snapshot
29
+ def with_image
30
+ render(Primer::OpenProject::AvatarWithFallback.new(src: Primer::ExampleImage::BASE64_SRC, alt: "@kittenuser"))
31
+ end
32
+
33
+ # @!group Fallback (Initials)
34
+ #
35
+ # @label Fallback with initials
36
+ # @snapshot
37
+ def fallback_default
38
+ render(Primer::OpenProject::AvatarWithFallback.new(alt: "OpenProject Admin", unique_id: 4))
39
+ end
40
+
41
+ # @label Fallback single name
42
+ # @snapshot
43
+ def fallback_single_name
44
+ render(Primer::OpenProject::AvatarWithFallback.new(alt: "John", unique_id: 2))
45
+ end
46
+
47
+ # @label Fallback multiple users
48
+ def fallback_multiple
49
+ render_with_template(locals: {})
50
+ end
51
+
52
+ # @label Fallback sizes
53
+ def fallback_sizes
54
+ render_with_template(locals: {})
55
+ end
56
+
57
+ # @label Fallback square shape
58
+ # @snapshot
59
+ def fallback_square
60
+ render(Primer::OpenProject::AvatarWithFallback.new(alt: "OpenProject Org", unique_id: 100, shape: :square))
61
+ end
62
+
63
+ # @label Fallback as link
64
+ def fallback_as_link
65
+ render(Primer::OpenProject::AvatarWithFallback.new(alt: "Jane Doe", unique_id: 3, href: "#"))
66
+ end
67
+ #
68
+ # @!endgroup
69
+ end
70
+ end
71
+ end
@@ -7,7 +7,7 @@
7
7
  <% end %>
8
8
 
9
9
  <% hogwarts.with_sub_tree(label: "Slytherin", select_variant: select_variant, expanded: expanded) do |hufflepuff| %>
10
- <% hufflepuff.with_leaf(label: "Draco Malfoy", select_variant: select_variant) %>
10
+ <% hufflepuff.with_leaf(label: "Draco Malfoy", select_variant: select_variant, checked: true) %>
11
11
  <% end %>
12
12
 
13
13
  <% hogwarts.with_sub_tree(label: "Hufflepuff", select_variant: select_variant, expanded: expanded) do |hufflepuff| %>
@@ -4031,6 +4031,12 @@
4031
4031
  "default": "`nil`",
4032
4032
  "description": "The URL to link to. If used, component will be wrapped by an `<a>` tag."
4033
4033
  },
4034
+ {
4035
+ "name": "tooltip",
4036
+ "type": "String",
4037
+ "default": "`nil`",
4038
+ "description": "Tooltip text to display on hover when href is provided."
4039
+ },
4034
4040
  {
4035
4041
  "name": "system_arguments",
4036
4042
  "type": "Hash",
@@ -4065,6 +4071,12 @@
4065
4071
  "default": "`false`",
4066
4072
  "description": "Whether to add a tooltip to the stack or not."
4067
4073
  },
4074
+ {
4075
+ "name": "disable_expand",
4076
+ "type": "Boolean",
4077
+ "default": "`false`",
4078
+ "description": "Whether to disable the expand behavior on hover. If true, avatars will not expand."
4079
+ },
4068
4080
  {
4069
4081
  "name": "body_arguments",
4070
4082
  "type": "Hash",
@@ -5705,6 +5717,104 @@
5705
5717
  }
5706
5718
  ]
5707
5719
  },
5720
+ {
5721
+ "component": "OpenProject::AvatarStack",
5722
+ "status": "open_project",
5723
+ "a11y_reviewed": false,
5724
+ "short_name": "OpenProjectAvatarStack",
5725
+ "source": "https://github.com/primer/view_components/tree/main/app/components/primer/open_project/avatar_stack.rb",
5726
+ "lookbook": "https://primer.style/view-components/lookbook/inspect/primer/open_project/avatar_stack/default/",
5727
+ "parameters": [
5728
+ {
5729
+ "name": "tag",
5730
+ "type": "Symbol",
5731
+ "default": "`:div`",
5732
+ "description": "One of `:div` or `:span`."
5733
+ },
5734
+ {
5735
+ "name": "align",
5736
+ "type": "Symbol",
5737
+ "default": "`:left`",
5738
+ "description": "One of `:left` or `:right`."
5739
+ },
5740
+ {
5741
+ "name": "tooltipped",
5742
+ "type": "Boolean",
5743
+ "default": "`false`",
5744
+ "description": "Whether to add a tooltip to the stack or not."
5745
+ },
5746
+ {
5747
+ "name": "disable_expand",
5748
+ "type": "Boolean",
5749
+ "default": "`false`",
5750
+ "description": "Whether to disable the expand behavior on hover. If true, avatars will not expand."
5751
+ },
5752
+ {
5753
+ "name": "body_arguments",
5754
+ "type": "Hash",
5755
+ "default": "`{}`",
5756
+ "description": "Parameters to add to the Body. If `tooltipped` is set, has the same arguments as [Tooltip](/components/tooltip). The default tag is `:div` but can be changed using `tag:` to one of `:div` or `:span`."
5757
+ },
5758
+ {
5759
+ "name": "system_arguments",
5760
+ "type": "Hash",
5761
+ "default": "N/A",
5762
+ "description": "[System arguments](/system-arguments)"
5763
+ }
5764
+ ]
5765
+ },
5766
+ {
5767
+ "component": "OpenProject::AvatarWithFallback",
5768
+ "status": "open_project",
5769
+ "a11y_reviewed": false,
5770
+ "short_name": "OpenProjectAvatarWithFallback",
5771
+ "source": "https://github.com/primer/view_components/tree/main/app/components/primer/open_project/avatar_with_fallback.rb",
5772
+ "lookbook": "https://primer.style/view-components/lookbook/inspect/primer/open_project/avatar_with_fallback/default/",
5773
+ "parameters": [
5774
+ {
5775
+ "name": "src",
5776
+ "type": "String",
5777
+ "default": "`nil`",
5778
+ "description": "The source url of the avatar image. When nil, renders a fallback with initials."
5779
+ },
5780
+ {
5781
+ "name": "alt",
5782
+ "type": "String",
5783
+ "default": "`nil`",
5784
+ "description": "Alt text for the avatar. Used for accessibility and to generate initials when src is nil."
5785
+ },
5786
+ {
5787
+ "name": "size",
5788
+ "type": "Integer",
5789
+ "default": "`20`",
5790
+ "description": "One of `16`, `20`, `24`, `32`, `40`, `48`, `64`, or `80`."
5791
+ },
5792
+ {
5793
+ "name": "shape",
5794
+ "type": "Symbol",
5795
+ "default": "`:circle`",
5796
+ "description": "Shape of the avatar. One of `:circle` or `:square`."
5797
+ },
5798
+ {
5799
+ "name": "href",
5800
+ "type": "String",
5801
+ "default": "`nil`",
5802
+ "description": "The URL to link to. If used, component will be wrapped by an `<a>` tag."
5803
+ },
5804
+ {
5805
+ "name": "unique_id",
5806
+ "type": "String, Integer",
5807
+ "default": "`nil`",
5808
+ "description": "Unique identifier for generating consistent avatar colors across renders."
5809
+ },
5810
+ {
5811
+ "name": "system_arguments",
5812
+ "type": "Hash",
5813
+ "default": "N/A",
5814
+ "description": "[System arguments](/system-arguments)"
5815
+ }
5816
+ ]
5817
+ },
5708
5818
  {
5709
5819
  "component": "OpenProject::BorderBox::CollapsibleHeader",
5710
5820
  "status": "open_project",
@@ -139,6 +139,8 @@
139
139
  "Primer::IconButton": "",
140
140
  "Primer::LayoutComponent": "",
141
141
  "Primer::Navigation::TabComponent": "",
142
+ "Primer::OpenProject::AvatarStack": "",
143
+ "Primer::OpenProject::AvatarWithFallback": "",
142
144
  "Primer::OpenProject::BorderBox::CollapsibleHeader": "",
143
145
  "Primer::OpenProject::BorderGrid": "",
144
146
  "Primer::OpenProject::BorderGrid::Cell": "",
data/static/classes.json CHANGED
@@ -96,7 +96,8 @@
96
96
  "Primer::Beta::AvatarStack"
97
97
  ],
98
98
  "AvatarStack-body": [
99
- "Primer::Beta::AvatarStack"
99
+ "Primer::Beta::AvatarStack",
100
+ "Primer::OpenProject::AvatarStack"
100
101
  ],
101
102
  "Banner": [
102
103
  "Primer::Alpha::Banner"
@@ -1695,6 +1695,13 @@
1695
1695
  "Primer::Navigation::TabComponent": {
1696
1696
  "GeneratedSlotMethods": "Primer::Navigation::TabComponent::GeneratedSlotMethods"
1697
1697
  },
1698
+ "Primer::OpenProject::AvatarStack": {
1699
+ "GeneratedSlotMethods": "Primer::OpenProject::AvatarStack::GeneratedSlotMethods"
1700
+ },
1701
+ "Primer::OpenProject::AvatarWithFallback": {
1702
+ "FONT_STACK": "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'",
1703
+ "GeneratedSlotMethods": "Primer::OpenProject::AvatarWithFallback::GeneratedSlotMethods"
1704
+ },
1698
1705
  "Primer::OpenProject::BorderBox::CollapsibleHeader": {
1699
1706
  "GeneratedSlotMethods": "Primer::OpenProject::BorderBox::CollapsibleHeader::GeneratedSlotMethods"
1700
1707
  },