lookbook 1.0.0.beta.0 → 1.0.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +231 -9
  3. data/app/assets/lookbook/js/stores/inspector.js +4 -4
  4. data/app/components/lookbook/{component.rb → base_component.rb} +1 -1
  5. data/app/components/lookbook/button/component.rb +1 -1
  6. data/app/components/lookbook/button_group/component.rb +1 -1
  7. data/app/components/lookbook/code/component.rb +1 -1
  8. data/app/components/lookbook/copy_button/component.html.erb +1 -1
  9. data/app/components/lookbook/copy_button/component.rb +1 -1
  10. data/app/components/lookbook/dimensions_display/component.html.erb +2 -1
  11. data/app/components/lookbook/dimensions_display/component.js +19 -12
  12. data/app/components/lookbook/dimensions_display/component.rb +1 -1
  13. data/app/components/lookbook/embed/component.html.erb +6 -5
  14. data/app/components/lookbook/embed/component.rb +1 -1
  15. data/app/components/lookbook/filter/component.html.erb +1 -1
  16. data/app/components/lookbook/filter/component.rb +1 -1
  17. data/app/components/lookbook/header/component.html.erb +7 -12
  18. data/app/components/lookbook/header/component.rb +1 -1
  19. data/app/components/lookbook/icon/component.rb +1 -1
  20. data/app/components/lookbook/nav/component.rb +1 -1
  21. data/app/components/lookbook/nav/item/component.html.erb +2 -2
  22. data/app/components/lookbook/nav/item/component.rb +1 -1
  23. data/app/components/lookbook/page_tabs/component.html.erb +18 -0
  24. data/app/components/lookbook/page_tabs/component.rb +19 -0
  25. data/app/components/lookbook/params_editor/component.rb +1 -1
  26. data/app/components/lookbook/params_editor/field/component.rb +1 -1
  27. data/app/components/lookbook/prose/component.rb +1 -1
  28. data/app/components/lookbook/split_layout/component.rb +1 -1
  29. data/app/components/lookbook/tab_panels/component.html.erb +5 -0
  30. data/app/components/lookbook/tab_panels/component.js +25 -0
  31. data/app/components/lookbook/tab_panels/component.rb +20 -0
  32. data/app/components/lookbook/{tabbed_content/section → tab_panels/panel}/component.html.erb +2 -2
  33. data/app/components/lookbook/tab_panels/panel/component.rb +9 -0
  34. data/app/components/lookbook/tabs/component.html.erb +8 -2
  35. data/app/components/lookbook/tabs/component.js +14 -6
  36. data/app/components/lookbook/tabs/component.rb +9 -11
  37. data/app/components/lookbook/tabs/dropdown_tab/component.html.erb +8 -2
  38. data/app/components/lookbook/tabs/dropdown_tab/component.rb +5 -4
  39. data/app/components/lookbook/tabs/tab/component.html.erb +9 -3
  40. data/app/components/lookbook/tabs/tab/component.rb +5 -4
  41. data/app/components/lookbook/toolbar/component.css +1 -1
  42. data/app/components/lookbook/toolbar/component.rb +1 -1
  43. data/app/components/lookbook/viewport/component.rb +1 -1
  44. data/app/controllers/lookbook/application_controller.rb +2 -2
  45. data/app/controllers/lookbook/pages_controller.rb +2 -1
  46. data/app/controllers/lookbook/previews_controller.rb +90 -91
  47. data/app/helpers/lookbook/application_helper.rb +8 -2
  48. data/app/helpers/lookbook/component_helper.rb +4 -0
  49. data/app/helpers/lookbook/page_helper.rb +2 -2
  50. data/app/views/layouts/lookbook/application.html.erb +1 -1
  51. data/app/views/layouts/lookbook/page.html.erb +2 -2
  52. data/app/views/layouts/lookbook/shell.html.erb +1 -1
  53. data/app/views/layouts/lookbook/skeleton.html.erb +7 -1
  54. data/app/views/lookbook/404.html.erb +1 -1
  55. data/app/views/lookbook/index.html.erb +1 -1
  56. data/app/views/lookbook/pages/show.html.erb +15 -5
  57. data/app/views/lookbook/preview.html.erb +3 -3
  58. data/app/views/lookbook/previews/panels/_content.html.erb +13 -0
  59. data/app/views/lookbook/previews/panels/_notes.html.erb +5 -5
  60. data/app/views/lookbook/previews/panels/_output.html.erb +3 -3
  61. data/app/views/lookbook/previews/panels/_params.html.erb +2 -2
  62. data/app/views/lookbook/previews/panels/_preview.html.erb +2 -2
  63. data/app/views/lookbook/previews/panels/_source.html.erb +6 -6
  64. data/app/views/lookbook/previews/show.html.erb +39 -36
  65. data/config/routes.rb +6 -6
  66. data/lib/lookbook/collection.rb +1 -1
  67. data/lib/lookbook/component.rb +31 -0
  68. data/lib/lookbook/config.rb +133 -33
  69. data/lib/lookbook/engine.rb +72 -12
  70. data/lib/lookbook/page.rb +34 -11
  71. data/lib/lookbook/page_section.rb +31 -0
  72. data/lib/lookbook/parser.rb +1 -4
  73. data/lib/lookbook/preview.rb +25 -8
  74. data/lib/lookbook/preview_example.rb +2 -2
  75. data/lib/lookbook/preview_group.rb +1 -1
  76. data/lib/lookbook/source_inspector.rb +10 -0
  77. data/lib/lookbook/store.rb +36 -0
  78. data/lib/lookbook/theme.rb +7 -0
  79. data/lib/lookbook/utils.rb +3 -3
  80. data/lib/lookbook/version.rb +1 -1
  81. data/lib/lookbook.rb +3 -12
  82. data/public/lookbook-assets/css/lookbook.css +34 -5
  83. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  84. data/public/lookbook-assets/js/lookbook.js +84 -71
  85. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  86. metadata +14 -8
  87. data/app/components/lookbook/tabbed_content/component.html.erb +0 -5
  88. data/app/components/lookbook/tabbed_content/component.js +0 -21
  89. data/app/components/lookbook/tabbed_content/component.rb +0 -20
  90. data/app/components/lookbook/tabbed_content/section/component.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aeef273a433c57159752664a6897e4fb17e1836fa7581db64446ee1674cbcd72
