showcase-rails 0.1.1 → 0.2.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +76 -7
  3. data/app/assets/builds/showcase.css +78 -78
  4. data/app/controllers/showcase/engine_controller.rb +12 -0
  5. data/app/controllers/showcase/pages_controller.rb +1 -4
  6. data/app/controllers/showcase/previews_controller.rb +5 -0
  7. data/app/models/showcase/{page/options.rb → options.rb} +1 -1
  8. data/app/models/showcase/path.rb +49 -12
  9. data/app/models/showcase/preview.rb +94 -0
  10. data/app/models/showcase/{page/sample.rb → sample.rb} +10 -6
  11. data/app/views/layouts/showcase.html.erb +3 -3
  12. data/app/views/showcase/engine/_javascripts.html.erb +1 -0
  13. data/app/views/showcase/engine/_options.html.erb +29 -0
  14. data/app/views/showcase/engine/_preview.html.erb +26 -0
  15. data/app/views/showcase/engine/_root.html.erb +13 -0
  16. data/app/views/showcase/engine/_sample.html.erb +37 -0
  17. data/app/views/showcase/engine/_stylesheets.html.erb +1 -0
  18. data/app/views/showcase/engine/index.html.erb +33 -0
  19. data/app/views/showcase/engine/path/_path.html.erb +3 -0
  20. data/app/views/showcase/engine/path/_tree.html.erb +4 -0
  21. data/app/views/showcase/engine/show.html.erb +1 -0
  22. data/config/routes.rb +2 -2
  23. data/config/tailwind.config.js +1 -0
  24. data/lib/showcase/integration_test.rb +23 -0
  25. data/lib/showcase/route_helper.rb +8 -0
  26. data/lib/showcase/version.rb +1 -1
  27. data/lib/showcase.rb +14 -10
  28. data/lib/tasks/showcase_tasks.rake +30 -4
  29. metadata +20 -14
  30. data/app/controllers/showcase/application_controller.rb +0 -3
  31. data/app/models/showcase/page.rb +0 -45
  32. data/app/views/showcase/_root.html.erb +0 -13
  33. data/app/views/showcase/pages/_options.html.erb +0 -27
  34. data/app/views/showcase/pages/_page.html.erb +0 -26
  35. data/app/views/showcase/pages/_sample.html.erb +0 -37
  36. data/app/views/showcase/pages/index.html.erb +0 -33
  37. data/app/views/showcase/pages/show.html.erb +0 -1
  38. data/app/views/showcase/path/_tree.html.erb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e84e94d8b861787bdbbcd87577beab2496d60c231b8803e1ba83d0a0e488708
4
- data.tar.gz: 7e95b0377b27c9f17df42f35a1491fa6d4aafb821bfc1df1db4c496b42fb86b4
3
+ metadata.gz: 38aa85b8e5c0a98ee2dbb45f0a184981de8a86371efbb2237e2a06f0d2f56eef
4
+ data.tar.gz: b4e44e25c0b76afcd33a2dc155cae5bdebe1a5a9ca3cd670d4cc2bae94d7f38b
5
5
  SHA512:
6
- metadata.gz: a1666dce260d55ba265e654dfd39bde2304bdb130b04b389f38352d16bdbe8771031fa79264ff2e13d479018aa33fb069dcc4e1cf835021e0003b9030c54f213
7
- data.tar.gz: f19f23e1545e075bd2f78e1750b3da6838ab78850368a866f2351ac0dacf6aad9b64ea680fefc0618721baf70c025625e29a2fdee7ceb616a4ca74dfaf9309ab
6
+ metadata.gz: 995f0b2b6f765c93936adb968c501218fccc592befe12df06e0aa19b9b092a0ea385cab086763f0b855e3e86eb784edf8365143b49e69dbda934bd8ce608016d
7
+ data.tar.gz: 123c59c68801489dec09d40c144c64fbc09dc6c65925833cbeade7a4c8f479595b6d59274d3ab7e74cdd18495dd8276ef60fa714b3f87662c786d6c190d55c39
data/README.md CHANGED
@@ -1,13 +1,14 @@
1
1
  # Showcase
