Skip to content

Commit

Permalink
Merge pull request #6 from jrogers-hedgeye/188233440-finalize-add-aut…
Browse files Browse the repository at this point in the history
…o-storybook-to-phlex_preview-engine

DSL for registering and configuring components
  • Loading branch information
hedgeye-sdeming authored Sep 6, 2024
2 parents 20bff46 + 20965ac commit b1bd86c
Show file tree
Hide file tree
Showing 22 changed files with 213 additions and 169 deletions.
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ group :development do
gem "sprockets-rails"
gem "foreman"
gem "github_changelog_generator", "~> 1.16"

# gem 'better_errors'
# gem 'binding_of_caller'
# gem 'listen'
gem 'web-console'
end
9 changes: 8 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
phlex_storybook (0.1.9)
phlex_storybook (0.2.0)
importmap-rails
phlex-icons (~> 0.11.0)
phlex-rails (~> 1.2)
Expand Down Expand Up @@ -109,6 +109,7 @@ GEM
traces
base64 (0.2.0)
bigdecimal (3.1.8)
bindex (0.8.1)
builder (3.3.0)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
Expand Down Expand Up @@ -300,6 +301,11 @@ GEM
concurrent-ruby (~> 1.0)
uri (0.13.1)
useragent (0.16.10)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webrick (1.8.1)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
Expand All @@ -320,6 +326,7 @@ DEPENDENCIES
phlex_storybook!
puma
sprockets-rails
web-console

BUNDLED WITH
2.5.5
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
}
}

li.story-preview-active, li.story-code-active {
li.story-button-active {
@apply rounded border-slate-200 bg-slate-900;
}

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/phlex_storybook/stories_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def story_components
end

def story_component
story_components.detect { |e| e.component_name == params[:id] }
story_components.detect { |_k, e| e.name == params[:id] }&.last
end
end
end
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
static targets = ["previewBtn", "codeBtn", "preview", "code"];
static targets = ["previewBtn", "codeBtn", "sourceBtn", "preview", "code", "source"];

showCode() {
this.previewTarget.classList.add('hidden');
this.codeTarget.classList.remove('hidden');
this.previewBtnTarget.classList.remove('story-preview-active');
this.codeBtnTarget.classList.add('story-code-active');
this.activate({displayTarget: this.codeTarget, buttonTarget: this.codeBtnTarget});
this.deactivate({displayTarget: this.previewTarget, buttonTarget: this.previewBtnTarget});
this.deactivate({displayTarget: this.sourceTarget, buttonTarget: this.sourceBtnTarget});
}

showComponentSource() {
this.activate({displayTarget: this.sourceTarget, buttonTarget: this.sourceBtnTarget});
this.deactivate({displayTarget: this.codeTarget, buttonTarget: this.codeBtnTarget});
this.deactivate({displayTarget: this.previewTarget, buttonTarget: this.previewBtnTarget});
}

showPreview() {
this.previewTarget.classList.remove('hidden');
this.codeTarget.classList.add('hidden');
this.previewBtnTarget.classList.add('story-preview-active');
this.codeBtnTarget.classList.remove('story-code-active');
this.activate({displayTarget: this.previewTarget, buttonTarget: this.previewBtnTarget});
this.deactivate({displayTarget: this.codeTarget, buttonTarget: this.codeBtnTarget});
this.deactivate({displayTarget: this.sourceTarget, buttonTarget: this.sourceBtnTarget});
}

activate({displayTarget, buttonTarget}) {
displayTarget.classList.remove('hidden');
buttonTarget.classList.add('story-button-active');
}

deactivate({displayTarget, buttonTarget}) {
displayTarget.classList.add('hidden');
buttonTarget.classList.remove('story-button-active');
}
}
13 changes: 13 additions & 0 deletions lib/phlex_storybook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
# loader.setup

module PhlexStorybook
autoload :DSL, "phlex_storybook/dsl"
autoload :ApplicationComponent, "phlex_storybook/application_component"
autoload :ApplicationView, "phlex_storybook/application_view"
autoload :ComponentStory, "phlex_storybook/component_story"

