summaryrefslogtreecommitdiff
path: root/doc/development
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2016-11-21 22:06:11 +0800
committerLin Jen-Shin <godfat@godfat.org>2016-11-21 22:06:11 +0800
commitb20c7846ffc0c78d6b483184363b6ccc7c11326d (patch)
tree05d232a4f877cd94481afcb8bf912410b58bbd0b /doc/development
parentf593abbc70ab02823cd99d2db11598b629cbb3a0 (diff)
parent77a4382712888131813ec008a8d4179bcf753b8b (diff)
downloadgitlab-ce-b20c7846ffc0c78d6b483184363b6ccc7c11326d.tar.gz
Merge remote-tracking branch 'upstream/master' into show-commit-status-from-latest-pipeline
* upstream/master: (754 commits) Add documentation about todos and failed builds Add Changelog entry for failed builds todos fix Do not create TODO when build is allowed to fail Fix 404 on some group pages when name contains dot Grapify the users API Remove duplicate sidekiq throttling parameters Fix regression in Merge request form Fix wrong link Fix test Fix broken test Changes for stop url to path fix typo in gitlab_flow.md ('munch'->'much') Fix spec Backport some changes done from Time Tracking feature in EE. Use build instead create in BroadcastMessage model spec Try to fix tests Remove unnecessary self from user model Expose stop_path for environment to not construct that in frontend Bring back the `commit_url` as it's used by CycleAnalytics Add api endpoint for creating a pipeline ...
Diffstat (limited to 'doc/development')
-rw-r--r--doc/development/README.md3
-rw-r--r--doc/development/frontend.md51
-rw-r--r--doc/development/gotchas.md89
-rw-r--r--doc/development/instrumentation.md10
-rw-r--r--doc/development/limit_ee_conflicts.md272
-rw-r--r--doc/development/migration_style_guide.md12
-rw-r--r--doc/development/shell_commands.md8
-rw-r--r--doc/development/testing.md2
-rw-r--r--doc/development/ux_guide/basics.md94
-rw-r--r--doc/development/ux_guide/components.md254
-rw-r--r--doc/development/ux_guide/copy.md99
-rw-r--r--doc/development/ux_guide/features.md57
-rw-r--r--doc/development/ux_guide/img/button-primary.pngbin0 -> 8410 bytes
-rw-r--r--doc/development/ux_guide/img/button-secondary.pngbin0 -> 11160 bytes
-rw-r--r--doc/development/ux_guide/img/color-blue.pngbin0 -> 3865 bytes
-rw-r--r--doc/development/ux_guide/img/color-green.pngbin0 -> 4127 bytes
-rw-r--r--doc/development/ux_guide/img/color-grey.pngbin0 -> 2384 bytes
-rw-r--r--doc/development/ux_guide/img/color-orange.pngbin0 -> 4698 bytes
-rw-r--r--doc/development/ux_guide/img/color-red.pngbin0 -> 3669 bytes
-rw-r--r--doc/development/ux_guide/img/components-alerts.pngbin0 -> 46785 bytes
-rw-r--r--doc/development/ux_guide/img/components-anchorlinks.pngbin0 -> 36456 bytes
-rw-r--r--doc/development/ux_guide/img/components-contentblock.pngbin0 -> 19841 bytes
-rw-r--r--doc/development/ux_guide/img/components-counts.pngbin0 -> 2438 bytes
-rw-r--r--doc/development/ux_guide/img/components-coverblock.pngbin0 -> 15757 bytes
-rw-r--r--doc/development/ux_guide/img/components-dateexact.pngbin0 -> 5609 bytes
-rw-r--r--doc/development/ux_guide/img/components-daterelative.pngbin0 -> 5843 bytes
-rw-r--r--doc/development/ux_guide/img/components-dropdown.pngbin0 -> 60448 bytes
-rw-r--r--doc/development/ux_guide/img/components-fileholder.pngbin0 -> 4953 bytes
-rw-r--r--doc/development/ux_guide/img/components-horizontalform.pngbin0 -> 5708 bytes
-rw-r--r--doc/development/ux_guide/img/components-listinsidepanel.pngbin0 -> 3962 bytes
-rw-r--r--doc/development/ux_guide/img/components-listwithavatar.pngbin0 -> 7952 bytes
-rw-r--r--doc/development/ux_guide/img/components-listwithhover.pngbin0 -> 3313 bytes
-rw-r--r--doc/development/ux_guide/img/components-panels.pngbin0 -> 32886 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencehover.pngbin0 -> 11519 bytes
-rw-r--r--doc/development/ux_guide/img/components-referenceissues.pngbin0 -> 14587 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencelabels.pngbin0 -> 4643 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencemilestone.pngbin0 -> 2468 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencemrs.pngbin0 -> 12646 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencepeople.pngbin0 -> 7214 bytes
-rw-r--r--doc/development/ux_guide/img/components-rowcontentblock.pngbin0 -> 19730 bytes
-rw-r--r--doc/development/ux_guide/img/components-simplelist.pngbin0 -> 3078 bytes
-rw-r--r--doc/development/ux_guide/img/components-table.pngbin0 -> 7668 bytes
-rw-r--r--doc/development/ux_guide/img/components-verticalform.pngbin0 -> 6541 bytes
-rw-r--r--doc/development/ux_guide/img/copy-form-addissuebutton.pngbin0 -> 26541 bytes
-rw-r--r--doc/development/ux_guide/img/copy-form-addissueform.pngbin0 -> 38242 bytes
-rw-r--r--doc/development/ux_guide/img/copy-form-editissuebutton.pngbin0 -> 16466 bytes
-rw-r--r--doc/development/ux_guide/img/copy-form-editissueform.pngbin0 -> 40660 bytes
-rw-r--r--doc/development/ux_guide/img/features-contextualnav.pngbin0 -> 8051 bytes
-rw-r--r--doc/development/ux_guide/img/features-emptystates.pngbin0 -> 114540 bytes
-rw-r--r--doc/development/ux_guide/img/features-filters.pngbin0 -> 4529 bytes
-rw-r--r--doc/development/ux_guide/img/features-globalnav.pngbin0 -> 8953 bytes
-rw-r--r--doc/development/ux_guide/img/icon-add.pngbin0 -> 155 bytes
-rw-r--r--doc/development/ux_guide/img/icon-close.pngbin0 -> 225 bytes
-rw-r--r--doc/development/ux_guide/img/icon-edit.pngbin0 -> 231 bytes
-rw-r--r--doc/development/ux_guide/img/icon-notification.pngbin0 -> 259 bytes
-rw-r--r--doc/development/ux_guide/img/icon-rss.pngbin0 -> 307 bytes
-rw-r--r--doc/development/ux_guide/img/icon-subscribe.pngbin0 -> 348 bytes
-rw-r--r--doc/development/ux_guide/img/icon-trash.pngbin0 -> 380 bytes
-rw-r--r--doc/development/ux_guide/img/monospacefont-sample.pngbin0 -> 14282 bytes
-rw-r--r--doc/development/ux_guide/img/sourcesanspro-sample.pngbin0 -> 10948 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-contentitemtitle.pngbin0 -> 7463 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-header.pngbin0 -> 6103 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-systeminformationblock.pngbin0 -> 15412 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-ux.pngbin0 -> 7673 bytes
-rw-r--r--doc/development/ux_guide/img/tooltip-placement.pngbin0 -> 2645 bytes
-rw-r--r--doc/development/ux_guide/img/tooltip-usage.pngbin0 -> 9160 bytes
-rw-r--r--doc/development/ux_guide/index.md58
-rw-r--r--doc/development/ux_guide/principles.md17
-rw-r--r--doc/development/ux_guide/resources.md13
-rw-r--r--doc/development/ux_guide/surfaces.md47
-rw-r--r--doc/development/ux_guide/tips.md44
-rw-r--r--doc/development/ux_guide/users.md16
72 files changed, 1130 insertions, 16 deletions
diff --git a/doc/development/README.md b/doc/development/README.md
index bf1f054b7d5..371bb55c127 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -14,7 +14,7 @@
contributing to documentation.
- [SQL Migration Style Guide](migration_style_guide.md) for creating safe SQL migrations
- [Testing standards and style guidelines](testing.md)
-- [UI guide](ui_guide.md) for building GitLab with existing CSS styles and elements
+- [UX guide](ux_guide/index.md) for building GitLab with existing CSS styles and elements
- [Frontend guidelines](frontend.md)
- [SQL guidelines](sql.md) for working with SQL queries
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
@@ -22,6 +22,7 @@
## Process
- [Generate a changelog entry with `bin/changelog`](changelog.md)
+- [Limit conflicts with EE when developing on CE](limit_ee_conflicts.md)
- [Code review guidelines](code_review.md) for reviewing code and having code reviewed.
- [Merge request performance guidelines](merge_request_performance_guidelines.md)
for ensuring merge requests do not negatively impact GitLab performance
diff --git a/doc/development/frontend.md b/doc/development/frontend.md
index ec8f2d6531c..9e782ab977f 100644
--- a/doc/development/frontend.md
+++ b/doc/development/frontend.md
@@ -205,6 +205,57 @@ command line.
Please note: Not all of the frontend fixtures are generated. Some are still static
files. These will not be touched by `rake teaspoon:fixtures`.
+## Design Patterns
+
+### Singletons
+
+When exactly one object is needed for a given task, prefer to define it as a
+`class` rather than as an object literal. Prefer also to explicitly restrict
+instantiation, unless flexibility is important (e.g. for testing).
+
+```
+// bad
+
+gl.MyThing = {
+ prop1: 'hello',
+ method1: () => {}
+};
+
+// good
+
+class MyThing {
+ constructor() {
+ this.prop1 = 'hello';
+ }
+ method1() {}
+}
+
+gl.MyThing = new MyThing();
+
+// best
+
+let singleton;
+
+class MyThing {
+ constructor() {
+ if (!singleton) {
+ singleton = this;
+ singleton.init();
+ }
+ return singleton;
+ }
+
+ init() {
+ this.prop1 = 'hello';
+ }
+
+ method1() {}
+}
+
+gl.MyThing = MyThing;
+
+```
+
## Supported browsers
For our currently-supported browsers, see our [requirements][requirements].
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index b25ce79e89f..7bfc9cb361f 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -32,6 +32,95 @@ spec/models/user_spec.rb|6 error| Failure/Error: u = described_class.new NoMeth
Except for the top-level `describe` block, always provide a String argument to
`describe`.
+## Don't assert against the absolute value of a sequence-generated attribute
+
+Consider the following factory:
+
+```ruby
+FactoryGirl.define do
+ factory :label do
+ sequence(:title) { |n| "label#{n}" }
+ end
+end
+```
+
+Consider the following API spec:
+
+```ruby
+require 'rails_helper'
+
+describe API::Labels do
+ it 'creates a first label' do
+ create(:label)
+
+ get api("/projects/#{project.id}/labels", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('label1')
+ end
+
+ it 'creates a second label' do
+ create(:label)
+
+ get api("/projects/#{project.id}/labels", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('label1')
+ end
+end
+```
+
+When run, this spec doesn't do what we might expect:
+
+```sh
+1) API::API reproduce sequence issue creates a second label
+ Failure/Error: expect(json_response.first['name']).to eq('label1')
+
+ expected: "label1"
+ got: "label2"
+
+ (compared using ==)
+```
+
+That's because FactoryGirl sequences are not reseted for each example.
+
+Please remember that sequence-generated values exist only to avoid having to
+explicitly set attributes that have a uniqueness constraint when using a factory.
+
+### Solution
+
+If you assert against a sequence-generated attribute's value, you should set it
+explicitly. Also, the value you set shouldn't match the sequence pattern.
+
+For instance, using our `:label` factory, writing `create(:label, title: 'foo')`
+is ok, but `create(:label, title: 'label1')` is not.
+
+Following is the fixed API spec:
+
+```ruby
+require 'rails_helper'
+
+describe API::Labels do
+ it 'creates a first label' do
+ create(:label, title: 'foo')
+
+ get api("/projects/#{project.id}/labels", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('foo')
+ end
+
+ it 'creates a second label' do
+ create(:label, title: 'bar')
+
+ get api("/projects/#{project.id}/labels", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('bar')
+ end
+end
+```
+
## Don't `rescue Exception`
See ["Why is it bad style to `rescue Exception => e` in Ruby?"][Exception].
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index 105e2f1242a..b8669964c84 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -24,7 +24,7 @@ namespace you can use the `configure` class method. This method simply yields
the supplied block while passing `Gitlab::Metrics::Instrumentation` as its
argument. An example:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_method(Foo, :bar)
conf.instrument_method(Foo, :baz)
@@ -41,7 +41,7 @@ Method instrumentation should be added in the initializer
Instrumenting a single method:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_method(User, :find_by)
end
@@ -49,7 +49,7 @@ end
Instrumenting an entire class hierarchy:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_class_hierarchy(ActiveRecord::Base)
end
@@ -57,7 +57,7 @@ end
Instrumenting all public class methods:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_methods(User)
end
@@ -68,7 +68,7 @@ end
The easiest way to check if a method has been instrumented is to check its
source location. For example:
-```
+```ruby
method = Rugged::TagCollection.instance_method(:[])
method.source_location
diff --git a/doc/development/limit_ee_conflicts.md b/doc/development/limit_ee_conflicts.md
new file mode 100644
index 00000000000..b7e6387838e
--- /dev/null
+++ b/doc/development/limit_ee_conflicts.md
@@ -0,0 +1,272 @@
+# Limit conflicts with EE when developing on CE
+
+This guide contains best-practices for avoiding conflicts between CE and EE.
+
+## Context
+
+Usually, GitLab Community Edition is merged into the Enterprise Edition once a
+week. During these merges, it's very common to get conflicts when some changes
+in CE do not apply cleanly to EE.
+
+There are a few things that can help you as a developer to:
+
+- know when your merge request to CE will conflict when merged to EE
+- avoid such conflicts in the first place
+- ease future conflict resolutions if conflict is inevitable
+
+## Check the `rake ee_compat_check` in your merge requests
+
+For each commit (except on `master`), the `rake ee_compat_check` CI job tries to
+detect if the current branch's changes will conflict during the CE->EE merge.
+
+The job reports what files are conflicting and how to setup a merge request
+against EE. Here is roughly how it works:
+
+1. Generates the diff between your branch and current CE `master`
+1. Tries to apply it to current EE `master`
+1. If it applies cleanly, the job succeeds, otherwise...
+1. Detects a branch with the `-ee` suffix in EE
+1. If it exists, generate the diff between this branch and current EE `master`
+1. Tries to apply it to current EE `master`
+1. If it applies cleanly, the job succeeds
+
+In the case where the job fails, it means you should create a `<ce_branch>-ee`
+branch, push it to EE and open a merge request against EE `master`. At this
+point if you retry the failing job in your CE merge request, it should now pass.
+
+Notes:
+
+- This task is not a silver-bullet, its current goal is to bring awareness to
+ developers that their work needs to be ported to EE.
+- Community contributors shouldn't submit merge requests against EE, but
+ reviewers should take actions by either creating such EE merge request or
+ asking a GitLab developer to do it once the merge request is merged.
+- If you branch is more than 500 commits behind `master`, the job will fail and
+ you should rebase your branch upon latest `master`.
+
+## Possible type of conflicts
+
+### Controllers
+
+#### List or arrays are augmented in EE
+
+In controllers, the most common type of conflict is with `before_action` that
+has a list of actions in CE but EE adds some actions to that list.
+
+The same problem often occurs for `params.require` / `params.permit` calls.
+
+##### Mitigations
+
+Separate CE and EE actions/keywords. For instance for `params.require` in
+`ProjectsController`:
+
+```ruby
+def project_params
+ params.require(:project).permit(project_params_ce)
+ # On EE, this is always:
+ # params.require(:project).permit(project_params_ce << project_params_ee)
+end
+
+# Always returns an array of symbols, created however best fits the use case.
+# It _should_ be sorted alphabetically.
+def project_params_ce
+ %i[
+ description
+ name
+ path
+ ]
+end
+
+# (On EE)
+def project_params_ee
+ %i[
+ approvals_before_merge
+ approver_group_ids
+ approver_ids
+ ...
+ ]
+end
+```
+
+#### Additional condition(s) in EE
+
+For instance for LDAP:
+
+```diff
+ def destroy
+ @key = current_user.keys.find(params[:id])
+ - @key.destroy
+ + @key.destroy unless @key.is_a? LDAPKey
+
+ respond_to do |format|
+```
+
+Or for Geo:
+
+```diff
+def after_sign_out_path_for(resource)
+- current_application_settings.after_sign_out_path.presence || new_user_session_path
++ if Gitlab::Geo.secondary?
++ Gitlab::Geo.primary_node.oauth_logout_url(@geo_logout_state)
++ else
++ current_application_settings.after_sign_out_path.presence || new_user_session_path
++ end
+end
+```
+
+Or even for audit log:
+
+```diff
+def approve_access_request
+- Members::ApproveAccessRequestService.new(membershipable, current_user, params).execute
++ member = Members::ApproveAccessRequestService.new(membershipable, current_user, params).execute
++
++ log_audit_event(member, action: :create)
+
+ redirect_to polymorphic_url([membershipable, :members])
+end
+```
+
+### Views
+
+#### Additional view code in EE
+
+A block of code added in CE conflicts because there is already another block
+at the same place in EE
+
+##### Mitigations
+
+Blocks of code that are EE-specific should be moved to partials as much as
+possible to avoid conflicts with big chunks of HAML code that that are not fun
+to resolve when you add the indentation to the equation.
+
+For instance this kind of thing:
+
+```haml
+- if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
+ - has_due_date = issuable.has_attribute?(:due_date)
+ %hr
+ .row
+ %div{ class: (has_due_date ? "col-lg-6" : "col-sm-12") }
+ .form-group.issue-assignee
+ = f.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ - if issuable.assignee_id
+ = f.hidden_field :assignee_id
+ = dropdown_tag(user_dropdown_label(issuable.assignee_id, "Assignee"), options: { toggle_class: "js-dropdown-keep-input js-user-search js-issuable-form-dropdown js-assignee-search", title: "Select assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
+ placeholder: "Search assignee", data: { first_user: current_user.try(:username), null_user: true, current_user: true, project_id: project.try(:id), selected: issuable.assignee_id, field_name: "#{issuable.class.model_name.param_key}[assignee_id]", default_label: "Assignee"} })
+ .form-group.issue-milestone
+ = f.label :milestone_id, "Milestone", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, extra_class: "js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
+ .form-group
+ - has_labels = @labels && @labels.any?
+ = f.label :label_ids, "Labels", class: "control-label #{"col-lg-4" if has_due_date}"
+ = f.hidden_field :label_ids, multiple: true, value: ''
+ .col-sm-10{ class: "#{"col-lg-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" }
+ .issuable-form-select-holder
+ = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false, show_menu_above: 'true' }, dropdown_title: "Select label"
+
+ - if issuable.respond_to?(:weight)
+ .form-group
+ = f.label :label_ids, class: "control-label #{"col-lg-4" if has_due_date}" do
+ Weight
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ = f.select :weight, issues_weight_options(issuable.weight, edit: true), { include_blank: true },
+ { class: 'select2 js-select2', data: { placeholder: "Select weight" }}
+
+ - if has_due_date
+ .col-lg-6
+ .form-group
+ = f.label :due_date, "Due date", class: "control-label"
+ .col-sm-10
+ .issuable-form-select-holder
+ = f.text_field :due_date, id: "issuable-due-date", class: "datepicker form-control", placeholder: "Select due date"
+```
+
+could be simplified by using partials:
+
+```haml
+= render 'metadata_form', issuable: issuable
+```
+
+and then the `_metadata_form.html.haml` could be as follows:
+
+```haml
+- return unless can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
+
+- has_due_date = issuable.has_attribute?(:due_date)
+%hr
+.row
+ %div{ class: (has_due_date ? "col-lg-6" : "col-sm-12") }
+ .form-group.issue-assignee
+ = f.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ - if issuable.assignee_id
+ = f.hidden_field :assignee_id
+ = dropdown_tag(user_dropdown_label(issuable.assignee_id, "Assignee"), options: { toggle_class: "js-dropdown-keep-input js-user-search js-issuable-form-dropdown js-assignee-search", title: "Select assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
+ placeholder: "Search assignee", data: { first_user: current_user.try(:username), null_user: true, current_user: true, project_id: project.try(:id), selected: issuable.assignee_id, field_name: "#{issuable.class.model_name.param_key}[assignee_id]", default_label: "Assignee"} })
+ .form-group.issue-milestone
+ = f.label :milestone_id, "Milestone", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, extra_class: "js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
+ .form-group
+ - has_labels = @labels && @labels.any?
+ = f.label :label_ids, "Labels", class: "control-label #{"col-lg-4" if has_due_date}"
+ = f.hidden_field :label_ids, multiple: true, value: ''
+ .col-sm-10{ class: "#{"col-lg-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" }
+ .issuable-form-select-holder
+ = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false, show_menu_above: 'true' }, dropdown_title: "Select label"
+
+ = render 'weight_form', issuable: issuable, has_due_date: has_due_date
+
+ - if has_due_date
+ .col-lg-6
+ .form-group
+ = f.label :due_date, "Due date", class: "control-label"
+ .col-sm-10
+ .issuable-form-select-holder
+ = f.text_field :due_date, id: "issuable-due-date", class: "datepicker form-control", placeholder: "Select due date"
+```
+
+and then the `_weight_form.html.haml` could be as follows:
+
+```haml
+- return unless issuable.respond_to?(:weight)
+
+- has_due_date = issuable.has_attribute?(:due_date)
+
+.form-group
+ = f.label :label_ids, class: "control-label #{"col-lg-4" if has_due_date}" do
+ Weight
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ = f.select :weight, issues_weight_options(issuable.weight, edit: true), { include_blank: true },
+ { class: 'select2 js-select2', data: { placeholder: "Select weight" }}
+```
+
+Note:
+
+- The safeguards at the top allow to get rid of an unneccessary indentation level
+- Here we only moved the 'Weight' code to a partial since this is the only
+ EE-specific code in that view, so it's the most likely to conflict, but you
+ are encouraged to use partials even for code that's in CE to logically split
+ big views into several smaller files.
+
+#### Indentation issue
+
+Sometimes a code block is indented more or less in EE because there's an
+additional condition.
+
+##### Mitigations
+
+Blocks of code that are EE-specific should be moved to partials as much as
+possible to avoid conflicts with big chunks of HAML code that that are not fun
+to resolve when you add the indentation in the equation.
+
+---
+
+[Return to Development documentation](README.md)
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 61b0fbc89c9..fd8335d251e 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -60,7 +60,7 @@ migration was tested.
If you need to remove index, please add a condition like in following example:
-```
+```ruby
remove_index :namespaces, column: :name if index_exists?(:namespaces, :name)
```
@@ -75,7 +75,7 @@ need for downtime. To use this method you must disable transactions by calling
the method `disable_ddl_transaction!` in the body of your migration class like
so:
-```
+```ruby
class MyMigration < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
@@ -96,7 +96,7 @@ the `up` and `down` methods in your migration class.
For example, to add the column `foo` to the `projects` table with a default
value of `10` you'd write the following:
-```
+```ruby
class MyMigration < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
@@ -125,7 +125,7 @@ set the limit to 8-bytes. This will allow the column to hold a value up to
Rails migration example:
-```
+```ruby
add_column_with_default(:projects, :foo, :integer, default: 10, limit: 8)
# or
@@ -145,7 +145,7 @@ Please prefer Arel and plain SQL over usual ActiveRecord syntax. In case of usin
Example with Arel:
-```
+```ruby
users = Arel::Table.new(:users)
users.group(users[:user_id]).having(users[:id].count.gt(5))
@@ -154,7 +154,7 @@ users.group(users[:user_id]).having(users[:id].count.gt(5))
Example with plain SQL and `quote_string` helper:
-```
+```ruby
select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag|
tag_name = quote_string(tag["name"])
duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]}
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index 65cdd74bdb6..73893f9dd46 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -129,7 +129,7 @@ Various methods for opening and reading files in Ruby can be used to read the
standard output of a process instead of a file. The following two commands do
roughly the same:
-```
+```ruby
`touch /tmp/pawned-by-backticks`
File.read('|touch /tmp/pawned-by-file-read')
```
@@ -142,7 +142,7 @@ attacker cannot control the start of the filename string you are opening. For
instance, the following is sufficient to protect against accidentally starting
a shell command with `|`:
-```
+```ruby
# we assume repo_path is not controlled by the attacker (user)
path = File.join(repo_path, user_input)
# path cannot start with '|' now.
@@ -160,7 +160,7 @@ Path traversal is a security where the program (GitLab) tries to restrict user
access to a certain directory on disk, but the user manages to open a file
outside that directory by taking advantage of the `../` path notation.
-```
+```ruby
# Suppose the user gave us a path and they are trying to trick us
user_input = '../other-repo.git/other-file'
@@ -177,7 +177,7 @@ File.open(full_path) do # Oops!
A good way to protect against this is to compare the full path with its
'absolute path' according to Ruby's `File.absolute_path`.
-```
+```ruby
full_path = File.join(repo_path, user_input)
if full_path != File.absolute_path(full_path)
raise "Invalid path: #{full_path.inspect}"
diff --git a/doc/development/testing.md b/doc/development/testing.md
index b0b26ccf57a..6106e47daa0 100644
--- a/doc/development/testing.md
+++ b/doc/development/testing.md
@@ -64,11 +64,13 @@ the command line via `bundle exec teaspoon`, or via a web browser at
methods.
- Use `context` to test branching logic.
- Don't `describe` symbols (see [Gotchas](gotchas.md#dont-describe-symbols)).
+- Don't assert against the absolute value of a sequence-generated attribute (see [Gotchas](gotchas.md#dont-assert-against-the-absolute-value-of-a-sequence-generated-attribute)).
- Don't supply the `:each` argument to hooks since it's the default.
- Prefer `not_to` to `to_not` (_this is enforced by Rubocop_).
- Try to match the ordering of tests to the ordering within the class.
- Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines
to separate phases.
+- Try to use `Gitlab.config.gitlab.host` rather than hard coding `'localhost'`
[four-phase-test]: https://robots.thoughtbot.com/four-phase-test
diff --git a/doc/development/ux_guide/basics.md b/doc/development/ux_guide/basics.md
new file mode 100644
index 00000000000..62ac56a6bce
--- /dev/null
+++ b/doc/development/ux_guide/basics.md
@@ -0,0 +1,94 @@
+# Basics
+
+## Contents
+* [Responsive](#responsive)
+* [Typography](#typography)
+* [Icons](#icons)
+* [Color](#color)
+* [Motion](#motion)
+* [Voice and tone](#voice-and-tone)
+
+---
+
+## Responsive
+GitLab is a responsive experience that works well across all screen sizes, from mobile devices to large monitors. In order to provide a great user experience, the core functionality (browsing files, creating issues, writing comments, etc.) must be available at all resolutions. However, due to size limitations, some secondary functionality may be hidden on smaller screens. Please keep this functionality limited to rare actions that aren't expected to be needed on small devices.
+
+---
+
+## Typography
+### Primary typeface
+GitLab's main typeface used throughout the UI is **Source Sans Pro**. We support both the bold and regular weight.
+
+![Source Sans Pro sample](img/sourcesanspro-sample.png)
+
+
+### Monospace typeface
+This is the typeface used for code blocks. GitLab uses the OS default font.
+- **Menlo** (Mac)
+- **Consolas** (Windows)
+- **Liberation Mono** (Linux)
+
+![Monospace font sample](img/monospacefont-sample.png)
+
+---
+
+## Icons
+GitLab uses Font Awesome icons throughout our interface.
+
+![Trash icon](img/icon-trash.png)
+The trash icon is used for destructive actions that deletes information.
+
+![Edit icon](img/icon-edit.png)
+The pencil icon is used for editing content such as comments.
+
+![Notification icon](img/icon-notification.png)
+The bell icon is for notifications, such as Todos.
+
+![Subscribe icon](img/icon-subscribe.png)
+The eye icon is for subscribing to updates. For example, you can subscribe to a label and get updated on issues with that label.
+
+![RSS icon](img/icon-rss.png)
+The standard RSS icon is used for linking to RSS/atom feeds.
+
+![Close icon](img/icon-close.png)
+An 'x' is used for closing UI elements such as dropdowns.
+
+![Add icon](img/icon-add.png)
+A plus is used when creating new objects, such as issues, projects, etc.
+
+> TODO: update this section, add more general guidance to icon usage and personality, etc.
+
+---
+
+## Color
+
+![Blue](img/color-blue.png)
+Blue is used to highlight primary active elements (such as current tab), as well as other organization and managing commands.
+
+![Green](img/color-green.png)
+Green is for actions that create new objects.
+
+![Orange](img/color-orange.png)
+Orange is used for warnings
+
+![Red](img/color-red.png)
+Red is reserved for delete and other destructive commands
+
+![Grey](img/color-grey.png)
+Grey, and white (depending on context) is used for netral, secondary elements
+
+> TODO: Establish a perspective for color in terms of our personality and rationalize with Marketing usage.
+
+---
+
+## Motion
+
+Motion is a tool to help convey important relationships, changes or transitions between elements. It should be used sparingly and intentionally, highlighting the right elements at the right moment.
+
+> TODO: Determine a more concrete perspective on motion, create consistent easing/timing curves to follow.
+
+---
+
+## Voice and tone
+
+The copy for GitLab is clear and direct. We strike a clear balance between professional and friendly. We can empathesize with users (such as celebrating completing all Todos), and remain respectful of the importance of the work. We are that trusted, friendly coworker that is helpful and understanding.
diff --git a/doc/development/ux_guide/components.md b/doc/development/ux_guide/components.md
new file mode 100644
index 00000000000..764c3355714
--- /dev/null
+++ b/doc/development/ux_guide/components.md
@@ -0,0 +1,254 @@
+# Components
+
+## Contents
+* [Tooltips](#tooltips)
+* [Anchor links](#anchor-links)
+* [Buttons](#buttons)
+* [Dropdowns](#dropdowns)
+* [Counts](#counts)
+* [Lists](#lists)
+* [Tables](#tables)
+* [Blocks](#blocks)
+* [Panels](#panels)
+* [Alerts](#alerts)
+* [Forms](#forms)
+* [File holders](#file-holders)
+* [Data formats](#data-formats)
+
+---
+
+## Tooltips
+
+### Usage
+A tooltip should only be added if additional information is required.
+
+![Tooltip usage](img/tooltip-usage.png)
+
+### Placement
+By default, tooltips should be placed below the element that they refer to. However, if there is not enough space in the viewpoint, the tooltip should be moved to the side as needed.
+
+![Tooltip placement location](img/tooltip-placement.png)
+
+---
+
+## Anchor links
+
+Anchor links are used for navigational actions and lone, secondary commands (such as 'Reset filters' on the Issues List) when deemed appropriate by the UX team.
+
+### States
+
+#### Rest
+
+Primary links are blue in their rest state. Secondary links (such as the time stamp on comments) are a neutral gray color in rest. Details on the main GitLab navigation links can be found on the [features](features.md#navigation) page.
+
+#### Hover
+
+An underline should always be added on hover. A gray link becomes blue on hover.
+
+#### Focus
+
+The focus state should match the hover state.
+
+![Anchor link states ](img/components-anchorlinks.png)
+
+---
+
+## Buttons
+
+Buttons communicate the command that will occur when the user clicks on them.
+
+### Types
+
+#### Primary
+Primary buttons communicate the main call to action. There should only be one call to action in any given experience. Visually, primary buttons are conveyed with a full background fill
+
+![Primary button example](img/button-primary.png)
+
+#### Secondary
+Secondary buttons are for alternative commands. They should be conveyed by a button with an stroke, and no background fill.
+
+![Secondary button example](img/button-secondary.png)
+
+### Icon and text treatment
+Text should be in sentence case, where only the first word is capitalized. "Create issue" is correct, not "Create Issue". Buttons should only contain an icon or a text, not both.
+
+>>>
+TODO: Rationalize this. Ensure that we still believe this.
+>>>
+
+### Colors
+Follow the color guidance on the [basics](basics.md#color) page. The default color treatment is the white/grey button.
+
+---
+
+## Dropdowns
+
+Dropdowns are used to allow users to choose one (or many) options from a list of options. If this list of options is more 20, there should generally be a way to search through and filter the options (see the complex filter dropdowns below.)
+
+>>>
+TODO: Will update this section when the new filters UI is implemented.
+>>>
+
+![Dropdown states](img/components-dropdown.png)
+
+
+
+---
+
+## Counts
+
+A count element is used in navigation contexts where it is helpful to indicate the count, or number of items, in a list. Always use the [`number_with_delimiter`][number_with_delimiter] helper to display counts in the UI.
+
+![Counts example](img/components-counts.png)
+
+[number_with_delimiter]: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_with_delimiter
+
+---
+
+## Lists
+
+Lists are used where ever there is a single column of information to display. Ths [issues list](https://gitlab.com/gitlab-org/gitlab-ce/issues) is an example of a important list in the GitLab UI.
+
+### Types
+
+Simple list using .content-list
+
+![Simple list](img/components-simplelist.png)
+
+List with avatar, title and description using .content-list
+
+![List with avatar](img/components-listwithavatar.png)
+
+List with hover effect .well-list
+
+![List with hover effect](img/components-listwithhover.png)
+
+List inside panel
+
+![List inside panel](img/components-listinsidepanel.png)
+
+---
+
+## Tables
+
+When the information is too complex for a list, with multiple columns of information, a table can be used. For example, the [pipelines page](https://gitlab.com/gitlab-org/gitlab-ce/pipelines) uses a table.
+
+![Table](img/components-table.png)
+
+---
+
+## Blocks
+
+Blocks are a way to group related information.
+
+### Types
+
+#### Content blocks
+
+Content blocks (`.content-block`) are the basic grouping of content. They are commonly used in [lists](#lists), and are separated by a botton border.
+
+![Content block](img/components-contentblock.png)
+
+#### Row content blocks
+
+A background color can be added to this blocks. For example, items in the [issue list](https://gitlab.com/gitlab-org/gitlab-ce/issues) have a green background if they were created recently. Below is an example of a gray content block with side padding using `.row-content-block`.
+
+![Row content block](img/components-rowcontentblock.png)
+
+#### Cover blocks
+Cover blocks are generally used to create a heading element for a page, such as a new project, or a user profile page. Below is a cover block (`.cover-block`) for the profile page with an avatar, name and description.
+
+![Cover block](img/components-coverblock.png)
+
+---
+
+## Panels
+
+>>>
+TODO: Catalog how we are currently using panels and rationalize how they relate to alerts
+>>>
+
+![Panels](img/components-panels.png)
+
+---
+
+## Alerts
+
+>>>
+TODO: Catalog how we are currently using alerts
+>>>
+
+![Alerts](img/components-alerts.png)
+
+---
+
+## Forms
+
+There are two options shown below regarding the positioning of labels in forms. Both are options to consider based on context and available size. However, it is important to have a consistent treatment of labels in the same form.
+
+### Types
+
+#### Labels stack vertically
+
+Form (`form`) with label rendered above input.
+
+![Vertical form](img/components-verticalform.png)
+
+#### Labels side-by-side
+
+Horizontal form (`form.horizontal-form`) with label rendered inline with input.
+
+![Horizontal form](img/components-horizontalform.png)
+
+---
+
+## File holders
+A file holder (`.file-holder`) is used to show the contents of a file inline on a page of GitLab.
+
+![File Holder component](img/components-fileholder.png)
+
+---
+
+## Data formats
+
+### Dates
+
+#### Exact
+
+Format for exacts dates should be ‘Mon DD, YYYY’, such as the examples below.
+
+![Exact date](img/components-dateexact.png)
+
+#### Relative
+
+This format relates how long since an action has occurred. The exact date can be shown as a tooltip on hover.
+
+![Relative date](img/components-daterelative.png)
+
+### References
+
+Referencing GitLab items depends on a symbol for each type of item. Typing that symbol will invoke a dropdown that allows you to search for and autocomplete the item you were looking for. References are shown as [links](#links) in context, and hovering on them shows the full title or name of the item.
+
+![Hovering on a reference](img/components-referencehover.png)
+
+#### `%` Milestones
+
+![Milestone reference](img/components-referencemilestone.png)
+
+#### `#` Issues
+
+![Issue reference](img/components-referenceissues.png)
+
+#### `!` Merge Requests
+
+![Merge request reference](img/components-referencemrs.png)
+
+#### `~` Labels
+
+![Labels reference](img/components-referencelabels.png)
+
+#### `@` People
+
+![People reference](img/components-referencepeople.png)
+
+> TODO: Open issue: Some commit references use monospace fonts, but others don't. Need to standardize this.
diff --git a/doc/development/ux_guide/copy.md b/doc/development/ux_guide/copy.md
new file mode 100644
index 00000000000..227b4fd3451
--- /dev/null
+++ b/doc/development/ux_guide/copy.md
@@ -0,0 +1,99 @@
+# Copy
+
+The copy and messaging is a core part of the experience of GitLab and the conversation with our users. Follow the below conventions throughout GitLab.
+
+>**Note:**
+We are currently inconsistent with this guidance. Images below are created to illustrate the point. As this guidance is refined, we will ensure that our experiences align.
+
+## Contents
+* [Brevity](#brevity)
+* [Sentence case](#sentence-case)
+* [Terminology](#terminology)
+
+---
+
+## Brevity
+Users will skim content, rather than read text carefully.
+When familiar with a web app, users rely on muscle memory, and may read even less when moving quickly.
+A good experience should quickly orient a user, regardless of their experience, to the purpose of the current screen. This should happen without the user having to consciously read long strings of text.
+In general, text is burdensome and adds cognitive load. This is especially pronounced in a powerful productivity tool such as GitLab.
+We should _not_ rely on words as a crutch to explain the purpose of a screen.
+The current navigation and composition of the elements on the screen should get the user 95% there, with the remaining 5% being specific elements such as text.
+This means that, as a rule, copy should be very short. A long message or label is a red flag hinting at design that needs improvement.
+
+>**Example:**
+Use `Add` instead of `Add issue` as a button label.
+Preferrably use context and placement of controls to make it obvious what clicking on them will do.
+
+---
+
+## Sentence case
+Use sentence case for all titles, headings, labels, menu items, and buttons.
+
+---
+
+## Terminology
+Only use the terms in the tables below.
+
+### Issues
+
+#### Adjectives (states)
+
+| Term |
+| ---- |
+| Open |
+| Closed |
+| Deleted |
+
+>**Example:**
+Use `5 open issues` and don't use `5 pending issues`.
+
+#### Verbs (actions)
+
+| Term | Use | Don't |
+| ---- | --- | --- |
+| Add | Add an issue | Don't use `create` or `new` |
+| View | View an open or closed issue ||
+| Edit | Edit an open or closed issue | Don't use `update` |
+| Close | Close an open issue ||
+| Re-open | Re-open a closed issue | There should never be a need to use `open` as a verb |
+| Delete | Delete an open or closed issue ||
+
+#### Add issue
+
+When viewing a list of issues, there is a button that is labeled `Add`. Given the context in the example, it is clearly referring to issues. If the context were not clear enough, the label could be `Add issue`. Clicking the button will bring you to the `Add issue` form. Other add flows should be similar.
+
+![Add issue button](img/copy-form-addissuebutton.png)
+
+The form should be titled `Add issue`. The submit button should be labeled `Submit`. Don't use `Add`, `Create`, `New`, or `Save changes`. The cancel button should be labeled `Cancel`. Don't use `Back`.
+
+![Add issue form](img/copy-form-addissueform.png)
+
+#### Edit issue
+
+When in context of an issue, the affordance to edit it is labeled `Edit`. If the context is not clear enough, `Edit issue` could be considered. Other edit flows should be similar.
+
+![Edit issue button](img/copy-form-editissuebutton.png)
+
+The form should be titled `Edit issue`. The submit button should be labeled `Save`. Don't use `Edit`, `Update`, `Submit`, or `Save changes`. The cancel button should be labeled `Cancel`. Don't use `Back`.
+
+![Edit issue form](img/copy-form-editissueform.png)
+
+
+### Merge requests
+
+#### Adjectives (states)
+
+| Term |
+| ---- |
+| Open |
+| Merged |
+
+#### Verbs (actions)
+
+| Term | Use | Don't |
+| ---- | --- | --- |
+| Add | Add a merge request | Do not use `create` or `new` |
+| View | View an open or merged merge request ||
+| Edit | Edit an open or merged merge request| Do not use `update` |
+| Merge | Merge an open merge request || \ No newline at end of file
diff --git a/doc/development/ux_guide/features.md b/doc/development/ux_guide/features.md
new file mode 100644
index 00000000000..9472995c68c
--- /dev/null
+++ b/doc/development/ux_guide/features.md
@@ -0,0 +1,57 @@
+# Features
+
+## Contents
+* [Navigation](#navigation)
+* [Filtering](#filtering)
+* [Search results](#search-results)
+* [Conversations](#conversations)
+* [Empty states](#empty-states)
+
+---
+
+## Navigation
+
+### Global navigation
+
+The global navigation is accessible via the menu button on the top left of the screen, and can be pinned to keep it open. It contains a consistent list of pages that allow you to view content that is across GitLab. For example, you can view your todos, issues and merge requests across projects and groups.
+
+![Global nav](img/features-globalnav.png)
+
+
+### Contextual navigation
+
+The navigation in the header is contextual to each page. These options change depending on if you are looking at a project, group, or settings page. There should be no more than 10 items on a level in the contextual navigation, allowing it to comfortably fit on a typical laptop screen. There can be up to too levels of navigation. Each sub nav group should be a self-contained group of functionality. For example, everything related to the issue tracker should be under the 'Issue' tab, while everything relating to the wiki will be grouped under the 'Wiki' tab. The names used for each section should be short and easy to remember, ideally 1-2 words in length.
+
+![Contextual nav](img/features-contextualnav.png)
+
+### Information architecture
+
+The [GitLab Product Map](https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png) shows a visual representation of the information architecture for GitLab.
+
+---
+
+## Filtering
+
+Today, lists are filtered by a series of dropdowns. Some of these dropdowns allow multiselect (labels), while others allow you to filter to one option (milestones). However, we are currently implementing a [new model](https://gitlab.com/gitlab-org/gitlab-ce/issues/21747) for this, and will update the guide when it is ready.
+
+![Filters](img/features-filters.png)
+
+---
+
+## Search results
+
+### Global search
+
+[Global search](https://gitlab.com/search?group_id=&project_id=13083&repository_ref=&scope=issues&search=mobile) allows you to search across items in a project, or even across multiple projects. You can switch tabs to filter on type of object, or filter by group.
+
+### List search
+
+There are several core lists in the GitLab experience, such as the Issue list and the Merge Request list. You are also able to [filter and search these lists](https://gitlab.com/gitlab-org/gitlab-ce/issues?utf8=%E2%9C%93&search=mobile). This UI will be updated with the [new filtering model](https://gitlab.com/gitlab-org/gitlab-ce/issues/21747).
+
+---
+
+## Empty states
+
+Empty states need to be considered in the design of features. They are vital to helping onboard new users, making the experience feel more approachable and understandable. Empty states should feel inviting and provide just enough information to get people started. There should be a single call to action and a clear explanation of what to use the feature for.
+
+![Empty states](img/features-emptystates.png)
diff --git a/doc/development/ux_guide/img/button-primary.png b/doc/development/ux_guide/img/button-primary.png
new file mode 100644
index 00000000000..f4c673f5b88
--- /dev/null
+++ b/doc/development/ux_guide/img/button-primary.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-secondary.png b/doc/development/ux_guide/img/button-secondary.png
new file mode 100644
index 00000000000..57fa65b247c
--- /dev/null
+++ b/doc/development/ux_guide/img/button-secondary.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-blue.png b/doc/development/ux_guide/img/color-blue.png
new file mode 100644
index 00000000000..6449613eb16
--- /dev/null
+++ b/doc/development/ux_guide/img/color-blue.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-green.png b/doc/development/ux_guide/img/color-green.png
new file mode 100644
index 00000000000..15475b36f02
--- /dev/null
+++ b/doc/development/ux_guide/img/color-green.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-grey.png b/doc/development/ux_guide/img/color-grey.png
new file mode 100644
index 00000000000..58c474d5ce9
--- /dev/null
+++ b/doc/development/ux_guide/img/color-grey.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-orange.png b/doc/development/ux_guide/img/color-orange.png
new file mode 100644
index 00000000000..f4fc09b2d9b
--- /dev/null
+++ b/doc/development/ux_guide/img/color-orange.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-red.png b/doc/development/ux_guide/img/color-red.png
new file mode 100644
index 00000000000..6fbbf0a885d
--- /dev/null
+++ b/doc/development/ux_guide/img/color-red.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-alerts.png b/doc/development/ux_guide/img/components-alerts.png
new file mode 100644
index 00000000000..0b2ecc16a5f
--- /dev/null
+++ b/doc/development/ux_guide/img/components-alerts.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-anchorlinks.png b/doc/development/ux_guide/img/components-anchorlinks.png
new file mode 100644
index 00000000000..950f348277d
--- /dev/null
+++ b/doc/development/ux_guide/img/components-anchorlinks.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-contentblock.png b/doc/development/ux_guide/img/components-contentblock.png
new file mode 100644
index 00000000000..31fc1eec9df
--- /dev/null
+++ b/doc/development/ux_guide/img/components-contentblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-counts.png b/doc/development/ux_guide/img/components-counts.png
new file mode 100644
index 00000000000..19280e988a0
--- /dev/null
+++ b/doc/development/ux_guide/img/components-counts.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-coverblock.png b/doc/development/ux_guide/img/components-coverblock.png
new file mode 100644
index 00000000000..c8f1f87a108
--- /dev/null
+++ b/doc/development/ux_guide/img/components-coverblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-dateexact.png b/doc/development/ux_guide/img/components-dateexact.png
new file mode 100644
index 00000000000..8c0c5c1be40
--- /dev/null
+++ b/doc/development/ux_guide/img/components-dateexact.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-daterelative.png b/doc/development/ux_guide/img/components-daterelative.png
new file mode 100644
index 00000000000..1dc6d89e4ef
--- /dev/null
+++ b/doc/development/ux_guide/img/components-daterelative.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-dropdown.png b/doc/development/ux_guide/img/components-dropdown.png
new file mode 100644
index 00000000000..5770a393b37
--- /dev/null
+++ b/doc/development/ux_guide/img/components-dropdown.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-fileholder.png b/doc/development/ux_guide/img/components-fileholder.png
new file mode 100644
index 00000000000..4b8962905d6
--- /dev/null
+++ b/doc/development/ux_guide/img/components-fileholder.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-horizontalform.png b/doc/development/ux_guide/img/components-horizontalform.png
new file mode 100644
index 00000000000..92e28cf9afc
--- /dev/null
+++ b/doc/development/ux_guide/img/components-horizontalform.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listinsidepanel.png b/doc/development/ux_guide/img/components-listinsidepanel.png
new file mode 100644
index 00000000000..30ceb3eaa08
--- /dev/null
+++ b/doc/development/ux_guide/img/components-listinsidepanel.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listwithavatar.png b/doc/development/ux_guide/img/components-listwithavatar.png
new file mode 100644
index 00000000000..d3cb0ebc02b
--- /dev/null
+++ b/doc/development/ux_guide/img/components-listwithavatar.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listwithhover.png b/doc/development/ux_guide/img/components-listwithhover.png
new file mode 100644
index 00000000000..1484ecba6a0
--- /dev/null
+++ b/doc/development/ux_guide/img/components-listwithhover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-panels.png b/doc/development/ux_guide/img/components-panels.png
new file mode 100644
index 00000000000..6e71d0ad9c9
--- /dev/null
+++ b/doc/development/ux_guide/img/components-panels.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencehover.png b/doc/development/ux_guide/img/components-referencehover.png
new file mode 100644
index 00000000000..e9fb27e2aa9
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencehover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referenceissues.png b/doc/development/ux_guide/img/components-referenceissues.png
new file mode 100644
index 00000000000..caf9477db38
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referenceissues.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencelabels.png b/doc/development/ux_guide/img/components-referencelabels.png
new file mode 100644
index 00000000000..a122b45d1f1
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencelabels.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencemilestone.png b/doc/development/ux_guide/img/components-referencemilestone.png
new file mode 100644
index 00000000000..5aa9ecd1a78
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencemilestone.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencemrs.png b/doc/development/ux_guide/img/components-referencemrs.png
new file mode 100644
index 00000000000..6280243859a
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencemrs.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencepeople.png b/doc/development/ux_guide/img/components-referencepeople.png
new file mode 100644
index 00000000000..99772a539cf
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencepeople.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-rowcontentblock.png b/doc/development/ux_guide/img/components-rowcontentblock.png
new file mode 100644
index 00000000000..1c2d7096955
--- /dev/null
+++ b/doc/development/ux_guide/img/components-rowcontentblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-simplelist.png b/doc/development/ux_guide/img/components-simplelist.png
new file mode 100644
index 00000000000..892f507cfc2
--- /dev/null
+++ b/doc/development/ux_guide/img/components-simplelist.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-table.png b/doc/development/ux_guide/img/components-table.png
new file mode 100644
index 00000000000..7e964c885cf
--- /dev/null
+++ b/doc/development/ux_guide/img/components-table.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-verticalform.png b/doc/development/ux_guide/img/components-verticalform.png
new file mode 100644
index 00000000000..38863ad3c1c
--- /dev/null
+++ b/doc/development/ux_guide/img/components-verticalform.png
Binary files differ
diff --git a/doc/development/ux_guide/img/copy-form-addissuebutton.png b/doc/development/ux_guide/img/copy-form-addissuebutton.png
new file mode 100644
index 00000000000..18839d447e8
--- /dev/null
+++ b/doc/development/ux_guide/img/copy-form-addissuebutton.png
Binary files differ
diff --git a/doc/development/ux_guide/img/copy-form-addissueform.png b/doc/development/ux_guide/img/copy-form-addissueform.png
new file mode 100644
index 00000000000..e6838c06eca
--- /dev/null
+++ b/doc/development/ux_guide/img/copy-form-addissueform.png
Binary files differ
diff --git a/doc/development/ux_guide/img/copy-form-editissuebutton.png b/doc/development/ux_guide/img/copy-form-editissuebutton.png
new file mode 100644
index 00000000000..2435820e14f
--- /dev/null
+++ b/doc/development/ux_guide/img/copy-form-editissuebutton.png
Binary files differ
diff --git a/doc/development/ux_guide/img/copy-form-editissueform.png b/doc/development/ux_guide/img/copy-form-editissueform.png
new file mode 100644
index 00000000000..5ddeda33e68
--- /dev/null
+++ b/doc/development/ux_guide/img/copy-form-editissueform.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-contextualnav.png b/doc/development/ux_guide/img/features-contextualnav.png
new file mode 100644
index 00000000000..df157f54c84
--- /dev/null
+++ b/doc/development/ux_guide/img/features-contextualnav.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-emptystates.png b/doc/development/ux_guide/img/features-emptystates.png
new file mode 100644
index 00000000000..3befc14588e
--- /dev/null
+++ b/doc/development/ux_guide/img/features-emptystates.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-filters.png b/doc/development/ux_guide/img/features-filters.png
new file mode 100644
index 00000000000..281e55d590c
--- /dev/null
+++ b/doc/development/ux_guide/img/features-filters.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-globalnav.png b/doc/development/ux_guide/img/features-globalnav.png
new file mode 100644
index 00000000000..3c0db2247ca
--- /dev/null
+++ b/doc/development/ux_guide/img/features-globalnav.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-add.png b/doc/development/ux_guide/img/icon-add.png
new file mode 100644
index 00000000000..0d4c1a7692a
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-add.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-close.png b/doc/development/ux_guide/img/icon-close.png
new file mode 100644
index 00000000000..88d2b3b0c6d
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-close.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-edit.png b/doc/development/ux_guide/img/icon-edit.png
new file mode 100644
index 00000000000..f73be7a10fb
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-edit.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-notification.png b/doc/development/ux_guide/img/icon-notification.png
new file mode 100644
index 00000000000..4758632edd7
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-notification.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-rss.png b/doc/development/ux_guide/img/icon-rss.png
new file mode 100644
index 00000000000..c7ac9fb1349
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-rss.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-subscribe.png b/doc/development/ux_guide/img/icon-subscribe.png
new file mode 100644
index 00000000000..5cb277bfd5d
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-subscribe.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-trash.png b/doc/development/ux_guide/img/icon-trash.png
new file mode 100644
index 00000000000..357289a6fff
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-trash.png
Binary files differ
diff --git a/doc/development/ux_guide/img/monospacefont-sample.png b/doc/development/ux_guide/img/monospacefont-sample.png
new file mode 100644
index 00000000000..1cd290b713c
--- /dev/null
+++ b/doc/development/ux_guide/img/monospacefont-sample.png
Binary files differ
diff --git a/doc/development/ux_guide/img/sourcesanspro-sample.png b/doc/development/ux_guide/img/sourcesanspro-sample.png
new file mode 100644
index 00000000000..f7ecf0c7c66
--- /dev/null
+++ b/doc/development/ux_guide/img/sourcesanspro-sample.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-contentitemtitle.png b/doc/development/ux_guide/img/surfaces-contentitemtitle.png
new file mode 100644
index 00000000000..2eb926c1c43
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-contentitemtitle.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-header.png b/doc/development/ux_guide/img/surfaces-header.png
new file mode 100644
index 00000000000..ab44d4de696
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-header.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-systeminformationblock.png b/doc/development/ux_guide/img/surfaces-systeminformationblock.png
new file mode 100644
index 00000000000..5d91e993e24
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-systeminformationblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-ux.png b/doc/development/ux_guide/img/surfaces-ux.png
new file mode 100644
index 00000000000..e692c51e8c0
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-ux.png
Binary files differ
diff --git a/doc/development/ux_guide/img/tooltip-placement.png b/doc/development/ux_guide/img/tooltip-placement.png
new file mode 100644
index 00000000000..29a61c8400a
--- /dev/null
+++ b/doc/development/ux_guide/img/tooltip-placement.png
Binary files differ
diff --git a/doc/development/ux_guide/img/tooltip-usage.png b/doc/development/ux_guide/img/tooltip-usage.png
new file mode 100644
index 00000000000..e8e4c6ded91
--- /dev/null
+++ b/doc/development/ux_guide/img/tooltip-usage.png
Binary files differ
diff --git a/doc/development/ux_guide/index.md b/doc/development/ux_guide/index.md
new file mode 100644
index 00000000000..8aed11ebac3
--- /dev/null
+++ b/doc/development/ux_guide/index.md
@@ -0,0 +1,58 @@
+# GitLab UX Guide
+
+The goal of this guide is to provide standards, principles and in-depth information to design beautiful and effective GitLab features. This will be a living document, and we welcome contributions, feedback and suggestions.
+
+## Design
+
+---
+
+### [Principles](principles.md)
+These guiding principles set a solid foundation for our design system, and should remain relatively stable over multiple releases. They should be referenced as new design patterns are created.
+
+---
+
+### [Basics](basics.md)
+The basic ingredients of our experience establish our personality and feel. This section includes details about typography, color, and motion.
+
+---
+
+### [Components](components.md)
+Components are the controls that make up the GitLab experience, including guidance around buttons, links, dropdowns, etc.
+
+---
+
+### [Surfaces](surfaces.md)
+The GitLab experience is broken apart into several surfaces. Each of these surfaces is designated for a specific scope or type of content. Examples include the header, global menu, side pane, etc.
+
+---
+
+### [Copy](copy.md)
+Conventions on text and messaging within labels, buttons, and other components.
+
+---
+
+### [Features](features.md)
+The previous building blocks are combined into complete features in the GitLab UX. Examples include our navigation, filters, search results, and empty states.
+
+---
+
+## Research
+
+---
+
+### [Users](users.md)
+How we think about the variety of users of GitLab, from small to large teams, comparing opensource usage to enterprise, etc.
+
+---
+
+## Other
+
+---
+
+### [Tips for designers](tips.md)
+Tips for exporting assets, and other guidance.
+
+---
+
+### [Resources](resources.md)
+Resources for GitLab UX
diff --git a/doc/development/ux_guide/principles.md b/doc/development/ux_guide/principles.md
new file mode 100644
index 00000000000..1a297cba2cc
--- /dev/null
+++ b/doc/development/ux_guide/principles.md
@@ -0,0 +1,17 @@
+# Principles
+
+These are the guiding principles that we should strive for to establish a solid foundation for the GitLab experience.
+
+## Professional and productive
+GitLab is a tool to support what people do, day in, day out. We need to respect the importance of their work, and avoid gimicky details.
+
+## Minimal and efficient
+While work can get complicated, GitLab is about bringing a sharp focus, helping our customers know what matters now.
+
+## Immediately recognizable
+When you look at any screen, you should know immediately that it is GitLab. Our personality is strong and consistent across product and marketing experiences.
+
+## Human and quirky
+We need to build empathy with our users, understanding their state of mind, and connect with them at a human level. Quirkiness is part of our DNA, and we should embrace it in the right moments and contexts.
+
+> TODO: Ensure these principles align well with the goals of the Marketing team
diff --git a/doc/development/ux_guide/resources.md b/doc/development/ux_guide/resources.md
new file mode 100644
index 00000000000..2f760c94414
--- /dev/null
+++ b/doc/development/ux_guide/resources.md
@@ -0,0 +1,13 @@
+# Resources
+
+## GitLab UI development kit
+
+We created a page inside GitLab where you can check commonly used html and css elements.
+
+When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples
+you can use during GitLab development.
+
+## Design repository
+
+All design files are stored in the [gitlab-design](https://gitlab.com/gitlab-org/gitlab-design)
+repository and maintained by GitLab UX designers. \ No newline at end of file
diff --git a/doc/development/ux_guide/surfaces.md b/doc/development/ux_guide/surfaces.md
new file mode 100644
index 00000000000..881d6aa4cd6
--- /dev/null
+++ b/doc/development/ux_guide/surfaces.md
@@ -0,0 +1,47 @@
+# Surfaces
+
+## Contents
+* [Header](#header)
+* [Global menu](#global-menu)
+* [Side pane](#side-pane)
+* [Content area](#content-area)
+
+---
+
+![Surfaces UX](img/surfaces-ux.png)
+
+## Global menu
+
+This menu is to navigate to pages that contain content global to GitLab.
+
+---
+
+## Header
+
+The header contains 3 main elements: Project switching and searching, user account avatar and settings, and a contextual menu that changes based on the current page.
+
+![Surfaces Header](img/surfaces-header.png)
+
+---
+
+## Side pane
+
+The side pane holds supporting information and meta data for the information in the content area.
+
+---
+
+## Content area
+
+The main content of the page. The content area can include other surfaces.
+
+### Item title bar
+
+The item title bar contains the top level information to identify the item, such as the name, id and status.
+
+![Item title](img/surfaces-contentitemtitle.png)
+
+### Item system information
+
+The system information block contains relevant system controlled information.
+
+![Item system information](img/surfaces-systeminformationblock.png)
diff --git a/doc/development/ux_guide/tips.md b/doc/development/ux_guide/tips.md
new file mode 100644
index 00000000000..8348de4f8a2
--- /dev/null
+++ b/doc/development/ux_guide/tips.md
@@ -0,0 +1,44 @@
+# Tips
+
+## Contents
+* [SVGs](#svgs)
+
+---
+
+## SVGs
+
+When exporting SVGs, be sure to follow the following guidelines:
+
+1. Convert all strokes to outlines.
+2. Use pathfinder tools to combine overlapping paths and create compound paths.
+3. SVGs that are limited to one color should be exported without a fill color so the color can be set using CSS.
+4. Ensure that exported SVGs have been run through an [SVG cleaner](https://github.com/RazrFalcon/SVGCleaner) to remove unused elements and attributes.
+
+You can open your svg in a text editor to ensure that it is clean.
+Incorrect files will look like this:
+
+```xml
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="16px" height="17px" viewBox="0 0 16 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
+ <title>Group</title>
+ <desc>Created with Sketch.</desc>
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Group" fill="#7E7C7C">
+ <path d="M15.1111,1 L0.8891,1 C0.3981,1 0.0001,1.446 0.0001,1.996 L0.0001,15.945 C0.0001,16.495 0.3981,16.941 0.8891,16.941 L15.1111,16.941 C15.6021,16.941 16.0001,16.495 16.0001,15.945 L16.0001,1.996 C16.0001,1.446 15.6021,1 15.1111,1 L15.1111,1 L15.1111,1 Z M14.0001,6.0002 L14.0001,14.949 L2.0001,14.949 L2.0001,6.0002 L14.0001,6.0002 Z M14.0001,4.0002 L14.0001,2.993 L2.0001,2.993 L2.0001,4.0002 L14.0001,4.0002 Z" id="Combined-Shape"></path>
+ <polygon id="Fill-11" points="3 2.0002 5 2.0002 5 0.0002 3 0.0002"></polygon>
+ <polygon id="Fill-16" points="11 2.0002 13 2.0002 13 0.0002 11 0.0002"></polygon>
+ <path d="M5.37709616,11.5511984 L6.92309616,12.7821984 C7.35112915,13.123019 7.97359761,13.0565604 8.32002627,12.6330535 L10.7740263,9.63305349 C11.1237073,9.20557058 11.0606364,8.57555475 10.6331535,8.22587373 C10.2056706,7.87619272 9.57565475,7.93926361 9.22597373,8.36674651 L6.77197373,11.3667465 L8.16890384,11.2176016 L6.62290384,9.98660159 C6.19085236,9.6425813 5.56172188,9.71394467 5.21770159,10.1459962 C4.8736813,10.5780476 4.94504467,11.2071781 5.37709616,11.5511984 L5.37709616,11.5511984 Z" id="Stroke-21"></path>
+ </g>
+ </g>
+</svg>
+```
+
+Correct file will look like this:
+
+```xml
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 17" enable-background="new 0 0 16 17"><path d="m15.1 1h-2.1v-1h-2v1h-6v-1h-2v1h-2.1c-.5 0-.9.5-.9 1v14c0 .6.4 1 .9 1h14.2c.5 0 .9-.4.9-1v-14c0-.5-.4-1-.9-1m-1.1 14h-12v-9h12v9m0-11h-12v-1h12v1"/><path d="m5.4 11.6l1.5 1.2c.4.3 1.1.3 1.4-.1l2.5-3c.3-.4.3-1.1-.1-1.4-.5-.4-1.1-.3-1.5.1l-1.8 2.2-.8-.6c-.4-.3-1.1-.3-1.4.2-.3.4-.3 1 .2 1.4"/></svg>
+```
+
+> TODO: Checkout [https://github.com/svg/svgo](https://github.com/svg/svgo)
diff --git a/doc/development/ux_guide/users.md b/doc/development/ux_guide/users.md
new file mode 100644
index 00000000000..717a902c424
--- /dev/null
+++ b/doc/development/ux_guide/users.md
@@ -0,0 +1,16 @@
+# Users
+
+> TODO: Create personas. Understand the similarities and differences across the below spectrums.
+
+## Users by organization
+
+- Enterprise
+- Medium company
+- Small company
+- Open source communities
+
+## Users by role
+
+- Admin
+- Manager
+- Developer