2
2
 
3
- Showcase lets you build previews for partials, components, view helpers and Stimulus controllers.
3
+ Showcase lets you build previews for your partials, components, view helpers, Stimulus controllers and more.
4
4
 
5
- Add a view template to `app/views/showcases` and it'll show up in Showcase's menu.
5
+ Add a template to `app/views/showcase/previews` and it'll show up in Showcase's menu.
6
6
 
7
7
  Here's how to showcase a standard button component:
8
8
 
9
9
  ```erb
10
- <%# app/views/showcases/components/button.html.erb %>
10
+ <%# app/views/showcase/previews/_button.html.erb %>
11
+ <% showcase.title "Button" %> <%# `title` is optional and inferred from the filename, by default. %>
11
12
  <% showcase.description "This button component handles what we click on" %>
12
13
 
13
14
  <% showcase.sample "Basic" do %>
@@ -19,17 +20,85 @@ Here's how to showcase a standard button component:
19
20
  <% end %>
20
21
 
21
22
  <% showcase.options do |o| %>
22
- <% o.required :content, String, "The content to output as the button text" %>
23
- <% o.optional :mode, default: :small, values: %i[ small medium large ], description: "We support three modes" %>
23
+ <% o.required :content, "The content to output as the button text" %>
24
+ <% o.optional :mode, "We support three modes", default: :small, options: %i[ small medium large ] %>
24
25
  <% end %>
25
26
  ```
26
27
 
28
+ Which will then render the following:
29
+
30
+ ![](/readme/example.png?raw=true "Showcase showing a button component")
31
+
32
+ ## Automatic smokescreen testing
33
+
34
+ Run `bin/rails showcase:install:integration_test` to automatic testing installed in `test/integration/showcase_test.rb`.
35
+
36
+ This will render every Showcase you've defined and assert they respond with `200 OK`. You can add custom assertions by overriding `assert_showcase_preview`.
37
+
38
+ ## View examples
39
+
40
+ Clone the repository, run `bundle install`, then run `bin/rails server`, visit localhost:3000 in your browser.
41
+
42
+ ## Overriding Showcase's default rendering
43
+
44
+ Showcase's rendering happens through two controllers:
45
+
46
+ 1. [`Showcase::EngineController`](app/controllers/showcase/engine_controller.rb)
47
+ 1. [`Showcase::PreviewsController`](app/controllers/showcase/previews_controller.rb)
48
+
49
+ All paths shown here are assumed to be in `app/views`.
50
+
51
+ The actions all use a `layout "showcase"`, which renders like this:
52
+
53
+ - [layouts/showcase.html.erb](app/views/layouts/showcase.html.erb)
54
+ - [showcase/engine/_root.html.erb](app/views/showcase/engine/_root.html.erb)
55
+ - [showcase/engine/path/_tree.html.erb](app/views/showcase/engine/path/_tree.html.erb)
56
+
57
+ So for `Showcase::EngineController#index` we render:
58
+
59
+ - [showcase/engine/index.html.erb](app/views/showcase/engine/index.html.erb)
60
+
61
+ And for `Showcase::PreviewsController#show` we render:
62
+
63
+ - [showcase/engine/show.html.erb](app/views/showcase/engine/show.html.erb)
64
+ - [showcase/engine/_preview.html.erb](app/views/showcase/engine/_preview.html.erb)
65
+ - [showcase/engine/_sample.html.erb](app/views/showcase/engine/_sample.html.erb)
66
+ - [showcase/engine/_options.html.erb](app/views/showcase/engine/_options.html.erb)
67
+
68
+ If you want to override any specific rendering, e.g. how a `Showcase::Preview` is rendered,
69
+ copy the file from our repo `app/views` directory into your `app/views` directory.
70
+
71
+ ### Loading your own assets
72
+
73
+ Showcase bundles its own `showcase.js` and `showcase.css` asset files through
74
+ Action View's [javascript_include_tag][] and [stylesheet_link_tag][].
75
+
76
+ If your assets require more sophisticated loading techniques, declare your own
77
+ versions of the [showcase/engine/_javascripts.html.erb][] and
78
+ [showcase/engine/_stylesheets.html.erb][] partials. When customizing those
79
+ partials, make sure to include `"showcase"` in your list of assets.
80
+
81
+
82
+ [javascript_include_tag]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-javascript_include_tag
83
+ [stylesheet_link_tag]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-stylesheet_link_tag
84
+ [showcase/engine/_javascripts.html.erb]: ./showcase/engine/_javascripts.html.erb
85
+ [showcase/engine/_stylesheets.html.erb]: ./showcase/engine/_stylesheets.html.erb
86
+
27
87
  ## Installation
