From 244b199877953f49c706493837b89e99ae324b29 Mon Sep 17 00:00:00 2001 From: Hong Minhee Date: Wed, 7 Sep 2011 08:21:06 +0900 Subject: [PATCH] Particularly applied Twitter Bootstrap. --- langdev/web/__init__.py | 1 + langdev/web/forum.py | 13 +- langdev/web/static/bootstrap/adaptive.less | 57 ++ langdev/web/static/bootstrap/bootstrap.less | 23 + langdev/web/static/bootstrap/forms.less | 393 +++++++++ langdev/web/static/bootstrap/patterns.less | 819 ++++++++++++++++++ langdev/web/static/bootstrap/preboot.less | 279 ++++++ langdev/web/static/bootstrap/reset.less | 136 +++ langdev/web/static/bootstrap/scaffolding.less | 110 +++ langdev/web/static/bootstrap/tables.less | 148 ++++ langdev/web/static/bootstrap/type.less | 188 ++++ langdev/web/static/style.less | 130 +-- langdev/web/templates/base.html | 87 +- langdev/web/templates/form.html | 61 +- langdev/web/templates/forum/posts.html | 5 +- langdev/web/templates/macro.html | 7 + langdev/web/templates/pager.html | 39 +- langdev/web/templates/user/signin_form.html | 9 +- langdev/web/templates/user/signup_form.html | 2 +- 19 files changed, 2317 insertions(+), 190 deletions(-) create mode 100755 langdev/web/static/bootstrap/adaptive.less create mode 100755 langdev/web/static/bootstrap/bootstrap.less create mode 100755 langdev/web/static/bootstrap/forms.less create mode 100755 langdev/web/static/bootstrap/patterns.less create mode 100755 langdev/web/static/bootstrap/preboot.less create mode 100755 langdev/web/static/bootstrap/reset.less create mode 100755 langdev/web/static/bootstrap/scaffolding.less create mode 100755 langdev/web/static/bootstrap/tables.less create mode 100755 langdev/web/static/bootstrap/type.less create mode 100644 langdev/web/templates/macro.html diff --git a/langdev/web/__init__.py b/langdev/web/__init__.py index 3483ab0..7c2ec24 100644 --- a/langdev/web/__init__.py +++ b/langdev/web/__init__.py @@ -198,6 +198,7 @@ def app(app): app.after_request_funcs.setdefault(None, []).extend(after_request_funcs) app.error_handlers.update(error_handlers) app.jinja_env.globals['method_for'] = method_for + app.jinja_env.globals['require'] = werkzeug.utils.import_string app.jinja_env.filters.update(template_filters) app.mail = flaskext.mail.Mail(app) middlewares = list(wsgi_middlewares) diff --git a/langdev/web/forum.py b/langdev/web/forum.py index 59e3d52..9dd6aa5 100644 --- a/langdev/web/forum.py +++ b/langdev/web/forum.py @@ -30,7 +30,7 @@ def get_post(post_id): def posts(): """Show a list of posts. - :query view: one of ``summary`` or ``board``. default is ``summary``. + :query view: one of ``summary`` or ``table``. default is ``table`` :query next: id of the next post what you want to fetch. It can be useful for calling API, or infinite scroll. :query offset: offset from a latest post. @@ -42,7 +42,7 @@ def posts(): posts = g.session.query(Post) \ .order_by(Post.sticky.desc(), Post.created_at.desc()) cnt = posts.count() - view = request.args.get('view', 'summary') + view = request.args.get('view', 'table') next_id = request.args.get('next') offset = int(request.args.get('offset', 0)) limit = min(int(request.args.get('limit', 20)), 100) @@ -73,9 +73,12 @@ def atom(): class PostForm(Form): - title = TextField('Title', validators=[Required()]) - body = TextAreaField('Body', validators=[Required()]) - sticky = BooleanField('Sticky') + title = TextField('Title', validators=[Required()], + description='This will be shown on the list.') + body = TextAreaField('Body', validators=[Required()], + description='Markdown format enabled.') + sticky = BooleanField('Sticky', + description='Show this post always on top.') submit = SubmitField('Submit') diff --git a/langdev/web/static/bootstrap/adaptive.less b/langdev/web/static/bootstrap/adaptive.less new file mode 100755 index 0000000..ef3054d --- /dev/null +++ b/langdev/web/static/bootstrap/adaptive.less @@ -0,0 +1,57 @@ +/* Responsive.less + * Adjusted grid styles to handle some common screen sizes + * ------------------------------------------------------- */ + + +// MOBILE PORTRAIT & LANDSCAPE +// --------------------------- +// For devices narrower than 480px +@media only screen and (max-width: 480px) { + + // Remove fixed width of containers + .container { + width: auto; + padding: 0 10px; + } + + // Undo the floating of columns + .row { + margin-left: 0; + } + .row [class^="span"] { + float: none; + width: 100%; + display: block; + margin-left: 0; + } + + // Stack form elements instead of floating them + fieldset legend { + margin-left: 0; + } + label { + float: none; + width: auto; + text-align: left; + } + div.input { + margin-left: 0; + width: 100%; + } + .input-xxlarge, + input.xxlarge, + textarea.xxlarge, + select.xxlarge { + width: 80%; + } + + // Adjust modal + .modal-backdrop { + padding: 10px; + } + .modal { + width: 100%; + margin: 0; + left: auto; + } +} \ No newline at end of file diff --git a/langdev/web/static/bootstrap/bootstrap.less b/langdev/web/static/bootstrap/bootstrap.less new file mode 100755 index 0000000..c31bd72 --- /dev/null +++ b/langdev/web/static/bootstrap/bootstrap.less @@ -0,0 +1,23 @@ +/*! + * Bootstrap v1.2.0 + * + * Copyright 2011 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + * Date: @DATE + */ + +// CSS Reset +@import "reset.less"; + +// Core +@import "preboot.less"; +@import "scaffolding.less"; + +// Styled patterns and elements +@import "type.less"; +@import "forms.less"; +@import "tables.less"; +@import "patterns.less"; \ No newline at end of file diff --git a/langdev/web/static/bootstrap/forms.less b/langdev/web/static/bootstrap/forms.less new file mode 100755 index 0000000..a16844a --- /dev/null +++ b/langdev/web/static/bootstrap/forms.less @@ -0,0 +1,393 @@ +/* Forms.less + * Base styles for various input types, form layouts, and states + * ------------------------------------------------------------- */ + + +// FORM STYLES +// ----------- + +form { + margin-bottom: @baseline; +} + +// Groups of fields with labels on top (legends) +fieldset { + margin-bottom: @baseline; + padding-top: @baseline; + legend { + display: block; + margin-left: 150px; + font-size: 20px; + line-height: 1; + *margin: 0 0 5px 145px; /* IE6-7 */ + *line-height: 1.5; /* IE6-7 */ + color: @grayDark; + } +} + +// Parent element that clears floats and wraps labels and fields together +.clearfix { + margin-bottom: @baseline; +} + +// Set font for forms +label, +input, +select, +textarea { + #font > .sans-serif(normal,13px,normal); +} + +// Float labels left +label { + padding-top: 6px; + font-size: 13px; + line-height: 18px; + float: left; + width: 130px; + text-align: right; + color: @grayDark; +} + +// Shift over the inside div to align all label's relevant content +div.input { + margin-left: 150px; +} + +// Checkboxs and radio buttons +input[type=checkbox], +input[type=radio] { + cursor: pointer; +} + +// Inputs, Textareas, Selects +input, +textarea, +select, +.uneditable-input { + display: inline-block; + width: 210px; + height: @baseline; + padding: 4px; + font-size: 13px; + line-height: @baseline; + color: @gray; + border: 1px solid #ccc; + .border-radius(3px); +} + +/* mini reset for non-html5 file types */ +input[type=checkbox], +input[type=radio] { + width: auto; + height: auto; + padding: 0; + margin: 3px 0; + *margin-top: 0; /* IE6-7 */ + line-height: normal; + border: none; +} + +input[type=file] { + background-color: #fff; + padding: initial; + border: initial; + line-height: initial; + .box-shadow(none); +} + +input[type=button], +input[type=reset], +input[type=submit] { + width: auto; + height: auto; +} + +select, +input[type=file] { + height: @baseline * 1.5; + line-height: @baseline * 1.5; +} + +textarea { + height: auto; +} + +.uneditable-input { + background-color: #eee; + display: block; + border-color: #ccc; + .box-shadow(inset 0 1px 2px rgba(0,0,0,.075)); +} + +// Placeholder text gets special styles; can't be bundled together though for some reason +:-moz-placeholder { + color: @grayLight; +} +::-webkit-input-placeholder { + color: @grayLight; +} + +// Focus states +input, +select, textarea { + @transition: border linear .2s, box-shadow linear .2s; + .transition(@transition); + .box-shadow(inset 0 1px 3px rgba(0,0,0,.1)); +} +input:focus, +textarea:focus { + outline: none; + border-color: rgba(82,168,236,.8); + @shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); + .box-shadow(@shadow); +} + +// Error styles +form div.error { + background: lighten(@red, 57%); + padding: 10px 0; + margin: -10px 0 10px; + .border-radius(4px); + @error-text: desaturate(lighten(@red, 25%), 25%); + > label, + span.help-inline, + span.help-block { + color: @red; + } + input, + textarea { + border-color: @error-text; + .box-shadow(0 0 3px rgba(171,41,32,.25)); + &:focus { + border-color: darken(@error-text, 10%); + .box-shadow(0 0 6px rgba(171,41,32,.5)); + } + } + .input-prepend, + .input-append { + span.add-on { + background: lighten(@red, 50%); + border-color: @error-text; + color: darken(@error-text, 10%); + } + } +} + +// Form element sizes +.input-mini, input.mini, textarea.mini, select.mini { + width: 60px; +} +.input-small, input.small, textarea.small, select.small { + width: 90px; +} +.input-medium, input.medium, textarea.medium, select.medium { + width: 150px; +} +.input-large, input.large, textarea.large, select.large { + width: 210px; +} +.input-xlarge, input.xlarge, textarea.xlarge, select.xlarge { + width: 270px; +} +.input-xxlarge, input.xxlarge, textarea.xxlarge, select.xxlarge { + width: 530px; +} +textarea.xxlarge { + overflow-y: scroll; +} + +// Turn off focus for disabled (read-only) form elements +input[readonly]:focus, +textarea[readonly]:focus, +input.disabled { + background: #f5f5f5; + border-color: #ddd; + .box-shadow(none); +} + +// Actions (the buttons) +.actions { + background: #f5f5f5; + margin-top: @baseline; + margin-bottom: @baseline; + padding: (@baseline - 1) 20px @baseline 150px; + border-top: 1px solid #ddd; + .border-radius(0 0 3px 3px); + .secondary-action { + float: right; + a { + line-height: 30px; + &:hover { + text-decoration: underline; + } + } + } +} + +// Help Text +.help-inline, +.help-block { + font-size: 12px; + line-height: @baseline; + color: @grayLight; +} +.help-inline { + padding-left: 5px; + *position: relative; /* IE6-7 */ + *top: -5px; /* IE6-7 */ +} + +// Big blocks of help text +.help-block { + display: block; + max-width: 600px; +} + +// Inline Fields (input fields that appear as inline objects +.inline-inputs { + color: @gray; + span, input { + display: inline-block; + } + input.mini { + width: 60px; + } + input.small { + width: 90px; + } + span { + padding: 0 2px 0 1px; + } +} + +// Allow us to put symbols and text within the input field for a cleaner look +.input-prepend, +.input-append { + input { + .border-radius(0 3px 3px 0); + } + .add-on { + background: #f5f5f5; + float: left; + display: block; + width: auto; + min-width: 16px; + padding: 4px 4px 4px 5px; + color: @grayLight; + font-weight: normal; + line-height: 18px; + height: 18px; + text-align: center; + text-shadow: 0 1px 0 #fff; + border: 1px solid #ccc; + border-right-width: 0; + .border-radius(3px 0 0 3px); + } + .active { + background: lighten(@green, 30); + border-color: @green; + } +} +.input-prepend { + .add-on { + *margin-top: 1px; /* IE6-7 */ + } +} +.input-append { + input { + float: left; + .border-radius(3px 0 0 3px); + } + .add-on { + .border-radius(0 3px 3px 0); + border-right-width: 1px; + border-left-width: 0; + } +} + +// Stacked options for forms (radio buttons or checkboxes) +.inputs-list { + margin: 0 0 5px; + width: 100%; + li { + display: block; + padding: 0; + width: 100%; + label { + display: block; + float: none; + width: auto; + padding: 0; + line-height: @baseline; + text-align: left; + white-space: normal; + strong { + color: @gray; + } + small { + font-size: 12px; + font-weight: normal; + } + } + ul.inputs-list { + margin-left: 25px; + margin-bottom: 10px; + padding-top: 0; + } + &:first-child { + padding-top: 5px; + } + } + input[type=radio], + input[type=checkbox] { + margin-bottom: 0; + } +} + +// Stacked forms +.form-stacked { + padding-left: 20px; + fieldset { + padding-top: @baseline / 2; + } + legend { + margin-left: 0; + } + label { + display: block; + float: none; + width: auto; + font-weight: bold; + text-align: left; + line-height: 20px; + padding-top: 0; + } + .clearfix { + margin-bottom: @baseline / 2; + div.input { + margin-left: 0; + } + } + .inputs-list { + margin-bottom: 0; + li { + padding-top: 0; + label { + font-weight: normal; + padding-top: 0; + } + } + } + div.error { + padding-top: 10px; + padding-bottom: 10px; + padding-left: 10px; + margin-top: 0; + margin-left: -10px; + } + .actions { + margin-left: -20px; + padding-left: 20px; + } +} diff --git a/langdev/web/static/bootstrap/patterns.less b/langdev/web/static/bootstrap/patterns.less new file mode 100755 index 0000000..413f821 --- /dev/null +++ b/langdev/web/static/bootstrap/patterns.less @@ -0,0 +1,819 @@ +/* Patterns.less + * Repeatable UI elements outside the base styles provided from the scaffolding + * ---------------------------------------------------------------------------- */ + + +// TOPBAR +// ------ + +// Topbar for Branding and Nav +.topbar { + height: 40px; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 10000; + overflow: visible; + + // Links get text shadow + a { + color: @grayLight; + text-shadow: 0 -1px 0 rgba(0,0,0,.25); + } + + // Hover and active states + a:hover, + ul .active a { + background-color: #333; + background-color: rgba(255,255,255,.05); + color: @white; + text-decoration: none; + } + + // Website name + h3 { + position: relative; + a { + float: left; + display: block; + padding: 8px 20px 12px; + margin-left: -20px; // negative indent to left-align the text down the page + color: @white; + font-size: 20px; + font-weight: 200; + line-height: 1; + } + } + + // Search Form + form { + float: left; + margin: 5px 0 0 0; + position: relative; + .opacity(100); + } + input { + background-color: #444; + background-color: rgba(255,255,255,.3); + #font > .sans-serif(13px, normal, 1); + padding: 4px 9px; + color: #fff; + color: rgba(255,255,255,.75); + border: 1px solid #111; + .border-radius(4px); + @shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0px rgba(255,255,255,.25); + .box-shadow(@shadow); + .transition(none); + + // Placeholder text gets special styles; can't be bundled together though for some reason + &:-moz-placeholder { + color: @grayLighter; + } + &::-webkit-input-placeholder { + color: @grayLighter; + } + // Hover states + &:hover { + background-color: @grayLight; + background-color: rgba(255,255,255,.5); + color: #fff; + } + // Focus states (we use .focused since IE8 and down doesn't support :focus) + &:focus, + &.focused { + outline: none; + background-color: #fff; + color: @grayDark; + text-shadow: 0 1px 0 #fff; + border: 0; + padding: 5px 10px; + .box-shadow(0 0 3px rgba(0,0,0,.15)); + } + } +} + +// gradient is applied to it's own element because overflow visible is not honored by ie when filter is present +// For backwards compatability, include .topbar .fill +.topbar-inner, +.topbar .fill { + background-color: #222; + #gradient > .vertical(#333, #222); + @shadow: 0 1px 3px rgba(0,0,0,.25), inset 0 -1px 0 rgba(0,0,0,.1); + .box-shadow(@shadow); +} + + +// NAVIGATION +// ---------- + +// Topbar Nav +// ul.nav for all topbar based navigation to avoid inheritance issues and over-specificity +// For backwards compatibility, leave in .topbar div > ul +.topbar div > ul, +.nav { + display: block; + float: left; + margin: 0 10px 0 0; + position: relative; + left: 0; + > li { + display: block; + float: left; + } + a { + display: block; + float: none; + padding: 10px 10px 11px; + line-height: 19px; + text-decoration: none; + &:hover { + color: #fff; + text-decoration: none; + } + } + .active a { + background-color: #222; + background-color: rgba(0,0,0,.5); + } + + // Secondary (floated right) nav in topbar + &.secondary-nav { + float: right; + margin-left: 10px; + margin-right: 0; + // backwards compatibility + .menu-dropdown, + .dropdown-menu { + right: 0; + } + } + // Dropdowns within the .nav + // a.menu:hover and li.open .menu for backwards compatibility + a.menu:hover, + li.open .menu, + .dropdown-toggle:hover, + .dropdown.open .dropdown-toggle { + background: #444; + background: rgba(255,255,255,.05); + } + // .menu-dropdown for backwards compatibility + .menu-dropdown, + .dropdown-menu { + background-color: #333; + // a.menu for backwards compatibility + a.menu, + .dropdown-toggle { + color: #fff; + &.open { + background: #444; + background: rgba(255,255,255,.05); + } + } + li a { + color: #999; + text-shadow: 0 1px 0 rgba(0,0,0,.5); + &:hover { + #gradient > .vertical(#292929,#191919); + color: #fff; + } + } + .divider { + background-color: #222; + border-color: #444; + } + } +} + +// For backwards compatability with new dropdowns, redeclare dropdown link padding +.topbar ul .menu-dropdown li a, +.topbar ul .dropdown-menu li a { + padding: 4px 15px; +} + +// Dropdown Menus +// Use the .menu class on any
  • element within the topbar or ul.tabs and you'll get some superfancy dropdowns +// li.menu for backwards compatibility +li.menu, +.dropdown { + position: relative; +} +// The link that is clicked to toggle the dropdown +// a.menu for backwards compatibility +a.menu:after, +.dropdown-toggle:after { + width: 0; + height: 0; + display: inline-block; + content: "↓"; + text-indent: -99999px; + vertical-align: top; + margin-top: 8px; + margin-left: 4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #fff; + .opacity(50); +} +// The dropdown menu (ul) +// .menu-dropdown for backwards compatibility +.menu-dropdown, +.dropdown-menu { + background-color: #fff; + float: left; + display: none; // None by default, but block on "open" of the menu + position: absolute; + top: 40px; + min-width: 160px; + max-width: 220px; + _width: 160px; + margin-left: 0; // override default ul styles + margin-right: 0; + padding: 6px 0; + zoom: 1; // do we need this? + border-color: #999; + border-color: rgba(0,0,0,.2); + border-style: solid; + border-width: 0 1px 1px; + .border-radius(0 0 6px 6px); + .box-shadow(0 2px 4px rgba(0,0,0,.2)); + .background-clip(padding-box); + + // Unfloat any li's to make them stack + li { + float: none; + display: block; + background-color: none; + } + // Dividers (basically an hr) within the dropdown + .divider { + height: 1px; + margin: 5px 0; + overflow: hidden; + background-color: #eee; + border-bottom: 1px solid #fff; + } +} + +.topbar .dropdown-menu, .dropdown-menu { + // Links within the dropdown menu + a { + display: block; + padding: 4px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: @gray; + text-shadow: 0 1px 0 #fff; + // Hover state + &:hover { + #gradient > .vertical(#eeeeee, #dddddd); + color: @grayDark; + text-decoration: none; + @shadow: inset 0 1px 0 rgba(0,0,0,.025), inset 0 -1px rgba(0,0,0,.025); + .box-shadow(@shadow); + } + } +} + +// Open state for the dropdown +// .open for backwards compatibility +.open, +.dropdown.open { + // .menu for backwards compatibility + .menu, + .dropdown-toggle { + color: #fff; + background: #ccc; + background: rgba(0,0,0,.3); + } + // .menu-dropdown for backwards compatibility + .menu-dropdown, + .dropdown-menu { + display: block; + } +} + + +// Tabs and Pills +.tabs, +.pills { + margin: 0 0 20px; + padding: 0; + list-style: none; + .clearfix(); + > li { + float: left; + > a { + display: block; + } + } +} + +// Basic Tabs +.tabs { + width: 100%; + border-bottom: 1px solid #ddd; + > li { + position: relative; // For the dropdowns mostly + top: 1px; + > a { + margin-right: 2px; + padding: 0 15px; + line-height: (@baseline * 2) - 1; + .border-radius(4px 4px 0 0); + &:hover { + background-color: #eee; + border-bottom: 1px solid #ddd; + text-decoration: none; + } + } + &.active > a { + background-color: #fff; + padding: 0 14px; + border: 1px solid #ddd; + border-bottom: 0; + color: @gray; + } + } + // first one for backwards compatibility + .menu-dropdown, + .dropdown-menu { + top: 35px; + border-width: 1px; + .border-radius(0 6px 6px 6px); + } + // first one for backwards compatibility + a.menu:after, + .dropdown-toggle:after { + border-top-color: #999; + margin-top: 15px; + margin-left: 5px; + } + // first one for backwards compatibility + li.open a.menu:after, + .dropdown.open .dropdown-toggle:after { + border-top-color: #555; + } +} + +// Basic pill nav +.pills { + a { + margin: 5px 3px 5px 0; + padding: 0 15px; + text-shadow: 0 1px 1px #fff; + line-height: 30px; + .border-radius(15px); + &:hover { + background: @linkColorHover; + color: #fff; + text-decoration: none; + text-shadow: 0 1px 1px rgba(0,0,0,.25); + } + } + .active a { + background: @linkColor; + color: #fff; + text-shadow: 0 1px 1px rgba(0,0,0,.25); + } +} + + +// PAGE HEADERS +// ------------ + +.hero-unit { + background-color: #f5f5f5; + margin-top: 60px; + margin-bottom: 30px; + padding: 60px; + .border-radius(6px); + h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + } + p { + font-size: 18px; + font-weight: 200; + line-height: @baseline * 1.5; + } +} +footer { + margin-top: @baseline - 1; + padding-top: @baseline - 1; + border-top: 1px solid #eee; +} + + +// PAGE HEADERS +// ------------ + +.page-header { + margin-bottom: @baseline - 1; + border-bottom: 1px solid #ddd; + .box-shadow(0 1px 0 rgba(255,255,255,.5)); + h1 { + margin-bottom: (@baseline / 2) - 1px; + } +} + + +// BUTTON STYLES +// ------------- + +// Base .btn styles +.btn { + // Button Base + cursor: pointer; + display: inline-block; + #gradient > .vertical-three-colors(#ffffff, #ffffff, 25%, darken(#ffffff, 10%)); // Don't use .gradientbar() here since it does a three-color gradient + padding: 5px 14px 6px; + text-shadow: 0 1px 1px rgba(255,255,255,.75); + color: #333; + font-size: 13px; + line-height: normal; + border: 1px solid #ccc; + border-bottom-color: #bbb; + .border-radius(4px); + @shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + .box-shadow(@shadow); + + &:hover { + background-position: 0 -15px; + color: #333; + text-decoration: none; + } + + // Primary Button Type + &.primary { + color:#fff; + .gradientBar(@blue, @blueDark) + } + + // Transitions + .transition(.1s linear all); + + // Active and Disabled states + &:active { + @shadow: inset 0 2px 4px rgba(0,0,0,.25), 0 1px 2px rgba(0,0,0,.05); + .box-shadow(@shadow); + } + &.disabled { + cursor: default; + background-image: none; + .reset-filter(); + .opacity(65); + .box-shadow(none); + } + &[disabled] { + // disabled pseudo can't be included with .disabled + // def because IE8 and below will drop it ;_; + cursor: default; + background-image: none; + .reset-filter(); + .opacity(65); + .box-shadow(none); + } + + // Button Sizes + &.large { + font-size: 16px; + line-height: normal; + padding: 9px 14px 9px; + .border-radius(6px); + } + &.small { + padding: 7px 9px 7px; + font-size: 11px; + } +} +// Super jank hack for removing border-radius from IE9 so we can keep filter gradients on alerts and buttons +:root .alert-message, +:root .btn { + border-radius: 0 \0; +} + +// Help Firefox not be a jerk about adding extra padding to buttons +button.btn, +input[type=submit].btn { + &::-moz-focus-inner { + padding: 0; + border: 0; + } +} + + +// ERROR STYLES +// ------------ + +// Base alert styles +.alert-message { + .gradientBar(#fceec1, #eedc94); // warning by default + margin-bottom: @baseline; + padding: 7px 14px; + color: @grayDark; + text-shadow: 0 1px 0 rgba(255,255,255,.5); + border-width: 1px; + border-style: solid; + .border-radius(4px); + .box-shadow(inset 0 1px 0 rgba(255,255,255,.25)); + + // Remove extra margin from content + h5 { + line-height: @baseline; + } + p { + margin-bottom: 0; + } + div { + margin-top: 5px; + margin-bottom: 2px; + line-height: 28px; + } + .btn { + // Provide actions with buttons + .box-shadow(0 1px 0 rgba(255,255,255,.25)); + } + .close { + float: right; + margin-top: -2px; + color: @black; + font-size: 20px; + font-weight: bold; + text-shadow: 0 1px 0 rgba(255,255,255,1); + .opacity(20); + &:hover { + color: @black; + text-decoration: none; + .opacity(40); + } + } + + &.block-message { + background-image: none; + background-color: lighten(#fceec1, 5%); + .reset-filter(); + padding: 14px; + border-color: #fceec1; + .box-shadow(none); + + p { + margin-right: 30px; + } + .alert-actions { + margin-top: 5px; + } + &.error, + &.success, + &.info { + color: @grayDark; + text-shadow: 0 1px 0 rgba(255,255,255,.5); + } + &.error { + background-color: lighten(#f56a66, 25%); + border-color: lighten(#f56a66, 20%); + } + &.success { + background-color: lighten(#62c462, 30%); + border-color: lighten(#62c462, 25%); + } + &.info { + background-color: lighten(#6bd0ee, 25%); + border-color: lighten(#6bd0ee, 20%); + } + } +} + + +// PAGINATION +// ---------- + +.pagination { + height: @baseline * 2; + margin: @baseline 0; + ul { + float: left; + margin: 0; + border: 1px solid #ddd; + border: 1px solid rgba(0,0,0,.15); + .border-radius(3px); + .box-shadow(0 1px 2px rgba(0,0,0,.05)); + } + li { + display: inline; + } + a { + float: left; + padding: 0 14px; + line-height: (@baseline * 2) - 2; + border-right: 1px solid; + border-right-color: #ddd; + border-right-color: rgba(0,0,0,.15); + *border-right-color: #ddd; /* IE6-7 */ + text-decoration: none; + } + a:hover, + .active a { + background-color: lighten(@blue, 45%); + } + .disabled a, + .disabled a:hover { + background-color: transparent; + color: @grayLight; + } + .next a { + border: 0; + } +} + + +// WELLS +// ----- + +.well { + background-color: #f5f5f5; + margin-bottom: 20px; + padding: 19px; + min-height: 20px; + border: 1px solid #eee; + border: 1px solid rgba(0,0,0,.05); + .border-radius(4px); + .box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); +} + + +// MODALS +// ------ + +.modal-backdrop { + background-color: rgba(0,0,0,.5); + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 1000; +} +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 2000; + width: 560px; + margin: -280px 0 0 -250px; + background-color: @white; + border: 1px solid #999; + border: 1px solid rgba(0,0,0,.3); + *border: 1px solid #999; /* IE6-7 */ + .border-radius(6px); + .box-shadow(0 3px 7px rgba(0,0,0,0.3)); + .background-clip(padding-box); +} +.modal-header { + border-bottom: 1px solid #eee; + padding: 5px 20px; + .close { + position: absolute; + right: 10px; + top: 10px; + color: #999; + line-height:10px; + font-size: 18px; + } +} +.modal-body { + padding: 20px; +} +.modal-footer { + background-color: #f5f5f5; + padding: 14px 20px 15px; + border-top: 1px solid #ddd; + .border-radius(0 0 6px 6px); + .box-shadow(inset 0 1px 0 #fff); + .clearfix(); + margin-bottom: 0; + .btn { + float: right; + margin-left: 10px; + } +} + + +// POPOVER ARROWS +// -------------- + +#popoverArrow { + .above(@arrowWidth: 5px) { + bottom: 0; + left: 50%; + margin-left: -@arrowWidth; + border-left: @arrowWidth solid transparent; + border-right: @arrowWidth solid transparent; + border-top: @arrowWidth solid #000; + } + .left(@arrowWidth: 5px) { + top: 50%; + right: 0; + margin-top: -@arrowWidth; + border-top: @arrowWidth solid transparent; + border-bottom: @arrowWidth solid transparent; + border-left: @arrowWidth solid #000; + } + .below(@arrowWidth: 5px) { + top: 0; + left: 50%; + margin-left: -@arrowWidth; + border-left: @arrowWidth solid transparent; + border-right: @arrowWidth solid transparent; + border-bottom: @arrowWidth solid #000; + } + .right(@arrowWidth: 5px) { + top: 50%; + left: 0; + margin-top: -@arrowWidth; + border-top: @arrowWidth solid transparent; + border-bottom: @arrowWidth solid transparent; + border-right: @arrowWidth solid #000; + } +} + +// TWIPSY +// ------ + +.twipsy { + display: block; + position: absolute; + visibility: visible; + padding: 5px; + font-size: 11px; + z-index: 1000; + .opacity(80); + &.above .twipsy-arrow { #popoverArrow > .above(); } + &.left .twipsy-arrow { #popoverArrow > .left(); } + &.below .twipsy-arrow { #popoverArrow > .below(); } + &.right .twipsy-arrow { #popoverArrow > .right(); } +} +.twipsy-inner { + padding: 3px 8px; + background-color: #000; + color: white; + text-align: center; + max-width: 200px; + text-decoration: none; + .border-radius(4px); +} +.twipsy-arrow { + position: absolute; + width: 0; + height: 0; +} + + +// POPOVERS +// -------- + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1000; + padding: 5px; + display: none; + &.above .arrow { #popoverArrow > .above(); } + &.right .arrow { #popoverArrow > .right(); } + &.below .arrow { #popoverArrow > .below(); } + &.left .arrow { #popoverArrow > .left(); } + .arrow { + position: absolute; + width: 0; + height: 0; + } + .inner { + background: #333; + background: rgba(0,0,0,.8); + padding: 3px; + overflow: hidden; + width: 280px; + .border-radius(6px); + .box-shadow(0 3px 7px rgba(0,0,0,0.3)); + } + .title { + background-color: #f5f5f5; + padding: 9px 15px; + line-height: 1; + .border-radius(3px 3px 0 0); + border-bottom:1px solid #eee; + } + .content { + background-color: @white; + padding: 14px; + .border-radius(0 0 3px 3px); + .background-clip(padding-box); + p, ul, ol { + margin-bottom: 0; + } + } +} \ No newline at end of file diff --git a/langdev/web/static/bootstrap/preboot.less b/langdev/web/static/bootstrap/preboot.less new file mode 100755 index 0000000..a922f56 --- /dev/null +++ b/langdev/web/static/bootstrap/preboot.less @@ -0,0 +1,279 @@ +/* Preboot.less + * Variables and mixins to pre-ignite any new web development project + * ------------------------------------------------------------------ */ + + +// VARIABLES +// --------- + +// Links +@linkColor: #0069d6; +@linkColorHover: darken(@linkColor, 10); + +// Grays +@black: #000; +@grayDark: lighten(@black, 25%); +@gray: lighten(@black, 50%); +@grayLight: lighten(@black, 75%); +@grayLighter: lighten(@black, 90%); +@white: #fff; + +// Accent Colors +@blue: #049CDB; +@blueDark: #0064CD; +@green: #46a546; +@red: #9d261d; +@yellow: #ffc40d; +@orange: #f89406; +@pink: #c3325f; +@purple: #7a43b6; + +// Baseline grid +@basefont: 13px; +@baseline: 18px; + +// Griditude +@gridColumns: 16; +@gridColumnWidth: 40px; +@gridGutterWidth: 20px; +@extraSpace: (@gridGutterWidth * 2); // For our grid calculations +@siteWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1)); + +// Color Scheme +@baseColor: @blue; // Set a base color +@complement: spin(@baseColor, 180); // Determine a complementary color +@split1: spin(@baseColor, 158); // Split complements +@split2: spin(@baseColor, -158); +@triad1: spin(@baseColor, 135); // Triads colors +@triad2: spin(@baseColor, -135); +@tetra1: spin(@baseColor, 90); // Tetra colors +@tetra2: spin(@baseColor, -90); +@analog1: spin(@baseColor, 22); // Analogs colors +@analog2: spin(@baseColor, -22); + + +// MIXINS +// ------ + +// Clearfix for clearing floats like a boss h5bp.com/q +.clearfix { + zoom: 1; + &:before, &:after { + display: table; + content: ""; + } + &:after { + clear: both; + } +} + +// Center-align a block level element +.center-block { + display: block; + margin: 0 auto; +} + +// Sizing shortcuts +.size(@height: 5px, @width: 5px) { + height: @height; + width: @width; +} +.square(@size: 5px) { + .size(@size, @size); +} + +// Input placeholder text +.placeholder(@color: @grayLight) { + :-moz-placeholder { + color: @color; + } + ::-webkit-input-placeholder { + color: @color; + } +} + +// Font Stacks +#font { + .shorthand(@weight: normal, @size: 14px, @lineHeight: 20px) { + font-size: @size; + font-weight: @weight; + line-height: @lineHeight; + } + .sans-serif(@weight: normal, @size: 14px, @lineHeight: 20px) { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: @size; + font-weight: @weight; + line-height: @lineHeight; + } + .serif(@weight: normal, @size: 14px, @lineHeight: 20px) { + font-family: "Georgia", Times New Roman, Times, serif; + font-size: @size; + font-weight: @weight; + line-height: @lineHeight; + } + .monospace(@weight: normal, @size: 12px, @lineHeight: 20px) { + font-family: "Monaco", Courier New, monospace; + font-size: @size; + font-weight: @weight; + line-height: @lineHeight; + } +} + +// Grid System +.container { + width: @siteWidth; + margin: 0 auto; + .clearfix(); +} +.columns(@columnSpan: 1) { + width: (@gridColumnWidth * @columnSpan) + (@gridGutterWidth * (@columnSpan - 1)); +} +.offset(@columnOffset: 1) { + margin-left: (@gridColumnWidth * @columnOffset) + (@gridGutterWidth * (@columnOffset - 1)) + @extraSpace; +} + +// Border Radius +.border-radius(@radius: 5px) { + -webkit-border-radius: @radius; + -moz-border-radius: @radius; + border-radius: @radius; +} + +// Drop shadows +.box-shadow(@shadow: 0 1px 3px rgba(0,0,0,.25)) { + -webkit-box-shadow: @shadow; + -moz-box-shadow: @shadow; + box-shadow: @shadow; +} + +// Transitions +.transition(@transition) { + -webkit-transition: @transition; + -moz-transition: @transition; + transition: @transition; +} + +// Background clipping +.background-clip(@clip) { + -webkit-background-clip: @clip; + -moz-background-clip: @clip; + background-clip: @clip; +} + +// CSS3 Content Columns +.content-columns(@columnCount, @columnGap: 20px) { + -webkit-column-count: @columnCount; + -moz-column-count: @columnCount; + column-count: @columnCount; + -webkit-column-gap: @columnGap; + -moz-column-gap: @columnGap; + column-gap: @columnGap; +} + +// Add an alphatransparency value to any background or border color (via Elyse Holladay) +#translucent { + .background(@color: @white, @alpha: 1) { + background-color: hsla(hue(@color), saturation(@color), lightness(@color), @alpha); + } + .border(@color: @white, @alpha: 1) { + border-color: hsla(hue(@color), saturation(@color), lightness(@color), @alpha); + background-clip: padding-box; + } +} + +// Gradient Bar Colors for buttons and allerts +.gradientBar(@primaryColor, @secondaryColor) { + #gradient > .vertical(@primaryColor, @secondaryColor); + text-shadow: 0 -1px 0 rgba(0,0,0,.25); + border-color: @secondaryColor @secondaryColor darken(@secondaryColor, 15%); + border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) fadein(rgba(0,0,0,.1), 15%); +} +// Shared colors for buttons and alerts +.btn, +.alert-message { + // Set text color + &.danger, + &.danger:hover, + &.error, + &.error:hover, + &.success, + &.success:hover, + &.info, + &.info:hover { + color: @white + } + // Danger and error appear as red + &.danger, + &.error { + .gradientBar(#ee5f5b, #c43c35); + } + // Success appears as green + &.success { + .gradientBar(#62c462, #57a957); + } + // Info appears as a neutral blue + &.info { + .gradientBar(#5bc0de, #339bb9); + } +} + +// Gradients +#gradient { + .horizontal (@startColor: #555, @endColor: #333) { + background-color: @endColor; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, right top, from(@startColor), to(@endColor)); // Konqueror + background-image: -moz-linear-gradient(left, @startColor, @endColor); // FF 3.6+ + background-image: -ms-linear-gradient(left, @startColor, @endColor); // IE10 + background-image: -webkit-gradient(linear, left top, right top, color-stop(0%, @startColor), color-stop(100%, @endColor)); // Safari 4+, Chrome 2+ + background-image: -webkit-linear-gradient(left, @startColor, @endColor); // Safari 5.1+, Chrome 10+ + background-image: -o-linear-gradient(left, @startColor, @endColor); // Opera 11.10 + background-image: linear-gradient(left, @startColor, @endColor); // Le standard + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",@startColor,@endColor)); // IE9 and down + } + .vertical (@startColor: #555, @endColor: #333) { + background-color: @endColor; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(@startColor), to(@endColor)); // Konqueror + background-image: -moz-linear-gradient(top, @startColor, @endColor); // FF 3.6+ + background-image: -ms-linear-gradient(top, @startColor, @endColor); // IE10 + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, @startColor), color-stop(100%, @endColor)); // Safari 4+, Chrome 2+ + background-image: -webkit-linear-gradient(top, @startColor, @endColor); // Safari 5.1+, Chrome 10+ + background-image: -o-linear-gradient(top, @startColor, @endColor); // Opera 11.10 + background-image: linear-gradient(top, @startColor, @endColor); // The standard + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",@startColor,@endColor)); // IE9 and down + } + .directional (@startColor: #555, @endColor: #333, @deg: 45deg) { + background-color: @endColor; + background-repeat: repeat-x; + background-image: -moz-linear-gradient(@deg, @startColor, @endColor); // FF 3.6+ + background-image: -ms-linear-gradient(@deg, @startColor, @endColor); // IE10 + background-image: -webkit-linear-gradient(@deg, @startColor, @endColor); // Safari 5.1+, Chrome 10+ + background-image: -o-linear-gradient(@deg, @startColor, @endColor); // Opera 11.10 + background-image: linear-gradient(@deg, @startColor, @endColor); // The standard + } + .vertical-three-colors(@startColor: #00b3ee, @midColor: #7a43b6, @colorStop: 50%, @endColor: #c3325f) { + background-color: @endColor; + background-repeat: no-repeat; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@startColor), color-stop(@colorStop, @midColor), to(@endColor)); + background-image: -webkit-linear-gradient(@startColor, @midColor @colorStop, @endColor); + background-image: -moz-linear-gradient(top, @startColor, @midColor @colorStop, @endColor); + background-image: -ms-linear-gradient(@startColor, @midColor @colorStop, @endColor); + background-image: -o-linear-gradient(@startColor, @midColor @colorStop, @endColor); + background-image: linear-gradient(@startColor, @midColor @colorStop, @endColor); + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",@startColor,@endColor)); // IE9 and down, gets no color-stop at all for proper fallback + } +} + +// Reset filters for IE +.reset-filter() { + filter: e(%("progid:DXImageTransform.Microsoft.gradient(enabled = false)")); +} + +// Opacity +.opacity(@opacity: 100) { + filter: e(%("alpha(opacity=%d)", @opacity)); + -khtml-opacity: @opacity / 100; + -moz-opacity: @opacity / 100; + opacity: @opacity / 100; +} \ No newline at end of file diff --git a/langdev/web/static/bootstrap/reset.less b/langdev/web/static/bootstrap/reset.less new file mode 100755 index 0000000..9e2c6be --- /dev/null +++ b/langdev/web/static/bootstrap/reset.less @@ -0,0 +1,136 @@ +/* Reset.less + * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). + * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ + + +// ERIC MEYER RESET +// -------------------------------------------------- + +html, body { margin: 0; padding: 0; } +h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, cite, code, del, dfn, em, img, q, s, samp, small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-weight: normal; font-style: normal; font-size: 100%; line-height: 1; font-family: inherit; } +table { border-collapse: collapse; border-spacing: 0; } +ol, ul { list-style: none; } +q:before, q:after, blockquote:before, blockquote:after { content: ""; } + + +// Normalize.css +// Pulling in select resets form the normalize.css project +// -------------------------------------------------- + +// Display in IE6-9 and FF3 +// ------------------------- +// Source: http://github.com/necolas/normalize.css +html { + overflow-y: scroll; + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +// Focus states +a:focus { + outline: thin dotted; +} + +// Display in IE6-9 and FF3 +// ------------------------- +// Source: http://github.com/necolas/normalize.css +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +// Display block in IE6-9 and FF3 +// ------------------------- +// Source: http://github.com/necolas/normalize.css +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +// Prevents modern browsers from displaying 'audio' without controls +// ------------------------- +// Source: http://github.com/necolas/normalize.css +audio:not([controls]) { + display: none; +} + +// Prevents sub and sup affecting line-height in all browsers +// ------------------------- +// Source: http://github.com/necolas/normalize.css +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} + +// Img border in a's and image quality +// ------------------------- +// Source: http://github.com/necolas/normalize.css +img { + border: 0; + -ms-interpolation-mode: bicubic; +} + +// Forms +// ------------------------- +// Source: http://github.com/necolas/normalize.css + +// Font size in all browsers, margin changes, misc consistency +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} +button, +input { + line-height: normal; // FF3/4 have !important on line-height in UA stylesheet + *overflow: visible; // Inner spacing ie IE6/7 +} +button::-moz-focus-inner, +input::-moz-focus-inner { // Inner padding and border oddities in FF3/4 + border: 0; + padding: 0; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; // Cursors on all buttons applied consistently + -webkit-appearance: button; // Style clicable inputs in iOS +} +input[type="search"] { // Appearance in Safari/Chrome + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5 +} +textarea { + overflow: auto; // Remove vertical scrollbar in IE6-9 + vertical-align: top; // Readability and alignment cross-browser +} \ No newline at end of file diff --git a/langdev/web/static/bootstrap/scaffolding.less b/langdev/web/static/bootstrap/scaffolding.less new file mode 100755 index 0000000..615e6be --- /dev/null +++ b/langdev/web/static/bootstrap/scaffolding.less @@ -0,0 +1,110 @@ +/* + * Scaffolding + * Basic and global styles for generating a grid system, structural layout, and page templates + * ------------------------------------------------------------------------------------------- */ + + +// GRID SYSTEM +// ----------- + +.row { + .clearfix(); + margin-left: -1 * @gridGutterWidth; + + // Find all .span# classes within .row and give them the necessary properties for grid columns (supported by all browsers back to IE7) + // Credit to @dhg for the idea + [class^="span"] { + display: inline; + float: left; + margin-left: @gridGutterWidth; + } + + // Default columns + .span1 { .columns(1); } + .span2 { .columns(2); } + .span3 { .columns(3); } + .span4 { .columns(4); } + .span5 { .columns(5); } + .span6 { .columns(6); } + .span7 { .columns(7); } + .span8 { .columns(8); } + .span9 { .columns(9); } + .span10 { .columns(10); } + .span11 { .columns(11); } + .span12 { .columns(12); } + .span13 { .columns(13); } + .span14 { .columns(14); } + .span15 { .columns(15); } + .span16 { .columns(16); } + + // Offset column options + .offset1 { .offset(1); } + .offset2 { .offset(2); } + .offset3 { .offset(3); } + .offset4 { .offset(4); } + .offset5 { .offset(5); } + .offset6 { .offset(6); } + .offset7 { .offset(7); } + .offset8 { .offset(8); } + .offset9 { .offset(9); } + .offset10 { .offset(10); } + .offset11 { .offset(11); } + .offset12 { .offset(12); } + + // Unique column sizes for 16-column grid + .span-one-third { width: 300px; } + .span-two-thirds { width: 620px; } + .offset-one-third { margin-left: 340px; } + .offset-two-thirds { margin-left: 660px; } +} + + +// STRUCTURAL LAYOUT +// ----------------- + +html, body { + background-color: #fff; +} +body { + margin: 0; + #font > .sans-serif(normal,@basefont,@baseline); + color: @gray; +} + +// Container (centered, fixed-width layouts) +.container { + width: 940px; + margin: 0 auto; +} + +// Fluid layouts (left aligned, with sidebar, min- & max-width content) +.container-fluid { + padding: 0 20px; + .clearfix(); + > .sidebar { + float: left; + width: 220px; + } + // TODO in v2: rename this and .popover .content to be more specific + > .content { + min-width: 700px; + max-width: 1180px; + margin-left: 240px; + } +} + + +// BASE STYLES +// ----------- + +// Links +a { + color: @linkColor; + text-decoration: none; + line-height: inherit; + font-weight: inherit; + &:hover { + color: @linkColorHover; + text-decoration: underline; + } +} diff --git a/langdev/web/static/bootstrap/tables.less b/langdev/web/static/bootstrap/tables.less new file mode 100755 index 0000000..d1af37d --- /dev/null +++ b/langdev/web/static/bootstrap/tables.less @@ -0,0 +1,148 @@ +/* + * Tables.less + * Tables for, you guessed it, tabular data + * ---------------------------------------- */ + + +// BASELINE STYLES +// --------------- + +table { + width: 100%; + margin-bottom: @baseline; + padding: 0; + border-collapse: separate; + font-size: 13px; + th, td { + padding: 10px 10px 9px; + line-height: @baseline * .75; + text-align: left; + vertical-align: middle; + border-bottom: 1px solid #ddd; + } + th { + padding-top: 9px; + font-weight: bold; + border-bottom-width: 2px; + } +} + + +// ZEBRA-STRIPING +// -------------- + +// Default zebra-stripe styles (alternating gray and transparent backgrounds) +.zebra-striped { + tbody { + tr:nth-child(odd) td { + background-color: #f9f9f9; + } + tr:hover td { + background-color: #f5f5f5; + } + } + + // Tablesorting styles w/ jQuery plugin + .header { + cursor: pointer; + &:after { + content: ""; + float: right; + margin-top: 7px; + border-width: 0 4px 4px; + border-style: solid; + border-color: #000 transparent; + visibility: hidden; + } + } + // Style the sorted column headers (THs) + .headerSortUp, + .headerSortDown { + background-color: rgba(141,192,219,.25); + text-shadow: 0 1px 1px rgba(255,255,255,.75); + .border-radius(3px 3px 0 0); + } + // Style the ascending (reverse alphabetical) column header + .header:hover { + &:after { + visibility:visible; + } + } + // Style the descending (alphabetical) column header + .headerSortDown, + .headerSortDown:hover { + &:after { + visibility:visible; + .opacity(60); + } + } + // Style the ascending (reverse alphabetical) column header + .headerSortUp { + &:after { + border-bottom: none; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #000; + visibility:visible; + .box-shadow(none); //can't add boxshadow to downward facing arrow :( + .opacity(60); + } + } +} + +table { + // Blue Table Headings + .blue { + color: @blue; + border-bottom-color: @blue; + } + .headerSortUp.blue, + .headerSortDown.blue { + background-color: lighten(@blue, 40%); + } + // Green Table Headings + .green { + color: @green; + border-bottom-color: @green; + } + .headerSortUp.green, + .headerSortDown.green { + background-color: lighten(@green, 40%); + } + // Red Table Headings + .red { + color: @red; + border-bottom-color: @red; + } + .headerSortUp.red, + .headerSortDown.red { + background-color: lighten(@red, 50%); + } + // Yellow Table Headings + .yellow { + color: @yellow; + border-bottom-color: @yellow; + } + .headerSortUp.yellow, + .headerSortDown.yellow { + background-color: lighten(@yellow, 40%); + } + // Orange Table Headings + .orange { + color: @orange; + border-bottom-color: @orange; + } + .headerSortUp.orange, + .headerSortDown.orange { + background-color: lighten(@orange, 40%); + } + // Purple Table Headings + .purple { + color: @purple; + border-bottom-color: @purple; + } + .headerSortUp.purple, + .headerSortDown.purple { + background-color: lighten(@purple, 40%); + } +} \ No newline at end of file diff --git a/langdev/web/static/bootstrap/type.less b/langdev/web/static/bootstrap/type.less new file mode 100755 index 0000000..7ee69f2 --- /dev/null +++ b/langdev/web/static/bootstrap/type.less @@ -0,0 +1,188 @@ +/* Typography.less + * Headings, body text, lists, code, and more for a versatile and durable typography system + * ---------------------------------------------------------------------------------------- */ + + +// BODY TEXT +// --------- + +p { + #font > .shorthand(normal,@basefont,@baseline); + margin-bottom: @baseline / 2; + small { + font-size: @basefont - 2; + color: @grayLight; + } +} + + +// HEADINGS +// -------- + +h1, h2, h3, h4, h5, h6 { + font-weight: bold; + color: @grayDark; + small { + color: @grayLight; + } +} +h1 { + margin-bottom: @baseline; + font-size: 30px; + line-height: @baseline * 2; + small { + font-size: 18px; + } +} +h2 { + font-size: 24px; + line-height: @baseline * 2; + small { + font-size: 14px; + } +} +h3, h4, h5, h6 { + line-height: @baseline * 2; +} +h3 { + font-size: 18px; + small { + font-size: 14px; + } +} +h4 { + font-size: 16px; + small { + font-size: 12px; + } +} +h5 { + font-size: 14px; +} +h6 { + font-size: 13px; + color: @grayLight; + text-transform: uppercase; +} + + +// COLORS +// ------ + +// Unordered and Ordered lists +ul, ol { + margin: 0 0 @baseline 25px; +} +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} +ul { + list-style: disc; +} +ol { + list-style: decimal; +} +li { + line-height: @baseline; + color: @gray; +} +ul.unstyled { + list-style: none; + margin-left: 0; +} + +// Description Lists +dl { + margin-bottom: @baseline; + dt, dd { + line-height: @baseline; + } + dt { + font-weight: bold; + } + dd { + margin-left: @baseline / 2; + } +} + +// MISC +// ---- + +// Horizontal rules +hr { + margin: 0 0 19px; + border: 0; + border-bottom: 1px solid #eee; +} + +// Emphasis +strong { + font-style: inherit; + font-weight: bold; + line-height: inherit; +} +em { + font-style: italic; + font-weight: inherit; + line-height: inherit; +} +.muted { + color: @grayLight; +} + +// Blockquotes +blockquote { + margin-bottom: @baseline; + border-left: 5px solid #eee; + padding-left: 15px; + p { + #font > .shorthand(300,14px,@baseline); + margin-bottom: 0; + } + small { + display: block; + #font > .shorthand(300,12px,@baseline); + color: @grayLight; + &:before { + content: '\2014 \00A0'; + } + } +} + +// Addresses +address { + display: block; + line-height: @baseline; + margin-bottom: @baseline; +} + +// Inline and block code styles +code, pre { + padding: 0 3px 2px; + font-family: Monaco, Andale Mono, Courier New, monospace; + font-size: 12px; + .border-radius(3px); +} +code { + background-color: lighten(@orange, 40%); + color: rgba(0,0,0,.75); + padding: 1px 3px; +} +pre { + background-color: #f5f5f5; + display: block; + padding: @baseline - 1; + margin: 0 0 @baseline; + line-height: @baseline; + font-size: 12px; + border: 1px solid #ccc; + border: 1px solid rgba(0,0,0,.15); + .border-radius(3px); + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; + +} \ No newline at end of file diff --git a/langdev/web/static/style.less b/langdev/web/static/style.less index 8681ad2..d6a3cf6 100644 --- a/langdev/web/static/style.less +++ b/langdev/web/static/style.less @@ -1,129 +1,15 @@ -.clearfix { - &:after { - content: "."; - display: block; - clear: both; - visibility: hidden; - line-height: 0; - height: 0; - } -} - -body { margin: 0; padding: 0; font-family: sans-serif; } - -header { - .clearfix; - padding: 1em; border-bottom: 1px solid silver; - a { text-decoration: none; color: black; } - h1 { margin: 0; color: silver; float: left; } - h1:before { content: '('; } - h1:after { content: ')'; } - nav.user { text-align: right; float: none; } -} - -.wf-nunito-n4-active { - header { font-family: Nunito, sans-serif; } -} +@import 'bootstrap/bootstrap.less'; -footer { - padding: 1em; border-top: 1px solid silver; - #intersites { - text-align: center; text-transform: lowercase; - a { - color: black; text-decoration: none; - &:hover { border-bottom: 1px solid silver; } - &:before { padding: 0 0.3em; content: ' / '; color: gray; } - &:first-child:before { content: ''; } - } - } +body { + padding-top: 40px; } -#body { - padding: 1em; +header { + h1 { display: none; } } -.forum { - &.posts { - table { - width: 100%; border-collapse: collapse; - thead tr { - th { text-align: left; } - } - tbody { - tr { - td.title { - width: 70%; text-align: left; font-weight: normal; - a { display: block; } - } - &:hover { background-color: #eee; } - - border-top: 1px solid silver; - line-height: 150%; - &.sticky + :not(.sticky) { border-top: 1px solid gray; } - } - } - } - - #post-summaries { - article { - margin: 1em 0; - border: 1px solid silver; - padding: 0; - - header { - margin: 0; - border-bottom: 1px solid silver; - padding: .5em 1em; - background: #eee; - overflow: hidden; - } - header dl { - .clearfix; - - margin: 0; padding: 0; - min-width: 60em; - font-family: sans-serif; - - dt, dd { - float: left; - margin: 0; padding: 0; - margin-right: 1em; - } - dt { min-width: 4em; color: lighten(#000, 20%); } - dd { margin-right: 2em; } - dt.title { clear: left; } - dd.title { - margin: 0; - h1 { font-size: medium; } - } - - a:hover { text-decoration: underline; } - } - - section.content { - margin: 0 0 1em; - padding: 1px 1em 0; - max-height: 6em; - overflow: hidden; - background-color: white; - } - - footer { - margin: 0; - border-top: 1px solid silver; - padding: .5em 1em; - background: #eee; - } - } - } - } +div#body { + .container; + padding-top: 20px; } -ul.pager { - margin: 0; padding: 0; - li { - display: inline; - &.first:after { content: ' ...'; } - &.last:before { content: '... '; } - } -} diff --git a/langdev/web/templates/base.html b/langdev/web/templates/base.html index 54912d4..1e44307 100644 --- a/langdev/web/templates/base.html +++ b/langdev/web/templates/base.html @@ -1,3 +1,4 @@ +{% from 'macro.html' import only_for_style %} {%- macro static_url_for(filename) -%} {%- set url = url_for('.static', filename=filename) -%} {%- if config['DEBUG'] -%} {{ url.replace('.min.', '.') }} @@ -15,56 +16,72 @@ - {% block head %} {% endblock %} -
    +

    LangDev

    - + {% call only_for_style() %} +
  • + {% endcall %} + + {% call only_for_style() %} + + {% endcall %}
    {% block body %} {% endblock %}
    - {% if config.INTERSITES %} - - {% endif %} diff --git a/langdev/web/templates/form.html b/langdev/web/templates/form.html index 78ee64f..f3b180e 100644 --- a/langdev/web/templates/form.html +++ b/langdev/web/templates/form.html @@ -12,13 +12,28 @@ {% endmacro %} -{% macro render_form(form, endpoint) %} +{% macro render_form(form, endpoint, legend=None, submit_class='primary') %} + {% set button_types = ['SubmitField'] %} + {% set rest = caller and caller() or '' %} {% call render_raw_form(endpoint, **kwargs) %}
    + {% if legend %} + {{ legend }} + {% endif %} {% for field in form %} - {{ render_field(field, form.errors[field.name]) }} + {% if field.type not in button_types %} + {{ render_field(field, form.errors[field.name]) }} + {% endif %} {% endfor %}
    +
    + {% for field in form %} + {% if field.type in button_types %} + {{ field(class_='btn ' + submit_class)|safe }} + {% endif %} + {% endfor %} + {{ rest }} +
    {% endcall %} {% endmacro %} @@ -26,18 +41,40 @@ {% if field.type == 'HiddenField' %} {{ field() }} {% else %} -
    - {% if field.type != 'SubmitField' %} +
    + {% if field.type == 'BooleanField' %} + + {% else %} {{ field.label }} {% endif %} - {{ field()|safe }} - {% if errors %} -
      - {% for error in errors %} -
    • {{ error }}
    • - {% endfor %} -
    - {% endif %} +
    + {% if field.type == 'BooleanField' %} +
      +
    • +
    + {% else %} + {{ field()|safe }} + {% with cls = field.type == 'TextAreaField' and 'block' or 'inline' %} + {% if field.description %} + {{ field.description }} + {% endif %} + {% endwith %} + {% endif %} + {% if errors|count == 1 %} + + {{ errors[0] }} + + {% elif errors|count > 1 %} +
      + {% for error in errors %} +
    • {{ error }}
    • + {% endfor %} +
    + {% endif %} +
    {% endif %} {% endmacro %} diff --git a/langdev/web/templates/forum/posts.html b/langdev/web/templates/forum/posts.html index 2b989a8..1072847 100644 --- a/langdev/web/templates/forum/posts.html +++ b/langdev/web/templates/forum/posts.html @@ -11,7 +11,8 @@ {% endblock %} {% block body %} {% if current_user %} - Write a post + Write a post {% endif %} {% if view == 'summary' %} {% set grouped = posts|groupby('sticky') %} @@ -19,7 +20,7 @@ {% set other_posts = (grouped[False]|default({})).list %} {% endif %} {% if posts %} - +
    diff --git a/langdev/web/templates/macro.html b/langdev/web/templates/macro.html new file mode 100644 index 0000000..05b7cc4 --- /dev/null +++ b/langdev/web/templates/macro.html @@ -0,0 +1,7 @@ +{%- macro only_for_style() -%} + +{%- endmacro -%} diff --git a/langdev/web/templates/pager.html b/langdev/web/templates/pager.html index eb93e68..3b201f9 100644 --- a/langdev/web/templates/pager.html +++ b/langdev/web/templates/pager.html @@ -1,15 +1,34 @@ +{% from 'macro.html' import only_for_style %} {% macro render_pager(pager, limit, endpoint) %} - + {% endmacro %} diff --git a/langdev/web/templates/user/signin_form.html b/langdev/web/templates/user/signin_form.html index 7e4aabf..490d8a5 100644 --- a/langdev/web/templates/user/signin_form.html +++ b/langdev/web/templates/user/signin_form.html @@ -1,7 +1,10 @@ {% extends 'user/base.html' %} {% from 'form.html' import render_form %} {% block body %} - {{ render_form(form, 'user.signin') }} - Sign up - I forgot my password + {% call render_form(form, 'user.signin', 'Sign in', 'primary') %} + Sign up + I forgot my password + {% endcall %} {% endblock %} diff --git a/langdev/web/templates/user/signup_form.html b/langdev/web/templates/user/signup_form.html index 522e366..4c0bdc2 100644 --- a/langdev/web/templates/user/signup_form.html +++ b/langdev/web/templates/user/signup_form.html @@ -1,5 +1,5 @@ {% extends 'user/base.html' %} {% from 'form.html' import render_form %} {% block body %} - {{ render_form(form, 'signup') }} + {{ render_form(form, 'user.signup', 'Sign up', 'primary big') }} {% endblock %}
    Author