view_component_storybook 0.6.0 → 0.10.1
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.
- checksums.yaml +4 -4
- data/README.md +7 -128
- data/app/controllers/view_component/storybook/stories_controller.rb +10 -11
- data/app/views/view_component/storybook/stories/show.html.erb +8 -1
- data/config/locales/en.yml +32 -0
- data/lib/view_component/storybook.rb +14 -0
- data/lib/view_component/storybook/content_concern.rb +42 -0
- data/lib/view_component/storybook/controls.rb +5 -1
- data/lib/view_component/storybook/controls/base_options_config.rb +41 -0
- data/lib/view_component/storybook/controls/boolean_config.rb +7 -6
- data/lib/view_component/storybook/controls/color_config.rb +4 -6
- data/lib/view_component/storybook/controls/control_config.rb +25 -25
- data/lib/view_component/storybook/controls/controls_helpers.rb +76 -0
- data/lib/view_component/storybook/controls/custom_config.rb +52 -0
- data/lib/view_component/storybook/controls/date_config.rb +14 -13
- data/lib/view_component/storybook/controls/multi_options_config.rb +46 -0
- data/lib/view_component/storybook/controls/number_config.rb +13 -10
- data/lib/view_component/storybook/controls/object_config.rb +13 -7
- data/lib/view_component/storybook/controls/options_config.rb +17 -33
- data/lib/view_component/storybook/controls/simple_control_config.rb +48 -0
- data/lib/view_component/storybook/controls/text_config.rb +1 -3
- data/lib/view_component/storybook/dsl.rb +1 -2
- data/lib/view_component/storybook/dsl/{controls_dsl.rb → legacy_controls_dsl.rb} +19 -22
- data/lib/view_component/storybook/engine.rb +2 -1
- data/lib/view_component/storybook/method_args.rb +16 -0
- data/lib/view_component/storybook/method_args/control_method_args.rb +91 -0
- data/lib/view_component/storybook/method_args/method_args.rb +52 -0
- data/lib/view_component/storybook/method_args/method_parameters_names.rb +97 -0
- data/lib/view_component/storybook/slots.rb +14 -0
- data/lib/view_component/storybook/slots/slot.rb +24 -0
- data/lib/view_component/storybook/slots/slot_config.rb +44 -0
- data/lib/view_component/storybook/stories.rb +60 -14
- data/lib/view_component/storybook/story.rb +18 -0
- data/lib/view_component/storybook/story_config.rb +140 -15
- data/lib/view_component/storybook/tasks/write_stories_json.rake +6 -0
- data/lib/view_component/storybook/version.rb +1 -1
- metadata +64 -23
- data/lib/view_component/storybook/controls/array_config.rb +0 -36
- data/lib/view_component/storybook/dsl/story_dsl.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6ef1bcb6cf8fd3beccec9242854aa913bd31fe1c7c44c44cdde6b59be8fd67f
|
4
|
+
data.tar.gz: de047bb6e4e453db106270ba7f28b4d252fed881816266e10b99bb8c2d4b93f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d96299b59366d1f50d034399299209a7edc01aa99f3ff728b0e6ed1721b1f80679aa8f7bbb953be549baa59fd74d090eb8d5b7e615bdc7b26164ebb0f011373
|
7
|
+
data.tar.gz: d97204b485ac6d1b61c7848e6c2b68cec798328eef7e78738f3f675daa805dc6db73a0e6d1e6e7f17373de4b5ca90cfe000716bb4b25f29f8ae77d9985f0580e
|
data/README.md
CHANGED
@@ -1,142 +1,21 @@
|
|
1
1
|
# ViewComponent::Storybook
|
2
2
|
|
3
|
-
The ViewComponent::Storybook gem provides Ruby api for writing stories describing [View Components](https://github.com/github/view_component) and allowing them to be previewed and tested in [Storybook](https://github.com/storybookjs/storybook/)
|
3
|
+
The ViewComponent::Storybook gem provides Ruby api for writing stories describing [View Components](https://github.com/github/view_component) and allowing them to be previewed and tested in [Storybook](https://github.com/storybookjs/storybook/) via its [Server](https://github.com/storybookjs/storybook/tree/next/app/server) support.
|
4
4
|
|
5
5
|
## Features
|
6
|
-
* A Ruby DSL for writing Stories describing View Components
|
7
|
-
* A Rails controller backend for Storybook Server compatible with Strobook Controls Addon parameters
|
8
|
-
* Coming Soon: Rake tasks to watch View Components and Stories and trigger Storybook hot reloading
|
9
6
|
|
10
|
-
|
7
|
+
- A Ruby DSL for writing Stories describing View Components
|
8
|
+
- A Rails controller backend for Storybook Server compatible with Storybook Controls Addon parameters
|
9
|
+
- Coming Soon: Rake tasks to watch View Components and Stories and trigger Storybook hot reloading
|
11
10
|
|
12
|
-
|
11
|
+
## Documentation
|
13
12
|
|
14
|
-
|
15
|
-
2. Run `bundle install`.
|
16
|
-
3. Add `require "view_component/storybook/engine"` to `config/application.rb`
|
17
|
-
4. Add `**/*.stories.json` to `.gitignore`
|
18
|
-
|
19
|
-
### Storybook Installation
|
20
|
-
|
21
|
-
1. Add Storybook server as a dev dependedncy. The Storybook Controls addon isn't needed but is strongly recommended
|
22
|
-
```sh
|
23
|
-
yarn add @storybook/server @storybook/addon-controls --dev
|
24
|
-
```
|
25
|
-
2. Add an NPM script to your package.json in order to start the storybook later in this guide
|
26
|
-
```json
|
27
|
-
{
|
28
|
-
"scripts": {
|
29
|
-
"storybook": "start-storybook"
|
30
|
-
}
|
31
|
-
}
|
32
|
-
```
|
33
|
-
3. Create the .storybook/main.js file to configure Storybook to find the json stories the gem creates. Also configure the Controls addon:
|
34
|
-
```javascript
|
35
|
-
module.exports = {
|
36
|
-
stories: ['../test/components/**/*.stories.json'],
|
37
|
-
addons: [
|
38
|
-
'@storybook/addon-controls',
|
39
|
-
],
|
40
|
-
};
|
41
|
-
```
|
42
|
-
4. Create the .storybook/preview.js file to configure Storybook with the Rails application url to call for the html content of the stories
|
43
|
-
```javascript
|
44
|
-
|
45
|
-
export const parameters = {
|
46
|
-
server: {
|
47
|
-
url: `http://localhost:3000/rails/stories`,
|
48
|
-
},
|
49
|
-
};
|
50
|
-
```
|
51
|
-
|
52
|
-
|
53
|
-
Note: `@storybook/server` will be part of the upcoming Storybook 6.0 release. Until that is released you'll need to use an [rc release](https://github.com/storybookjs/storybook/releases/tag/v6.0.0-rc.14)
|
54
|
-
|
55
|
-
## Usage
|
56
|
-
|
57
|
-
### Writing Stories
|
58
|
-
|
59
|
-
`ViewComponent::Storybook::Stories` provides a way to preview components in Storybook.
|
60
|
-
|
61
|
-
Suppose our app has a `ButtonComponent` that takes a `button_text` parameter:
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
class ButtonComponent < ViewComponent::Base
|
65
|
-
def initialize(button_text:)
|
66
|
-
@button_text = button_text
|
67
|
-
end
|
68
|
-
end
|
69
|
-
```
|
70
|
-
|
71
|
-
We can write a stories desecibing the `ButtonComponent`
|
72
|
-
|
73
|
-
```ruby
|
74
|
-
class ButtonComponentStories < ViewComponent::Storybook::Stories
|
75
|
-
story(:with_short_text) do
|
76
|
-
controls do
|
77
|
-
text(:button_text, 'OK')
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
story(:with_long_text) do
|
82
|
-
controls do
|
83
|
-
text(:button_text, 'Push Me Please!')
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
```
|
88
|
-
|
89
|
-
### Generating Storybook Stories JSON
|
90
|
-
|
91
|
-
Generate the Storybook JSON stories by tunning the rake task:
|
92
|
-
```sh
|
93
|
-
rake view_component_storybook:write_stories_json
|
94
|
-
```
|
95
|
-
|
96
|
-
### Start the Rails app and Storybook
|
97
|
-
|
98
|
-
In separate shells start the Rails app and Storybook
|
99
|
-
|
100
|
-
```sh
|
101
|
-
rails s
|
102
|
-
```
|
103
|
-
```sh
|
104
|
-
yarn storybook
|
105
|
-
```
|
106
|
-
|
107
|
-
Alternatively you can use tools like [Foreman](https://github.com/ddollar/foreman) to start both Rails and Storybook with one command.
|
108
|
-
|
109
|
-
### Configuration
|
110
|
-
|
111
|
-
By Default ViewComponent::Storybook expects to find stories in the folder `test/components/stories`. This can be configured but setting `stories_path` in `config/applicaion.rb`. For example is you're using RSpec you might set the following configuration:
|
112
|
-
|
113
|
-
```ruby
|
114
|
-
config.view_component_storybook.stories_path = Rails.root.join("spec/components/stories")
|
115
|
-
```
|
116
|
-
|
117
|
-
### The Story DSL
|
118
|
-
|
119
|
-
Coming Soon
|
120
|
-
|
121
|
-
#### Parameters
|
122
|
-
#### Layout
|
123
|
-
#### Controls
|
124
|
-
|
125
|
-
|
126
|
-
## Development
|
127
|
-
|
128
|
-
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.
|
129
|
-
|
130
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
13
|
+
See [jonspalmer.github.io/view_component_storybook](https://jonspalmer.github.io/view_component_storybook) for documentation.
|
131
14
|
|
132
15
|
## Contributing
|
133
16
|
|
134
|
-
|
17
|
+
This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. We recommend reading the [contributing guide](./docs/CONTRIBUTING.md) as well.
|
135
18
|
|
136
19
|
## License
|
137
20
|
|
138
21
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
139
|
-
|
140
|
-
## Code of Conduct
|
141
|
-
|
142
|
-
Everyone interacting in the ViewComponent::Storybook project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/jonspalmer/view_component_storybook/blob/master/CODE_OF_CONDUCT.md).
|
@@ -8,19 +8,18 @@ module ViewComponent
|
|
8
8
|
prepend_view_path File.expand_path("../../../views", __dir__)
|
9
9
|
prepend_view_path Rails.root.join("app/views") if defined?(Rails.root)
|
10
10
|
|
11
|
-
before_action :
|
11
|
+
before_action :find_story_configs, :find_story_config, only: :show
|
12
12
|
before_action :require_local!, unless: :show_stories?
|
13
13
|
|
14
14
|
content_security_policy(false) if respond_to?(:content_security_policy)
|
15
15
|
|
16
16
|
def show
|
17
|
-
|
17
|
+
params_hash = params.permit!.to_h
|
18
18
|
|
19
|
-
@
|
19
|
+
@story = @story_config.story(params_hash)
|
20
20
|
|
21
|
-
|
21
|
+
layout = @story_config.layout
|
22
22
|
|
23
|
-
layout = @story.layout
|
24
23
|
render layout: layout unless layout.nil?
|
25
24
|
end
|
26
25
|
|
@@ -30,17 +29,17 @@ module ViewComponent
|
|
30
29
|
ViewComponent::Storybook.show_stories
|
31
30
|
end
|
32
31
|
|
33
|
-
def
|
32
|
+
def find_story_configs
|
34
33
|
stories_name = params[:stories]
|
35
|
-
@
|
34
|
+
@story_configs = Stories.find_story_configs(stories_name)
|
36
35
|
|
37
|
-
head :not_found unless @
|
36
|
+
head :not_found unless @story_configs
|
38
37
|
end
|
39
38
|
|
40
|
-
def
|
39
|
+
def find_story_config
|
41
40
|
story_name = params[:story]
|
42
|
-
@
|
43
|
-
head :not_found unless @
|
41
|
+
@story_config = @story_configs.find_story_config(story_name)
|
42
|
+
head :not_found unless @story_config
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
@@ -1 +1,8 @@
|
|
1
|
-
<%= render(@component
|
1
|
+
<%= render(@story.component) do |c| -%>
|
2
|
+
<% @story.slots.each do |slot| -%>
|
3
|
+
<%- slot.call do -%>
|
4
|
+
<%= instance_eval(&slot.content_block) if slot.content_block -%>
|
5
|
+
<%- end -%>
|
6
|
+
<%- end -%>
|
7
|
+
<%- instance_eval(&@story.content_block) if @story.content_block -%>
|
8
|
+
<%- end -%>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
en:
|
2
|
+
activemodel:
|
3
|
+
errors:
|
4
|
+
models:
|
5
|
+
view_component/storybook/method_args/method_args:
|
6
|
+
attributes:
|
7
|
+
args:
|
8
|
+
too_few: expected at least %{min} but found %{count}
|
9
|
+
too_many: expected no more than %{max} but found %{count}
|
10
|
+
kwargs:
|
11
|
+
invalid_arg: "'%{kwarg}' is invalid"
|
12
|
+
invalid: expected keys [%{expected_keys}] but found [%{actual_keys}]
|
13
|
+
view_component/storybook/method_args/control_method_args:
|
14
|
+
attributes:
|
15
|
+
controls:
|
16
|
+
invalid_control: "'%{control_name}' is invalid: (%{control_errors})"
|
17
|
+
view_component/storybook/stories:
|
18
|
+
attributes:
|
19
|
+
story_configs:
|
20
|
+
invalid_story: "'%{story_name}' is invalid: (%{story_errors})"
|
21
|
+
duplicate_stories:
|
22
|
+
one: duplicate story name %{duplicate_names}
|
23
|
+
other: duplicate story names %{duplicate_names}
|
24
|
+
view_component/storybook/story_config:
|
25
|
+
attributes:
|
26
|
+
constructor_args:
|
27
|
+
invalid: "invalid: (%{errors})"
|
28
|
+
view_component/storybook/controls/custom_config:
|
29
|
+
attributes:
|
30
|
+
value_method_args:
|
31
|
+
invalid: "invalid: (%{errors})"
|
32
|
+
|
@@ -10,6 +10,10 @@ module ViewComponent
|
|
10
10
|
autoload :Controls
|
11
11
|
autoload :Stories
|
12
12
|
autoload :StoryConfig
|
13
|
+
autoload :Story
|
14
|
+
autoload :Slots
|
15
|
+
autoload :ContentConcern
|
16
|
+
autoload :MethodArgs
|
13
17
|
autoload :Dsl
|
14
18
|
|
15
19
|
include ActiveSupport::Configurable
|
@@ -27,6 +31,16 @@ module ViewComponent
|
|
27
31
|
#
|
28
32
|
mattr_accessor :show_stories, instance_writer: false
|
29
33
|
|
34
|
+
# Set the entry route for component stories:
|
35
|
+
#
|
36
|
+
# config.view_component_storybook.stories_route = "/stories"
|
37
|
+
#
|
38
|
+
# Defaults to `/rails/stories` when `show_stories` is enabled.
|
39
|
+
#
|
40
|
+
mattr_accessor :stories_route, instance_writer: false do
|
41
|
+
"/rails/stories"
|
42
|
+
end
|
43
|
+
|
30
44
|
ActiveSupport.run_load_hooks(:view_component_storybook, self)
|
31
45
|
end
|
32
46
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module ContentConcern
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
attr_reader :content_control, :content_block
|
10
|
+
end
|
11
|
+
|
12
|
+
def content(content = nil, &block)
|
13
|
+
case content
|
14
|
+
when Storybook::Controls::ControlConfig
|
15
|
+
@content_control = content.param(content_param)
|
16
|
+
@content_block = nil
|
17
|
+
when String
|
18
|
+
@content_control = nil
|
19
|
+
@content_block = proc { content }
|
20
|
+
else
|
21
|
+
@content_control = nil
|
22
|
+
@content_block = block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve_content_block(params)
|
27
|
+
if content_control
|
28
|
+
content = content_control.value_from_params(params)
|
29
|
+
proc { content }
|
30
|
+
else
|
31
|
+
content_block
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def content_param
|
38
|
+
:content
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -8,14 +8,18 @@ module ViewComponent
|
|
8
8
|
extend ActiveSupport::Autoload
|
9
9
|
|
10
10
|
autoload :ControlConfig
|
11
|
+
autoload :SimpleControlConfig
|
11
12
|
autoload :TextConfig
|
12
13
|
autoload :BooleanConfig
|
13
14
|
autoload :ColorConfig
|
14
15
|
autoload :NumberConfig
|
16
|
+
autoload :BaseOptionsConfig
|
15
17
|
autoload :OptionsConfig
|
16
|
-
autoload :
|
18
|
+
autoload :MultiOptionsConfig
|
17
19
|
autoload :DateConfig
|
18
20
|
autoload :ObjectConfig
|
21
|
+
autoload :CustomConfig
|
22
|
+
autoload :ControlsHelpers
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module Controls
|
6
|
+
class BaseOptionsConfig < SimpleControlConfig
|
7
|
+
attr_reader :type, :options, :labels
|
8
|
+
|
9
|
+
validates :type, :options, presence: true
|
10
|
+
|
11
|
+
def initialize(type, options, default_value, labels: nil, param: nil, name: nil)
|
12
|
+
super(default_value, param: param, name: name)
|
13
|
+
@type = type
|
14
|
+
@options = options
|
15
|
+
@labels = labels
|
16
|
+
normalize_options
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_csf_params
|
20
|
+
super.deep_merge(argTypes: { param => { options: options } })
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def csf_control_params
|
26
|
+
labels.nil? ? super : super.merge(labels: labels)
|
27
|
+
end
|
28
|
+
|
29
|
+
def normalize_options
|
30
|
+
return unless options.is_a?(Hash)
|
31
|
+
|
32
|
+
warning = "Hash options is deprecated and will be removed in v1.0.0. Use array options and `labels` instead."
|
33
|
+
ActiveSupport::Deprecation.warn(warning)
|
34
|
+
|
35
|
+
@labels = options.invert
|
36
|
+
@options = options.values
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -3,25 +3,26 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class BooleanConfig <
|
6
|
+
class BooleanConfig < SimpleControlConfig
|
7
7
|
BOOLEAN_VALUES = [true, false].freeze
|
8
8
|
|
9
|
-
validates :
|
9
|
+
validates :default_value, inclusion: { in: BOOLEAN_VALUES }, unless: -> { default_value.nil? }
|
10
10
|
|
11
11
|
def type
|
12
12
|
:boolean
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
15
|
+
def value_from_params(params)
|
16
|
+
params_value = super(params)
|
17
|
+
if params_value.is_a?(String) && params_value.present?
|
18
|
+
case params_value
|
18
19
|
when "true"
|
19
20
|
true
|
20
21
|
when "false"
|
21
22
|
false
|
22
23
|
end
|
23
24
|
else
|
24
|
-
|
25
|
+
params_value
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
@@ -3,12 +3,11 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class ColorConfig <
|
6
|
+
class ColorConfig < SimpleControlConfig
|
7
7
|
attr_reader :preset_colors
|
8
|
-
validates :value, presence: true
|
9
8
|
|
10
|
-
def initialize(
|
11
|
-
super(
|
9
|
+
def initialize(default_value, preset_colors: nil, param: nil, name: nil)
|
10
|
+
super(default_value, param: param, name: name)
|
12
11
|
@preset_colors = preset_colors
|
13
12
|
end
|
14
13
|
|
@@ -19,8 +18,7 @@ module ViewComponent
|
|
19
18
|
private
|
20
19
|
|
21
20
|
def csf_control_params
|
22
|
-
|
23
|
-
params.merge(presetColors: preset_colors).compact
|
21
|
+
super.merge(presetColors: preset_colors).compact
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|