facades 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +24 -0
- data/Rakefile +1 -0
- data/app/helpers/facades_helper.rb +30 -0
- data/facades.gemspec +24 -0
- data/lib/facades/debug/html.rb +6 -0
- data/lib/facades/engine.rb +9 -0
- data/lib/facades/helpers/elements.rb +78 -0
- data/lib/facades/helpers/layout.rb +119 -0
- data/lib/facades/helpers/navigation.rb +130 -0
- data/lib/facades/stylesheets/facades/_layout.scss +2 -0
- data/lib/facades/stylesheets/facades/_reset.scss +84 -0
- data/lib/facades/stylesheets/facades/_util.css.scss +18 -0
- data/lib/facades/stylesheets/facades/layout/_forms.scss +128 -0
- data/lib/facades/stylesheets/facades/layout/_grid.scss +62 -0
- data/lib/facades/stylesheets/facades/typography/_rhythm.scss +15 -0
- data/lib/facades/version.rb +3 -0
- data/lib/facades.rb +33 -0
- data/spec/facades/helpers/elements_spec.rb +86 -0
- data/spec/facades/helpers/layout_helpers_spec.rb +5 -0
- data/spec/facades/helpers/navigation_spec.rb +4 -0
- metadata +96 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Facades
|
2
|
+
|
3
|
+
Facades is a gem designed to assist with front-end development and misc design. It includes a compass plugin / mixins, and various Rails view helpers to help with
|
4
|
+
common development tasks.
|
5
|
+
|
6
|
+
## CSS / SASS
|
7
|
+
|
8
|
+
Facades includes several mixins and includes for setting up a few defaults within your css.
|
9
|
+
|
10
|
+
### Reset
|
11
|
+
A HTML5-friendly reset is included to ensure elements like `aside`, `section` etc are setup properly. It also sets up a few typography defaults using Compass'
|
12
|
+
vertical-rhythm format.
|
13
|
+
|
14
|
+
To configure, assign the variables to `$font-size` and `$line-height`. These will default to 12px / 24px. Vertical-rhythm is defaulted to relative font sizes.
|
15
|
+
|
16
|
+
### Layout
|
17
|
+
Mixins are provided for a fixed grid, forms, and grid debugging. To setup a grid, `@include 'facades/layout/grid'` ( or simply `facades/layout`) and configure the following:
|
18
|
+
|
19
|
+
* `$grid-width` The full width of the container in which your layout resides (default 960px)
|
20
|
+
* `$grid-columns` The number of columns within the grid (default 24)
|
21
|
+
* `$grid-gutter-width` The spacing between each column (default 10px)
|
22
|
+
|
23
|
+
To debug grid alignment, a shortcut to the Compass' grid background is provided. `@include debug-grid;` into your container element to debug.
|
24
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module FacadesHelper
|
2
|
+
|
3
|
+
include Facades::Helpers::Layout
|
4
|
+
include Facades::Helpers::Navigation
|
5
|
+
|
6
|
+
def facade_assets
|
7
|
+
content = if_ie(8) do
|
8
|
+
javascript_include_tag("https://html5shim.googlecode.com/svn/trunk/html5.js")
|
9
|
+
end
|
10
|
+
content.to_s.html_safe
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Render an IE conditional statement. By default conditionals use a less-than-or-equal-to format. Use the `specific`
|
15
|
+
# param to force only that version.
|
16
|
+
#
|
17
|
+
# @param version [Integer] The IE version to target
|
18
|
+
# @param specific [Boolean] optional Target the IE version specificially.
|
19
|
+
#
|
20
|
+
#
|
21
|
+
def if_ie(version, specific = false, &block)
|
22
|
+
content = capture(&block)
|
23
|
+
condition = specific ? "IE #{version}" : "lte IE #{version}"
|
24
|
+
str = "<!--[if #{condition}]>"
|
25
|
+
str << content.html_safe.lstrip
|
26
|
+
str << "<![endif]-->"
|
27
|
+
str.html_safe
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/facades.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "facades/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "facades"
|
7
|
+
s.version = Facades::VERSION
|
8
|
+
s.authors = ["Brent Kirby"]
|
9
|
+
s.email = ["brent@kurbmedia.com"]
|
10
|
+
s.homepage = "https://github.com/kurbmedia/facades"
|
11
|
+
s.summary = %q{Mixins, utilities, and helpers for front-end design/development with Compass / Rails}
|
12
|
+
s.description = %q{Facades includes various helpers, methods, and compass/sass mixins for simplifying frontend development.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "facades"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency('sass', ['~> 3.1'])
|
22
|
+
s.add_dependency('compass', ['>= 0.11'])
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Facades
|
2
|
+
module Helpers
|
3
|
+
##
|
4
|
+
#
|
5
|
+
# Generates misc html elements that aren't included in Rails core, or are custom.
|
6
|
+
#
|
7
|
+
module Elements
|
8
|
+
|
9
|
+
##
|
10
|
+
# Generates a "button" link tag. Simply a convenience method to skip adding 'class="button"' and also adds an +icon+ option
|
11
|
+
# @see Motr::Forms::Builder#button For form related buttons
|
12
|
+
#
|
13
|
+
# @param [String] txt The link text
|
14
|
+
# @param [String] path The link href
|
15
|
+
# @param [Types] Name Description
|
16
|
+
#
|
17
|
+
# @example Create a plain link.button
|
18
|
+
# button_link('Blog', '/blog') #=> <a href="/blog" class="button">Blog</a>
|
19
|
+
# @example Create a link.button with icon
|
20
|
+
# button_link('Blog', '/blog', :icon => 'blog_image.png') #=> <a href="/blog" class="button"><img src="/images/blog_image.png" alt="Blog" /> Blog</a>
|
21
|
+
|
22
|
+
def button_link(txt, path, attrs = {}, incl_span = false)
|
23
|
+
image = attrs.delete(:icon)
|
24
|
+
klasses = (attrs.delete(:class) || "").split(" ")
|
25
|
+
klasses << 'button'
|
26
|
+
klasses = klasses.uniq.compact
|
27
|
+
content = ""
|
28
|
+
content << image_tag(image) unless image.nil?
|
29
|
+
content << (incl_span ? "<span>#{txt}</span>" : txt)
|
30
|
+
link_to content.html_safe, path, attrs.merge(:class => klasses.join(" "))
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
#
|
35
|
+
# Convenience method for outputting all current flash messages. This allows you to avoid
|
36
|
+
# using things like "if flash[:success]" and so on, which is far from DRY
|
37
|
+
#
|
38
|
+
# @param [Hash] attrs Options to modify the html attributes and settings
|
39
|
+
# @option attrs [Symbol] closer Specify HTML to be appended to the message in case you want a "close" button/link. Defaults to "<span>X</span>"
|
40
|
+
# @option attrs [Symbol] wrapper Specify the HTML element which wraps each message. Defaults to :div
|
41
|
+
#
|
42
|
+
# @example Output any available flash messages, appending a "closer" span
|
43
|
+
# In your controller:
|
44
|
+
# flash[:success] = "You did something awesome"
|
45
|
+
# In your view or layout
|
46
|
+
# <%= flash_messages :close => "<span>X</span>" %> #=> <div class="flash_message flash_message_success success">You did something awesome <span>X</span></div>
|
47
|
+
#
|
48
|
+
# @example Output a message without a "close"
|
49
|
+
# <%= flash_messages :close => false %> #=> <div class="flash_message flash_message_success success">You did something awesome</div>
|
50
|
+
#
|
51
|
+
#
|
52
|
+
def flash_messages(attrs = {})
|
53
|
+
|
54
|
+
return if flash.nil? or flash.empty?
|
55
|
+
|
56
|
+
wrapper = attrs.delete(:wrapper) || :div
|
57
|
+
closer = attrs.delete(:closer)
|
58
|
+
unless closer === false
|
59
|
+
closer ||= "<span>X</span>"
|
60
|
+
end
|
61
|
+
klasses = (attrs.delete(:class) || "").split(" ")
|
62
|
+
klasses << "flash_message"
|
63
|
+
content = ""
|
64
|
+
|
65
|
+
flash.each do |key, value|
|
66
|
+
klasses << "flash_message_#{key.to_s.underscore}"
|
67
|
+
msg_attrs = attrs.merge(:class => [key.to_s, klasses].flatten.join(' '))
|
68
|
+
content.concat content_tag(wrapper, "#{value} #{closer}".html_safe, msg_attrs).html_safe
|
69
|
+
end
|
70
|
+
|
71
|
+
content.html_safe
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Facades
|
2
|
+
module Helpers
|
3
|
+
##
|
4
|
+
#
|
5
|
+
# # Convenience helpers generally used in layout files
|
6
|
+
#
|
7
|
+
module Layout
|
8
|
+
|
9
|
+
##
|
10
|
+
#
|
11
|
+
# Allows easy assigning of meta tags from templates
|
12
|
+
# @param [Symbol] name Name of the meta tag (ie: keywords / description)
|
13
|
+
# @param [String] content The content to be used in the meta tag
|
14
|
+
# @return [String] A html meta tag with the name and content attributes set
|
15
|
+
#
|
16
|
+
def meta_tag(name, content = nil)
|
17
|
+
return _retrieve_variable(:"__#{name}") if content.nil?
|
18
|
+
content = tag(:meta, :name => name, :content => content)
|
19
|
+
_create_variable(:"__#{name}", content, false)
|
20
|
+
content
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
#
|
25
|
+
# Creates a page id to be used for identifying a page for CSS/design purposes. If a variable
|
26
|
+
# is defined, it will be used. If not, one will be generated from the current controller/action.
|
27
|
+
#
|
28
|
+
# @param [String] content The string to be used as the page id.
|
29
|
+
# @return [String] The assigned page id
|
30
|
+
# @example Create a page_id and use it in the body tag
|
31
|
+
# <%= page_id('home') %>
|
32
|
+
#
|
33
|
+
# <body id="<%= page_id %>"> #=> <body id="home">
|
34
|
+
#
|
35
|
+
# @example Defaulting page id to controller/action
|
36
|
+
# # IndexController#home
|
37
|
+
# <body id="<%= page_id %>"> #=> <body id="index_home">
|
38
|
+
#
|
39
|
+
#
|
40
|
+
def page_id(content = nil)
|
41
|
+
_create_variable(:__page_id, content, false) and return unless content.nil?
|
42
|
+
return _retrieve_variable(:__page_id) if content_for?(:__page_id)
|
43
|
+
cname = controller.class.to_s.gsub(/controller$/i,'').underscore.split("/").join('_')
|
44
|
+
aname = controller.action_name
|
45
|
+
"#{cname}_#{aname}"
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
#
|
50
|
+
# Convenienve method to create a page title for the <title></title> tag.
|
51
|
+
#
|
52
|
+
# @param [String] content The text for the page title
|
53
|
+
# @return [String] The provided content
|
54
|
+
# @example Set the page title from a view template
|
55
|
+
# <%= page_title('This is my page title') %>
|
56
|
+
#
|
57
|
+
# # In the layout:
|
58
|
+
# <title><%= page_title %></title> #=> <title>This is my page title</title>
|
59
|
+
#
|
60
|
+
def page_title(content = nil)
|
61
|
+
_create_variable(:__page_title, content, false) and return unless content.nil?
|
62
|
+
return _retrieve_variable(:__page_title) if content_for?(:__page_title)
|
63
|
+
return ""
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
#
|
68
|
+
# Convenience method for content_for allowing for single-line variable creation. Also defines a method that can be
|
69
|
+
# re-used within a template.
|
70
|
+
#
|
71
|
+
# @param [Symbol] var_name The name of the variable to create
|
72
|
+
# @param [String] content The content that variable defines
|
73
|
+
# @return [String] An empty string. Use the newly created method from +var_name+ to return the value
|
74
|
+
#
|
75
|
+
# @example Setting a "page_class" variable
|
76
|
+
# <% set_var(:page_class, 'cool') %>
|
77
|
+
# <%= page_class %> #=> 'cool'
|
78
|
+
#
|
79
|
+
#
|
80
|
+
def set_var(var_name, content)
|
81
|
+
_create_variable("#{var_name}", content) and return ''
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
#
|
86
|
+
# Configures a "robots" meta tag based on the rails environment. In environments other than 'production'
|
87
|
+
# it sets the value to "noindex, nofollow" for each page that uses the layout in which it is called. This
|
88
|
+
# helps prevent spiders from crawling / indexing content when used on staging sites.
|
89
|
+
#
|
90
|
+
# @return [String] A html meta tag for "robots" with the appropriate content attribute set
|
91
|
+
#
|
92
|
+
def robot_meta_tag
|
93
|
+
tag(:meta, :name => 'robots', :content => (Rails.env.eql?('production') ? 'index, follow' : 'noindex, nofollow'))
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def _create_variable(var, content, create_method = true) #:nodoc:
|
99
|
+
content_for(var.to_sym) do
|
100
|
+
content
|
101
|
+
end
|
102
|
+
return '' unless create_method
|
103
|
+
class_eval <<-MAKE_VAR, __FILE__, __LINE__ + 1
|
104
|
+
def #{var}
|
105
|
+
content_for(:#{var})
|
106
|
+
end
|
107
|
+
public :#{var}
|
108
|
+
MAKE_VAR
|
109
|
+
end
|
110
|
+
|
111
|
+
def _retrieve_variable(var) #:nodoc:
|
112
|
+
(content_for?(var.to_sym) ? content_for(var.to_sym) : "")
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Facades
|
2
|
+
module Helpers
|
3
|
+
##
|
4
|
+
#
|
5
|
+
# Convenience helpers for building navigation lists, and defining 'on' states.
|
6
|
+
#
|
7
|
+
module Navigation
|
8
|
+
|
9
|
+
##
|
10
|
+
#
|
11
|
+
# Creates a link wrapped in a list item, to be used within a list-based navigation.
|
12
|
+
#
|
13
|
+
# @param [String] text The text used within the link
|
14
|
+
# @param [String] path The url used as the link's +href+ attribute
|
15
|
+
# @param [Hash] attrs Hash of attributes to be applied to the link. This format is the same as Rail's +link_to+ helper
|
16
|
+
# @option attrs [String] :active_class The class to use if this link is 'active'. Defaults to "on"
|
17
|
+
# @option attrs [Proc] :proc A callback which, when called, determines the active state of the link
|
18
|
+
# @option attrs [Regex] :matcher A regular expression to be matched against +path+
|
19
|
+
# @param [Symbol] wrapper The html tag to be used as the wrapper. Defaults to +:li+
|
20
|
+
#
|
21
|
+
# @example Create a list item link to any page
|
22
|
+
# nav_link('Home Page', '/home') #=> <li><a href="/home">Home Page</a>
|
23
|
+
#
|
24
|
+
# @example 'Active state' functionality for the current page
|
25
|
+
# nav_link('Current Page', '/current_url') #=> <li class="on"><a href="/current_url" class="on">Current Page</a></li>
|
26
|
+
#
|
27
|
+
def nav_link(text, path, attrs = {}, wrapper = :li, &block)
|
28
|
+
|
29
|
+
if block_given?
|
30
|
+
return sub_nav_link(text, path, attrs, wrapper, :ol, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
link_attrs = update_link_attrs(path, attrs)
|
34
|
+
wrapper_attrs = link_attrs.delete(:wrapper)
|
35
|
+
child_link = link_to(text, path, link_attrs)
|
36
|
+
wrapper === false ? child_link : content_tag(wrapper, child_link, wrapper_attrs)
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def sub_nav_link(text, path, attrs = {}, wrapper = :li, container = :ol, &block)
|
41
|
+
wrapper_attrs = attrs.delete(:wrapper)
|
42
|
+
link_attrs = update_link_attrs(path, attrs.merge(:wrapper => (attrs.delete(:item) || {}) ))
|
43
|
+
parent_link = nav_link_to(text, path, attrs, false)
|
44
|
+
child_links = content_tag(container, capture(&block), wrapper_attrs)
|
45
|
+
content_tag(container) do
|
46
|
+
content_tag(wrapper, (parent_link << child_links), wrapper_attrs)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
private :sub_nav_link
|
50
|
+
|
51
|
+
##
|
52
|
+
#
|
53
|
+
# Creates a navigational list format, including a parent list / wrapper. Useful for nested list navigation
|
54
|
+
# @param [String] text The text used within the link
|
55
|
+
# @param [String] path The url used as the link's +href+ attribute
|
56
|
+
# @param [Hash] attrs Hash of attributes to be applied to the link. This format is the same as Rail's +link_to+ helper
|
57
|
+
# @option attrs [String] :active_class The class to use if this link is 'active'. Defaults to "on"
|
58
|
+
# @option attrs [Proc] :proc A callback which, when called, determines the active state of the link
|
59
|
+
# @option attrs [Regex] :matcher A regular expression to be matched against +path+
|
60
|
+
# @param [Symbol] wrapper The html tag to be used as the wrapper. Defaults to +:li+
|
61
|
+
# @param [Symbol] container The element that will be used as a container for the nested list
|
62
|
+
# @param [Block] &block A block containing the content of the nested items
|
63
|
+
#
|
64
|
+
# @example Create a nested list navigation
|
65
|
+
# nav do
|
66
|
+
# nav_link('About Page', '/about')
|
67
|
+
# end
|
68
|
+
# @example
|
69
|
+
# <ol>
|
70
|
+
# <li><a href="/home">Home Page</a>
|
71
|
+
# <ol>
|
72
|
+
# <li><a href="/about">Sub Page</a></li>
|
73
|
+
# </ol>
|
74
|
+
# </li>
|
75
|
+
# </ol>
|
76
|
+
#
|
77
|
+
def nav(container = :ol, html_attrs = {}, &block)
|
78
|
+
|
79
|
+
wrapper_attrs = html_attrs.delete(:wrapper) || {}
|
80
|
+
|
81
|
+
if Facades.enable_html5
|
82
|
+
content_tag(:nav, html_attrs) do
|
83
|
+
content_tag(container, capture(&block), wrapper_attrs)
|
84
|
+
end
|
85
|
+
else
|
86
|
+
content_tag(container, capture(&block), html_attrs)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# @private
|
94
|
+
def update_link_attrs(path, attrs)
|
95
|
+
|
96
|
+
proc = attrs.delete(:proc) || false
|
97
|
+
regex = attrs.delete(:matcher) || false
|
98
|
+
klasses = attrs.delete(:class).try(:split, ' ')
|
99
|
+
on_class = attrs.delete(:active_class) || "on"
|
100
|
+
wrapper_attrs = attrs.delete(:wrapper) || {}
|
101
|
+
wklasses = wrapper_attrs[:class].try(:split, ' ')
|
102
|
+
|
103
|
+
klasses ||= []
|
104
|
+
wklasses ||= []
|
105
|
+
|
106
|
+
matcher = (proc || regex || request.path)
|
107
|
+
|
108
|
+
active = case matcher
|
109
|
+
when Proc then proc.call(path)
|
110
|
+
when Regexp then request.path.match(regex)
|
111
|
+
when String then (request.path == path || request.path.match(/#{path}\/\w/im))
|
112
|
+
else raise Motr::Errors::InvalidOptions.new('Proc, Regexp or String required... passed #{matcher.class}.')
|
113
|
+
end
|
114
|
+
|
115
|
+
if active
|
116
|
+
klasses << on_class
|
117
|
+
wklasses << on_class
|
118
|
+
end
|
119
|
+
|
120
|
+
attrs.merge!(:class => klasses.join(" ")) unless klasses.compact.empty?
|
121
|
+
wrapper_attrs.merge!(:class => wklasses.join(" ")) unless wklasses.compact.empty?
|
122
|
+
|
123
|
+
attrs.merge!(:wrapper => wrapper_attrs)
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
@import 'facades/typography/rhythm';
|
2
|
+
|
3
|
+
//
|
4
|
+
// Establishes a default baseline for vertical rhythm
|
5
|
+
// CSS Reset from html5doctor.com
|
6
|
+
//
|
7
|
+
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
|
8
|
+
small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td,
|
9
|
+
article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, time, mark, audio, video {
|
10
|
+
margin:0; padding:0; border:0; outline:0; vertical-align:baseline; background:transparent;
|
11
|
+
}
|
12
|
+
body { line-height:1; }
|
13
|
+
article,aside,canvas,details,figcaption,figure,footer,header,hgroup,menu,nav,section,summary{ display:block; }
|
14
|
+
nav ul { list-style:none; }
|
15
|
+
blockquote, q {
|
16
|
+
quotes:none;
|
17
|
+
&:before, &:after{
|
18
|
+
content:'';
|
19
|
+
content:none;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
a{ margin:0; padding:0; font-size:100%; vertical-align:baseline; background:transparent; }
|
24
|
+
ins { background-color:#ff9; color:#000; text-decoration:none; }
|
25
|
+
mark { background-color:#ff9; color:#000; font-style:italic; font-weight:bold; }
|
26
|
+
del { text-decoration: line-through; }
|
27
|
+
abbr[title], dfn[title] { border-bottom:1px dotted #000; cursor:help; }
|
28
|
+
table { border-collapse:collapse; border-spacing:0; }
|
29
|
+
hr { display:block; height:1px; border:0; border-top:1px solid #cccccc; margin:1em 0; padding:0; }
|
30
|
+
input, select { vertical-align:middle; }
|
31
|
+
|
32
|
+
$base-font-size: $font-size;
|
33
|
+
$base-line-height: $line-height;
|
34
|
+
|
35
|
+
// Establish a baseline by default.
|
36
|
+
@include establish-baseline($font-size);
|
37
|
+
body{
|
38
|
+
font-size-adjust:none;
|
39
|
+
@include normal-text;
|
40
|
+
}
|
41
|
+
img{ margin:0; }
|
42
|
+
|
43
|
+
// Establish reasonable heading and font sizes, with line-heights based on vertical rhythm.
|
44
|
+
|
45
|
+
h1,h2,h3,h4,h5,h6{ font-weight:normal; }
|
46
|
+
h1{ @include font-size(32px, 2); }
|
47
|
+
h2{ @include font-size(28px, 2); }
|
48
|
+
h3{ @include font-size(26px, 2); }
|
49
|
+
h4{ @include font-size(22px, 2); }
|
50
|
+
h5{ @include font-size(16px, 1); }
|
51
|
+
h6{ @include font-size(11px, 1); }
|
52
|
+
p{ @include font-size($font-size, 1); }
|
53
|
+
|
54
|
+
a{ text-decoration:underline; color:$link-color;
|
55
|
+
&:hover{ color:$link-hover-color; }
|
56
|
+
&:focus{ color:$link-focus-color; }
|
57
|
+
&:active{ color:$link-active-color; }
|
58
|
+
&:visited{ color:$link-visited-color; }
|
59
|
+
}
|
60
|
+
|
61
|
+
blockquote{ font-style:italic; }
|
62
|
+
strong, dfn{ font-weight: bold; }
|
63
|
+
em, dfn{ font-style: italic; }
|
64
|
+
sup, sub{ line-height: 0; }
|
65
|
+
abbr, acronym{ border-bottom: 1px dotted lighten($font-color, 10%); }
|
66
|
+
address{ margin: 0 0 1.5em; font-style: italic; }
|
67
|
+
pre{ margin: 1.5em 0; white-space:pre; }
|
68
|
+
pre, code, tt{ @include fixed-width-text; }
|
69
|
+
li ul, li ol{ margin: 0; }
|
70
|
+
ul, ol{ margin: 0 1.5em 1.5em 0; padding-left: 1.5em; }
|
71
|
+
ul{ list-style-type: $unordered-list-type; }
|
72
|
+
ol{ list-style-type: $ordered-list-type; }
|
73
|
+
dl{ margin: 0 0 1.5em 0;
|
74
|
+
dt{ font-weight: bold; }
|
75
|
+
}
|
76
|
+
dd{ margin-left: 1.5em; }
|
77
|
+
table{ margin-bottom: 1.4em; width: 100%;
|
78
|
+
th{ font-weight: bold; }
|
79
|
+
thead th{ background: $table-header-color; }
|
80
|
+
th,td,caption{ padding: 4px 10px 4px 5px; }
|
81
|
+
table.striped tr:nth-child(even) td,
|
82
|
+
table tr.even td{ background:$table-stripe-color; }
|
83
|
+
}
|
84
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
// From thoughtbot/bourbon
|
2
|
+
@mixin position ($position: relative, $coordinates: 0 0 0 0) {
|
3
|
+
@if type-of($position) == list {
|
4
|
+
$coordinates: $position;
|
5
|
+
$position: relative;
|
6
|
+
}
|
7
|
+
|
8
|
+
$top: nth($coordinates, 1);
|
9
|
+
$right: nth($coordinates, 2);
|
10
|
+
$bottom: nth($coordinates, 3);
|
11
|
+
$left: nth($coordinates, 4);
|
12
|
+
position: $position;
|
13
|
+
|
14
|
+
@if not(unitless($top)){ top: $top; }
|
15
|
+
@if not(unitless($right)) { right: $right; }
|
16
|
+
@if not(unitless($bottom)) { bottom: $bottom; }
|
17
|
+
@if not(unitless($left)) { left: $left; }
|
18
|
+
}
|
@@ -0,0 +1,128 @@
|
|
1
|
+
// Default border radius used on inputs
|
2
|
+
$input-border-radius:2px !default;
|
3
|
+
// Default font size for form fields... slightly smaller than body font size
|
4
|
+
$input-font-size: .95em !default;
|
5
|
+
// Default input border color
|
6
|
+
$unfocused-border-color:#bbbbbb !default;
|
7
|
+
// Input border color when focused
|
8
|
+
$focus-border-color: #666666 !default;
|
9
|
+
// Class used on fields which are invalid
|
10
|
+
$form-error-class: 'field-with-error' !default;
|
11
|
+
// Selector representing the error class and element used to display error messages
|
12
|
+
$form-error-message-selector: 'span.error-for-field' !default;
|
13
|
+
// Text color for field hints
|
14
|
+
$form-hint-color: #ccc;
|
15
|
+
// Selector for field hints
|
16
|
+
$form-hint-selector: 'span.hint';
|
17
|
+
// Default fieldset border color
|
18
|
+
$fieldset-border-color: #ccc !default;
|
19
|
+
// Default error text color
|
20
|
+
$error-color: #bd132a !default;
|
21
|
+
// Default error background color, applies to inputs / selects / textareas
|
22
|
+
$error-bg-color: #fde0e4 !default;
|
23
|
+
// Default error border color, applies to inputs / selects / textareas
|
24
|
+
$error-border-color: #E41D38 !default;
|
25
|
+
|
26
|
+
// Mixin for styling select boxes
|
27
|
+
@mixin form-select( $font-size: $input-font-size, $normal-border: $unfocused-border-color, $focus-border: $focus-border-color, $border-radius: $input-border-radius ){
|
28
|
+
@include form-field($font-size, $input-size, $normal-border, $focus-border, $border-radius);
|
29
|
+
border-style:solid;
|
30
|
+
&:focus{ outline:none; }
|
31
|
+
&[multiple=multiple]{ border-color:$unfocused-border-color; }
|
32
|
+
}
|
33
|
+
|
34
|
+
// Mixin for styling textareas
|
35
|
+
@mixin form-textarea( $font-size: $input-font-size, $normal-border: $unfocused-border-color, $focus-border: $focus-border-color, $border-radius: $input-border-radius ){
|
36
|
+
@include form-field($font-size, $input-size, $normal-border, $focus-border, $border-radius);
|
37
|
+
margin:0.5em; padding:5px;
|
38
|
+
}
|
39
|
+
|
40
|
+
// Default input styling
|
41
|
+
@mixin form-input( $font-size: $input-font-size, $normal-border: $unfocused-border-color, $focus-border: $focus-border-color, $border-radius: $input-border-radius ){
|
42
|
+
&.text,
|
43
|
+
&[type=text],
|
44
|
+
&[type=password],
|
45
|
+
&[type=email]{
|
46
|
+
@include form-field($font-size, $input-size, $normal-border, $focus-border, $border-radius); padding:.65em;
|
47
|
+
}
|
48
|
+
&[type=checkbox],
|
49
|
+
&[type=radio]{
|
50
|
+
@include inline-block; margin-right:1em; vertical-align:baseline; width:auto;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
// Global base styles for all input types
|
55
|
+
@mixin form-field( $font-size: $input-font-size, $normal-border: $unfocused-border-color, $focus-border: $focus-border-color, $border-radius: $input-border-radius ){
|
56
|
+
@include border-radius($border-radius);
|
57
|
+
font-size:$font-size;
|
58
|
+
border-color:$normal-border;
|
59
|
+
&:focus{ outline:none; border-color:$focus-border; }
|
60
|
+
}
|
61
|
+
|
62
|
+
// Mixin for displaying errors and error messages on fields.
|
63
|
+
@mixin form-errors( $color:$error-color, $border-color:$error-border-color, $bg-color:$error-bg-color ){
|
64
|
+
&.#{$form-error-class}{
|
65
|
+
input[type=text],
|
66
|
+
input[type=password],
|
67
|
+
input[type=email],
|
68
|
+
textarea{
|
69
|
+
border:1px solid $border-color;
|
70
|
+
background:$bg-color;
|
71
|
+
}
|
72
|
+
label{ color:$color; }
|
73
|
+
#{$form-hint-selector}{ display:none; }
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
// Mixin for displaying form hints
|
78
|
+
@mixin form-field-hint( $color: $form-hint-color ){
|
79
|
+
font-size:.95em; line-height:.95em; font-weight:normal; color:$color; display:block;
|
80
|
+
}
|
81
|
+
|
82
|
+
// Mixin for styling field error messages
|
83
|
+
@mixin form-error-message($color: $error-color){
|
84
|
+
font-size:.95em; line-height:.95em; color:$error-color; display:block;
|
85
|
+
}
|
86
|
+
|
87
|
+
// Creates a column based list of fields within a form. Forms elements should be marked up using ordered lists for semantic value.
|
88
|
+
@mixin form-split-field-list{
|
89
|
+
display:block; clear:both; margin:-.5em 0px; @include pie-clearfix;
|
90
|
+
li{ float:left; margin:0 1em 0 0; vertical-align:middle;
|
91
|
+
label,
|
92
|
+
input{
|
93
|
+
&[type=text],
|
94
|
+
&[type=password],
|
95
|
+
&[type=email]{ display:block; }
|
96
|
+
}
|
97
|
+
select{ margin:.75em 0px; }
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
// Creates a single column list of fields within a form. Form elements should be marked up using ordered lists for semantic value.
|
102
|
+
@mixin form-field-list{
|
103
|
+
ol{ list-style-type:none; margin:0px; padding:0px; padding-right:10px;
|
104
|
+
li{ padding:.5em 0px;
|
105
|
+
&.clear{ clear:both; }
|
106
|
+
&.buttons{ clear:both; padding:.25em 0px 0px 0px; }
|
107
|
+
&.inline label{ @include inline-block; }
|
108
|
+
&.multifield{
|
109
|
+
input, select{ @include inline-block; }
|
110
|
+
}
|
111
|
+
ol{ @include form-split-field-list; }
|
112
|
+
@include form-errors;
|
113
|
+
|
114
|
+
#{$form-hint-selector}{ @include form-hint; }
|
115
|
+
#{$form-error-message-selector}{ @include form-error-messages( $color ); }
|
116
|
+
|
117
|
+
}
|
118
|
+
label{ display:block; }
|
119
|
+
@include form-select; @include form-input; @include form-textarea;
|
120
|
+
}
|
121
|
+
ol.inline li.label{ @include inline-block; }
|
122
|
+
label abbr{ outline:none; border:none; color:red; }
|
123
|
+
label{
|
124
|
+
font-size:12px;
|
125
|
+
height:20px;
|
126
|
+
}
|
127
|
+
fieldset{ border:none; }
|
128
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
// Fixed grid system based on a merge of Blueprint and 960gs.
|
2
|
+
$grid-gutter-width: 10px !default;
|
3
|
+
$grid-width: 960px !default;
|
4
|
+
$grid-columns: 24 !default;
|
5
|
+
$grid-column-width: $grid-width / $grid-columns * 1 - $grid-gutter-width;
|
6
|
+
|
7
|
+
@mixin container{
|
8
|
+
margin-left: auto;
|
9
|
+
margin-right: auto;
|
10
|
+
width: $grid-width;
|
11
|
+
@include pie-clearfix;
|
12
|
+
}
|
13
|
+
|
14
|
+
@function span($n){
|
15
|
+
@return $grid-width / $grid-columns * $n - $grid-gutter-width;
|
16
|
+
}
|
17
|
+
|
18
|
+
@mixin column-base($gutter: $gutter-width){
|
19
|
+
display: inline; float: left;
|
20
|
+
margin-left: $gutter / 2;
|
21
|
+
margin-right: $gutter / 2;
|
22
|
+
}
|
23
|
+
|
24
|
+
@mixin column($n, $cols: $grid-columns, $gutter: $grid-gutter-width){
|
25
|
+
@include column-base($gutter);
|
26
|
+
width:span($n);
|
27
|
+
}
|
28
|
+
|
29
|
+
@mixin first{ margin-left:0; }
|
30
|
+
@mixin last{ margin-right:0; }
|
31
|
+
|
32
|
+
@mixin prefix($n, $cols: $grid-columns){
|
33
|
+
padding-left: $grid-width / $cols * $n;
|
34
|
+
}
|
35
|
+
|
36
|
+
@mixin suffix($n, $cols: $grid-columns){
|
37
|
+
padding-right: $grid-width / $cols * $n;
|
38
|
+
}
|
39
|
+
|
40
|
+
@mixin push($n){
|
41
|
+
position:relative;
|
42
|
+
left: ($grid-width / $cols) * $n;
|
43
|
+
}
|
44
|
+
|
45
|
+
@mixin pull($n){
|
46
|
+
position:relative;
|
47
|
+
right: -($grid-width / $cols) * $n;
|
48
|
+
}
|
49
|
+
|
50
|
+
@import 'compass/layout/grid-background';
|
51
|
+
$grid-background-column-color: #eef2f9;
|
52
|
+
$grid-background-baseline-color: rgba(0,0,0,0.15);
|
53
|
+
$grid-background-gutter-color: #fff;
|
54
|
+
$grid-background-total-columns: $grid-columns;
|
55
|
+
$grid-background-column-width: $grid-column-width;
|
56
|
+
$grid-background-gutter-width: $grid-gutter-width;
|
57
|
+
$grid-background-baseline-height: #{($line-height / $font-size)}em;
|
58
|
+
|
59
|
+
|
60
|
+
@mixin debug-grid{
|
61
|
+
@include grid-background;
|
62
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
@import "compass/typography/vertical_rhythm";
|
2
|
+
@import "compass/utilities/general/clearfix";
|
3
|
+
|
4
|
+
@mixin normal-text { font-family: $font-family; color: $font-color; }
|
5
|
+
@mixin fixed-width-text { font: 1em $fixed-font-family; line-height: 1.5; }
|
6
|
+
|
7
|
+
// Shorthand overrides for Compass' adjust-font-size/leading-to
|
8
|
+
// because well.. they are freakin long.
|
9
|
+
//
|
10
|
+
@mixin font-size($size, $lines){
|
11
|
+
@include adjust-font-size-to($size, $lines);
|
12
|
+
}
|
13
|
+
@mixin leading($size, $lines){
|
14
|
+
@include adjust-leading-to($size, $lines);
|
15
|
+
}
|
data/lib/facades.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'facades/version'
|
3
|
+
|
4
|
+
module Facades
|
5
|
+
|
6
|
+
module Debug
|
7
|
+
autoload :Html, 'facades/debug/html'
|
8
|
+
end
|
9
|
+
|
10
|
+
module Helpers
|
11
|
+
autoload :Layout, 'facades/helpers/layout'
|
12
|
+
autoload :Navigation, 'facades/helpers/navigation'
|
13
|
+
autoload :Elements, 'facades/helpers/elements'
|
14
|
+
end
|
15
|
+
|
16
|
+
mattr_accessor :enable_html5
|
17
|
+
mattr_accessor :debug_html
|
18
|
+
|
19
|
+
def setup(&block)
|
20
|
+
yield self
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
Facades.enable_html5 = true
|
26
|
+
Facades.debug_html = true
|
27
|
+
|
28
|
+
require 'compass'
|
29
|
+
Compass::Frameworks.register('facades',
|
30
|
+
:stylesheets_directory => File.join(File.dirname(__FILE__), 'facades/stylesheets'),
|
31
|
+
:templates_directory => File.join(File.dirname(__FILE__), 'facades/templates'))
|
32
|
+
|
33
|
+
require 'facades/engine' if defined?(Rails)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Facades::Helpers::Elements, :type => :helper do
|
4
|
+
|
5
|
+
describe '#button_link' do
|
6
|
+
|
7
|
+
subject{ button_link("home", "/", attrs).to_html }
|
8
|
+
let(:attrs){ {} }
|
9
|
+
|
10
|
+
it { should have_selector('a.button') }
|
11
|
+
|
12
|
+
context 'when passing classes' do
|
13
|
+
let(:attrs){ { :class => 'test_class' } }
|
14
|
+
|
15
|
+
it { should have_selector('a.test_class') }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when providing an icon' do
|
19
|
+
|
20
|
+
let(:attrs) do
|
21
|
+
{ icon: 'sample.png' }
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'adds an image to the link' do
|
25
|
+
subject.should have_selector('img')
|
26
|
+
end
|
27
|
+
it 'should use the icon attribute as the image' do
|
28
|
+
subject.first('img')[:src].should match "sample.png"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#flash_messages' do
|
35
|
+
|
36
|
+
let!(:flash) do
|
37
|
+
{ success: 'test flash message' }
|
38
|
+
end
|
39
|
+
subject{ flash_messages(attrs).to_html }
|
40
|
+
|
41
|
+
let(:attrs){ {} }
|
42
|
+
|
43
|
+
context 'when rendering normally' do
|
44
|
+
|
45
|
+
it 'wraps the content in a div.flash_message' do
|
46
|
+
should have_selector('div.flash_message')
|
47
|
+
end
|
48
|
+
it 'should have a span closer' do
|
49
|
+
subject.first('div').should have_selector('span')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'adds the flash key as a html class' do
|
53
|
+
should have_selector("div.success")
|
54
|
+
end
|
55
|
+
it 'adds :key_flash_message as a html class' do
|
56
|
+
should have_selector("div.flash_message_success")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when passed false to :closer' do
|
61
|
+
|
62
|
+
let(:attrs) do
|
63
|
+
{ closer: false }
|
64
|
+
end
|
65
|
+
it 'should not add a closer span' do
|
66
|
+
subject.first('div').should_not have_selector('span')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when span is passed to :wrapper' do
|
71
|
+
|
72
|
+
let(:attrs) do
|
73
|
+
{ wrapper: :span }
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should not use a div wrapper' do
|
77
|
+
should_not have_selector('div')
|
78
|
+
end
|
79
|
+
it 'should have a span wrapper' do
|
80
|
+
should have_selector('span.flash_message')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: facades
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brent Kirby
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-07-30 00:00:00.000000000 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sass
|
17
|
+
requirement: &70302667237140 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3.1'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70302667237140
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: compass
|
28
|
+
requirement: &70302667236100 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.11'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70302667236100
|
37
|
+
description: Facades includes various helpers, methods, and compass/sass mixins for
|
38
|
+
simplifying frontend development.
|
39
|
+
email:
|
40
|
+
- brent@kurbmedia.com
|
41
|
+
executables: []
|
42
|
+
extensions: []
|
43
|
+
extra_rdoc_files: []
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- Gemfile
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- app/helpers/facades_helper.rb
|
50
|
+
- facades.gemspec
|
51
|
+
- lib/facades.rb
|
52
|
+
- lib/facades/debug/html.rb
|
53
|
+
- lib/facades/engine.rb
|
54
|
+
- lib/facades/helpers/elements.rb
|
55
|
+
- lib/facades/helpers/layout.rb
|
56
|
+
- lib/facades/helpers/navigation.rb
|
57
|
+
- lib/facades/stylesheets/facades/_layout.scss
|
58
|
+
- lib/facades/stylesheets/facades/_reset.scss
|
59
|
+
- lib/facades/stylesheets/facades/_util.css.scss
|
60
|
+
- lib/facades/stylesheets/facades/layout/_forms.scss
|
61
|
+
- lib/facades/stylesheets/facades/layout/_grid.scss
|
62
|
+
- lib/facades/stylesheets/facades/typography/_rhythm.scss
|
63
|
+
- lib/facades/version.rb
|
64
|
+
- spec/facades/helpers/elements_spec.rb
|
65
|
+
- spec/facades/helpers/layout_helpers_spec.rb
|
66
|
+
- spec/facades/helpers/navigation_spec.rb
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: https://github.com/kurbmedia/facades
|
69
|
+
licenses: []
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project: facades
|
88
|
+
rubygems_version: 1.6.2
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Mixins, utilities, and helpers for front-end design/development with Compass
|
92
|
+
/ Rails
|
93
|
+
test_files:
|
94
|
+
- spec/facades/helpers/elements_spec.rb
|
95
|
+
- spec/facades/helpers/layout_helpers_spec.rb
|
96
|
+
- spec/facades/helpers/navigation_spec.rb
|