Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Added

* Sidebar component.

### Changed

### Fixed
Expand Down
62 changes: 62 additions & 0 deletions app/components/flowbite/sidebar.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

module Flowbite
# Renders a fixed-position sidebar container.
#
# Use {Flowbite::Sidebar} as the outer shell and
# {Flowbite::Sidebar::Navigation} inside it to render the list of
# {Flowbite::Sidebar::Item}s.
#
# @example Usage
# <%= render(Flowbite::Sidebar.new) do %>
# <%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
# <% nav.with_item do %>
# <%= render(Flowbite::Sidebar::Item.new(href: "/dashboard")) { "Dashboard" } %>
# <% end %>
# <% end %>
# <% end %>
#
# @see https://flowbite.com/docs/components/sidebar/
# @lookbook_embed SidebarPreview
class Sidebar < ViewComponent::Base
class << self
def classes
[
"fixed", "top-0", "left-0", "z-40", "w-64", "h-screen",
"transition-transform", "-translate-x-full", "sm:translate-x-0"
]
end
end

# @param class [Array<String>] Additional CSS classes for the sidebar
# container.
# @param options [Hash] Additional HTML options for the sidebar container.
def initialize(class: nil, **options)
super()
@class = Array.wrap(binding.local_variable_get(:class))
@options = options
end

def call
content_tag(:aside, aside_options) do
content_tag(:div, class: wrapper_classes) do
content
end
end
end

private

def aside_classes
self.class.classes + @class
end

def aside_options
{class: aside_classes, "aria-label": "Sidebar"}.merge(@options)
end

def wrapper_classes
["h-full", "px-3", "py-4", "overflow-y-auto", "bg-neutral-primary-soft"]
end
end
end
68 changes: 68 additions & 0 deletions app/components/flowbite/sidebar/item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# frozen_string_literal: true

module Flowbite
class Sidebar
# Renders a sidebar navigation item.
#
# Each item renders as a list item containing a link. Optionally, an icon
# can be provided using the +icon+ slot, which will be displayed before the
# label text.
#
# @example Basic item
# <%= render Flowbite::Sidebar::Item.new(href: "/dashboard") { "Dashboard" } %>
#
# @example Item with icon
# <%= render(Flowbite::Sidebar::Item.new(href: "/dashboard")) do |item| %>
# <% item.with_icon do %>
# <svg class="w-5 h-5" ...>...</svg>
# <% end %>
# Dashboard
# <% end %>
#
# @viewcomponent_slot icon An optional icon displayed before the label text.
class Item < ViewComponent::Base
renders_one :icon

attr_reader :href, :options

class << self
def classes
[
"flex", "items-center", "px-2", "py-1.5", "text-body",
"rounded-base", "hover:bg-neutral-tertiary", "hover:text-fg-brand", "group"
]
end
end

# @param class [Array<String>] Additional CSS classes for the link element.
# @param href [String] The URL for the navigation link.
# @param options [Hash] Additional HTML attributes for the link element.
def initialize(href:, class: nil, **options)
super()
@class = Array.wrap(binding.local_variable_get(:class))
@href = href
@options = options
end

def call
content_tag(:li) do
link_options = {class: link_classes}.merge(options)
content_tag(:a, href: href, **link_options) do
concat(icon) if icon?
concat(content_tag(:span, content, class: label_classes))
end
end
end

private

def label_classes
"ms-3" if icon?
end

def link_classes
self.class.classes + @class
end
end
end
end
62 changes: 62 additions & 0 deletions app/components/flowbite/sidebar/navigation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

module Flowbite
class Sidebar
# Renders the navigation list for a sidebar.
#
# This component renders a +<ul>+ with navigation items. It can be used
# inside a {Flowbite::Sidebar} for a fixed-position sidebar, or standalone
# in any layout that needs sidebar-style navigation.
#
# @example Inside a Sidebar
# <%= render(Flowbite::Sidebar.new) do %>
# <%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
# <% nav.with_item do %>
# <%= render(Flowbite::Sidebar::Item.new(href: "/")) { "Home" } %>
# <% end %>
# <% end %>
# <% end %>
#
# @example Standalone
# <%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
# <% nav.with_item do %>
# <%= render(Flowbite::Sidebar::Item.new(href: "/")) { "Home" } %>
# <% end %>
# <% end %>
class Navigation < ViewComponent::Base
renders_many :items

