-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5bacd2f
commit 23db4f2
Showing
4 changed files
with
315 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# frozen_string_literal: true | ||
|
||
module PhlexyUI | ||
class Drawer < Base | ||
def initialize(*, id:, as: :section, **) | ||
super(*, **) | ||
@as = as | ||
@id = id | ||
end | ||
|
||
def view_template(&) | ||
generate_classes!( | ||
component_html_class: :drawer, | ||
modifiers_map: DRAWER_MODIFIERS_MAP, | ||
base_modifiers:, | ||
options: | ||
).then do |classes| | ||
public_send(as, class: classes, **options, &) | ||
end | ||
end | ||
|
||
def toggle(**options, &) | ||
generate_classes!( | ||
component_html_class: :"drawer-toggle", | ||
options: | ||
).then do |classes| | ||
input(id:, type: :checkbox, class: classes, **options, &) | ||
end | ||
end | ||
|
||
def content(as: :div, **options, &) | ||
generate_classes!( | ||
component_html_class: :"drawer-content", | ||
options: | ||
).then do |classes| | ||
public_send(as, class: classes, **options, &) | ||
end | ||
end | ||
|
||
def side(as: :div, **options, &) | ||
generate_classes!( | ||
component_html_class: :"drawer-side", | ||
options: | ||
).then do |classes| | ||
public_send(as, class: classes, **options, &) | ||
end | ||
end | ||
|
||
def overlay(**options, &) | ||
generate_classes!( | ||
component_html_class: :"drawer-overlay", | ||
options: | ||
).then do |classes| | ||
label(for: id, class: classes, **options, &) | ||
end | ||
end | ||
|
||
def button(*, **, &) | ||
render Button.new(*, as: :label, for: id, **, &) | ||
end | ||
|
||
private | ||
|
||
DRAWER_MODIFIERS_MAP = { | ||
end: "drawer-end", | ||
open: "drawer-open" | ||
}.freeze | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
require "spec_helper" | ||
|
||
describe PhlexyUI::Drawer do | ||
subject(:output) { render described_class.new } | ||
|
||
describe "conditions" do | ||
{ | ||
end: "drawer-end", | ||
open: "drawer-open" | ||
}.each do |condition, css| | ||
context "when given :#{condition} condition" do | ||
subject(:output) { render described_class.new(condition, id: :my_drawer) } | ||
|
||
it "renders it apart from the main class" do | ||
expected_html = html <<~HTML | ||
<section class="drawer #{css}"></section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
end | ||
|
||
context "when condition doesn't exist" do | ||
it "raises an error" do | ||
expect { render described_class.new(:foo, id: :my_drawer) } | ||
.to raise_error( | ||
ArgumentError, | ||
"Condition `foo` is not defined for PhlexyUI::Drawer" | ||
) | ||
end | ||
end | ||
|
||
context "when given multiple conditions" do | ||
subject(:output) { render described_class.new(:end, :open, id: :my_drawer) } | ||
|
||
it "renders them separately" do | ||
expected_html = html <<~HTML | ||
<section class="drawer drawer-end drawer-open"></section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
end | ||
|
||
describe "data" do | ||
subject(:output) do | ||
render described_class.new(:open, id: :my_drawer, data: {foo: "bar"}) | ||
end | ||
|
||
it "renders it correctly" do | ||
expected_html = html <<~HTML | ||
<section class="drawer drawer-open" data-foo="bar"></section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
|
||
describe "prefix" do | ||
around do |example| | ||
original_prefix = PhlexyUI.configuration.prefix | ||
|
||
PhlexyUI.configure do |config| | ||
config.prefix = "foo-" | ||
end | ||
|
||
example.run | ||
|
||
PhlexyUI.configure do |config| | ||
config.prefix = original_prefix | ||
end | ||
end | ||
|
||
subject(:output) do | ||
render described_class.new(:open, id: :my_drawer) | ||
end | ||
|
||
it "renders it correctly" do | ||
expected_html = html <<~HTML | ||
<section class="foo-drawer foo-drawer-open"></section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
|
||
describe "responsiveness" do | ||
%i[sm md lg].each do |viewport| | ||
context "when given an :#{viewport} responsive option as a single argument" do | ||
subject(:output) do | ||
render described_class.new(:open, viewport => :end, :id => :my_drawer) | ||
end | ||
|
||
it "renders it separately with a responsive prefix" do | ||
expected_html = html <<~HTML | ||
<section class="drawer drawer-open #{viewport}:drawer-end"> | ||
</section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
|
||
context "when given multiple responsive options as an array" do | ||
subject(:output) do | ||
render described_class.new(:open, viewport => [:open, :end], :id => :my_drawer) | ||
end | ||
|
||
it "renders it separately with a responsive prefix" do | ||
expected_html = html <<~HTML | ||
<section class=" | ||
drawer | ||
drawer-open | ||
#{viewport}:drawer-open | ||
#{viewport}:drawer-end"> | ||
</section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
|
||
context "when it's prefixed" do | ||
around do |example| | ||
original_prefix = PhlexyUI.configuration.prefix | ||
|
||
PhlexyUI.configure do |config| | ||
config.prefix = "foo-" | ||
end | ||
|
||
example.run | ||
|
||
PhlexyUI.configure do |config| | ||
config.prefix = original_prefix | ||
end | ||
end | ||
|
||
subject(:output) do | ||
render described_class.new(:open, viewport => [:open, :end], :id => :my_drawer) | ||
end | ||
|
||
it "renders it separately with a responsive prefix" do | ||
expected_html = html <<~HTML | ||
<section class=" | ||
foo-drawer | ||
foo-drawer-open | ||
#{viewport}:foo-drawer-open | ||
#{viewport}:foo-drawer-end"> | ||
</section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
end | ||
end | ||
|
||
describe "rendering via Kit" do | ||
subject(:output) do | ||
Drawer(:end, id: :my_drawer) | ||
end | ||
|
||
it "renders it correctly" do | ||
expected_html = html <<~HTML | ||
<section class="drawer drawer-end"></section> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
|
||
describe "passing :as option" do | ||
subject(:output) { render described_class.new(as: :div, id: :my_drawer) } | ||
|
||
it "renders the card as the given tag" do | ||
expected_html = html <<~HTML | ||
<div class="drawer"></div> | ||
HTML | ||
|
||
expect(output).to eq(expected_html) | ||
end | ||
end | ||
|
||
describe "rendering a full drawer" do | ||
let(:component) do | ||
Class.new(Phlex::HTML) do | ||
def view_template(&) | ||
render PhlexyUI::Drawer.new(:end, id: :my_drawer) do |drawer| | ||
drawer.toggle(class: "my-toggle", data: {my: "toggles"}) | ||
drawer.content(class: "my-content", data: {my: "contents"}) do | ||
drawer.button(:primary, class: "my-button", data: {my: "buttons"}) do | ||
"Open Drawer" | ||
end | ||
|
||
div do | ||
"Content" | ||
end | ||
end | ||
drawer.side(class: "my-side", data: {my: "sides"}) do |side| | ||
side.overlay | ||
|
||
ul do | ||
li do | ||
a do | ||
"Sidebar Item 1" | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
subject(:output) do | ||
render component.new | ||
end | ||
|
||
it "is expected to match the formatted HTML" do | ||
expected_html = html <<~HTML | ||
<section class="drawer drawer-end"> | ||
<input id="my_drawer" type="checkbox" class="drawer-toggle my-toggle" data-my="toggles"> | ||
<div class="drawer-content my-content" data-my="contents"> | ||
<label class="btn btn-primary my-button" for="my_drawer" data-my="buttons">Open Drawer</label> | ||
<div>Content</div> | ||
</div> | ||
<div class="drawer-side my-side" data-my="sides"> | ||
<label for="my_drawer" class="drawer-overlay"></label> | ||
<ul> | ||
<li> | ||
<a>Sidebar Item 1</a> | ||
</li> | ||
</ul> | ||
</div> | ||
</section> | ||
HTML | ||
|
||
is_expected.to eq(expected_html) | ||
end | ||
end | ||
end |