4
- data.tar.gz: 74411f7b3b81d3a442772d1c1dd2ba46f3af684248f96aafd445014278b73b2e
3
+ metadata.gz: 6ad3d5561ec7db31b1681dfb07bd3c4233baf75ab4865ad58de9c5bd48ae327e
4
+ data.tar.gz: 52e1363d495943316286f41d564ef19d29f2ac525b10988079c0cbb57db7d88e
5
5
  SHA512:
6
- metadata.gz: b722bd45d02ce7588a1babfe7b6920c30b42a6c7f4517da03c9faaec4777766fff6eee11c9280758a294b30340a2e9526ed4f35f5459f54eb675a427fff8f943
7
- data.tar.gz: 17997ac9bfebed9c4f56999dbdc8ddbc13b9a47acab70137113b1cdf12d69fff3c40c466cb5412eed2878c7bd99363cdcafea3718af2c28f59afce161d34c3db
6
+ metadata.gz: c726d88df050f17317a9e9ec849ddf47c6650d244ae0e11b4627365d283f3a8acf10c15fa6d930ec6e48d64954b84f559ec984f5fb8981e5c37ac4d256029b02
7
+ data.tar.gz: ea985b9135c8c7f1422edc2aa20122685947d786737f6532842c677a11d9afc40a9d08f3f3db04cdb0d7051dc8194d62c0dad21faa5e9870931f0fe0ba2bf2a4
data/README.md CHANGED
@@ -11,13 +11,18 @@ The main goals of the v1.0 release are:
11
11
  - [x] Rebuild app UI using ViewComponent components
12
12
  - [x] Improve usability of the small screen/mobile layout
13
13
  - [x] Add support for some limited UI color theme customisation