class << self
def classes
["space-y-2", "font-medium"]
end
end

# @param class [Array<String>] Additional CSS classes for the list element.
# @param options [Hash] Additional HTML options for the list element.
def initialize(class: nil, **options)
super()
@class = Array.wrap(binding.local_variable_get(:class))
@options = options
end

def call
content_tag(:ul, list_options) do
items.each do |item|
concat(item)
end
end
end

private

def list_classes
self.class.classes + @class
end

def list_options
{class: list_classes}.merge(@options)
end
end
end
end
3 changes: 3 additions & 0 deletions demo/.yardoc/checksums
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ app/components/flowbite/style.rb ef063360cc99cd7a6b8e67a7693326bb5dfb0e42
app/components/flowbite/toast.rb 6b822405dd55d87d56979e6cfba55e8f73965047
app/components/flowbite/button.rb 6ae7681d3b842d73aa99cddfa5a9b107ede7fea4
app/components/flowbite/styles.rb 929c42e428ba5a8e16efacaae0f35380e2f5f95c
app/components/flowbite/sidebar.rb 85033b602a098f3334b9b3e180239ef20a1b6f90
app/components/flowbite/input/url.rb f1046824f9b06c8df8e0f567979321b82baac6fa
app/components/flowbite/breadcrumb.rb c69ffb465b6e7f2489d4ac9a928e08bdf252fe99
app/components/flowbite/card/title.rb 8067aa1e027c725896b063b67364aecfbf2f7d4e
Expand All @@ -19,6 +20,7 @@ app/components/flowbite/input/phone.rb 0dfe3e9a83c4fb9f558405a20601649c7b08922a
app/components/flowbite/input_field.rb 8ef98ace7d4ccb4f474d3063cf48cc5c83cd8068
app/components/flowbite/input/number.rb a33580788ad91308b85955fdb44d37883329dd4e
app/components/flowbite/input/select.rb 9f1a6406efdda2e29d479117a35c2a924bd888c2
app/components/flowbite/sidebar/item.rb 8dc762357988fdf6e9308de129bd7c89b6700472
app/components/flowbite/button/outline.rb 2829cf352a03c00dd99a56a05181c4e1a6794d18
app/components/flowbite/input/checkbox.rb 500f109206a47997bf2bc0732399297a92005dc0
app/components/flowbite/input/password.rb 39a4c2bb2684a0a310175307bd1bdfd9c99c6cd1
Expand All @@ -34,6 +36,7 @@ app/components/flowbite/input_field/phone.rb 6a3da98a2dded98b1c4d14c2419077fc9de
app/components/flowbite/input/radio_button.rb 60ccac6862b459b89f9f3335246a51d83ae4af63
app/components/flowbite/input_field/number.rb 32dce4e2bb586f64229dc78b541700df829068c7
app/components/flowbite/input_field/select.rb 1f9788b5fff4be2b65184e73e739da8fa9de0264
app/components/flowbite/sidebar/navigation.rb 0f79a28928a40c222210352eaad86eb111e3a401
app/components/flowbite/breadcrumb/home_icon.rb bd2e47a31a793a79f20bd792a2a7e2dd8094fc5d
app/components/flowbite/input_field/checkbox.rb 4cbc6f541842838234189b383f813b164a06379b
app/components/flowbite/input_field/password.rb 37e592f55f258cc4b81859d48763b9c0eff12f61
Expand Down
Binary file modified demo/.yardoc/object_types
Binary file not shown.
Binary file modified demo/.yardoc/objects/root.dat
Binary file not shown.
22 changes: 10 additions & 12 deletions demo/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ../..
specs:
flowbite-components (0.2.0)
flowbite-components (0.2.1)
view_component (>= 4.0.0)

