rails-storybook 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83b229f8189dd57281db3c891bb6b36b8a437777bdb964ea059a652c8c2c9aad
4
- data.tar.gz: 616420336b4acf5a60967d24498ebeeb004d31169ca7f5de85a309d4795c0ca2
3
+ metadata.gz: 458c8b46779f2ff4f95162603bbef83351fa665f74abb0ad05c964c001695807
4
+ data.tar.gz: aabbc888656b99c56c3d1bb337c8291d7dec9497ca0ed00724c01977f3bc1dbb
5
5
  SHA512:
6
- metadata.gz: 941d4806670ba38473617ecab1a385788da1d56de11267c9372d884c47bf6b45fd191d6b5d40816858f247b70242e1cb089a2bf1ac16da2633be49fbb8a92587
7
- data.tar.gz: 9cc2e89ded7fd27eec72f7b3127acdf854bc6de168e8ffbfe1409ea168ca2bb869702e016ae18e9752cd13657bf96ceb59b624f30cc0102563eb16d59463cb34
6
+ metadata.gz: fb49d7e4d163b9ce723dfaa28c9fa22d67c53279e5364ba86af01e895a3059f526af125f427e95c4ab5b18674beb7f1c654031981de62219e24ea759f97fd8df
7
+ data.tar.gz: e8892db80deae244450745ed86ca751731f9d62c2e51905ad12a80593c840fbdab1a55111a3ba92e63f5177fc0d5dbbc29e2dbb6d9814f3ca5e36a89becd301b
data/Gemfile.lock CHANGED
@@ -3,6 +3,8 @@ PATH
3
3
  specs:
4
4
  rails-storybook (0.1.0)
5
5
  rails (~> 7.0)
6
+ rails-previews (~> 0.1.0)
7
+ react_on_rails (~> 14.0)
6
8
  slim (~> 5.2)
7
9
 
8
10
  GEM
@@ -82,6 +84,8 @@ GEM
82
84
  minitest (>= 5.1)
83
85
  mutex_m
84
86
  tzinfo (~> 2.0)
87
+ addressable (2.8.7)
88
+ public_suffix (>= 2.0.2, < 7.0)
85
89
  ast (2.4.2)
86
90
  base64 (0.2.0)
87
91
  bigdecimal (3.1.8)
@@ -96,6 +100,7 @@ GEM
96
100
  diff-lcs (1.5.1)
97
101
  drb (2.2.1)
98
102
  erubi (1.13.0)
103
+ execjs (2.9.1)
99
104
  globalid (1.2.1)
100
105
  activesupport (>= 6.1)
101
106
  i18n (1.14.5)
@@ -140,6 +145,7 @@ GEM
140
145
  racc
141
146
  psych (5.1.2)
142
147
  stringio
148
+ public_suffix (6.0.1)
143
149
  racc (1.8.1)
144
150
  rack (3.1.7)
145
151
  rack-session (2.0.0)
@@ -170,6 +176,8 @@ GEM
170
176
  rails-html-sanitizer (1.6.0)
171
177
  loofah (~> 2.21)
172
178
  nokogiri (~> 1.14)
179
+ rails-previews (0.1.0)
180
+ slim (~> 5.2)
173
181
  railties (7.1.3.4)
174
182
  actionpack (= 7.1.3.4)
175
183
  activesupport (= 7.1.3.4)
@@ -182,6 +190,12 @@ GEM
182
190
  rake (13.2.1)
183
191
  rdoc (6.7.0)
184
192
  psych (>= 4.0.0)
193
+ react_on_rails (14.0.5)
194
+ addressable
195
+ connection_pool
196
+ execjs (~> 2.5)
197
+ rails (>= 5.2)
198
+ rainbow (~> 3.0)
185
199
  regexp_parser (2.9.2)
186
200
  reline (0.5.9)
187
201
  io-console (~> 0.5)
data/README.md CHANGED
@@ -21,33 +21,36 @@ rails g storybook:install
21
21
 
