lookbook 0.5.0.beta.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -20
  3. data/app/assets/lookbook/css/app.css +4 -1
  4. data/app/assets/lookbook/js/app.js +2 -0
  5. data/app/assets/lookbook/js/components/code.js +5 -0
  6. data/app/assets/lookbook/js/components/copy.js +4 -2
  7. data/app/assets/lookbook/js/components/inspector.js +15 -7
  8. data/app/assets/lookbook/js/components/page.js +3 -1
  9. data/app/assets/lookbook/js/components/param.js +15 -13
  10. data/app/assets/lookbook/js/config.js +3 -2
  11. data/app/assets/lookbook/js/lib/socket.js +1 -1
  12. data/app/assets/lookbook/js/stores/inspector.js +3 -2
  13. data/app/controllers/lookbook/app_controller.rb +23 -11
  14. data/app/views/layouts/lookbook/app.html.erb +3 -1
  15. data/app/views/lookbook/components/_code.html.erb +6 -1
  16. data/app/views/lookbook/components/_drawer.html.erb +38 -35
  17. data/app/views/lookbook/components/_header.html.erb +2 -2
  18. data/app/views/lookbook/components/_nav_preview.html.erb +4 -2
  19. data/app/views/lookbook/components/_param.html.erb +2 -5
  20. data/app/views/lookbook/components/_preview.html.erb +65 -46
  21. data/app/views/lookbook/inputs/_select.html.erb +1 -2
  22. data/app/views/lookbook/inputs/_text.html.erb +2 -3
  23. data/app/views/lookbook/inputs/_textarea.html.erb +1 -2
  24. data/app/views/lookbook/inputs/_toggle.html.erb +2 -2
  25. data/app/views/lookbook/panels/_output.html.erb +2 -2
  26. data/app/views/lookbook/panels/_preview.html.erb +52 -0
  27. data/app/views/lookbook/panels/_source.html.erb +1 -1
  28. data/app/views/lookbook/show.html.erb +5 -54
  29. data/lib/lookbook/features.rb +1 -1
  30. data/lib/lookbook/version.rb +1 -1
  31. data/public/lookbook-assets/css/app.css +1 -1
  32. data/public/lookbook-assets/css/app.css.map +1 -1
  33. data/public/lookbook-assets/js/app.js +1 -1
  34. data/public/lookbook-assets/js/app.js.map +1 -1
  35. metadata +6 -5
  36. data/app/views/lookbook/components/_copy.html.erb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95624cc7d6d6e9389e87c3b13c6f4980f0be8ae2f13ac81757a9ed7acbaf554d
4
- data.tar.gz: e8e8c6787b96e23fc3d71bc3b47c4a9253ef8a607f8f41c292c52e2ecc99549d
3
+ metadata.gz: e7d08534bdd08e8ec3807fb35c3b8a0a97fecb0b2a4e866174a6b496c6eae82c
4
+ data.tar.gz: dc7cffa78d20043283268eab5d7817c280281a08b73b52fb73a3591d8fb4a357
5
5
  SHA512:
6
- metadata.gz: 5ac7b680d183349e374b1a2368b2839fa9c9ec8790f53cbf76a97171c0da7375cf6599d2e4936e2fcb1a0dca685aae9d37cfd54672e68ef0e935086af43b60bc
7
- data.tar.gz: 03bee3f6b73191fc5bcfd5afed389fee54b3ec41ce31827ddedf647dc17f68740db1314f6f4a0c78d7dfe4960851d9cce12e23e6598970b74d8ec428f258db88
6
+ metadata.gz: f2f1365fea4478385905b1700595e3bcde6eb477b2486e37555ecdc035982e7c7e390e92145f0d5c715794423680ec3df420b8bb8f8c5c3104d4e82585d97e29
7
+ data.tar.gz: 62556f502dd2afaabc8c25f6b0887c9175f8ee4c32a8eb4515b3063bc77a25220d076d99cc71878c1550056d752c599adf208f92b948c6f3d89d89fd85b1e670
data/README.md CHANGED
@@ -28,7 +28,7 @@ Lookbook uses [RDoc/Yard-style comment tags](#annotating-preview-files) to exten
28
28
  - Auto-updating UI when component or preview files are updated _(Rails v6.0+ only)_
29
29
  - Use comment tag annotations for granular customisation of the preview experience
30
30
  - Fully compatible with standard the ViewComponent preview system
31
- - [**Experimental**] In-browser live editable preview parameters (similar to Storybook Controls/Knobs)
31
+ - In-browser live-editable preview parameters (similar to basic Storybook Controls/Knobs)
32
32
 
33
33
  ## Lookbook demo
34
34
 
@@ -63,10 +63,16 @@ end
63
63
 
64
64
  The `at` property determines the root URL that the Lookbook UI will be served at.
65
65
 
66
- > If you would like to expose the Lookbook UI in production as well as in development, just remove the `if Rails.env.development?` condition from around the mount statement.
67
-
68
66
  Then you can start your app as normal and navigate to `http://localhost:3000/lookbook` (or whatever mount path you specified) to view your component previews in the Lookbook UI.
69
67
 
68
+ #### Mounting in Production
69
+
70
+ If you would like to expose the Lookbook UI in production as well as in development
71
+
72
+ 1. Remove the `if Rails.env.development?` condition from around the mount statement in `routes.rb`
73
+ 2. Add `config.view_component.show_previews = true` to `config/environments/production.rb`
74
+
75
+
70
76
  ## Usage
71
77
 
72
78
  You don't need to do anything special to see your ViewComponent previews and examples in Lookbook - just create them as normal and they'll automatically appear in the Lookbook UI. Preview templates, custom layouts and even bespoke [preview controllers](https://viewcomponent.org/guide/previews.html#configuring-preview-controller) should all work as you would expect.
@@ -96,7 +102,7 @@ class ButtonComponentPreview < ViewComponent::Preview
96
102
  # Button with icon
97
103
  # ----------------
98
104
  # This example uses dynamic preview parameters
99
- # which can be edited live in the Lookbook UI
105
+ # which can be edited live in the Lookbook UI
100
106
  #
101
107
  # @param text
102
108
  # @param icon select [heart, cog, alert]
@@ -161,7 +167,7 @@ The following Lookbook-specific tags are available for use:
161
167
  * [`@display`](#display-tag)
162
168
  * [`@!group ... @!endgroup`](#group-tag)
163
169
  * [`@hidden`](#hidden-tag)
164
- * [`@param`](#param-tag) [⚠️ **experimental!** - requires [feature opt-in](#experimental-features) ⚠️]
170
+ * [`@param`](#param-tag)
165
171
 
166
172
  <h3 id="label-tag">🏷 @label</h3>
167
173
 
@@ -311,9 +317,7 @@ class FooComponentPreview < ViewComponent::Preview
311
317
  end
312
318
  ```
313
319
 
314
- <h3 id="param-tag"> 🚧 @param (experimental)</h3>
315
-
316
- > ⚠️ This feature is currently flagged as an **experimental** feature which requires [feature opt-in](#experimental-features) to use. Its API and implementation may change in the future.
320
+ <h3 id="param-tag">@param</h3>
317
321
 
318
322
  The `@param` tag provides the ability to specify **editable preview parameters** which can be changed in the Lookbook UI in order to customise the rendered output on the fly, much like the [Controls (knobs) addon](https://storybook.js.org/addons/@storybook/addon-controls) for Storybook.
319
323
 
@@ -326,7 +330,7 @@ The `@param` tag takes the following format:
326
330
  ```
327
331
 
328
332
  - `<name>` - name of the dynamic preview param
329
- - `<input_type>` - input field type to generate in the UI
333
+ - `<input_type>` - input field type to generate in the UI
330
334
  - `<opts?>` - YAML-encoded field options, used for some field types
331
335
 
332
336
  #### Input types
@@ -357,7 +361,7 @@ The following **input field types** are available for use:
357
361
  @param <name> select <options>
358
362
  ```
359
363
 
360
- `<options>` should be a [YAML array](https://yaml.org/YAML_for_ruby.html#simple_inline_array) of options which must be formatted in the same style as the input for Rails' [`options_for_select`](https://apidock.com/rails/v6.0.0/ActionView/Helpers/FormOptionsHelper/options_for_select) helper:
364
+ `<options>` should be a [YAML array](https://yaml.org/YAML_for_ruby.html#simple_inline_array) of options which must be formatted in the same style as the input for Rails' [`options_for_select`](https://apidock.com/rails/v6.0.0/ActionView/Helpers/FormOptionsHelper/options_for_select) helper:
361
365
 
362
366
  ```ruby
363
367
  # Basic options:
@@ -437,7 +441,7 @@ The following structured types are also available but should be considered **exp
437
441
 
438
442
  ```ruby
439
443
  class ButtonComponentPreview < ViewComponent::Preview
440
-
444
+
441
445
  # The params defined below will be editable in the UI:
442
446
  #
443
447
  # @param content text
@@ -470,8 +474,6 @@ class ProfileCardComponentPreview < ViewComponent::Preview
470
474
  end
471
475
  ```
472
476
 
473
- <img src=".github/assets/preview_example_notes.png" width="400">
474
-
475
477
  ## Configuration
476
478
 
477
479
  Lookbook will use the ViewComponent [configuration](https://viewcomponent.org/api.html#configuration) for your project to find and render your previews so you generally you won't need to configure anything separately.
@@ -496,6 +498,17 @@ If you wish to add additional paths to listen for changes in, you can use the `l
496
498
  config.lookbook.listen_paths << Rails.root.join('app/other/directory')
497
499
  ```
498
500
 
501
+ ### Custom favicon
502
+
503
+ If you want to change the favicon used by the Lookbook UI, you can provide a path to your own (or a data-uri string) using the `ui_favicon` option:
504
+
505
+ ```ruby
506
+ config.lookbook.ui_favicon = "/path/to/my/favicon.png"
507
+ ```
508
+
509
+ > To disable the favicon entirely, set the value to `false`.
510
+
511
+
499
512
  <h3 id="experimental-features">Experimental features opt-in</h3>
500
513
 
501
514
  Some features may occasionally be released behind a 'experimental' feature flag while they are being tested and refined, to allow people to try them out and provide feedback.
@@ -510,10 +523,6 @@ To opt into individual experimental features, include the name of the feature in
510
523
  config.lookbook.experimental_features = ["feature_name"]
511
524
  ```
512
525
 
513
- The current experimental features that can be opted into are:
514
-
515
- - `params`: Live-editable, dynamic preview parameters ([read more](#param-tag)). Include `"params"` in the `experimental_features` config option to opt in.
516
-
517
526
  #### Opting into all experimental features (not recommended!)
518
527
 
519
528
  If you want to live life on the bleeding-edge you can opt-in to all current **and future** experimental features (usual caveats apply):
@@ -529,9 +538,10 @@ Lookbook provides a few keyboard shortcuts to help you quickly move around the U
529
538
 
530
539
  - `f` - move focus to the nav filter box
531
540
  - `Esc` [when focus is in nav filter box] - Clear contents if text is present, or return focus to the UI if the box is already empty
532
- - `s` - Switch to Source tab in the inspector
533
- - `o` - Switch to Output tab in the inspector
534
- - `n` - Switch to Notes tab in the inspector
541
+ - `s` - Switch to Source tab in the drawer
542
+ - `n` - Switch to Notes tab in the drawer
543
+ - `v` - Switch to the rendered preview
544
+ - `o` - Switch to the code preview
535
545
  - `r` - Refresh the preview (useful if using something like Faker to generate randomised data for the preview)
536
546
  - `w` - Open the standalone rendered preview in a new window
537
547
 
@@ -76,7 +76,10 @@
76
76
 
77
77
  .code pre {
78
78
  @apply block;
79
- /* @apply whitespace-pre-wrap; */
79
+ }
80
+
81
+ .code.wrapped pre {
82
+ @apply whitespace-pre-wrap;
80
83
  }
81
84
 
82
85
  .code .line {
@@ -15,6 +15,7 @@ import navGroup from "./components/nav-group";
15
15
  import splitter from "./components/splitter";
16
16
  import tabs from "./components/tabs";
17
17
  import copy from "./components/copy";
18
+ import code from "./components/code";
18
19
  import sizes from "./components/sizes";
19
20
 
20
21
  import initFilterStore from "./stores/filter";
@@ -43,6 +44,7 @@ Alpine.data("page", page);
43
44
  Alpine.data("splitter", splitter);
44
45
  Alpine.data("previewWindow", previewWindow);
45
46
  Alpine.data("copy", copy);
47
+ Alpine.data("code", code);
46
48
  Alpine.data("inspector", inspector);
47
49
  Alpine.data("filter", filter);
48
50
  Alpine.data("param", param);
@@ -0,0 +1,5 @@
1
+ export default function code() {
2
+ return {
3
+ wrap: false,
4
+ };
5
+ }
@@ -1,7 +1,9 @@
1
- export default function copy(id) {
1
+ export default function copy() {
2
2
  return {
3
3
  get content() {
4
- const target = document.getElementById(id);
4
+ const target = document.getElementById(
5
+ this.$root.getAttribute("data-target")
6
+ );
5
7
  return (target ? target.innerHTML : "").trim();
6
8
  },
7
9
  done: false,
@@ -32,15 +32,23 @@ export default function inspector() {
32
32
  get drawerHidden() {
33
33
  return this.$store.inspector.drawer.hidden;
34
34
  },
35
- isActivePanel(panel) {
36
- return this.$store.inspector.drawer.active == panel;
35
+ get maxDrawerHeight() {
36
+ return Math.round(this.height * 0.7);
37
37
  },
38
- switchPanel(panel) {
39
- this.$store.inspector.drawer.active = panel;
38
+ get maxDrawerWidth() {
39
+ return Math.round(this.width * 0.7);
40
40
  },
41
- toggleView() {
42
- this.$store.inspector.preview.view =
43
- this.view === "html" ? "preview" : "html";
41
+ isActiveDrawerPanel(panel) {
42
+ return this.$store.inspector.drawer.panel === panel;
43
+ },
44
+ switchDrawerPanel(panel) {
45
+ this.$store.inspector.drawer.panel = panel;
46
+ },
47
+ isActivePreviewPanel(panel) {
48
+ return this.$store.inspector.preview.panel === panel;
49
+ },
50
+ switchPreviewPanel(panel) {
51
+ this.$store.inspector.preview.panel = panel;
44
52
  },
45
53
  toggleOrientation() {
46
54
  this.$store.inspector.drawer.orientation =
@@ -26,7 +26,9 @@ export default function page() {
26
26
  const response = await fetch(window.document.location);
27
27
  if (!response.ok) return window.location.reload();
28
28
  const html = await response.text();
29
- this.morph(new DOMParser().parseFromString(html, "text/html"));
29
+ const newDoc = new DOMParser().parseFromString(html, "text/html");
30
+ this.morph(newDoc);
31
+ document.title = newDoc.title;
30
32
  },
31
33
  setLocation(loc) {
32
34
  const path = loc instanceof Event ? loc.currentTarget.href : loc;
@@ -1,23 +1,25 @@
1
1
  import debounce from "debounce";
2
2
 
3
- export default function param(name, value) {
3
+ export default function param(name, value, opts = {}) {
4
4
  return {
5
5
  name,
6
6
  value,
7
+ updating: false,
7
8
  init() {
8
- this.$watch(
9
- "value",
10
- debounce(() => {
11
- if (this.validate()) {
12
- this.update();
13
- }
14
- }, 300)
15
- );
9
+ if (opts.debounce) {
10
+ this.$watch(
11
+ "value",
12
+ debounce(() => this.updateIfValid(), opts.debounce)
13
+ );
14
+ } else {
15
+ this.$watch("value", () => this.updateIfValid());
16
+ }
16
17
  },
17
18
  setFocus() {
18
- if (this.$refs.input) {
19
- setTimeout(() => this.$refs.input.focus(), 0);
20
- }
19
+ setTimeout(() => this.$root.focus(), 0);
20
+ },
21
+ updateIfValid() {
22
+ if (this.validate()) this.update();
21
23
  },
22
24
  update() {
23
25
  const searchParams = new URLSearchParams(window.location.search);
@@ -26,7 +28,7 @@ export default function param(name, value) {
26
28
  this.setLocation(`${path}?${searchParams.toString()}`);
27
29
  },
28
30
  validate() {
29
- return this.$el.reportValidity ? this.$el.reportValidity() : true;
31
+ return this.$root.reportValidity ? this.$root.reportValidity() : true;
30
32
  },
31
33
  };
32
34
  }
@@ -9,12 +9,13 @@ export default {
9
9
  drawer: {
10
10
  orientation: "horizontal",
11
11
  defaultPanel: "source",
12
- defaultHeight: 200,
12
+ defaultHeight: 300,
13
13
  defaultWidth: 500,
14
14
  minWidth: 350,
15
+ minHeight: 200,
15
16
  },
16
17
  preview: {
17
- view: "preview",
18
+ defaultPanel: "preview",
18
19
  },
19
20
  },
20
21
  };
@@ -10,7 +10,7 @@ export default function socket(endpoint) {
10
10
  received: debounce((data) => {
11
11
  console.log("Lookbook files changed");
12
12
  callback(data);
13
- }, 300),
13
+ }, 200),
14
14
  connected() {
15
15
  console.log("Lookbook websocket connected");
16
16
  },
@@ -6,16 +6,17 @@ export default function createInspectorStore(Alpine) {
6
6
  drawer: {
7
7
  hidden: Alpine.$persist(false).as("drawer-hidden"),
8
8
  orientation: Alpine.$persist(drawer.orientation).as("drawer-orientation"),
9
- active: Alpine.$persist(drawer.defaultPanel).as("drawer-active"),
9
+ panel: Alpine.$persist(drawer.defaultPanel).as("drawer-panel"),
10
10
  height: Alpine.$persist(drawer.defaultHeight).as("drawer-height"),
11
11
  width: Alpine.$persist(drawer.defaultWidth).as("drawer-width"),
12
12
  minWidth: drawer.minWidth,
13
+ minHeight: drawer.minHeight,
13
14
  visibleTabCount: Infinity,
14
15
  },
15
16
  preview: {
16
17
  width: Alpine.$persist("100%").as("preview-width"),
17
18
  height: Alpine.$persist("100%").as("preview-height"),
18
- view: Alpine.$persist(preview.view).as("preview-view"),
19
+ panel: Alpine.$persist(preview.defaultPanel).as("preview-panel"),
19
20
  lastWidth: null,
20
21
  lastHeight: null,
21
22
  resizing: false,
@@ -27,10 +27,8 @@ module Lookbook
27
27
  begin
28
28
  set_params
29
29
  @examples = examples_data
30
- @preview_srcdoc = if Lookbook.config.preview_srcdoc
31
- render_examples(examples_data).gsub("\"", "&quot;")
32
- end
33
- @panels = panels.filter { |name, panel| panel[:show] }
30
+ @drawer_panels = drawer_panels.filter { |name, panel| panel[:show] }
31
+ @preview_panels = preview_panels.filter { |name, panel| panel[:show] }
34
32
  rescue *EXCEPTIONS
35
33
  render "error"
36
34
  end
@@ -119,23 +117,37 @@ module Lookbook
119
117
  @nav
120
118
  end
121
119
 
122
- def panels
120
+ def preview_panels
123
121
  {
124
- source: {
125
- label: "Source",
126
- template: "lookbook/panels/source",
127
- hotkey: "s",
122
+ preview: {
123
+ label: "Preview",
124
+ template: "lookbook/panels/preview",
125
+ srcdoc: Lookbook.config.preview_srcdoc ? render_examples(examples_data).gsub("\"", "&quot;") : nil,
126
+ hotkey: "v",
128
127
  show: true,
129
128
  disabled: false,
130
- copy: true
129
+ copy: false
131
130
  },
132
131
  output: {
133
- label: "Output",
132
+ label: "HTML",
134
133
  template: "lookbook/panels/output",
135
134
  hotkey: "o",
136
135
  show: true,
137
136
  disabled: false,
138
137
  copy: true
138
+ }
139
+ }
140
+ end
141
+
142
+ def drawer_panels
143
+ {
144
+ source: {
145
+ label: "Source",
146
+ template: "lookbook/panels/source",
147
+ hotkey: "s",
148
+ show: true,
149
+ disabled: false,
150
+ copy: true
139
151
  },
140
152
  notes: {
141
153
  label: "Notes",
@@ -6,7 +6,9 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
7
7
 
8
8
  <link href="/lookbook-assets/css/app.css?v=<%= Lookbook::VERSION %>" rel="stylesheet">
9
- <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>👀</text></svg>">
9
+ <% if config.ui_favicon != false %>
10
+ <link rel="icon" href="<%= config.ui_favicon || "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>👀</text></svg>" %>">
11
+ <% end %>
10
12
 
11
13
  <% if config.auto_refresh %>
12
14
  <script>
@@ -1,8 +1,13 @@
1
1
  <%
2
2
  line_numbers ||= false
3
3
  language ||= "html"
4
+ wrap ||= nil;
4
5
  %>
5
6
  <% code = capture do %><%= yield %><% end %>
6
- <div class="code <%= "numbered" if line_numbers %> <%= classes %>">
7
+ <div class="code <%= "numbered" if line_numbers %> <%= classes %>"
8
+ x-data="code"
9
+ :class="{'wrapped': wrap}"
10
+ <% if wrap.present? %>x-effect="wrap = <%= wrap %>"<% end %>
11
+ >
7
12
  <pre><code class="highlight"><%= highlight(code.strip, language, line_numbers: line_numbers) %></code></pre>
8
13
  </div>
@@ -1,10 +1,10 @@
1
1
  <div id="drawer" class="bg-white w-full h-full flex flex-col min-w-0">
2
- <div class="px-4 border-b border-gray-200 select-none flex-none" x-show="!drawerHidden">
3
- <div class="-mb-px flex cursor-auto relative">
2
+ <div class="pl-4 border-b border-gray-300 select-none flex-none" x-show="!drawerHidden">
3
+ <div class="flex cursor-auto relative">
4
4
  <div
5
5
  id="inspector-tabs-<%= example.id %>"
6
6
  x-data="tabs"
7
- class="min-w-0"
7
+ class="min-w-0 -mb-px"
8
8
  x-effect="$store.inspector.drawer.visibleTabCount = visibleTabCount"
9
9
  >
10
10
  <nav x-ref="tabs" class="flex h-10 space-x-8 flex-grow pr-8">
@@ -14,11 +14,11 @@
14
14
  href="#inspector-panel-<%= key %>"
15
15
  class="whitespace-nowrap pt-2.5 pb-1.5 px-1 border-b-2 cursor-pointer <%= "!text-gray-300" if props[:disabled] %>"
16
16
  :class="{
17
- 'border-indigo-400': isActivePanel('<%= key %>'),
18
- 'border-transparent text-gray-500 hover:text-gray-700': !isActivePanel('<%= key %>'),
17
+ 'border-indigo-400': isActiveDrawerPanel('<%= key %>'),
18
+ 'border-transparent text-gray-500 hover:text-gray-700': !isActiveDrawerPanel('<%= key %>'),
19
19
  'invisible': (<%= i %> > visibleTabCount)
20
20
  }"
21
- @click.stop.prevent="switchPanel('<%= key %>')"
21
+ @click.stop.prevent="switchDrawerPanel('<%= key %>')"
22
22
  <% if props[:hotkey] %>data-hotkey="<%= props[:hotkey] %>"<% end %>
23
23
  >
24
24
  <%== props[:label] %>
@@ -41,14 +41,13 @@
41
41
  <template id="inspector-dropdown-tab-<%= key %>-<%= example.id %>" x-if="<%= i %> > $store.inspector.drawer.visibleTabCount">
42
42
  <div :class="{'border-t border-gray-300': (<%= i %> > $store.inspector.drawer.visibleTabCount + 1)}">
43
43
  <a
44
-
45
44
  href="#inspector-panel-<%= key %>"
46
45
  class="block whitespace-nowrap py-2 px-4 border-l-2 cursor-pointer <%= "!text-gray-300" if props[:disabled] %>"
47
46
  :class="{
48
- 'border-indigo-400': $store.inspector.drawer.active === '<%= key %>',
49
- 'border-transparent text-gray-500 hover:text-gray-700': $store.inspector.drawer.active !== '<%= key %>',
47
+ 'border-indigo-400': $store.inspector.drawer.panel === '<%= key %>',
48
+ 'border-transparent text-gray-500 hover:text-gray-700': $store.inspector.drawer.panel !== '<%= key %>',
50
49
  }"
51
- @click.stop.prevent=" hideDropdown(); switchPanel('<%= key %>')"
50
+ @click.stop.prevent=" hideDropdown(); switchDrawerPanel('<%= key %>')"
52
51
  >
53
52
  <%== props[:label] %>
54
53
  </a>
@@ -58,31 +57,35 @@
58
57
  </div>
59
58
  </nav>
60
59
  </div>
61
- <div class="flex items-center ml-auto pl-8 space-x-3">
62
- <% panels.each do |key, props| %>
63
- <div
64
- ref="<%= "inspector-panel-#{example.id}-#{key}-copy" %>"
65
- class="flex items-center"
66
- :class="{'pointer-events-none opacity-30': <%= !props[:copy].present? %>}"
67
- x-show="isActivePanel('<%= key %>')"
68
- >
69
- <button
70
- class="text-gray-400 transition"
71
- x-data="copy('<%= "inspector-panel-#{example.id}-#{key}-clipboard" %>')"
72
- x-tooltip.theme.lookbook="done ? 'copied!' : 'copy to clipboard'"
73
- @click="save"
74
- :class="{
75
- '!text-green-600 hover:text-green-600': done,
76
- 'hover:text-indigo-500': !done}"
60
+ <div class="flex items-center bg-white border-l border-gray-200 ml-auto space-x-3 px-3">
61
+ <div>
62
+ <% panels.each do |key, props| %>
63
+ <div
64
+ ref="<%= "inspector-panel-#{example.id}-#{key}-copy" %>"
65
+ class="flex items-center"
66
+ :class="{'pointer-events-none opacity-30': <%= !props[:copy].present? %>}"
67
+ x-show="isActiveDrawerPanel('<%= key %>')"
77
68
  x-cloak
78
- <% unless props[:copy].present? %>disabled<% end %>
79
69
  >
80
- <%= icon "${done ? 'check' : 'clipboard'}", size: 4 %>
81
- </button>
82
- </div>
83
- <% end %>
70
+ <button
71
+ data-target="<%= "inspector-panel-#{example.id}-#{key}-clipboard" %>"
72
+ class="text-gray-400 transition"
73
+ x-data="copy"
74
+ x-tooltip.theme.lookbook="done ? 'copied!' : 'copy to clipboard'"
75
+ @click="save"
76
+ :class="{
77
+ '!text-green-600 hover:text-green-600': done,
78
+ 'hover:text-indigo-500': !done}"
79
+ x-cloak
80
+ <% unless props[:copy].present? %>disabled<% end %>
81
+ >
82
+ <%= icon "${done ? 'check' : 'clipboard'}", size: 4 %>
83
+ </button>
84
+ </div>
85
+ <% end %>
86
+ </div>
84
87
  <button
85
- x-tooltip.theme.lookbook="`switch orientation`"
88
+ x-tooltip.theme.lookbook="`${horizontal ? 'pin drawer on right' : 'pin drawer on bottom'}`"
86
89
  @click="toggleOrientation"
87
90
  :class="{'pointer-events-none opacity-30': !canBeVertical}"
88
91
  >
@@ -91,10 +94,10 @@
91
94
  class: "scale-[-1] text-gray-400 hover:text-indigo-800" %>
92
95
  </button>
93
96
  <button
94
- x-tooltip.theme.lookbook="`close drawer`"
97
+ x-tooltip.theme.lookbook="`hide drawer`"
95
98
  @click="toggleDrawer"
96
99
  >
97
- <%= icon "x",
100
+ <%= icon "x-circle",
98
101
  size: 4,
99
102
  class: "text-gray-400 hover:text-indigo-800" %>
100
103
  </button>
@@ -105,7 +108,7 @@
105
108
  <% panels.each do |key, props| %>
106
109
  <div
107
110
  class="h-full w-full absolute inset-0"
108
- x-show="$store.inspector.drawer.active === '<%= key %>'"
111
+ x-show="isActiveDrawerPanel('<%= key %>')"
109
112
  x-cloak
110
113
  >
111
114
  <div id="inspector-panel-<%= example.id %>-<%= key %>" class="h-full">
@@ -1,5 +1,5 @@
1
- <header class="py-2 px-4 w-full flex-none bg-white border-b border-gray-300 flex items-center h-10 select-none min-w-0">
2
- <button class="flex-none mr-3" x-show="!$store.layout.desktop" @click="$store.sidebar.toggle">
1
+ <header class="pl-4 w-full flex-none bg-white border-b border-gray-300 flex items-center h-10 select-none min-w-0">
2
+ <button class="flex-none mr-6" x-show="!$store.layout.desktop" @click="$store.sidebar.toggle">
3
3
  <svg class="feather w-5 h-5 hover:text-indigo-500 transition">
4
4
  <use xlink:href="/lookbook-assets/feather-sprite.svg#menu" />
5
5
  </svg>
@@ -6,6 +6,8 @@
6
6
  <% end %>
7
7
  <% end %>
8
8
  <% else %>
9
- <% example = examples.first %>
10
- <%= component "nav_item", item: example, depth: example.hierarchy_depth, label: node.label, display: :node %>
9
+ <% if examples.any? %>
10
+ <% example = examples.first %>
11
+ <%= component "nav_item", item: example, depth: example.hierarchy_depth, label: node.label, display: :node %>
12
+ <% end %>
11
13
  <% end %>
@@ -2,10 +2,8 @@
2
2
  value = params.key?(param[:name]) ? params[param[:name]] : param[:default]
3
3
  %>
4
4
  <div
5
- id="<%= @example.id %>-param-<%= param[:name] %>-input"
5
+ ref="<%= @example.id %>-param-<%= param[:name] %>-input"
6
6
  class="px-4 py-3"
7
- x-data="param('<%= param[:name] %>', <%= value.to_json %>)"
8
- <% if i == 0 %>x-effect="if ($store.inspector.drawer.active === 'params') setFocus()"<% end %>
9
7
  >
10
8
  <div class="flex items-start max-w-[800px]">
11
9
  <div class="flex-none py-2" :style="`width: ${horizontal ? '200' : '120' }px`">
@@ -16,8 +14,7 @@ value = params.key?(param[:name]) ? params[param[:name]] : param[:default]
16
14
  <div class="flex-grow">
17
15
  <%= render "lookbook/inputs/#{param[:input]}",
18
16
  **param,
19
- value: value,
20
- id: "#{@example.id}-param-#{param[:name]}-input"
17
+ value: value
21
18
  %>
22
19
  </div>
23
20
  </div>