Skip to content

Commit

Permalink
Hammy template implements new design on static pages controller
Browse files Browse the repository at this point in the history
  • Loading branch information
martinemde committed Oct 9, 2024
1 parent ea8688c commit b11b1d6
Show file tree
Hide file tree
Showing 43 changed files with 1,165 additions and 101 deletions.
1 change: 1 addition & 0 deletions app/assets/config/manifest.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//= link application.css
//= link hammy.css
//= link_tree ../../../vendor/assets/images
//= link_tree ../builds
//= link_tree ../../javascript .js
Expand Down
8 changes: 5 additions & 3 deletions app/assets/stylesheets/application.tailwind.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
@config "../../../config/tailwind.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
@font-face {
font-family: "Titillium Web";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/fonts/Roboto.woff2) format('woff2');
src: url("/fonts/Titillium Web.woff2") format('woff2');
}

}

@tailwind components;
@tailwind utilities;
11 changes: 11 additions & 0 deletions app/assets/stylesheets/hammy.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*/

/* Default browser style adds a max width that is hard to override with tailwind directly */
dialog:modal {
max-width: 100vw;
}
9 changes: 9 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ def self.http_basic_authenticate_with(**options)
super
end

def breadcrumbs
@breadcrumbs ||= []
end
helper_method :breadcrumbs

def add_breadcrumb(name, link = nil)
breadcrumbs << [name, link]
end

protected

def http_basic_authentication_options_valid?(**options)
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/dashboards_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ class DashboardsController < ApplicationController
before_action :redirect_to_new_mfa, if: :mfa_required_not_yet_enabled?
before_action :redirect_to_settings_strong_mfa_required, if: :mfa_required_weak_level_enabled?

layout "hammy"

def show
add_breadcrumb t("breadcrumbs.dashboard"), dashboard_path

respond_to do |format|
format.html do
@my_gems = current_user.rubygems.with_versions.by_name.preload(:most_recent_version)
Expand Down
3 changes: 3 additions & 0 deletions app/controllers/pages_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
class PagesController < ApplicationController
before_action :find_page

layout "hammy"

def show
add_breadcrumb t("pages.#{@page}.title")
render @page
end

Expand Down
4 changes: 2 additions & 2 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def flash_message(name, msg)
msg
end