28
88
 
29
- Add this line to your application's Gemfile:
89
+ Add this line to your application's Gemfile. If you're utilizing the
90
+ [Showcase::IntegrationTest](lib/showcase/integration_test.rb) class, make sure
91
+ that the `showcase-rails` gems is available to your test environment:
92
+
30
93
 
31
94
  ```ruby
32
- gem "showcase"
95
+ # nested in the default group
96
+ gem "showcase-rails"
97
+
98
+ # or nested in the :development and :test groups
99
+ group :development, :test do
100
+ gem "showcase-rails"
101
+ end
33
102
  ```
34
103
 
35
104
  And then execute:
@@ -679,280 +679,280 @@ select {
679
679
  --tw-backdrop-sepia: ;
680
680
  }
681
681
 
682
- .relative {
682
+ .sc-relative {
683
683
  position: relative;
684
684
  }
685
685
 
686
- .col-span-3 {
686
+ .sc-col-span-3 {
687
687
  grid-column: span 3 / span 3;
688
688
  }
689
689
 
690
- .col-span-9 {
690
+ .sc-col-span-9 {
691
691
  grid-column: span 9 / span 9;
692
692
  }
693
693
 
694
- .mb-2 {
694
+ .sc-mb-2 {
695
695
  margin-bottom: 0.5rem;
696
696
  }
697
697
 
698
- .mb-4 {
698
+ .sc-mb-4 {
699
699
  margin-bottom: 1rem;
700
700
  }
701
701
 
702
- .inline-block {
702
+ .sc-inline-block {
703
703
  display: inline-block;
704
704
  }
705
705
 
706
- .flex {
706
+ .sc-flex {
707
707
  display: flex;
708
708
  }
709
709
 
710
- .table {
710
+ .sc-table {
711
711
  display: table;
712
712
  }
713
713
 
714
- .grid {
714
+ .sc-grid {
715
715
  display: grid;
716
716
  }
717
717
 
718
- .h-full {
718
+ .sc-h-full {
719
719
  height: 100%;
720
720
  }
721
721
 
722
- .max-h-20 {
722
+ .sc-max-h-20 {
723
723
  max-height: 5rem;
724
724
  }
725
725
 
726
- .min-h-screen {
726
+ .sc-min-h-screen {
727
727
  min-height: 100vh;
728
728
  }
729
729
 
730
- .w-full {
730
+ .sc-w-full {
731
731
  width: 100%;
732
732
  }
733
733
 
734
- .border-collapse {
734
+ .sc-border-collapse {
735
735
  border-collapse: collapse;
736
736
  }
737
737
 
738
- .cursor-pointer {
738
+ .sc-cursor-pointer {
739
739
  cursor: pointer;
740
740
  }
741
741
 
742
- .select-none {
742
+ .sc-select-none {
743
743
  -webkit-user-select: none;
744
744
  -moz-user-select: none;
745
745
  user-select: none;
746
746
  }
747
747
 
748
- .list-none {
748
+ .sc-list-none {
749
749
  list-style-type: none;
750
750
  }
751
751
 
752
- .grid-cols-12 {
752
+ .sc-grid-cols-12 {
753
753
  grid-template-columns: repeat(12, minmax(0, 1fr));
754
754
  }
755
755
 
756
- .flex-col {
756
+ .sc-flex-col {
757
757
  flex-direction: column;
758
758
  }
759
759
 
760
- .flex-wrap {
760
+ .sc-flex-wrap {
761
761
  flex-wrap: wrap;
762
762
  }
763
763
 
764
- .items-center {
764
+ .sc-items-center {
765
765
  align-items: center;
766
766
  }
767
767
 
768
- .space-y-8 > :not([hidden]) ~ :not([hidden]) {
768
+ .sc-space-y-8 > :not([hidden]) ~ :not([hidden]) {
769
769
  --tw-space-y-reverse: 0;
770
770
  margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));
771
771
  margin-bottom: calc(2rem * var(--tw-space-y-reverse));
772
772
  }
773
773
 
774
- .space-x-2 > :not([hidden]) ~ :not([hidden]) {
774
+ .sc-space-x-2 > :not([hidden]) ~ :not([hidden]) {
775
775
  --tw-space-x-reverse: 0;
776
776
  margin-right: calc(0.5rem * var(--tw-space-x-reverse));
777
777
  margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
778
778
  }
779
779
 
780
- .space-y-4 > :not([hidden]) ~ :not([hidden]) {
780
+ .sc-space-y-4 > :not([hidden]) ~ :not([hidden]) {
781
781
  --tw-space-y-reverse: 0;
782
782
  margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
783
783
  margin-bottom: calc(1rem * var(--tw-space-y-reverse));
784
784
  }
785
785
 
786
- .overflow-hidden {
787
- overflow: hidden;
788
- }
789
-
790
- .overflow-scroll {
786
+ .sc-overflow-scroll {
791
787
  overflow: scroll;
792
788
  }
793
789
 
794
- .overflow-x-auto {
790
+ .sc-overflow-x-auto {
795
791
  overflow-x: auto;
796
792
  }
797
793
 
798
- .truncate {
794
+ .sc-overflow-y-auto {
795
+ overflow-y: auto;
796
+ }
797
+
798
+ .sc-truncate {
799
799
  overflow: hidden;
800
800
  text-overflow: ellipsis;
801
801
  white-space: nowrap;
802
802
  }
803
803
 
804
- .rounded-md {
804
+ .sc-rounded-md {
805
805
  border-radius: 0.375rem;
806
806
  }
807
807
 
808
- .border {
808
+ .sc-border {
809
809
  border-width: 1px;
810
810
  }
811
811
 
812
- .border-0 {
812
+ .sc-border-0 {
813
813
  border-width: 0px;
814
814
  }
815
815
 
816
- .border-r {
817
- border-right-width: 1px;
816
+ .sc-border-t {
817
+ border-top-width: 1px;
818
818
  }
819
819
 
820
- .border-t {
821
- border-top-width: 1px;
820
+ .sc-border-r {
821
+ border-right-width: 1px;
822
822
  }
823
823
 
824
- .border-b {
824
+ .sc-border-b {
825
825
  border-bottom-width: 1px;
826
826
  }
827
827
 
828
- .border-gray-200 {
828
+ .sc-border-gray-200 {
829
829
  --tw-border-opacity: 1;
830
830
  border-color: rgb(229 231 235 / var(--tw-border-opacity));
831
831
  }
832
832
 
833
- .bg-slate-50 {
833
+ .sc-bg-slate-50 {
834
834
  --tw-bg-opacity: 1;
835
835
  background-color: rgb(248 250 252 / var(--tw-bg-opacity));
836
836
  }
837
837
 
838
- .bg-slate-100\/50 {
838
+ .sc-bg-slate-100\/50 {
839
839
  background-color: rgb(241 245 249 / 0.5);
840
840
  }
841
841
 
842
- .bg-indigo-50 {
842
+ .sc-bg-indigo-50 {
843
843
  --tw-bg-opacity: 1;
844
844
  background-color: rgb(238 242 255 / var(--tw-bg-opacity));
845
845
  }
846
846
 
847
- .p-12 {
848
- padding: 3rem;
847
+ .sc-p-4 {
848
+ padding: 1rem;
849
849
  }
850
850
 
851
- .p-4 {
852
- padding: 1rem;
851
+ .sc-p-12 {
852
+ padding: 3rem;
853
853
  }
854
854
 
855
- .py-5 {
856
- padding-top: 1.25rem;
857
- padding-bottom: 1.25rem;
855
+ .sc-px-4 {
856
+ padding-left: 1rem;
857
+ padding-right: 1rem;
858
858
  }
859
859
 
860
- .py-2 {
860
+ .sc-py-2 {
861
861
  padding-top: 0.5rem;
862
862
  padding-bottom: 0.5rem;
863
863
  }
864
864
 
865
- .px-4 {
866
- padding-left: 1rem;
867
- padding-right: 1rem;
865
+ .sc-py-5 {
866
+ padding-top: 1.25rem;
867
+ padding-bottom: 1.25rem;
868
868
  }
869
869
 
870
- .px-8 {
870
+ .sc-px-8 {
871
871
  padding-left: 2rem;
872
872
  padding-right: 2rem;
873
873
  }
874
874
 
875
- .pl-4 {
875
+ .sc-pl-4 {
876
876
  padding-left: 1rem;
877
877
  }
878
878
 
879
- .pt-7 {
879
+ .sc-pt-7 {
880
880
  padding-top: 1.75rem;
881
881
  }
882
882
 
883
- .text-2xl {
884
- font-size: 1.5rem;
885
- line-height: 2rem;
886
- }
887
-
888
- .text-xl {
883
+ .sc-text-xl {
889
884
  font-size: 1.25rem;
890
885
  line-height: 1.75rem;
891
886
  }
892
887
 
893
- .text-3xl {
888
+ .sc-text-3xl {
894
889
  font-size: 1.875rem;
895
890
  line-height: 2.25rem;
896
891
  }
897
892
 
898
- .text-base {
893
+ .sc-text-base {
899
894
  font-size: 1rem;
900
895
  line-height: 1.5rem;
901
896
  }
902
897
 
903
- .font-black {
904
- font-weight: 900;
898
+ .sc-text-2xl {
899
+ font-size: 1.5rem;
900
+ line-height: 2rem;
905
901
  }
906
902
 
907
- .font-semibold {
903
+ .sc-font-semibold {
908
904
  font-weight: 600;
909
905
  }
910
906
 
911
- .font-normal {
907
+ .sc-font-normal {
912
908
  font-weight: 400;
913
909
  }
914
910
 
915
- .font-medium {
911
+ .sc-font-black {
912
+ font-weight: 900;
913
+ }
914
+
915
+ .sc-font-medium {
916
916
  font-weight: 500;
917
917
  }
918
918
 
919
- .italic {
919
+ .sc-italic {
920
920
  font-style: italic;
921
921
  }
922
922
 
923
- .leading-snug {
923
+ .sc-leading-snug {
924
924
  line-height: 1.375;
925
925
  }
926
926
 
927
- .text-black {
927
+ .sc-text-black {
928
928
  --tw-text-opacity: 1;
929
929
  color: rgb(0 0 0 / var(--tw-text-opacity));
930
930
  }
931
931
 
932
- .hover\:select-all:hover {
932
+ .hover\:sc-select-all:hover {
933
933
  -webkit-user-select: all;
934
934
  -moz-user-select: all;
935
935
  user-select: all;
936
936
  }
937
937
 
938
- .hover\:bg-indigo-50:hover {
938
+ .hover\:sc-bg-indigo-50:hover {
939
939
  --tw-bg-opacity: 1;
940
940
  background-color: rgb(238 242 255 / var(--tw-bg-opacity));
941
941
  }
942
942
 
943
943
  @media (min-width: 768px) {
944
- .md\:text-lg {
944
+ .md\:sc-text-lg {
945
945
  font-size: 1.125rem;
946
946
  line-height: 1.75rem;
947
947
  }
948
948
  }
949
949
 
950
950
  @media (min-width: 1280px) {
951
- .xl\:col-span-2 {
951
+ .xl\:sc-col-span-2 {
952
952
  grid-column: span 2 / span 2;
953
953
  }
954
954
 
955
- .xl\:col-span-10 {
955
+ .xl\:sc-col-span-10 {
956
956
  grid-column: span 10 / span 10;
957
957
  }
958
958
  }
@@ -0,0 +1,12 @@
1
+ class Showcase::EngineController < ActionController::Base
2
+ layout "showcase"
3
+
4
+ helper Showcase::RouteHelper
5
+
6
+ if defined?(::ApplicationController)
7
+ helper all_helpers_from_path ::ApplicationController.helpers_path
8
+ end
9
+
10
+ def index
11
+ end
12
+ end
@@ -1,7 +1,4 @@
1
- class Showcase::PagesController < Showcase::ApplicationController
2
- def index
3
- end
4
-
1
+ class Showcase::PagesController < Showcase::EngineController
5
2
  def show
6
3
  @page = Showcase::Path.new(params[:id]).page_for view_context
7
4
  end
@@ -0,0 +1,5 @@
1
+ class Showcase::PreviewsController < Showcase::EngineController
2
+ def show
3
+ @preview = Showcase::Path.new(params[:id]).preview_for view_context
4
+ end
5
+ end
@@ -1,4 +1,4 @@
1
- class Showcase::Page::Options
1
+ class Showcase::Options
2
2
  include Enumerable
3
3
 
4
4
  def initialize(view_context)
@@ -1,30 +1,67 @@
1
1
  class Showcase::Path
2
- class Tree < Struct.new(:id, :paths)
2
+ class Tree < Struct.new(:id, :children)
3
+ def initialize(id, children = [])
4
+ super
5
+ end
6
+ delegate :<<, to: :children
7
+
8
+ cached_partial_path = "showcase/engine/path/tree"
9
+ define_method(:to_partial_path) { cached_partial_path }
10
+
3
11
  def name
4
- root? ? "Pages" : id
12
+ root? ? "Previews" : id
5
13
  end
6
14
 
7
15
  def root?
8
16
  id == "."
9
17
  end
10
- end
11
18
 
12
- def self.tree
13
- all.group_by(&:dirname).map { Tree.new _1, _2 }
19
+ def ordered_children
20
+ children.partition { !_1.is_a?(Tree) }.flatten
21
+ end
22
+
23
+ def ordered_paths
24
+ children.flat_map { _1.is_a?(Tree) ? _1.ordered_paths : _1 }
25
+ end
26
+
27
+ def self.index(...)
28
+ new(:discardable_root).tap { _1.index(...) }.ordered_children
29
+ end
30
+
31
+ def index(paths)
32
+ paths.each do |path|
33
+ ids = yield path
34
+ ids.inject(self, :edge_for) << path
35
+ end
36
+ end
37
+
38
+ def edge_for(id)
39
+ find(id) || insert(id)
40
+ end
41
+
42
+ private
43
+
44
+ def find(id) = children.find { _1.id == id }
45
+ def insert(id) = self.class.new(id).tap { self << _1 }
14
46
  end
15
47
 
16
- def self.all
17
- Showcase.filenames.map { new _1 }.sort_by!(&:id)
48
+ def self.tree
49
+ paths = Showcase.previews.map { new _1 }.sort_by!(&:id)
50
+ Tree.index(paths, &:segments)
18
51
  end
19
52
 
20
- attr_reader :id, :dirname, :basename
53
+ attr_reader :id, :segments, :basename
21
54
 
22
55
  def initialize(path)
23
- @id = path.split(".").first
24
- @dirname, @basename = File.split(@id)
56
+ @id = path.split(".").first.delete_prefix("_").sub(/\/_/, "/")
57
+ @basename = File.basename(@id)
58
+ @segments = File.dirname(@id).split("/")
25
59
  end
26
60
 
27
- def page_for(view_context)
28
- Showcase::Page.new(view_context, id: id, title: basename.titleize).tap(&:render_template)
61
+ cached_partial_path = "showcase/engine/path/path"
62
+ define_method(:to_partial_path) { cached_partial_path }
63
+
64
+ def preview_for(view_context)
65
+ Showcase::Preview.new(view_context, id: id, title: basename.titleize).tap(&:render_associated_partial)
29
66
  end
30
67
  end
@@ -0,0 +1,94 @@
1
+ class Showcase::Preview
2
+ attr_reader :id, :badges, :samples
3
+
4
+ def initialize(view_context, id:, title: nil)
5
+ @view_context, @id = view_context, id
6
+ @badges, @samples = [], []
7
+ title title
8
+ end
9
+
10
+ # Set a custom title for the Preview. By default, it's automatically inferred from the sidebar title,
11
+ # e.g. showcase/previews/_button.html.erb will have Button as the title.
12
+ def title(content = nil)
13
+ @title = content if content
14
+ @title
15
+ end
16
+
17
+ # Describe the Preview in more detail to help guide other developers on what the inner partial/component etc.'s purpose is.
18
+ #
19
+ # <% showcase.description "Our button element" %>
20
+ # <% showcase.description do %>
21
+ # <h3>Our button element</h3> — <span>but with custom description HTML</span>
22
+ # <% end %>
23
+ def description(content = nil, &block)
24
+ @description = content || @view_context.capture(&block) if content || block_given?
25
+ @description
26
+ end
27
+
28
+ # Optional badges you can give to a preview:
29
+ #
30
+ # <% showcase.badge :partial, :view_helper %>
31
+ def badge(*badges)
32
+ @badges.concat badges
33
+ end
34
+
35
+ # Adds a named sample to demonstrate with the Showcase can do.
36
+ #
37
+ # By default, sample takes a block that'll automatically have its source extracted, like this:
38
+ #
39
+ # <% showcase.sample "Basic" do %>
40
+ # <%= render "components/button", content: "Button Content", mode: :small %>
41
+ # <% end %>
42
+ #
43
+ # This outputs a `<showcase-sample>` custom HTML element.
44
+ # The sample name is used to generate the `id` via `name.parameterize` by default, pass `id:` to override.
45
+ #
46
+ # If more advanced rendering is needed, the sample is available as a block argument:
47
+ #
48
+ # <% showcase.sample "Advanced" do |sample| %>
49
+ # <% sample.preview do %>
50
+ # <%= render "components/button", content: "Button Content", mode: :small %>
51
+ # <% end %>
52
+ #
53
+ # <% sample.extract do %>
54
+ # This will be in the source output.
55
+ # <% end %>
56
+ #
57
+ # The sample also supports several extra options:
58
+ #
59
+ # <% showcase.sample "Basic", id: "custom-id", description: "Please use this", events: "toggle:toggled", custom: "option" do %>
60
+ # <%# … %>
61
+ # <% end %>
62
+ #
63
+ # Here we set:
64
+ # - the `sample.id` with the HTML element `id` is overriden
65
+ # - the `sample.description`
66
+ # - the `sample.events` what JavaScript `events` to listen for on the element
67
+ # - any other custom options are available in `sample.details`.
68
+ def sample(name, **options, &block)
69
+ @samples << Showcase::Sample.new(@view_context, name, **options).tap { _1.collect(&block) }
70
+ end
71
+
72
+ # Yields an Options object to help define the configuration table for a Preview.
73
+ #
74
+ # <% showcase.options do |o| %>
75
+ # <% o.required :content, "Pass the inner content text that the button should display" %>
76
+ # <% o.optional :mode, "Pass an optional mode override", default: :small, options: %i[ small medium large ] %>
77
+ # <% o.optional :method, "What HTTP method to use", type: "String | Symbol", default: :post %>
78
+ # <% o.optional :reversed, "Whether the inner text should be reversed", default: false %> # type: "Boolean" is inferred from the default here.
79
+ # <% o.optional "**options", "Every other option is passed on as options to the inner `button_tag`", type: Hash %>
80
+ # <% end %>
81
+ #
82
+ # The `type:` is derived if a `default:` is passed, otherwise it's assumed to be a String.
83
+ #
84
+ # Showcase outputs the columns with this order [:name, :required, :type, :default, :description], any other passed column is
85
+ # automatically rendered after those.
86
+ def options
87
+ @options ||= Showcase::Options.new(@view_context).tap { yield _1 if block_given? }
88
+ end
89
+
90
+ def render_associated_partial
91
+ @view_context.render "#{Showcase.previews_path}/#{id}", showcase: self
92
+ nil
93
+ end
94
+ end