22
22
  Then, optionally:
23
23
  ```bash
24
- rails g storybook:example
24
+ rails g storybook:examples
25
25
  ```
26
26
 
27
27
  Restart your processes (stop and restart `./bin/dev`) and viola! Opens up a Storybook connected to your Rails server, and if you've also generated the example, will have a simple View Component showing up in Storybook.
28
28
 
29
29
  ## Usage
30
30
 
31
- Today, write a JSON to describe your View Component's "story":
32
- ```
33
- {
34
- "title": "ExampleComponent",
35
- "stories": [
36
- {
37
- "name": "default",
38
- "parameters": {
39
- "server": { "id": "example_component/default" }
40
- }
41
- }
42
- ]
43
- }
31
+ Write a preview for your component, just like normal - but include the StoryBook::Preview module. You can also use the `PartialPreviewComponent` to render regular Rails partials as previews.
32
+ ```ruby
33
+ class ExampleComponentPreview < ViewComponent::Preview
34
+ include Storybook::Preview
35
+ def default
36
+ render(ExampleComponent.new(title: "title"))
37
+ end
38
+
39
+ def default
40
+ render(PartialPreviewComponent.new(partial: "application/example"))
41
+ end
42
+ end
44
43
  ```
44
+ Note that the module will set the preview's layout to `storybook`, as there's steps to be done to make it look good (and work!) inside of Storybook.
45
+
46
+ Then run `rake storybook:stories` to generate the CSF JSON that Storybook uses to find your previews.
47
+
48
+ And... that's it! :D
45
49
 
46
- Tomorrow(tm), run a rake task to generate those stories for you.
47
50
 
48
51
  ## Development
49
52
 
50
- Inspired by [gem view_component-storybook](https://github.com/jonspalmer/view_component-storybook), but, I want to accomplish things in a different way (using the existing view component previews), to aim higher (handling view components, partials, *and* React components), and to aim specifically at integration with Chromatic.
53
+ Inspired by [gem view_component-storybook](https://github.com/jonspalmer/view_component-storybook), but, I want to accomplish things in a different way, to aim higher (handling ~~view components~~, ~~partials~~, *and* React components), and to aim specifically at integration with Chromatic.
51
54
 
52
55
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
53
56
 
@@ -0,0 +1,144 @@
1
+ require "rails/generators"
2
+
3
+ class Storybook::ExamplesGenerator < Rails::Generators::Base
4
+ def create_example_partial
5
+ create_file "app/views/application/_example.html.slim", <<~SLIM
6
+ h3 Example Partial
7
+ span= @title
8
+ SLIM
9
+ end
10
+
11
+ def create_example_partial_preview
12
+ create_file "spec/previews/example_partial.rb", <<~RUBY
13
+ # frozen_string_literal: true
14
+ module Previews
15
+ class ExamplePartial < Rails::Previews::Preview
16
+ def default
17
+ render_partial "application/example", locals: { title: "Hello, World!" }
18
+ end
19
+ end
20
+ end
21
+ RUBY
22
+ end
23
+
24
+ def install_view_components
25
+ insert_into_file "Gemfile", "gem \"view_component\""
26
+ system "bundle install"
27
+ end
28
+
29
+ def create_example_view_component
30
+ create_file "app/components/example_component.rb", <<~RUBY
31
+ # frozen_string_literal: true
32
+
33
+ class ExampleComponent < ViewComponent::Base
34
+ slim_template <<~SLIM
35
+ h3 Example Component
36
+ span= @title
37
+ SLIM
38
+
39
+ def initialize(title:)
40
+ @title = title
41
+ end
42
+ end
43
+ RUBY
44
+ end
45
+
46
+ def create_example_view_component_preview
47
+ create_file "spec/previews/example_view_component.rb", <<~RUBY
48
+ # frozen_string_literal: true
49
+
50
+ module Previews
51
+ class ExampleViewComponent < Rails::Previews::Preview
52
+ def default
53
+ ExampleComponent.new(title: "Hello, World!")
54
+ end
55
+
56
+ # TODO - This doesn't work with the current Previews implementation
57
+ # def with_content_block
58
+ # render(ExampleComponent.new(title: "This component accepts a block of content")) do
59
+ # tag.div do
60
+ # content_tag(:span, "Hello")
61
+ # end
62
+ # end
63
+ # end
64
+ end
65
+ end
66
+ RUBY
67
+ end
68
+
69
+ def install_react_on_rails
70
+ insert_into_file "Gemfile", "\ngem \"react_on_rails\""
71
+ system "bundle install"
72
+ end
73
+
74
+ def setup_application_bundle
75
+ # TODO: I have my pack in not the default location
76
+ end
77
+
78
+ def create_example_react_component
79
+ create_file "client/bundles/application/components/HelloWorld.jsx", <<~JSX
80
+ import PropTypes from 'prop-types';
81
+ import React, { useState } from 'react';
82
+ import * as style from './HelloWorld.module.css';
83
+
84
+ const HelloWorld = (props) => {
85
+ return (
86
+ <div>
87
+ <h3>Example React Component</h3>
88
+ <span>{props.name}</span>
89
+ </div>
90
+ );
91
+ };
92
+
93
+ HelloWorld.propTypes = {
94
+ name: PropTypes.string.isRequired, // this is passed from the Rails view
95
+ };
96
+
97
+ export default HelloWorld;
98
+ JSX
99
+
100
+ create_file "client/bundles/application/components/HelloWorld.module.css", <<~CSS
101
+ .bright {
102
+ color: green;
103
+ font-weight: bold;
104
+ }#{' '}
105
+ CSS
106
+
107
+ # TODO: Is this necessary?
108
+ create_file "client/bundles/application/components/HelloWorldServer.js", <<~JS
109
+ import HelloWorld from './HelloWorldServer';
110
+ export default HelloWorld;
111
+ JS
112
+
113
+ create_file "client/packs/application.js", <<~JS
114
+ import ReactOnRails from 'react-on-rails';
115
+ import HelloWorld from '../bundles/application/components/HelloWorld';
116
+ ReactOnRails.register({ HelloWorld });
117
+ JS
118
+
119
+ # TODO: Is this necessary?
120
+ create_file "client/packs/server-bundle.js", <<~JS
121
+ import ReactOnRails from 'react-on-rails';
122
+ import HelloWorld from '../bundles/application/components/HelloWorld';
123
+ ReactOnRails.register({ HelloWorld });
124
+ JS
125
+ end
126
+
127
+ def create_example_react_component_preview
128
+ create_file "spec/previews/example_react_component.rb", <<~RUBY
129
+ # frozen_string_literal: true
130
+
131
+ module Previews
132
+ class ExampleReactComponent < Rails::Previews::Preview
133
+ def default
134
+ render_react_on_rails "HelloWorld", props: { name: "Hello, World!" }
135
+ end
136
+ end
137
+ end
138
+ RUBY
139
+ end
140
+
141
+ def generate_stories
142
+ `rails storybook:stories`
143
+ end
144
+ end
@@ -2,6 +2,7 @@ require "rails/generators"
2
2
 
3
3
  class Storybook::InstallGenerator < Rails::Generators::Base
4
4
  def install_storybook
5
+ # TODO: Tell storybook not to install it's examples
5
6
  system "npx storybook@latest init --yes --dev --no-dev --builder webpack5"
6
7
  system "yarn add @storybook/server --dev"
7
8
  system "yarn add @storybook/server-webpack5 --dev"
@@ -10,7 +11,7 @@ class Storybook::InstallGenerator < Rails::Generators::Base
10
11
  end
11
12
 
12
13
  def install_rack_cors
13
- insert_into_file "Gemfile", " gem 'rack-cors'\n", after: "group :development do\n"
14
+ insert_into_file "Gemfile", " gem \"rack-cors\"\n", after: "group :development do\n"
14
15
  system "bundle install"
15
16
  create_file "config/initializers/cors.rb", <<~RUBY
16
17
  Rails.application.config.middleware.insert_before 0, Rack::Cors do
@@ -22,36 +23,31 @@ class Storybook::InstallGenerator < Rails::Generators::Base
22
23
  RUBY
23
24
  end
24
25
 
25
- def create_storybook_layout_slim
26
- create_file "app/views/layouts/storybook.html.slim", <<~SLIM
27
- doctype html
28
- html lang='en'
29
- head
30
- title Trainyard
31
- meta charset="UTF-8"
32
- meta[name="viewport" content="width=device-width,initial-scale=1"]
33
- = csrf_meta_tags
34
- = csp_meta_tag
35
- = stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload"
36
- = stylesheet_link_tag "application"
37
- = javascript_pack_tag "application"
38
- body
39
- div
40
- main.ml-64.p-8
41
- == yield
42
- SLIM
43
- end
44
-
45
26
  def update_storybook
46
27
  # Main.js
47
28
  insert_into_file ".storybook/main.js", "\n \"@storybook/server\",", after: "addons: ["
48
- gsub_file ".storybook/main.js", "*.stories.@(js|jsx|mjs|ts|tsx)", "*.stories.@(js|jsx|mjs|ts|tsx|json)"
29
+ gsub_file ".storybook/main.js", "*.stories.@(js|jsx|mjs|ts|tsx)", "*.stories.json"
49
30
  gsub_file ".storybook/main.js", "@storybook/react-webpack5", "@storybook/server-webpack5"
50
31
 
51
32
  # Preview.js
52
- base_url = "http://localhost:3000/rails/view_components"
33
+ # TODO: Server & port
34
+ base_url = "http://localhost:3000/previews"
35
+
36
+ # Preferred method to get the styling loaded in:
37
+ # insert_into_file ".storybook/preview.js", "\nimport '../public/assets/tailwind-0c2ceb08e52f57602c2ff891790dee8451074b84335e77f107abdb57f99a2c37.css'", before: "export default preview;"
38
+ # insert_into_file ".storybook/preview.js", "\nimport '../public/assets/application-9f334b542cffee1084a19870f2b1f16b1ef66ff68bfa765286993d260bc9556a.css'", before: "export default preview;"
39
+
53
40
  insert_into_file ".storybook/preview.js", "\n server: { url: \"#{base_url}\", },", after: "parameters: {"
54
41
 
55
42
  # insert_into_file ".storybook/main.js", "@storybook/addon-controls", after: "addons: ["
43
+
44
+ # Stylesheets so Storybook can find them
45
+ # TODO: TailwindCSS / JS packs name, etc
46
+ # TODO: Server & port
47
+ create_file ".storybook/.preview-head.html", <<~HTML
48
+ <link rel="stylesheet" href="http://localhost:3000/assets/tailwind.css" data-turbo-track="reload">
49
+ <link rel="stylesheet" href="http://localhost:3000/assets/inter-font.css" data-turbo-track="reload">
50
+ <link rel="stylesheet" href="http://localhost:3000/assets/application.css" data-turbo-track="reload">
51
+ HTML
56
52
  end
57
53
  end
@@ -0,0 +1,2 @@
1
+ require_relative "../storybook.rb"
2
+ # TODO: Fix the gem naming, etc
@@ -0,0 +1,17 @@
1
+
2
+ module Rails::Previews
3
+ # Re-open the class to add the Storybook methods
4
+ class Preview
5
+ class << self
6
+ def to_csf
7
+ { title: preview_name, stories: stories }
8
+ end
9
+
10
+ def stories
11
+ examples.collect do |name|
12
+ { name:, parameters: { server: { id: "#{preview_name}/#{name}" } } }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ require "storybook"
2
+ require "rails"
3
+
4
+ # https://gist.github.com/ntamvl/7a6658b4cd82d6fbd15434f0a9953411
5
+ module Storybook
6
+ class Railtie < Rails::Railtie
7
+ railtie_name :storybook
8
+
9
+ rake_tasks do
10
+ path = File.expand_path(__dir__)
11
+ Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ namespace :storybook do
2
+ desc "Write CSF JSON stories for all Stories"
3
+ task stories: :environment do
4
+ stories_dir = "stories"
5
+ Rails::Previews::Preview.all.map do |preview|
6
+ filename = Rails.root.join("#{stories_dir}/#{preview.preview_name}.stories.json")
7
+ stories_json = JSON.pretty_generate(preview.to_csf)
8
+ File.open(filename, "w") { |f| f.write(stories_json) }
9
+ end
10
+ end
11
+ end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Storybook
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
data/lib/storybook.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require "storybook/version"
2
+ require "storybook/preview"
3
+ require "storybook/railtie" if defined?(Rails::Railtie)
2
4
 
3
- module Storybook
4
- class Error < StandardError; end
5
- # Your code goes here...
6
- end
5
+ module Storybook; end
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_dependency "rails", "~> 7.0"
28
28
  spec.add_dependency "slim", "~> 5.2"
29
+ spec.add_dependency "rails-previews", "~> 0.1.0"
29
30
  spec.add_development_dependency "rails", "~> 7.0"
30
31
 
31
32
  spec.add_development_dependency "bundler", "~> 2.5"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-storybook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicholas Barone
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-08 00:00:00.000000000 Z
11
+ date: 2024-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '5.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rails-previews
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rails
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -157,9 +171,13 @@ files:
157
171
  - Rakefile
158
172
  - bin/console
159
173
  - bin/setup
160
- - lib/generators/storybook/example_generator.rb
174
+ - lib/generators/storybook/examples_generator.rb
161
175
  - lib/generators/storybook/install_generator.rb
176
+ - lib/rails/storybook.rb
162
177
  - lib/storybook.rb
178
+ - lib/storybook/preview.rb
179
+ - lib/storybook/railtie.rb
180
+ - lib/storybook/tasks/stories.rake
163
181
  - lib/storybook/version.rb
164
182
  - rails-storybook.gemspec
165
183
  homepage: https://github.com/rangerscience/rails-storybook
@@ -1,62 +0,0 @@
1
- require "rails/generators"
2
-
3
- class Storybook::ExampleGenerator < Rails::Generators::Base
4
- def install_view_components
5
- insert_into_file "Gemfile", "gem 'view_component'"
6
- system "bundle install"
7
- end
8
-
9
- def create_example_component
10
- create_file "app/components/example_component.rb", <<~RUBY
11
- # frozen_string_literal: true
12
-
13
- class ExampleComponent < ViewComponent::Base
14
- slim_template <<~SLIM
15
- span
16
- = @title
17
- SLIM
18
-
19
- def initialize(title:)
20
- @title = title
21
- end
22
- end
23
- RUBY
24
- end
25
-
26
- def create_example_component_preview
27
- create_file "test/components/previews/example_component_preview.rb", <<~RUBY
28
- # frozen_string_literal: true
29
-
30
- class ExampleComponentPreview < ViewComponent::Preview
31
- layout "storybook"
32
- def default
33
- render(ExampleComponent.new(title: "title"))
34
- end
35
-
36
- def with_content_block
37
- render(ExampleComponent.new(title: "This component accepts a block of content")) do
38
- tag.div do
39
- content_tag(:span, "Hello")
40
- end
41
- end
42
- end
43
- end
44
- RUBY
45
- end
46
-
47
- def create_example_story
48
- create_file "stories/example_component.stories.json", <<~JSON
49
- {
50
- "title": "ExampleComponent",
51
- "stories": [
52
- {
53
- "name": "default",
54
- "parameters": {
55
- "server": { "id": "example_component/default" }
56
- }
57
- }
58
- ]
59
- }
60
- JSON
61
- end
62
- end