def rubygem_search_field(home: false)
def rubygem_search_field(home: false, **kwargs)
data = {
autocomplete_target: "query",
action: %w[
Expand All @@ -96,7 +96,7 @@ def rubygem_search_field(home: false)
params[:query],
placeholder: t("layouts.application.header.search_gem_html"),
autofocus: current_page?(root_url),
class: home ? "home__search" : "header__search",
class: kwargs[:class] || (home ? "home__search" : "header__search"),
autocomplete: "off",
aria: { autocomplete: "list" },
data: data
Expand Down
2 changes: 2 additions & 0 deletions app/javascript/controllers/autocomplete_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default class extends Controller {
this.suggestionsTarget.innerHTML = ""
this.suggestionsTarget.removeAttribute('tabindex');
this.suggestionsTarget.removeAttribute('aria-activedescendant');
this.suggestionsTarget.classList.add('hidden');
}

hide(e) {
Expand Down Expand Up @@ -78,6 +79,7 @@ export default class extends Controller {
items.forEach((item, idx) => this.appendItem(item, idx));
this.suggestionsTarget.setAttribute('tabindex', 0);
this.suggestionsTarget.setAttribute('role', 'listbox');
this.suggestionsTarget.classList.remove('hidden');

this.suggestLength = items.length;
this.indexNumber = -1;
Expand Down
24 changes: 24 additions & 0 deletions app/javascript/controllers/dialog_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Dialog from '@stimulus-components/dialog'

export default class extends Dialog {
static targets = ["dialog", "button"]
static classes = ["button"]

connect() {
super.connect()
}

open() {
super.open()
if (this.hasButtonTarget) {
this.buttonTarget.ariaExpanded = true
}
}

close() {
if (this.hasButtonTarget) {
this.buttonTarget.ariaExpanded = false
}
super.open()
}
}
42 changes: 42 additions & 0 deletions app/javascript/controllers/reveal_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Reveal from '@stimulus-components/reveal'

export default class extends Reveal {
static targets = ["item", "toggle", "button"]
static classes = ["hidden", "toggle"]

connect() {
super.connect()
if (this.hasButtonTarget) {
this.buttonTarget.ariaExpanded = false
}
}
toggle() {
super.toggle()
if (this.hasButtonTarget) {
this.buttonTarget.ariaExpanded = this.buttonTarget.ariaExpanded !== "true"
}
if (this.hasToggleTarget && this.hasToggleClass) {
this.toggleTarget.classList.toggle(...this.toggleClasses)
}
}

show() {
super.show()
if (this.hasButtonTarget) {
this.buttonTarget.ariaExpanded = true
}
if (this.hasToggleTarget && this.hasToggleClass) {
this.toggleTarget.classList.add(...this.toggleClasses)
}
}

hide() {
super.hide()
if (this.hasToggleTarget) {
this.buttonTarget.ariaExpanded = false
}
if (this.hasToggleTarget && this.hasToggleClass) {
this.toggleTarget.classList.add(...this.toggleClasses)
}
}
}
37 changes: 37 additions & 0 deletions app/models/organization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,41 @@ def unique_with_user_handle
after_create do
record_event!(Events::OrganizationEvent::CREATED, actor_gid: memberships.first&.to_gid)
end

def self.find_by_handle(handle)
not_deleted.find_by("lower(handle) = lower(?)", handle)
end

def self.find_by_handle!(handle)
find_by_handle(handle) || raise(ActiveRecord::RecordNotFound)
end

def to_param
handle
end

def confirm_membership!(user)
membership = unconfirmed_memberships.find_by(user: user)
membership.update!(confirmed_at: Time.current)
record_event!(Events::OrganizationEvent::MEMBERSHIP_CONFIRMED, actor_gid: membership.to_gid)
end

def add_member!(user, role)
memberships.create!(user: user, role: role)
end

def remove_member!(user)
membership = memberships.find_by(user: user)
membership.destroy!
record_event!(Events::OrganizationEvent::MEMBERSHIP_REMOVED, actor_gid: membership.to_gid)
end

def delete!
update!(deleted_at: Time.current)
record_event!(Events::OrganizationEvent::DELETED, actor_gid: memberships.first&.to_gid)
end

def deleted?
deleted_at.present?
end
end
62 changes: 62 additions & 0 deletions app/views/components/button_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

class ButtonComponent < ApplicationComponent
include Phlex::Rails::Helpers::LinkTo
include Phlex::Rails::Helpers::ButtonTo

attr_reader :text, :href, :type, :options, :color_css

def initialize(text=nil, href: nil, type: :button, color: :primary, outline: false, size: :large, **options)
@text = text
@href = href
@type = type
@options = options
@options[:name] ||= nil
@color_css = button_color(color, outline)
end

def view_template(&)
css = "text-nowrap text-b2 font-semibold tracking-tight " \
"px-4 py-3 h-9 min-h-9 rounded inline-flex border-box " \
"justify-content-center items-center hover:shadow-md " \
"transition duration-200 ease-in-out focus:outline-none " \
"#{color_css} #{options.delete(:class)}"

if type == :link
link_to text, href, class: css, **options, &
elsif href
button_to text, href, class: css, **options, &
else
button(class: css, type:, **options, &)
end
end

private

def button_color(color, outline)
color = color.to_sym
color = :orange if color == :primary
color = :orange2 if color == :secondary
@color_css = outline ? OUTLINE_BUTTON_COLOR[color] : FILL_BUTTON_COLOR[color]
end

FILL_BUTTON_COLOR = {
orange: "text-white bg-orange-500 dark:bg-orange-500 hover:bg-orange-600 dark:hover:bg-orange-700 active:bg-orange-600 dark:active:bg-orange-700",
orange2: "text-neutral-800 dark:text-white bg-orange-200 dark:bg-orange-800 hover:bg-orange-300 dark:hover:bg-orange-900 active:bg-orange-300 dark:active:bg-orange-900",
yellow: "text-neutral-800 dark:text-white bg-yellow-500 dark:bg-yellow-500 hover:bg-yellow-600 dark:hover:bg-yellow-900 active:bg-yellow-600 dark:active:bg-yellow-900",
blue: "text-white bg-blue-500 dark:bg-blue-500 hover:bg-blue-600 dark:hover:bg-blue-700 active:bg-blue-600 dark:active:bg-blue-700",
green: "text-white bg-green-500 dark:bg-green-500 hover:bg-green-600 dark:hover:bg-green-700 active:bg-green-600 dark:active:bg-green-700",
red: "text-white bg-red-500 dark:bg-red-500 hover:bg-red-600 dark:hover:bg-red-700 active:bg-red-600 dark:active:bg-red-700",
neutral: "text-white bg-neutral-700 dark:bg-neutral-700 hover:bg-neutral-600 dark:hover:bg-neutral-700 active:bg-neutral-600 dark:active:bg-neutral-700",
}.freeze

OUTLINE_BUTTON_COLOR = {
orange: "border-2 border-orange-500 text-orange-500 dark:border-orange-500 dark:text-orange-500 hover:border-orange-600 hover:text-orange-600 active:border-orange-600 active:text-orange-600 dark:hover:border-orange-700 dark:hover:text-orange-700 dark:active:border-orange-700 dark:active:text-orange-700",
orange2: "border-2 border-orange-200 text-orange-200 dark:border-orange-800 dark:text-orange-800 hover:border-orange-300 hover:text-orange-300 active:border-orange-300 active:text-orange-300 dark:hover:border-orange-900 dark:hover:text-orange-900 dark:active:border-orange-900 dark:active:text-orange-900",
yellow: "border-2 border-yellow-500 text-yellow-500 dark:border-yellow-500 dark:text-yellow-500 hover:border-yellow-600 hover:text-yellow-600 active:border-yellow-600 active:text-yellow-600 dark:hover:border-yellow-900 dark:hover:text-yellow-900 dark:active:border-yellow-900 dark:active:text-yellow-900",
blue: "border-2 border-blue-500 text-blue-500 dark:border-blue-500 dark:text-blue-500 hover:border-blue-600 hover:text-blue-600 active:border-blue-600 active:text-blue-600 dark:hover:border-blue-700 dark:hover:text-blue-700 dark:active:border-blue-700 dark:active:text-blue-700",
green: "border-2 border-green-500 text-green-500 dark:border-green-500 dark:text-green-500 hover:border-green-600 hover:text-green-600 active:border-green-600 active:text-green-600 dark:hover:border-green-700 dark:hover:text-green-700 dark:active:border-green-700 dark:active:text-green-700",
red: "border-2 border-red-500 text-red-500 dark:border-red-500 dark:text-red-500 hover:border-red-600 hover:text-red-600 active:border-red-600 active:text-red-600 dark:hover:border-red-700 dark:hover:text-red-700 dark:active:border-red-700 dark:active:text-red-700",
neutral: "border-2 border-neutral-700 text-neutral-700 dark:border-neutral-700 dark:text-neutral-700 hover:border-neutral-600 hover:text-neutral-600 active:border-neutral-600 active:text-neutral-600 dark:hover:border-neutral-700 dark:hover:text-neutral-700 dark:active:border-neutral-700 dark:active:text-neutral-700",
}.freeze
end
43 changes: 43 additions & 0 deletions app/views/components/card_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

class CardComponent < ApplicationComponent
def view_template(&)
color = "bg-white dark:bg-black border border-neutral-400 dark:border-neutral-800 rounded-md shadow text-neutral-900 dark:text-neutral-100"
box = "w-full px-4 py-6 md:p-10"
article(**classes(color, box), &)
end

def head(title, icon: nil, url: nil, count: nil)
div(class: "flex justify-between items-center mb-8") do
h3(class: "flex items-center space-x-2 text-lg") do
render_icon(icon) if icon
span(class: "font-semibold") { title }
span(class: "font-light text-neutral-600") { count } if count
end

a(href: url, class: "text-sm text-orange-500 hover:underline") { t("view_all") } if url
end
end

def with_list(items, &)
ul(class: "mx-6 my-8") do
items.each do |item|
li(class: "flex justify-between items-center py-3 px-4 rounded-md border border-white dark:border-neutral-850 hover:border-neutral-700") do
yield(item)
end
end
end
end

def with_content(&)
div(class: "space-y-4", &)
end

private

def render_icon(name, width: 20, height: 20)
svg(class: "fill-orange", width:, height:) do
"<use href=\"/images/icons.svg##{name}\"/>".html_safe
end
end
end
25 changes: 25 additions & 0 deletions app/views/layouts/_breadcrumbs.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<div class="w-full bg-neutral-050 dark:bg-neutral-950 px-8 py-1 text-neutral-800 dark:text-neutral-200">
<div class="max-w-screen-xl mx-auto flex items-center">
<nav class="flex justify-start items-center text-b2" aria-label="Breadcrumb">
<!-- Home breadcrumb -->
<%= link_to root_path, class: "inline-block p-1 -ml-1 hover:text-neutral-400 content-center align-middle", title: t("breadcrumbs.home"), aria: { label: t("breadcrumbs.home") } do %>
<svg class="fill-current" height="24" width="24" role="graphics-symbol">
<title><%= t('breadcrumbs.home') %></title>
<use href="/images/icons.svg#house-siding"/>
</svg>
<% end %>
<% breadcrumbs.each do |name, link| %>
<svg class="fill-neutral-600 dark:fill-neutral-700" height="24" width="24" role="graphics-symbol" aria-hidden="true">
<use href="/images/icons.svg#chevron-right"/>
</svg>
<% if link %>
<%= link_to name, link, class: "inline-block p-1 hover:text-orange" %>
<% else %>
<!-- Current page -->
<span class="inline-block p-1 text-black dark:text-white font-semibold" aria-current="page"><%= name %></span>
<% end %>
<% end %>
</nav>
</div>
</div>
Loading

0 comments on commit b11b1d6

Please sign in to comment.