GEM
Expand Down Expand Up @@ -81,11 +81,11 @@ GEM
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
base64 (0.3.0)
benchmark (0.4.1)
bigdecimal (3.2.2)
benchmark (0.5.0)
bigdecimal (4.0.1)
builder (3.3.0)
concurrent-ruby (1.3.5)
connection_pool (2.5.3)
concurrent-ruby (1.3.6)
connection_pool (3.0.2)
crass (1.0.6)
css_parser (1.21.1)
addressable
Expand Down Expand Up @@ -118,7 +118,7 @@ GEM
herb (0.8.10-x86_64-linux-musl)
htmlbeautifier (1.4.3)
htmlentities (4.3.4)
i18n (1.14.7)
i18n (1.14.8)
concurrent-ruby (~> 1.0)
io-console (0.8.1)
irb (1.15.2)
Expand Down Expand Up @@ -155,7 +155,6 @@ GEM
net-smtp
marcel (1.0.4)
mini_mime (1.1.5)
mini_portile2 (2.8.9)
minitest (6.0.1)
prism (~> 1.5)
net-imap (0.5.7)
Expand Down Expand Up @@ -257,8 +256,6 @@ GEM
rexml (3.4.4)
rouge (4.5.2)
securerandom (0.4.1)
sqlite3 (2.6.0)
mini_portile2 (~> 2.8.0)
sqlite3 (2.6.0-aarch64-linux-gnu)
sqlite3 (2.6.0-aarch64-linux-musl)
sqlite3 (2.6.0-arm-linux-gnu)
Expand All @@ -282,10 +279,11 @@ GEM
timeout (0.4.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uri (1.0.4)
uri (1.1.1)
useragent (0.16.11)
view_component (4.0.2)
activesupport (>= 7.1.0, < 8.1)
view_component (4.4.0)
actionview (>= 7.1.0)
activesupport (>= 7.1.0)
concurrent-ruby (~> 1)
websocket-driver (0.7.7)
base64
Expand Down
26 changes: 10 additions & 16 deletions demo/app/views/docs/components/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
<article
class="
flex flex-wrap md:flex-nowrap gap-8 w-full items-center
flex flex-wrap md:flex-nowrap gap-8 w-full
justify-between mx-auto
"
>
<nav
class="
-ml-2 pr-6 py-4 overflow-y-auto border-e border-default
"
id="default-sidebar"
class="flex-none h-full transition-transform -translate-x-full sm:translate-x-0"
aria-label="Sidebar"
>
<div
class="
h-full -ml-2 pr-6 py-4 overflow-y-auto border-e
border-default
"
>
<ul class="space-y-2 font-medium">
<% all_components.each do |component| %>
<li>
<%= link_to component.name, docs_component_path(:id => component.path), class: "flex items-center px-2 py-1.5 text-body rounded-base hover:bg-neutral-tertiary hover:text-fg-brand group" %>
</li>
<%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
<% all_components.each do |component| %>
<% nav.with_item do %>
<%= render(Flowbite::Sidebar::Item.new(href: docs_component_path(id: component.path)).with_content(component.name)) %>
<% end %>
</ul>
</div>
<% end %>
<% end %>
</nav>

<main class="py-4 flex-1 space-y-8">
<%= render(Docs::Headline::H1.new) { @code_object.path } %>

Expand Down
26 changes: 10 additions & 16 deletions demo/app/views/docs/pages/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
<article
class="
flex flex-wrap gap-8 w-full max-w-screen-xl items-center
flex flex-wrap gap-8 w-full max-w-screen-xl
justify-between mx-auto
"
>
<nav
class="
-ml-2 pr-6 py-4 overflow-y-auto border-e border-default
"
id="default-sidebar"
class="flex-none h-full transition-transform -translate-x-full sm:translate-x-0"
aria-label="Sidebar"
>
<div
class="
h-full -ml-2 pr-6 py-4 overflow-y-auto border-e
border-default
"
>
<ul class="space-y-2 font-medium">
<% all_pages.each do |page| %>
<li>
<%= link_to page.title, docs_page_path(page.slug), class: "flex items-center px-2 py-1.5 text-body rounded-base hover:bg-neutral-tertiary hover:text-fg-brand group" %>
</li>
<%= render(Flowbite::Sidebar::Navigation.new) do |nav| %>
<% all_pages.each do |page| %>
<% nav.with_item do %>
<%= render(Flowbite::Sidebar::Item.new(href: docs_page_path(page.slug)).with_content(page.title)) %>
<% end %>
</ul>
</div>
<% end %>
<% end %>
</nav>

<main class="py-4 flex-1">
<div class="format dark:format-invert">
<h1 class="mb-4 text-4xl tracking-tight font-bold text-gray-900 dark:text-white"><%= @page.title %></h1>
Expand Down
Loading