14
+ - [x] Add support for custom inspector panels
14
15
  - [x] Remove the `experimental` flag from the [Pages](https://github.com/allmarkedup/lookbook#pages)
15
16
  - [x] Improve the development/debugging setup, and allow previewing Lookbook's own components in Lookbook :-)
16
17
  - [ ] Improve the test setup and test coverage, switch to RSpec **[in progress]**
17
18
 
18
19
  **No breaking changes** are planned for user-facing features, although the app UI will include some minor visual updates and usability improvements.
19
20
 
20
- ![Lookbook UI](.github/assets/lookbook_screenshot_v1.0_beta.png)
21
+ ## Demo app
22
+
23
+ There is a demo of the current v1.0-beta here: https://lookbook-demo-app-v1-0-beta.herokuapp.com/lookbook/
24
+
25
+ [![Lookbook UI](.github/assets/lookbook_screenshot_v1.0_beta.png)](https://lookbook-demo-app-v1-0-beta.herokuapp.com/lookbook/)
21
26
 
22
27
  ## 👋 Testing and feedback - help wanted!
23
28
 
@@ -25,21 +30,21 @@ The bulk of the v1.0 'new feature' development work is now mostly complete, alth
25
30
 
26
31
  **If you are an existing Lookbook user** I'd greatly appreciate if you can kick the tyres on the v1.0 beta and open an issue with any bug reports, suggestions or feedback you might have.
27
32
 
28
- ### Main areas/points for testing:
33
+ ### Main areas/points for testing/feedback:
29
34
 
30
35
  - Existing Lookbook setups should continue to work **with no changes required**
31
- - There have been a number of small UI changes - do any of them negatively affect your experience of using Lookbook?
32
- - The Pages feature should work without opting in to any experimental features.
33
- - It's now possible to pick from one of a small set of pre-defined UI themes (finer-grained customisation coming soon!). See below for details. Any thoughts on this?
36
+ - It's now possible to pick from one of a small set of pre-defined **UI themes** (plus finer-grained customisation coming soon). [See below](#ui-theming) for details.
37
+ - You can now [extend Lookbook](#extending-lookbook) to more closely customise it to your needs - testing and feedback around this area would be a great help!
38
+
39
+ > Any thoughts, comments or bug reports (even if unrelated to the specific areas above) would be much appreciated!
34
40
 
35
- > However absolutely any thoughts, comments or bug reports (even if unrelated to the specific areas above) would be much appreciated!
36
41
 
37
- ### UI theming
42
+ ## UI theming
38
43
 
39
- Lookbook now ships with a small set of pre-defined UI themes, which can be set using the `ui_theme` config option:
44
+ Lookbook v1.0 ships with a small set of pre-defined UI themes, which can be set using the `ui_theme` config option:
40
45
 
41
46
  ```ruby
42
- # config/application.rb (or similar)
47
+ # config/application.rb
43
48
  config.lookbook.ui_theme = "blue"
44
49
  ```
45
50
 
@@ -51,6 +56,223 @@ Currently available themes are:
51
56
 
52
57
  > More themes and finer-grained customisation of theme colours is coming soon!
53
58
 
59
+ ## Extending Lookbook
60
+
61
+ > Opening up Lookbook to more in-depth customisation is a work in progress and any feedback or use-case examples would be greatly appreciated!
62
+
63
+ * [Lifecycle Hooks](#lifecycle-hooks)
64
+ * [Adding inspector panels](#adding-inspector-panels)
65
+ * [Removing inspector panels](#removing-inspector-panels)
66
+
67
+ ### Lifecycle hooks
68
+
69
+ A number of lifecycle hooks are available for use in triggering actions outside of Lookbook.
70
+
71
+ All hook callback blocks are yielded a `Lookbook` instance as the first argument. Some hooks additionally supply other arguments, see below for details.
72
+
73
+ #### `:after_initialize`
74
+
75
+ This is run once Lookbook has been set up and the initial parsing of files has been completed.
76
+
77
+ ```ruby
78
+ Lookbook.after_initialize do |app|
79
+ puts "Lookbook version #{app.version} has started"
80
+ puts "There are #{app.previews.size} previews and #{app.pages.size} pages"
81
+ # other code here...
82
+ end
83
+ ```
84
+
85
+ #### `:after_change`
86
+
87
+ Run each time a change is detected to a file that Lookbook is watching, unless listening for changes has been disabled in the config.
88
+
89
+ Receives a hash as the second argument with `:modified`, `:added`, and `:removed` properties, each of which is an array of affected file paths.
90
+
91
+ ```ruby
92
+ Lookbook.after_change do |app, changes|
93
+ puts "Modified files: #{changes.modified.join("\n")}"
94
+ puts "Added files: #{changes.added.join("\n")}"
95
+ puts "Removed files: #{changes.removed.join("\n")}"
96
+ end
97
+ ```
98
+
99
+ #### `:before_exit`
100
+
101
+ Run when the current process exits, after Lookbook has stopped any listeners.
102
+
103
+ ```ruby
104
+ Lookbook.after_initialize do |app|
105
+ puts "Shutting down..."
106
+ end
107
+ ```
108
+
109
+ ### Adding inspector panels
110
+
111
+ It's now possible to add custom inspector panels/tabs to Lookbook using the `:define_panel` method:
112
+
113
+ ```ruby
114
+ Lookbook.define_panel(<name>, <opts>)
115
+ ```
116
+
117
+ * `<name>`: A unique name for the panel
118
+ * `<opts>`: A `Hash` of options (see below for details)
119
+
120
+ For example, a very simple 'info' panel could be created as follows:
121
+
122
+ ```ruby
123
+ # config/application.rb
124
+ Lookbook.define_panel(:info, {
125
+ label: "Extra Info",
126
+ partial: "panels/info"
127
+ })
128
+ ```
129
+
130
+ ```erb
131
+ <!-- views/panels/_info.html.erb -->
132
+ <div>
133
+ <h2>Some information</h2>
134
+ <ul>
135
+ <li>You are looking at the '<%= preview.label %>' preview</li>
136
+ <li>The preview file path is: '<%= preview.full_path %>'<li>
137
+ <li>There are <%= examples.size %> examples in this preview<li>
138
+ </ul>
139
+ </div>
140
+ ```
141
+
142
+ #### Panel templates
143
+
144
+ The panel partial template will have access to any `locals` defined in the [panel options](#panel-options), plus the following variables:
145
+
146
+ #### `panel`
147
+
148
+ The resolved panel options object (see below for details)
149
+
150
+ ```erb
151
+ <h2><%= panel.label =></h2>
152
+ ```
153
+
154
+ #### `preview`
155
+
156
+ An object representing the current preview:
157
+
158
+ * `preview.id`
159
+ * `preview.label`
160
+ * `preview.full_path`
161
+ * `preview.url_path`
162
+ * ...
163
+
164
+ #### `examples`
165
+
166
+ An array of objects representing the individual examples being rendered in the current preview. (For non-grouped previews, this array will always only have one item.)
167
+
168
+ Each example has the following properties:
169
+
170
+ * `example.output` - the rendered preview example output (String)
171
+ * `example.source` - the example source code (String)
172
+ * `example.source_lang` - a hash of information about the source language (Ruby or HTML/ERB, depending on whether the example uses a preview template)
173
+ * `example.id`
174
+ * `example.label`
175
+ * `example.full_path`
176
+ * `example.url_path`
177
+ * ...
178
+
179
+
180
+ #### `components`
181
+
182
+ An array of objects representing the components that are rendered in the preview. The components are 'guessed' from the Preview class name but if that doesn't work then they can be manually specified via annotations.
183
+
184
+ Each component object has the following properties:
185
+
186
+ * `component.name`
187
+ * `component.full_path`
188
+ * `component.dir_path`
189
+ * `component.template_path`
190
+ * `component.inline?`
191
+
192
+ To manually specify one or more components in the preview class, you can use the `@component` tag at the class level:
193
+
194
+ ```ruby
195
+ # @component Elements::BigDangerButton
196
+ class ButtonComponentPreview < ViewComponent::Preview
197
+
198
+ def default
199
+ render Elements::BigDangerButton.new do
200
+ "Click here"
201
+ end
202
+ end
203
+
204
+ end
205
+ ```
206
+
207
+ #### `context`
208
+
209
+ An object containing data about the request context:
210
+
211
+ * `context.preview_params`
212
+ * `context.path`
213
+
214
+ #### `app`
215
+
216
+ The main `Lookbook` app instance.
217
+
218
+ * `app.previews` - Array of preview objects
219
+ * `app.pages` - Array of page objects
220
+ * `app.logger` - Logger instance
221
+
222
+ #### Panel options
223
+
224
+ ```ruby
225
+ {
226
+ label: "New Panel",
227
+ position: 1,
228
+ partial: "path/to/view_partial",
229
+ content: "Some **markdown** content",
230
+ hotkey: "ctrl.n",
231
+ disabled: false,
232
+ show: true,
233
+ copy: "Content to be copied",
234
+ locals: {}
235
+ }
236
+ ```
237
+
238
+ * `label`: the text to be displayed in the tab
239
+ * `position`: used for ordering the tabs
240
+ * `partial`: the path to the view template partial used to render the panel
241
+ * `content`: the default partial renders and displays the contents of this (markdown supported)
242
+ * `hotkey`: [keyboard shortcut](https://alpinejs.dev/directives/on#keyboard-events) to make panel become the active tab
243
+ * `disabled`: `true` or `false` - disabled tabs are still accessible but are greyed out in the UI
244
+ * `show`: `true` or `false` - whether or not to display the tab/panel
245
+ * `copy`: if present, the panel will display a copy button that copies the value of this property to the clipboard when clicked
246
+ * `locals`: a `Hash` of local variables that will be made available to the partial when rendering the panel
247
+
248
+
249
+ All panel option values can be provided either as a **simple static value** or as a **lambda function** which will receive a hash of data relating to the currently active preview/example. For example:
250
+
251
+ ```ruby
252
+ {
253
+ label: "Params",
254
+ disabled: ->(data) { data.preview.params.none? } # grey out the Params tab if no params are set for the current preview
255
+ }
256
+ ```
257
+
258
+ The `data` hash contains the same set of objects that are passed to the panel partial template:
259
+
260
+ * `data.preview`
261
+ * `data.examples`
262
+ * `data.components`
263
+ * `data.context`
264
+ * `data.app`
265
+
266
+ **See the [panel templates section above]((#panel-templates)) for more details.**
267
+
268
+ ### Removing inspector panels
269
+
270
+ To remove a panel entirely from the UI you can use the `Lookbook.remove_panel` method:
271
+
272
+ ```ruby
273
+ # config/application.rb
274
+ Lookbook.remove_panel(:notes)
275
+ ```
54
276
 
55
277
  ## 🛠 Workbench
56
278
 
@@ -4,15 +4,15 @@ export default function initInspectorStore(Alpine, { prefix }) {
4
4
  return {
5
5
  minVerticalSplitWidth: 800,
6
6
 
7
- preview: {
7
+ main: {
8
8
  activeTab: Alpine.$persist("").as(
9
- prefixString("inspector-preview-active-tab", prefix)
9
+ prefixString("inspector-main-active-tab", prefix)
10
10
  ),
11
11
  width: Alpine.$persist("100%").as(
12
- prefixString("inspector-preview-width", prefix)
12
+ prefixString("inspector-main-width", prefix)
13
13
  ),
14
14
  height: Alpine.$persist("100%").as(
15
- prefixString("inspector-preview-height", prefix)
15
+ prefixString("inspector-main-height", prefix)
16
16
  ),
17
17
  lastWidth: null,
18
18
  lastHeight: null,
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Component < ViewComponent::Base
2
+ class BaseComponent < ViewComponent::Base
3
3
  include Lookbook::ComponentHelper
4
4
 
5
5
  def initialize(alpine_data: [], **html_attrs)
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Button::Component < Lookbook::Component
2
+ class Button::Component < Lookbook::BaseComponent
3
3
  renders_one :icon, Lookbook::Icon::Component
4
4
  renders_one :dropdown
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class ButtonGroup::Component < Lookbook::Component
2
+ class ButtonGroup::Component < Lookbook::BaseComponent
3
3
  renders_many :buttons, ->(copy: nil, **attrs, &block) do
4
4
  attrs[:size] = @size
5
5
  instance = if copy.present?
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Code::Component < Lookbook::Component
2
+ class Code::Component < Lookbook::BaseComponent
3
3
  include Lookbook::OutputHelper
4
4
 
5
5
  def initialize(
@@ -4,7 +4,7 @@
4
4
  x_data: prepare_alpine_data,
5
5
  "@click.prevent": "copyToClipboard" do |button| %>
6
6
  <% button.icon name: @icon, size: icon_size, x_show: "!copied", cloak: true %>
7
- <%= render_component :icon, name: :check, size: icon_size, class: "text-green-500", x_show: "copied", cloak: true %>
7
+ <%= icon :check, size: icon_size, class: "text-green-500", x_show: "copied", cloak: true %>
8
8
  <% if content %>
9
9
  <div x-ref="copyTarget" class="hidden"><%== content %></div>
10
10
  <% end %>
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class CopyButton::Component < Lookbook::Component
2
+ class CopyButton::Component < Lookbook::BaseComponent
3
3
  def initialize(target: nil, icon: :code, **attrs)
4
4
  @icon = icon
5
5
  @target = target
@@ -3,7 +3,8 @@
3
3
  "@viewport:resize-start.window": "resizing = true",
4
4
  "@viewport:resize-complete.window": "resizing = false",
5
5
  "@dom:update-start.window": "tearDown",
6
- "@dom:update-complete.window": "createObserver" do %>
6
+ "@dom:update-complete.window": "createObserver",
7
+ "x-show": "target" do %>
7
8
  <span x-text="`${width}px`"></span>
8
9
  <span class="opacity-70">x</span>
9
10
  <span x-text="`${height}px`"></span>
@@ -5,26 +5,33 @@ export default function dimensionsDisplayComponent(targetSelector) {
5
5
  width: 0,
6
6
  height: 0,
7
7
  resizing: false,
8
+ target: null,
8
9
 
9
10
  init() {
10
- const target = document.querySelector(targetSelector);
11
- this.width = Math.round(target.clientWidth);
12
- this.height = Math.round(target.clientHeight);
13
- this.createObserver();
11
+ this.target = document.querySelector(targetSelector);
12
+ if (this.target) {
13
+ this.width = Math.round(this.target.clientWidth);
14
+ this.height = Math.round(this.target.clientHeight);
15
+ this.createObserver();
16
+ }
14
17
  },
15
18
 
16
19
  createObserver() {
17
- this.observer = observeSize(
18
- document.querySelector(targetSelector),
19
- ({ width, height }) => {
20
- this.width = width;
21
- this.height = height;
22
- }
23
- );
20
+ if (this.target) {
21
+ this.observer = observeSize(
22
+ document.querySelector(targetSelector),
23
+ ({ width, height }) => {
24
+ this.width = width;
25
+ this.height = height;
26
+ }
27
+ );
28
+ }
24
29
  },
25
30
 
26
31
  tearDown() {
27
- this.observer.disconnect();
32
+ if (this.observer) {
33
+ this.observer.disconnect();
34
+ }
28
35
  },
29
36
  };
30
37
  }
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class DimensionsDisplay::Component < Lookbook::Component
2
+ class DimensionsDisplay::Component < Lookbook::BaseComponent
3
3
  def initialize(target:, **html_attrs)
4
4
  @target = target
5
5
  super(**html_attrs)
@@ -10,10 +10,10 @@
10
10
  <% toolbar.section align: :right, divide: :left do %>
11
11
  <%= render_component :button_group do |group| %>
12
12
  <% group.button icon: :eye,
13
- href: helpers.lookbook.inspect_path(@example.path, @params),
13
+ href: helpers.lookbook_inspect_path(@example.path, @params),
14
14
  tooltip: "View in Inspector" %>
15
15
  <% group.button icon: :external_link,
16
- href: helpers.lookbook.inspect_path(@example.path, @params),
16
+ href: helpers.lookbook_inspect_path(@example.path, @params),
17
17
  tooltip: "Open in new window",
18
18
  target: "_blank" %>
19
19
  <% end %>
@@ -25,9 +25,10 @@
25
25
  @viewport:loaded="loadResizer"
26
26
  @dom:update-complete="loadResizer"
27
27
  @viewport:resize-progress="resizeIframe"
28
- @viewport:resize-complete="resizeIframe">
28
+ @viewport:resize-complete="resizeIframe"
29
+ @tabs:change.window="resizeIframe">
29
30
  <%= render_component :viewport,
30
- src: helpers.lookbook.preview_path(@example.path, @params.merge(lookbook_embed: true)),
31
+ src: helpers.lookbook_preview_path(@example.path, @params.merge(lookbook_embed: true)),
31
32
  alpine_data: "store",
32
33
  resize_height: false,
33
34
  max_height: @max_height,
@@ -38,7 +39,7 @@
38
39
  <% else %>
39
40
  <%= render_component_tag class: "bg-white flex flex-col items-center justify-center border-2 border-dashed border-gray-200 p-6 rounded-md not-prose" do %>
40
41
  <div class="px-4 text-center">
41
- <%= render_component :icon, name: :alert_triangle, size: 6, class: "text-red-300 mx-auto" %>
42
+ <%= icon :alert_triangle, size: 6, class: "text-red-300 mx-auto" %>
42
43
  <div class="mt-2 max-w-xs">
43
44
  <h5 class="text-base">Preview not found</h5>
44
45
  <p class="mt-1 opacity-50 text-sm">
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Embed::Component < Lookbook::Component
2
+ class Embed::Component < Lookbook::BaseComponent
3
3
  def initialize(id:, example:, params: {}, opts: {}, max_height: nil, **html_attrs)
4
4
  @id = id
5
5
  @example = example
@@ -11,7 +11,7 @@
11
11
  @keydown.f.stop.prevent.window="focus"
12
12
  @keydown.stop>
13
13
  <button class="text-lookbook-button-text hover:text-lookbook-button-text-hover focus:ring-0 focus:outline-none absolute top-1/2 right-3 -translate-y-1/2" @click="clear" :class="{hidden: !active}">
14
- <%= render_component :icon, name: :x, size: 3 %>
14
+ <%= icon :x, size: 3 %>
15
15
  </button>
16
16
  </div>
17
17
  <% end %>
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Filter::Component < Lookbook::Component
2
+ class Filter::Component < Lookbook::BaseComponent
3
3
  def initialize(store: nil, placeholder: "Type to filter&hellip;", **html_attrs)
4
4
  @model = store.nil? ? "{}" : "#{store}.raw"
5
5
  @placeholder = placeholder
@@ -24,15 +24,10 @@
24
24
  x-data="clipboardComponent"
25
25
  @click.prevent.stop="copyToClipboard('#debug-data')">
26
26
  <span x-show="copied" x-cloak>
27
- <%= render_component :icon,
28
- name: :check,
29
- size: 2.5,
30
- class: "text-green-600" %>
27
+ <%= icon :check, size: 2.5, class: "text-green-600" %>
31
28
  </span>
32
29
  <span x-show="!copied">
33
- <%= render_component :icon,
34
- name: :clipboard,
35
- size: 2.5 %>
30
+ <%= icon :clipboard, size: 2.5 %>
36
31
  </span>
37
32
  <span class="ml-2">Copy debug data</span>
38
33
  </a>
@@ -41,7 +36,7 @@
41
36
  <a href="#"
42
37
  class="text-xs flex items-center hover:underline"
43
38
  @click.stop="localStorage.clear(); window.location.reload();">
44
- <%= render_component :icon, name: :refresh_cw, size: 2.5 %>
39
+ <%= icon :refresh_cw, size: 2.5 %>
45
40
  <span class="ml-2">Reset local storage</span>
46
41
  </a>
47
42
  </li>
@@ -51,11 +46,11 @@
51
46
  <span class="opacity-70 mr-1">Lookbook</span>
52
47
  <span class="mr-6">v<%= Lookbook::VERSION %></span>
53
48
  <div class="flex items-center space-x-2">
54
- <a href="https://github.com/allmarkedup/lookbook" target="_blank" class="ml-auto opacity-70" title="Documentation">
55
- <%= render_component :icon, name: :book, size: 3 %>
56
- </a>
49
+ <!-- a href="https://github.com/allmarkedup/lookbook" target="_blank" class="ml-auto opacity-70" title="Documentation">
50
+ <%= icon :book, size: 3 %>
51
+ </a -->
57
52
  <a href="https://github.com/allmarkedup/lookbook" target="_blank" class="ml-auto opacity-70" title="Github">
58
- <%= render_component :icon, name: :github, size: 3 %>
53
+ <%= icon :github, size: 3 %>
59
54
  </a>
60
55
  </div>
61
56
  </div>
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Header::Component < Lookbook::Component
2
+ class Header::Component < Lookbook::BaseComponent
3
3
  renders_one :branding
4
4
 
5
5
  def landing_path
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Icon::Component < Lookbook::Component
2
+ class Icon::Component < Lookbook::BaseComponent
3
3
  def initialize(name:, size: 4, **html_attrs)
4
4
  @icon_name = name.is_a?(Symbol) ? name.to_s.tr("_", "-").to_json : name
5
5
  @size = size || 4
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Nav::Component < Lookbook::Component
2
+ class Nav::Component < Lookbook::BaseComponent
3
3
  renders_one :filter, Lookbook::Filter::Component
4
4
 
5
5
  def initialize(
@@ -6,11 +6,11 @@
6
6
  style: "padding-left: #{left_pad}px",
7
7
  x_bind: "bindings.#{href.present? ? "link" : "toggle"}" do %>
8
8
  <div class="relative flex items-center">
9
- <%= render_component :icon, name: nil,
9
+ <%= icon nil,
10
10
  size: 3,
11
11
  class: "mr-1 text-lookbook-nav-toggle absolute -left-4",
12
12
  x_effect: "iconName = open ? 'chevron-down' : 'chevron-right'" if children? %>
13
- <%= render_component :icon, name: nav_icon(@item), size: 3.5, class: "mr-1.5 text-lookbook-nav-icon" %>
13
+ <%= icon nav_icon(@item), size: 3.5, class: "mr-1.5 text-lookbook-nav-icon" %>
14
14
  <span><%= label %></span>
15
15
  </div>
16
16
  <% end %>
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Nav::Item::Component < Lookbook::Component
2
+ class Nav::Item::Component < Lookbook::BaseComponent
3
3
  ICONS = {
4
4
  page: :file,
5
5
  page_collection: :folder,
@@ -0,0 +1,18 @@
1
+ <%= render_component_tag x_data: "{ activeTab: null }" do %>
2
+ <div class="flex w-full border-b border-lookbook-divider mb-6">
3
+ <%= render_component :tabs, theme: :page do |t| %>
4
+ <% @tabs.each do |props| %>
5
+ <%= t.tab **props %>
6
+ <% end %>
7
+ <% end %>
8
+ </div>
9
+ <%= render_component :tab_panels do |t| %>
10
+ <% @tabs.each do |props| %>
11
+ <% t.panel name: props[:name] do %>
12
+ <%= render_component :prose, markdown: props[:markdown], class: "max-w-none flex-none" do %>
13
+ <%== props[:content] %>
14
+ <% end %>
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
@@ -0,0 +1,19 @@
1
+ module Lookbook
2
+ class PageTabs::Component < Lookbook::BaseComponent
3
+ renders_many :tabs, ->(**attrs, &block) do
4
+ @tabs ||= []
5
+ attrs[:content] = capture(&block)
6
+ attrs[:markdown] ||= @markdown
7
+ @tabs << attrs
8
+ end
9
+
10
+ def initialize(markdown: true, **html_attrs)
11
+ @markdown = markdown
12
+ super(**html_attrs)
13
+ end
14
+
15
+ def before_render
16
+ tabs.size
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class ParamsEditor::Component < Lookbook::Component
2
+ class ParamsEditor::Component < Lookbook::BaseComponent
3
3
  renders_many :fields, Lookbook::ParamsEditor::Field::Component
4
4
 
5
5
  protected
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class ParamsEditor::Field::Component < Lookbook::Component
2
+ class ParamsEditor::Field::Component < Lookbook::BaseComponent
3
3
  def initialize(input:, name:, default: nil, value: nil, input_type: nil, type: nil, options: nil, **html_attrs)
4
4
  @input = input
5
5
  @name = name
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Prose::Component < Lookbook::Component
2
+ class Prose::Component < Lookbook::BaseComponent
3
3
  include Lookbook::OutputHelper
4
4
 
5
5
  def initialize(size: :md, markdown: true, **html_attrs)
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class SplitLayout::Component < Lookbook::Component
2
+ class SplitLayout::Component < Lookbook::BaseComponent
3
3
  renders_many :panes, Lookbook::TagComponent
4
4
 
5
5
  protected
@@ -0,0 +1,5 @@
1
+ <%= render_component_tag class: "h-full" do %>
2
+ <div x-ref="panels" class="h-full">
3
+ <%= safe_join(panels) %>
4
+ </div>
5
+ <% end %>