module Props
autoload :Base, "phlex_storybook/props/base"
autoload :String, "phlex_storybook/props/string"
autoload :Select, "phlex_storybook/props/select"
autoload :Text, "phlex_storybook/props/text"
autoload :Boolean, "phlex_storybook/props/boolean"
end

class << self
attr_writer :configuration

Expand Down
2 changes: 1 addition & 1 deletion lib/phlex_storybook/application_view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ class ApplicationView < ApplicationComponent
include Phlex::Rails::Helpers::PathToAsset
include Phlex::Rails::Helpers::Request
include Phlex::Rails::Helpers::Tag
include ApplicationHelper
# include ApplicationHelper
end
end
2 changes: 1 addition & 1 deletion lib/phlex_storybook/assets/phlex_storybook_application.css
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,7 @@ fieldset{
}
}

li.story-preview-active, li.story-code-active{
li.story-button-active{
border-radius: 0.25rem;
--tw-border-opacity: 1;
border-color: rgb(226 232 240 / var(--tw-border-opacity));
Expand Down
39 changes: 20 additions & 19 deletions lib/phlex_storybook/components/stories/component_display.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,23 @@ def view_template

turbo_frame_tag("component_display") do
div(class: "flex flex-col h-screen max-h-screen", data: { controller: "story-display copy" }) do
render_header @story_component.component_name
render_header @story_component.name
div(class: "px-2 flex-1 overflow-y-scroll overflow-x-hidden") do
props = @props.blank? ? @story_component.story_for(@story_id) : @props
if @story_id && props.nil?
h1 { "Story not found" }
next
end

div(class: "mb-4") { @story_component.component_description }
div(class: "mb-4") { @story_component.description }

if @story_id
div(class: "container w-full h-fit min-w-0 mr-0") do
render_story_header
render ComponentRendering.new(
story_component: @story_component,
story_id: @story_id,
**props.except(:title).map.with_object({}) { |(k, v), h| h[k] = v }
)
end
elsif @story_component.component_stories.present?
div { "Select a story from the left to see its usage..." }
else
div(class: "container w-full h-fit min-w-0 mr-0") do
render_story_header
render ComponentRendering.new(story_component: @story_component, **@props)
end
div(class: "container w-full h-fit min-w-0 mr-0") do
render_story_header
render ComponentRendering.new(
story_component: @story_component,
story_id: @story_id,
**@story_component.default_story.merge(props || {}),
)
end
end
end
Expand All @@ -69,7 +60,7 @@ def render_story_header
div(class: "flex justify-between") do
ul(class: "text-sm text-white inline-flex bg-slate-700 rounded border-slate-200") do
li(
class: "relative px-3 py-2 flex-grow-1 story-preview-active",
class: "relative px-3 py-2 flex-grow-1 story-button-active",
data: {
action: "click->story-display#showPreview click->copy#disable:prevent",
story_display_target: "previewBtn",
Expand All @@ -87,6 +78,16 @@ def render_story_header
) do
button(class: "font-semibold") { "Ruby Code" }
end

li(
class: "relative px-3 py-2 flex-grow-1",
data: {
action: 'click->story-display#showComponentSource click->copy#disable:prevent',
story_display_target: 'sourceBtn',
},
) do
button(class: "font-semibold") { "Component Source" }
end
end
button(
disabled: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def initialize(story_component:, story_id: nil)
end

def view_template
if @story_component&.component_props.blank?
if @story_component&.props.blank?
turbo_frame_tag("component_properties") do
h2(class: "bg-slate-900 p-2") { "Properties" }
div(class: "px-2") { "No properties" }
Expand All @@ -27,7 +27,7 @@ def view_template
div(class: "px-2") do
form(action: helpers.story_path(@story_component, story_id: @story_id), method: 'PUT') do
ul do
@story_component.component_props.each do |prop|
@story_component.props.each do |prop|
li do
label(class: 'grid grid-cols-1 w-full') do
div { prop.label || prop.key.to_s.capitalize }
Expand Down
42 changes: 24 additions & 18 deletions lib/phlex_storybook/components/stories/component_rendering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,30 @@ def view_template
render @story_component.component.new(**@props)
end

div(
class: "hidden mt-4 w-full",
data: { story_display_target: "code" },
) do
div(id: "component-code", class: "p-2 overflow-auto scroll") do
source = @props.blank? ? "render #{@story_component.component.name}.new" : <<~RUBY.strip
render #{@story_component.component.name}.new(
#{@props.map { |k, v| "#{k}: #{v.inspect}," }.join("\n ")}
)
RUBY
pre(class: "hidden", data: { copy_target: "source" }) { source }
formatter = Rouge::Formatters::HTMLLineTable.new(Rouge::Formatters::HTML.new)
lexer = Rouge::Lexers::Ruby.new
unsafe_raw formatter.format(lexer.lex(source))
end
style do
unsafe_raw Rouge::Themes::Molokai.render(scope: '#component-code')
end
source = @props.blank? ? "render #{@story_component.component.name}.new" : <<~RUBY.strip
render #{@story_component.component.name}.new(
#{@props.map { |k, v| "#{k}: #{v.inspect}," }.join("\n ")}
)
RUBY

render_ruby_code "code", source
render_ruby_code "source", @story_component.source
end
end

def render_ruby_code(id, source)
div(
class: "hidden mt-4 w-full",
data: { story_display_target: id },
) do
div(id: id, class: "p-2 overflow-auto scroll") do
pre(class: "hidden", data: { copy_target: "source" }) { source }
formatter = Rouge::Formatters::HTMLLineTable.new(Rouge::Formatters::HTML.new)
lexer = Rouge::Lexers::Ruby.new
unsafe_raw formatter.format(lexer.lex(source))
end
style do
unsafe_raw Rouge::Themes::Molokai.render(scope: "##{id}")
end
end
end
Expand Down
15 changes: 7 additions & 8 deletions lib/phlex_storybook/components/stories/component_selector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Components
module Stories
class ComponentSelector < ApplicationView
def initialize(story_components:, selected: nil, selected_story: nil)
@story_components_by_category = story_components.group_by(&:component_category).sort
@story_components_by_category = story_components.values.group_by(&:category).sort
@selected = selected
@selected_story = selected_story
end
Expand All @@ -21,10 +21,10 @@ def view_template
li do
component_link(story_component)

if story_component.component_stories.present?
if story_component.stories.present?
ul do
story_component.component_stories&.each do |props|
li(class: "pl-4 text-sm") { story_link(story_component, props) }
story_component.stories&.each do |title, props|
li(class: "pl-4 text-sm") { story_link(story_component, title, props) }
end
end
end
Expand All @@ -46,22 +46,21 @@ def component_link(story_component)
active = story_component == @selected
a(
data: { turbo_stream: true },
href: helpers.story_path(story_component.component_name),
href: helpers.story_path(story_component.name),
class: "#{active ? active_selection : ''}",
) do
span(class: "pr-1") do
render Phlex::Icons::Lucide::Component.new(classes: "#{icon_color(active)} size-4 inline")
end
span { story_component.component_name }
span { story_component.name }
end
end

def icon_color(state)
state ? 'stroke-sky-500' : 'stroke-slate-300'
end

def story_link(story_component, props)
title = props.delete :title
def story_link(story_component, title, props)
id = story_component.id_for(title)
active = id == @selected_story
icon = active ? Phlex::Icons::Lucide::NotebookText : Phlex::Icons::Lucide::Notebook
Expand Down
22 changes: 6 additions & 16 deletions lib/phlex_storybook/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
require_relative "story_component"

module PhlexStorybook
class Configuration
attr_accessor :component_directories
attr_reader :components

def initialize
@component_directories = %w[app/components]
end

def components
component_directories.flat_map do |dir|
Dir.glob("#{dir}/**/*.rb").select { |f| File.file?(f) }.map do |file|
StoryComponent.new File.basename(file, ".rb").camelize.constantize, file
end
end
end

def component_directories
@component_directories.map { |dir| Rails.root.join dir }
@components = {}
end

def component_directories=(directories)
@component_directories = directories
def register(component, location)
@components[component] = StoryComponent.new(component, location: location)
end
end
end
Loading

0 comments on commit b1bd86c

Please sign in to comment.