diff --git a/README.md b/README.md index 2e56dd8..dd5b657 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,15 @@ Itacomp is a [View Component](https://viewcomponent.org/) and [Helper](https://a * [ita_progress](app/helpers/itacomp/common_helper.rb) * [ita_spinner](app/helpers/itacomp/common_helper.rb) * [ita_visually_hidden](app/helpers/itacomp/common_helper.rb) +* [ita_size](app/helpers/itacomp/common_helper.rb) +* [ita_bg](app/helpers/itacomp/common_helper.rb) +* [ita_text](app/helpers/itacomp/common_helper.rb) ### Components -* [TurboFrameComponent](app/components/itacomp/turbo_frame_component.rb) * [AlertComponent](app/components/itacomp/alert_component.rb) +* [AvatorComponent](app/components/itacomp/avator_component.rb) +* [NotificationComponent](app/components/itacomp/notification_component.rb) +* [TurboFrameComponent](app/components/itacomp/turbo_frame_component.rb) ## Installation Itacomp is in a rapid development phase and the gem will not be released on Rubygem until the [first project](https://github.com/orgs/isprambiente/projects/1) will be completed. diff --git a/app/components/itacomp/alert_component.rb b/app/components/itacomp/alert_component.rb index 6cfea9f..28256bb 100644 --- a/app/components/itacomp/alert_component.rb +++ b/app/components/itacomp/alert_component.rb @@ -6,9 +6,6 @@ module Itacomp # @example with no options # <%= render ItacompAlertComponent.new %> # - # @example with text as params - # <%= render ItacompAlertComponent.new('text') %> - # # @example with text as block # <%= render ItacompAlertComponent.new do %> # text @@ -31,19 +28,17 @@ module Itacomp # <%= render ItacompAlertComponent.new(id: 'my-id', data: {test: 'test'}) %> # class AlertComponent < BaseComponent - # @param [String] text content for alert component, default nil # @param [String,Sym] :type of alert, default 'primary' # @param [Boolean] :close if true is added close button # @param [String] :class add other class after "alsert alert-#{type}" classes # @param [Hash] **opts each other oprion is delegated to container tag # @yield [optional] turbo frame content - def initialize(text = nil, type: :primary, close: false, **opts) + def initialize(type: :primary, close: false, **opts) @close = close @opts = opts @opts[:class] = [ "alert", "alert-#{ITA_TYPES[type]}", @opts[:class] ] @opts[:class] << "alert-dismissible fade show" if close @opts[:role] = "alert" - @text = text end # @return html for close button if @close is true diff --git a/app/components/itacomp/alert_component/alert_component.html.erb b/app/components/itacomp/alert_component/alert_component.html.erb index 82b30ae..dfaa71a 100644 --- a/app/components/itacomp/alert_component/alert_component.html.erb +++ b/app/components/itacomp/alert_component/alert_component.html.erb @@ -1,4 +1,4 @@ <%= tag.div **@opts do %> - <%= content || @text%> + <%= content %> <%= close_button %> <% end %> diff --git a/app/components/itacomp/avatar_component.rb b/app/components/itacomp/avatar_component.rb index fcd9c48..6b6970b 100644 --- a/app/components/itacomp/avatar_component.rb +++ b/app/components/itacomp/avatar_component.rb @@ -4,7 +4,7 @@ module Itacomp # Make a bootstrap-italia compatible [Avatar](https://italia.github.io/bootstrap-italia/docs/componenti/avatar/) tag. # # ==== Example - # With no params + # With no params # <%= render Itacomp::Avatar.new %> #
# With content @@ -33,7 +33,7 @@ module Itacomp #
a
# With other options # <%= render itacomp::avatar(id: "my_avatar", data: {turbo_frame: 'main'}).new.with_content('a') %> - #
a
+ #
a
class AvatarComponent < BaseComponent # Initialize avatar component # @@ -43,8 +43,8 @@ class AvatarComponent < BaseComponent # * class [String,Array] default nil if present is add class style after avatar # * **opts each key is delegated as tag options # * yield avatar content - def initialize(size: nil, bg: nil, class: nil ,**opts) - opts[:class] = ["avatar", opts[:class]] + def initialize(size: nil, bg: nil, class: nil, **opts) + opts[:class] = [ "avatar", opts[:class] ] opts[:class] << ita_size(size) if size.present? opts[:class] << avatar_bg(bg) if bg.present? @opts = opts diff --git a/app/components/itacomp/notification_component.rb b/app/components/itacomp/notification_component.rb new file mode 100644 index 0000000..f79da83 --- /dev/null +++ b/app/components/itacomp/notification_component.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Itacomp + # make a strcture for [notification component](https://italia.github.io/bootstrap-italia/docs/componenti/notification/) + # ==== Example + # With only required title (default show and dismissable) + # <%= render Itacomp::NotificationComponent.new(title: 'test') %> + # + # Mo dismissable and no show + # <%= render Itacomp::NotificationComponent.new(title: 'test', dismissable: false, show: false) %> + # + class NotificationComponent < BaseComponent + # Initialize notification component + # + # ==== Options + # * title [String], mandatory, default: nil, Notification title; + # * show [Boolean], default true, if true set notification visible + # * icon [String] default nil if present is add nontification icon + # * dismissable [Boolean] default true if true add dismiss button + # * **opts each key is delegated as tag options. Default: {class: 'notification', id: Time.now.strftime("%H%M%S%L"), aria: {role: 'alert'}} + # * yield notification content (content is automarically added in a `p` tag) + def initialize(title:, show: true, icon: nil, dismissable: true, **opts) + opts[:class] = [ "notification", opts[:class] ] + opts[:class] << "with-icon" if icon.present? + opts[:class] << "dismissable" if dismissable == true + opts[:id] = "not-#{Time.now.strftime("%H%M%S%L")}" if opts[:id].blank? + opts[:aria] = { labelledby: "#{opts[:id]}-title" } if opts[:aria].blank? + opts[:role] = "alert" + if show == true + opts[:class] << "show" + opts[:style] = "display: block;" + end + @title = title + @icon = icon + @dismissable = dismissable + @opts = opts + end + + # return full title: text and optional icon + def full_title + @icon.present? ? safe_join([ ita_icon(@icon), @title ]) : @title + end + end +end diff --git a/app/components/itacomp/notification_component/notification_component.html.erb b/app/components/itacomp/notification_component/notification_component.html.erb new file mode 100644 index 0000000..4b17f4e --- /dev/null +++ b/app/components/itacomp/notification_component/notification_component.html.erb @@ -0,0 +1,10 @@ +<%= tag.div **@opts do %> + <%= tag.h2 full_title, id: @opts[:aria][:labelledby], class: 'h5' %> + <%= tag.p content if content.present? %> + <% if @dismissable == true %> + <%= tag.button class: "btn notification-close", data: {bs_toggle: "notification", bs_target: "##{@opts[:id]}"} do %> + <%= ita_icon "it-close" %> + <%= ita_visually_hidden "#{t(".close")} #{@title}" %> + <% end %> + <% end %> +<% end %> diff --git a/app/components/itacomp/notification_component/notification_component.yml b/app/components/itacomp/notification_component/notification_component.yml new file mode 100644 index 0000000..1be780c --- /dev/null +++ b/app/components/itacomp/notification_component/notification_component.yml @@ -0,0 +1,7 @@ +--- +en: + close: "close notification:" +fr: + close: "fermer la notification:" +it: + close: "Chiudi la notifica:" diff --git a/app/components/itacomp/turbo_frame_component.rb b/app/components/itacomp/turbo_frame_component.rb index dfd63a8..c070496 100644 --- a/app/components/itacomp/turbo_frame_component.rb +++ b/app/components/itacomp/turbo_frame_component.rb @@ -3,7 +3,7 @@ module Itacomp # Make a bootstrap-italia compatible structure for a [turbo Frame](https://turbo.hotwired.dev/handbook/frames) tag. # - # ==== Example + # ==== Example # Empty turbo frame # = render Itacomp::TurboFrameComponent.new # @@ -40,7 +40,9 @@ class TurboFrameComponent < BaseComponent # * * [Symbol], each key going as tag option # * yield optional turbo frame content def initialize(**keys) + @busy = keys[:href].present? && content.blank? @keys = keys + @keys[:aria] = { busy: true } if @busy end end end diff --git a/app/components/itacomp/turbo_frame_component/turbo_frame_component.html.erb b/app/components/itacomp/turbo_frame_component/turbo_frame_component.html.erb index fdbd888..e2759b0 100644 --- a/app/components/itacomp/turbo_frame_component/turbo_frame_component.html.erb +++ b/app/components/itacomp/turbo_frame_component/turbo_frame_component.html.erb @@ -1,7 +1,3 @@ <%= tag.turbo_frame **@keys do %> - <% if @keys[:href].present? && content.blank? %> - <%= ita_spinner t('.loading') %> - <% else %> - <%= content %> - <% end %> + <%= @busy ? ita_spinner(t('.loading')) : content %> <% end %> diff --git a/app/helpers/itacomp/common_helper.rb b/app/helpers/itacomp/common_helper.rb index 30c137c..f018589 100644 --- a/app/helpers/itacomp/common_helper.rb +++ b/app/helpers/itacomp/common_helper.rb @@ -148,7 +148,7 @@ def ita_progress(value = nil, type: nil) # with invalid params # ira_size(:other) # # => "size-md" - def ita_size(type=nil) + def ita_size(type = nil) "size-#{ITA_SIZES[type]}" end @@ -167,7 +167,7 @@ def ita_size(type=nil) # with invalid params # ira_size(:other) # # => "size-primary" - def ita_bg(type=nil) + def ita_bg(type = nil) "bg-#{ITA_TYPES[type]}" end @@ -186,7 +186,7 @@ def ita_bg(type=nil) # with invalid params # ira_text(:other) # # => "text-primary" - def ita_text(type=nil) + def ita_text(type = nil) "text-#{ITA_TYPES[type]}" end end diff --git a/lib/itacomp.rb b/lib/itacomp.rb index a0e54e9..d77e1e0 100644 --- a/lib/itacomp.rb +++ b/lib/itacomp.rb @@ -3,6 +3,6 @@ module Itacomp # this constant define available bootstrap-italia type - ITA_TYPES = Hash.new { :primary }.with_indifferent_access.merge(primary: "primary", secondary: "secondary", info: "info", success: "success", warning: "warning", danger: "danger", white: "white", dark: "dark", black: 'black') - ITA_SIZES = Hash.new { :md}.with_indifferent_access.merge(xs: "xs", sm: "sm", md: "md", lg: "md", xl: "xl", xxl: "xxl") + ITA_TYPES = Hash.new { :primary }.with_indifferent_access.merge(primary: "primary", secondary: "secondary", info: "info", success: "success", warning: "warning", danger: "danger", white: "white", dark: "dark", black: "black") + ITA_SIZES = Hash.new { :md }.with_indifferent_access.merge(xs: "xs", sm: "sm", md: "md", lg: "md", xl: "xl", xxl: "xxl") end diff --git a/test/components/itacomp/alert_component_test.rb b/test/components/itacomp/alert_component_test.rb index f992f70..733ec60 100644 --- a/test/components/itacomp/alert_component_test.rb +++ b/test/components/itacomp/alert_component_test.rb @@ -8,12 +8,7 @@ class Itacomp::AlertComponentTest < ViewComponent::TestCase assert_selector "div.alert.alert-primary[role='alert']", text: nil end - test "render text as params" do - render_inline Itacomp::AlertComponent.new("test") - assert_selector "div.alert.alert-primary[role='alert']", text: "test" - end - - test "render text as block" do + test "render with content" do render_inline Itacomp::AlertComponent.new.with_content("test") assert_selector "div.alert.alert-primary[role='alert']", text: "test" end diff --git a/test/components/itacomp/avatar_component_test.rb b/test/components/itacomp/avatar_component_test.rb index b4a710c..f8f389c 100644 --- a/test/components/itacomp/avatar_component_test.rb +++ b/test/components/itacomp/avatar_component_test.rb @@ -9,27 +9,27 @@ class Itacomp::AvatarComponentTest < ViewComponent::TestCase end test "avatar with content" do - render_inline Itacomp::AvatarComponent.new.with_content('test') - assert_selector "div.avatar", text: 'test' + render_inline Itacomp::AvatarComponent.new.with_content("test") + assert_selector "div.avatar", text: "test" end test "set size" do - render_inline Itacomp::AvatarComponent.new(size: 'md') - assert_selector "div.avatar.size-md", text: nil + render_inline Itacomp::AvatarComponent.new(size: "md") + assert_selector "div.avatar.size-md", text: nil end test "set bg" do - render_inline Itacomp::AvatarComponent.new(bg: 'md') - assert_selector "div.avatar.avatar-primary", text: nil + render_inline Itacomp::AvatarComponent.new(bg: "md") + assert_selector "div.avatar.avatar-primary", text: nil end test "add id" do - render_inline Itacomp::AvatarComponent.new(id: 'test') + render_inline Itacomp::AvatarComponent.new(id: "test") assert_selector "div#test.avatar", text: nil end test "add data" do - render_inline Itacomp::AvatarComponent.new(data: {test: 'tost'}) - assert_selector "div.avatar[data-test='tost']", text: nil + render_inline Itacomp::AvatarComponent.new(data: { test: "tost" }) + assert_selector "div.avatar[data-test='tost']", text: nil end end diff --git a/test/components/itacomp/notification_component_test.rb b/test/components/itacomp/notification_component_test.rb new file mode 100644 index 0000000..b3ec466 --- /dev/null +++ b/test/components/itacomp/notification_component_test.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require "test_helper" + +class Itacomp::NotificationComponentTest < ViewComponent::TestCase + test "only required title" do + render_inline Itacomp::NotificationComponent.new(title: "test") + assert_selector "div.notification.dismissable.show[role='alert']", text: "test" + assert_selector "div.notification.dismissable.show h2.h5", text: "test" + assert_selector "div.notification.dismissable.show button.btn.notification-close svg.icon" + assert_selector "div.notification.dismissable.show button.btn.notification-close span.visually-hidden", text: "close notification: test" + end + + test "with id can be set ids and aria-labelledid" do + render_inline Itacomp::NotificationComponent.new(title: "test", id: "test") + assert_selector "div.notification.dismissable.show#test[aria-labelledby='test-title'] h2.h5#test-title", text: "test" + end + + test "can render with icon" do + render_inline Itacomp::NotificationComponent.new(title: "test", icon: "test") + assert_selector "div.notification.dismissable.show.with-icon h2.h5 svg.icon" + end +end diff --git a/test/components/previews/itacomp/alert_component_preview.rb b/test/components/previews/itacomp/alert_component_preview.rb index 01d9040..6b47088 100644 --- a/test/components/previews/itacomp/alert_component_preview.rb +++ b/test/components/previews/itacomp/alert_component_preview.rb @@ -3,7 +3,7 @@ module Itacomp class AlertComponentPreview < ViewComponent::Preview def default - render(AlertComponent.new(text: "text", type: "type", close: "close")) + render(AlertComponent.new(type: "primary", close: true)) end end end diff --git a/test/components/previews/itacomp/notification_component_preview.rb b/test/components/previews/itacomp/notification_component_preview.rb new file mode 100644 index 0000000..8f0cd2d --- /dev/null +++ b/test/components/previews/itacomp/notification_component_preview.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Itacomp + class NotificationComponentPreview < ViewComponent::Preview + def default + render(NotificationComponent.new(title: "text")) + end + end +end