Commit 066f1b93 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'winh-unify-modals' into 'master'

Unify dialog modal/popup dialog/confirmation dialog/modal to modal

See merge request gitlab-org/gitlab-ce!15865
parents 9d0fc98c 16a8a594
<script> <script>
import { s__ } from '../../locale'; import { s__ } from '../../locale';
import tooltip from '../../vue_shared/directives/tooltip'; import tooltip from '../../vue_shared/directives/tooltip';
import PopupDialog from '../../vue_shared/components/popup_dialog.vue'; import modal from '../../vue_shared/components/modal.vue';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import { COMMON_STR } from '../constants'; import { COMMON_STR } from '../constants';
import Icon from '../../vue_shared/components/icon.vue'; import Icon from '../../vue_shared/components/icon.vue';
...@@ -9,7 +9,7 @@ import Icon from '../../vue_shared/components/icon.vue'; ...@@ -9,7 +9,7 @@ import Icon from '../../vue_shared/components/icon.vue';
export default { export default {
components: { components: {
Icon, Icon,
PopupDialog, modal,
}, },
directives: { directives: {
tooltip, tooltip,
...@@ -27,7 +27,7 @@ export default { ...@@ -27,7 +27,7 @@ export default {
}, },
data() { data() {
return { return {
dialogStatus: false, modalStatus: false,
}; };
}, },
computed: { computed: {
...@@ -43,10 +43,10 @@ export default { ...@@ -43,10 +43,10 @@ export default {
}, },
methods: { methods: {
onLeaveGroup() { onLeaveGroup() {
this.dialogStatus = true; this.modalStatus = true;
}, },
leaveGroup(leaveConfirmed) { leaveGroup(leaveConfirmed) {
this.dialogStatus = false; this.modalStatus = false;
if (leaveConfirmed) { if (leaveConfirmed) {
eventHub.$emit('leaveGroup', this.group, this.parentGroup); eventHub.$emit('leaveGroup', this.group, this.parentGroup);
} }
...@@ -82,8 +82,8 @@ export default { ...@@ -82,8 +82,8 @@ export default {
class="fa fa-sign-out" class="fa fa-sign-out"
aria-hidden="true"/> aria-hidden="true"/>
</a> </a>
<popup-dialog <modal
v-show="dialogStatus" v-show="modalStatus"
:primary-button-label="__('Leave')" :primary-button-label="__('Leave')"
kind="warning" kind="warning"
:title="__('Are you sure?')" :title="__('Are you sure?')"
......
...@@ -9,7 +9,7 @@ import titleComponent from './title.vue'; ...@@ -9,7 +9,7 @@ import titleComponent from './title.vue';
import descriptionComponent from './description.vue'; import descriptionComponent from './description.vue';
import editedComponent from './edited.vue'; import editedComponent from './edited.vue';
import formComponent from './form.vue'; import formComponent from './form.vue';
import RecaptchaDialogImplementor from '../../vue_shared/mixins/recaptcha_dialog_implementor'; import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
export default { export default {
props: { props: {
...@@ -152,7 +152,7 @@ export default { ...@@ -152,7 +152,7 @@ export default {
}, },
mixins: [ mixins: [
RecaptchaDialogImplementor, recaptchaModalImplementor,
], ],
methods: { methods: {
...@@ -197,7 +197,7 @@ export default { ...@@ -197,7 +197,7 @@ export default {
}); });
}, },
closeRecaptchaDialog() { closeRecaptchaModal() {
this.store.setFormState({ this.store.setFormState({
updateLoading: false, updateLoading: false,
}); });
...@@ -273,10 +273,10 @@ export default { ...@@ -273,10 +273,10 @@ export default {
:enable-autocomplete="enableAutocomplete" :enable-autocomplete="enableAutocomplete"
/> />
<recaptcha-dialog <recaptcha-modal
v-show="showRecaptcha" v-show="showRecaptcha"
:html="recaptchaHTML" :html="recaptchaHTML"
@close="closeRecaptchaDialog" @close="closeRecaptchaModal"
/> />
</div> </div>
<div v-else> <div v-else>
......
<script> <script>
import animateMixin from '../mixins/animate'; import animateMixin from '../mixins/animate';
import TaskList from '../../task_list'; import TaskList from '../../task_list';
import RecaptchaDialogImplementor from '../../vue_shared/mixins/recaptcha_dialog_implementor'; import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
export default { export default {
mixins: [ mixins: [
animateMixin, animateMixin,
RecaptchaDialogImplementor, recaptchaModalImplementor,
], ],
props: { props: {
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
> >
</textarea> </textarea>
<recaptcha-dialog <recaptcha-modal
v-show="showRecaptcha" v-show="showRecaptcha"
:html="recaptchaHTML" :html="recaptchaHTML"
@close="closeRecaptcha" @close="closeRecaptcha"
......
<script> <script>
import popupDialog from '../../../vue_shared/components/popup_dialog.vue'; import modal from '../../../vue_shared/components/modal.vue';
import { __, s__, sprintf } from '../../../locale'; import { __, s__, sprintf } from '../../../locale';
import csrf from '../../../lib/utils/csrf'; import csrf from '../../../lib/utils/csrf';
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
}; };
}, },
components: { components: {
popupDialog, modal,
}, },
computed: { computed: {
csrfToken() { csrfToken() {
...@@ -89,7 +89,7 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`), ...@@ -89,7 +89,7 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
<template> <template>
<div> <div>
<popup-dialog <modal
v-if="isOpen" v-if="isOpen"
:title="s__('Profiles|Delete your account?')" :title="s__('Profiles|Delete your account?')"
:text="text" :text="text"
...@@ -134,7 +134,7 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`), ...@@ -134,7 +134,7 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
</form> </form>
</template> </template>
</popup-dialog> </modal>
<button <button
type="button" type="button"
......
<script> <script>
import { mapActions } from 'vuex'; import { mapActions } from 'vuex';
import { __ } from '../../../locale'; import { __ } from '../../../locale';
import popupDialog from '../../../vue_shared/components/popup_dialog.vue'; import modal from '../../../vue_shared/components/modal.vue';
export default { export default {
props: { props: {
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
}; };
}, },
components: { components: {
popupDialog, modal,
}, },
methods: { methods: {
...mapActions([ ...mapActions([
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
</script> </script>
<template> <template>
<popup-dialog <modal
:title="modalTitle" :title="modalTitle"
:primary-button-label="buttonLabel" :primary-button-label="buttonLabel"
kind="success" kind="success"
...@@ -94,5 +94,5 @@ ...@@ -94,5 +94,5 @@
</div> </div>
</fieldset> </fieldset>
</form> </form>
</popup-dialog> </modal>
</template> </template>
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
import { mapGetters, mapState, mapActions } from 'vuex'; import { mapGetters, mapState, mapActions } from 'vuex';
import tooltip from '../../vue_shared/directives/tooltip'; import tooltip from '../../vue_shared/directives/tooltip';
import icon from '../../vue_shared/components/icon.vue'; import icon from '../../vue_shared/components/icon.vue';
import PopupDialog from '../../vue_shared/components/popup_dialog.vue'; import modal from '../../vue_shared/components/modal.vue';
import commitFilesList from './commit_sidebar/list.vue'; import commitFilesList from './commit_sidebar/list.vue';
export default { export default {
components: { components: {
PopupDialog, modal,
icon, icon,
commitFilesList, commitFilesList,
}, },
...@@ -16,7 +16,7 @@ export default { ...@@ -16,7 +16,7 @@ export default {
}, },
data() { data() {
return { return {
showNewBranchDialog: false, showNewBranchModal: false,
submitCommitsLoading: false, submitCommitsLoading: false,
startNewMR: false, startNewMR: false,
commitMessage: '', commitMessage: '',
...@@ -58,7 +58,7 @@ export default { ...@@ -58,7 +58,7 @@ export default {
start_branch: createNewBranch ? this.currentBranch : undefined, start_branch: createNewBranch ? this.currentBranch : undefined,
}; };
this.showNewBranchDialog = false; this.showNewBranchModal = false;
this.submitCommitsLoading = true; this.submitCommitsLoading = true;
this.commitChanges({ payload, newMr: this.startNewMR }) this.commitChanges({ payload, newMr: this.startNewMR })
...@@ -76,7 +76,7 @@ export default { ...@@ -76,7 +76,7 @@ export default {
this.checkCommitStatus() this.checkCommitStatus()
.then((branchChanged) => { .then((branchChanged) => {
if (branchChanged) { if (branchChanged) {
this.showNewBranchDialog = true; this.showNewBranchModal = true;
} else { } else {
this.makeCommit(); this.makeCommit();
} }
...@@ -99,13 +99,13 @@ export default { ...@@ -99,13 +99,13 @@ export default {
'is-collapsed': collapsed, 'is-collapsed': collapsed,
}" }"
> >
<popup-dialog <modal
v-if="showNewBranchDialog" v-if="showNewBranchModal"
:primary-button-label="__('Create new branch')" :primary-button-label="__('Create new branch')"
kind="primary" kind="primary"
:title="__('Branch has changed')" :title="__('Branch has changed')"
:text="__('This branch has changed since you started editing. Would you like to create a new branch?')" :text="__('This branch has changed since you started editing. Would you like to create a new branch?')"
@toggle="showNewBranchDialog = false" @toggle="showNewBranchModal = false"
@submit="makeCommit(true)" @submit="makeCommit(true)"
/> />
<button <button
......
<script> <script>
import { mapGetters, mapActions, mapState } from 'vuex'; import { mapGetters, mapActions, mapState } from 'vuex';
import popupDialog from '../../vue_shared/components/popup_dialog.vue'; import modal from '../../vue_shared/components/modal.vue';
export default { export default {
components: { components: {
popupDialog, modal,
}, },
computed: { computed: {
...mapState([ ...mapState([
...@@ -43,7 +43,7 @@ export default { ...@@ -43,7 +43,7 @@ export default {
{{buttonLabel}} {{buttonLabel}}
</span> </span>
</button> </button>
<popup-dialog <modal
v-if="discardPopupOpen" v-if="discardPopupOpen"
class="text-left" class="text-left"
:primary-button-label="__('Discard changes')" :primary-button-label="__('Discard changes')"
......
<script> <script>
export default { export default {
name: 'popup-dialog', name: 'modal',
props: { props: {
title: { title: {
...@@ -75,7 +75,7 @@ export default { ...@@ -75,7 +75,7 @@ export default {
<template> <template>
<div class="modal-open"> <div class="modal-open">
<div <div
class="modal popup-dialog" class="modal show"
role="dialog" role="dialog"
tabindex="-1" tabindex="-1"
> >
......
<script> <script>
import PopupDialog from './popup_dialog.vue'; import modal from './modal.vue';
export default { export default {
name: 'recaptcha-dialog', name: 'recaptcha-modal',
props: { props: {
html: { html: {
...@@ -20,7 +20,7 @@ export default { ...@@ -20,7 +20,7 @@ export default {
}, },
components: { components: {
PopupDialog, modal,
}, },
methods: { methods: {
...@@ -65,9 +65,9 @@ export default { ...@@ -65,9 +65,9 @@ export default {
</script> </script>
<template> <template>
<popup-dialog <modal
kind="warning" kind="warning"
class="recaptcha-dialog js-recaptcha-dialog" class="recaptcha-modal js-recaptcha-modal"
:hide-footer="true" :hide-footer="true"
:title="__('Please solve the reCAPTCHA')" :title="__('Please solve the reCAPTCHA')"
@toggle="close" @toggle="close"
...@@ -81,5 +81,5 @@ export default { ...@@ -81,5 +81,5 @@ export default {
v-html="html" v-html="html"
></div> ></div>
</div> </div>
</popup-dialog> </modal>
</template> </template>
import RecaptchaDialog from '../components/recaptcha_dialog.vue'; import recaptchaModal from '../components/recaptcha_modal.vue';
export default { export default {
data() { data() {
...@@ -9,7 +9,7 @@ export default { ...@@ -9,7 +9,7 @@ export default {
}, },
components: { components: {
RecaptchaDialog, recaptchaModal,
}, },
methods: { methods: {
......
...@@ -44,11 +44,18 @@ body.modal-open { ...@@ -44,11 +44,18 @@ body.modal-open {
} }
} }
.modal.popup-dialog { .modal {
display: block; background-color: $black-transparent;
z-index: 2100;
@media (min-width: $screen-md-min) {
.modal-dialog {
margin: 30px auto;
}
}
} }
.recaptcha-dialog .recaptcha-form { .recaptcha-modal .recaptcha-form {
display: inline-block; display: inline-block;
.recaptcha { .recaptcha {
......
.modal.popup-dialog {
display: block;
background-color: $black-transparent;
z-index: 2100;
@media (min-width: $screen-md-min) {
.modal-dialog {
width: 600px;
margin: 30px auto;
}
}
}
.project-refs-form, .project-refs-form,
.project-refs-target-form { .project-refs-target-form {
display: inline-block; display: inline-block;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* [Tables](#tables) * [Tables](#tables)
* [Blocks](#blocks) * [Blocks](#blocks)
* [Panels](#panels) * [Panels](#panels)
* [Dialog modals](#dialog-modals) * [Modals](#modals)
* [Alerts](#alerts) * [Alerts](#alerts)
* [Forms](#forms) * [Forms](#forms)
* [Search box](#search-box) * [Search box](#search-box)
...@@ -255,18 +255,18 @@ Skeleton loading can replace any existing UI elements for the period in which th ...@@ -255,18 +255,18 @@ Skeleton loading can replace any existing UI elements for the period in which th
--- ---
## Dialog modals ## Modals
Dialog modals are only used for having a conversation and confirmation with the user. The user is not able to access the features on the main page until closing the modal. Modals are only used for having a conversation and confirmation with the user. The user is not able to access the features on the main page until closing the modal.
### Usage ### Usage
* When the action is irreversible, dialog modals provide the details and confirm with the user before they take an advanced action. * When the action is irreversible, modals provide the details and confirm with the user before they take an advanced action.
* When the action will affect privacy or authorization, dialog modals provide advanced information and confirm with the user. * When the action will affect privacy or authorization, modals provide advanced information and confirm with the user.
### Style ### Style
* Dialog modals contain the header, body, and actions. * Modals contain the header, body, and actions.
* **Header(1):** The header title is a question instead of a descriptive phrase. * **Header(1):** The header title is a question instead of a descriptive phrase.
* **Body(2):** The content in body should never be ambiguous and unclear. It provides specific information. * **Body(2):** The content in body should never be ambiguous and unclear. It provides specific information.
* **Actions(3):** Contains a affirmative action, a dismissive action, and an extra action. The order of actions from left to right: Dismissive action → Extra action → Affirmative action * **Actions(3):** Contains a affirmative action, a dismissive action, and an extra action. The order of actions from left to right: Dismissive action → Extra action → Affirmative action
...@@ -277,13 +277,13 @@ Dialog modals are only used for having a conversation and confirmation with the ...@@ -277,13 +277,13 @@ Dialog modals are only used for having a conversation and confirmation with the
### Placement ### Placement
* Dialog modals should always be the center of the screen horizontally and be positioned **72px** from the top. * Modals should always be the center of the screen horizontally and be positioned **72px** from the top.
| Dialog with 2 actions | Dialog with 3 actions | Special confirmation | | Modal with 2 actions | Modal with 3 actions | Special confirmation |
| --------------------- | --------------------- | -------------------- | | --------------------- | --------------------- | -------------------- |
| ![two-actions](img/modals-general-confimation-dialog.png) | ![three-actions](img/modals-three-buttons.png) | ![spcial-confirmation](img/modals-special-confimation-dialog.png) | | ![two-actions](img/modals-general-confimation-dialog.png) | ![three-actions](img/modals-three-buttons.png) | ![spcial-confirmation](img/modals-special-confimation-dialog.png) |
> TODO: Special case for dialog modal. > TODO: Special case for modal.
--- ---
......
...@@ -46,11 +46,11 @@ Avoid using periods in solitary sentences in these elements: ...@@ -46,11 +46,11 @@ Avoid using periods in solitary sentences in these elements:
* Labels * Labels
* Hover text * Hover text
* Bulleted lists * Bulleted lists
* Dialog body text * Modal body text
Periods should be used for: Periods should be used for:
* Lists or dialogs with multiple sentences * Lists or modals with multiple sentences
* Any sentence followed by a link * Any sentence followed by a link
| :white_check_mark: **Do** place periods after sentences followed by a link | :no_entry_sign: **Don’t** place periods after a link if it‘s not followed by a sentence | | :white_check_mark: **Do** place periods after sentences followed by a link | :no_entry_sign: **Don’t** place periods after a link if it‘s not followed by a sentence |
...@@ -80,7 +80,7 @@ Omit punctuation after phrases and labels to create a cleaner and more readable ...@@ -80,7 +80,7 @@ Omit punctuation after phrases and labels to create a cleaner and more readable
| Punctuation mark | Copy and paste | HTML entity | Unicode | Mac shortcut | Windows shortcut | Description | | Punctuation mark | Copy and paste | HTML entity | Unicode | Mac shortcut | Windows shortcut | Description |
|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
| Period | **.** | | | | | Omit for single sentences in affordances like labels, hover text, bulleted lists, and dialog body text.<br><br>Use in lists or dialogs with multiple sentences, and any sentence followed by a link or inline code.<br><br>Place inside quotation marks unless you’re telling the reader what to enter and it’s ambiguous whether to include the period. | | Period | **.** | | | | | Omit for single sentences in affordances like labels, hover text, bulleted lists, and modal body text.<br><br>Use in lists or modals with multiple sentences, and any sentence followed by a link or inline code.<br><br>Place inside quotation marks unless you’re telling the reader what to enter and it’s ambiguous whether to include the period. |
| Comma | **,** | | | | | Place inside quotation marks.<br><br>Use a [serial comma][serial comma] in lists of three or more terms. | | Comma | **,** | | | | | Place inside quotation marks.<br><br>Use a [serial comma][serial comma] in lists of three or more terms. |
| Exclamation point | **!** | | | | | Avoid exclamation points as they tend to come across as shouting. Some exceptions include greetings or congratulatory messages. | | Exclamation point | **!** | | | | | Avoid exclamation points as they tend to come across as shouting. Some exceptions include greetings or congratulatory messages. |
| Colon | **:** | `&#58;` | `\u003A` | | | Omit from labels, for example, in the labels for fields in a form. | | Colon | **:** | `&#58;` | `\u003A` | | | Omit from labels, for example, in the labels for fields in a form. |
...@@ -88,7 +88,7 @@ Omit punctuation after phrases and labels to create a cleaner and more readable ...@@ -88,7 +88,7 @@ Omit punctuation after phrases and labels to create a cleaner and more readable
| Quotation marks | **“**<br><br>**”**<br><br>**‘**<br><br>**’** | `&ldquo;`<br><br>`&rdquo;`<br><br>`&lsquo;`<br><br>`&rsquo;` | `\u201C`<br><br>`\u201D`<br><br>`\u2018`<br><br>`\u2019` | <kbd>⌥ Option</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>]</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>]</kbd> | <kbd>Alt</kbd>+<kbd>0 1 4 7</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 8</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 5</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 6</kbd> | Use proper quotation marks (also known as smart quotes, curly quotes, or typographer’s quotes) for quotes. Single quotation marks are used for quotes inside of quotes.<br><br>The right single quotation mark symbol is also used for apostrophes.<br><br>Don’t use primes, straight quotes, or free-standing accents for quotation marks. | | Quotation marks | **“**<br><br>**”**<br><br>**‘**<br><br>**’** | `&ldquo;`<br><br>`&rdquo;`<br><br>`&lsquo;`<br><br>`&rsquo;` | `\u201C`<br><br>`\u201D`<br><br>`\u2018`<br><br>`\u2019` | <kbd>⌥ Option</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>]</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>]</kbd> | <kbd>Alt</kbd>+<kbd>0 1 4 7</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 8</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 5</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 6</kbd> | Use proper quotation marks (also known as smart quotes, curly quotes, or typographer’s quotes) for quotes. Single quotation marks are used for quotes inside of quotes.<br><br>The right single quotation mark symbol is also used for apostrophes.<br><br>Don’t use primes, straight quotes, or free-standing accents for quotation marks. |
| Primes | **′**<br><br>**″** | `&prime;`<br><br>`&Prime;` | `\u2032`<br><br>`\u2033` | | <kbd>Alt</kbd>+<kbd>8 2 4 2</kbd><br><br><kbd>Alt</kbd>+<kbd>8 2 4 3</kbd> | Use prime (′) only in abbreviations for feet, arcminutes, and minutes: 3° 15′<br><br>Use double-prime (″) only in abbreviations for inches, arcseconds, and seconds: 3° 15′ 35″<br><br>Don’t use quotation marks, straight quotes, or free-standing accents for primes. | | Primes | **′**<br><br>**″** | `&prime;`<br><br>`&Prime;` | `\u2032`<br><br>`\u2033` | | <kbd>Alt</kbd>+<kbd>8 2 4 2</kbd><br><br><kbd>Alt</kbd>+<kbd>8 2 4 3</kbd> | Use prime (′) only in abbreviations for feet, arcminutes, and minutes: 3° 15′<br><br>Use double-prime (″) only in abbreviations for inches, arcseconds, and seconds: 3° 15′ 35″<br><br>Don’t use quotation marks, straight quotes, or free-standing accents for primes. |
| Straight quotes and accents | **"**<br><br>**'**<br><br>**`**<br><br>**´** | `&quot;`<br><br>`&#39;`<br><br>`&#96;`<br><br>`&acute;` | `\u0022`<br><br>`\u0027`<br><br>`\u0060`<br><br>`\u00B4` | | | Don’t use straight quotes or free-standing accents for primes or quotation marks.<br><br>Proper typography never uses straight quotes. They are left over from the age of typewriters and their only modern use is for code. | | Straight quotes and accents | **"**<br><br>**'**<br><br>**`**<br><br>**´** | `&quot;`<br><br>`&#39;`<br><br>`&#96;`<br><br>`&acute;` | `\u0022`<br><br>`\u0027`<br><br>`\u0060`<br><br>`\u00B4` | | | Don’t use straight quotes or free-standing accents for primes or quotation marks.<br><br>Proper typography never uses straight quotes. They are left over from the age of typewriters and their only modern use is for code. |
| Ellipsis | **…** | `&hellip;` | | <kbd>⌥ Option</kbd>+<kbd>;</kbd> | <kbd>Alt</kbd>+<kbd>0 1 3 3</kbd> | Use to indicate an action in progress (“Downloading…”) or incomplete or truncated text. No space before the ellipsis.<br><br>Omit from menu items or buttons that open a dialog or start some other process. | | Ellipsis | **…** | `&hellip;` | | <kbd>⌥ Option</kbd>+<kbd>;</kbd> | <kbd>Alt</kbd>+<kbd>0 1 3 3</kbd> | Use to indicate an action in progress (“Downloading…”) or incomplete or truncated text. No space before the ellipsis.<br><br>Omit from menu items or buttons that open a modal or start some other process. |
| Chevrons | **«**<br><br>**»**<br><br>**‹**<br><br>**›**<br><br>**<**<br><br>**>** | `&#171;`<br><br>`&#187;`<br><br>`&#8249;`<br><br>`&#8250;`<br><br>`&lt;`<br><br>`&gt;` | `\u00AB`<br><br>`\u00BB`<br><br>`\u2039`<br><br>`\u203A`<br><br>`\u003C`<br><br>`\u003E`<br><br> | | | Omit from links or buttons that open another page or move to the next or previous step in a process. Also known as angle brackets, angular quote brackets, or guillemets. | | Chevrons | **«**<br><br>**»**<br><br>**‹**<br><br>**›**<br><br>**<**<br><br>**>** | `&#171;`<br><br>`&#187;`<br><br>`&#8249;`<br><br>`&#8250;`<br><br>`&lt;`<br><br>`&gt;` | `\u00AB`<br><br>`\u00BB`<br><br>`\u2039`<br><br>`\u203A`<br><br>`\u003C`<br><br>`\u003E`<br><br> | | | Omit from links or buttons that open another page or move to the next or previous step in a process. Also known as angle brackets, angular quote brackets, or guillemets. |
| Em dash | **—** | `&mdash;` | `\u2014` | <kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 1</kbd> | Avoid using dashes to separate text. If you must use dashes for this purpose — like this — use an em dash surrounded by spaces. | | Em dash | **—** | `&mdash;` | `\u2014` | <kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 1</kbd> | Avoid using dashes to separate text. If you must use dashes for this purpose — like this — use an em dash surrounded by spaces. |
| En dash | **–** | `&ndash;` | `\u2013` | <kbd>⌥ Option</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 0</kbd> | Use an en dash without spaces instead of a hyphen to indicate a range of values, such as numbers, times, and dates: “3–5 kg”, “8:00 AM–12:30 PM”, “10–17 Jan” | | En dash | **–** | `&ndash;` | `\u2013` | <kbd>⌥ Option</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 0</kbd> | Use an en dash without spaces instead of a hyphen to indicate a range of values, such as numbers, times, and dates: “3–5 kg”, “8:00 AM–12:30 PM”, “10–17 Jan” |
...@@ -175,7 +175,7 @@ A **comment** is a written piece of text that users of GitLab can create. Commen ...@@ -175,7 +175,7 @@ A **comment** is a written piece of text that users of GitLab can create. Commen
#### Discussion #### Discussion
A **discussion** is a group of 1 or more comments. A discussion can include subdiscussions. Some discussions have the special capability of being able to be **resolved**. Both the comments in the discussion and the discussion itself can be resolved. A **discussion** is a group of 1 or more comments. A discussion can include subdiscussions. Some discussions have the special capability of being able to be **resolved**. Both the comments in the discussion and the discussion itself can be resolved.
## Confirmation dialogs ## Modals
- Destruction buttons should be clear and always say what they are destroying. - Destruction buttons should be clear and always say what they are destroying.
E.g., `Delete page` instead of just `Delete`. E.g., `Delete page` instead of just `Delete`.
...@@ -184,6 +184,8 @@ A **discussion** is a group of 1 or more comments. A discussion can include subd ...@@ -184,6 +184,8 @@ A **discussion** is a group of 1 or more comments. A discussion can include subd
- Avoid the word `cancel` or `canceled` in the descriptive copy. It can be - Avoid the word `cancel` or `canceled` in the descriptive copy. It can be
confusing when you then see the `Cancel` button. confusing when you then see the `Cancel` button.
see also: guidelines for [modal components](components.md#modals)
--- ---
Portions of this page are modifications based on work created and shared by the [Android Open Source Project][android project] and used according to terms described in the [Creative Commons 2.5 Attribution License][creative commons]. Portions of this page are modifications based on work created and shared by the [Android Open Source Project][android project] and used according to terms described in the [Creative Commons 2.5 Attribution License][creative commons].
......
...@@ -25,7 +25,7 @@ describe 'Profile account page', :js do ...@@ -25,7 +25,7 @@ describe 'Profile account page', :js do
fill_in 'password', with: '12345678' fill_in 'password', with: '12345678'
page.within '.popup-dialog' do page.within '.modal' do
click_button 'Delete account' click_button 'Delete account'
end end
...@@ -38,7 +38,7 @@ describe 'Profile account page', :js do ...@@ -38,7 +38,7 @@ describe 'Profile account page', :js do
fill_in 'password', with: 'testing123' fill_in 'password', with: 'testing123'
page.within '.popup-dialog' do page.within '.modal' do
click_button 'Delete account' click_button 'Delete account'
end end
......
...@@ -20,7 +20,7 @@ feature 'Multi-file editor new directory', :js do ...@@ -20,7 +20,7 @@ feature 'Multi-file editor new directory', :js do
click_link('New directory') click_link('New directory')
page.within('.popup-dialog') do page.within('.modal') do
find('.form-control').set('foldername') find('.form-control').set('foldername')
click_button('Create directory') click_button('Create directory')
......
...@@ -20,7 +20,7 @@ feature 'Multi-file editor new file', :js do ...@@ -20,7 +20,7 @@ feature 'Multi-file editor new file', :js do
click_link('New file') click_link('New file')
page.within('.popup-dialog') do page.within('.modal') do
find('.form-control').set('filename') find('.form-control').set('filename')
click_button('Create file') click_button('Create file')
......
...@@ -36,27 +36,27 @@ describe('ItemActionsComponent', () => { ...@@ -36,27 +36,27 @@ describe('ItemActionsComponent', () => {
describe('methods', () => { describe('methods', () => {
describe('onLeaveGroup', () => { describe('onLeaveGroup', () => {
it('should change `dialogStatus` prop to `true` which shows confirmation dialog', () => { it('should change `modalStatus` prop to `true` which shows confirmation dialog', () => {
expect(vm.dialogStatus).toBeFalsy(); expect(vm.modalStatus).toBeFalsy();
vm.onLeaveGroup(); vm.onLeaveGroup();
expect(vm.dialogStatus).toBeTruthy(); expect(vm.modalStatus).toBeTruthy();
}); });
}); });
describe('leaveGroup', () => { describe('leaveGroup', () => {
it('should change `dialogStatus` prop to `false` and emit `leaveGroup` event with required params when called with `leaveConfirmed` as `true`', () => { it('should change `modalStatus` prop to `false` and emit `leaveGroup` event with required params when called with `leaveConfirmed` as `true`', () => {
spyOn(eventHub, '$emit'); spyOn(eventHub, '$emit');
vm.dialogStatus = true; vm.modalStatus = true;
vm.leaveGroup(true); vm.leaveGroup(true);
expect(vm.dialogStatus).toBeFalsy(); expect(vm.modalStatus).toBeFalsy();
expect(eventHub.$emit).toHaveBeenCalledWith('leaveGroup', vm.group, vm.parentGroup); expect(eventHub.$emit).toHaveBeenCalledWith('leaveGroup', vm.group, vm.parentGroup);
}); });
it('should change `dialogStatus` prop to `false` and should NOT emit `leaveGroup` event when called with `leaveConfirmed` as `false`', () => { it('should change `modalStatus` prop to `false` and should NOT emit `leaveGroup` event when called with `leaveConfirmed` as `false`', () => {
spyOn(eventHub, '$emit'); spyOn(eventHub, '$emit');
vm.dialogStatus = true; vm.modalStatus = true;
vm.leaveGroup(false); vm.leaveGroup(false);
expect(vm.dialogStatus).toBeFalsy(); expect(vm.modalStatus).toBeFalsy();
expect(eventHub.$emit).not.toHaveBeenCalled(); expect(eventHub.$emit).not.toHaveBeenCalled();
}); });
}); });
...@@ -99,9 +99,9 @@ describe('ItemActionsComponent', () => { ...@@ -99,9 +99,9 @@ describe('ItemActionsComponent', () => {
newVm.$destroy(); newVm.$destroy();
}); });
it('should show modal dialog when `dialogStatus` is set to `true`', () => { it('should show modal dialog when `modalStatus` is set to `true`', () => {
vm.dialogStatus = true; vm.modalStatus = true;
const modalDialogEl = vm.$el.querySelector('.modal.popup-dialog'); const modalDialogEl = vm.$el.querySelector('.modal');
expect(modalDialogEl).toBeDefined(); expect(modalDialogEl).toBeDefined();
expect(modalDialogEl.querySelector('.modal-title').innerText.trim()).toBe('Are you sure?'); expect(modalDialogEl.querySelector('.modal-title').innerText.trim()).toBe('Are you sure?');
expect(modalDialogEl.querySelector('.btn.btn-warning').innerText.trim()).toBe('Leave'); expect(modalDialogEl.querySelector('.btn.btn-warning').innerText.trim()).toBe('Leave');
......
...@@ -272,10 +272,10 @@ describe('Issuable output', () => { ...@@ -272,10 +272,10 @@ describe('Issuable output', () => {
}); });
}); });
it('opens recaptcha dialog if update rejected as spam', (done) => { it('opens recaptcha modal if update rejected as spam', (done) => {
function mockScriptSrc() { function mockScriptSrc() {
const recaptchaChild = vm.$children const recaptchaChild = vm.$children
.find(child => child.$options._componentTag === 'recaptcha-dialog'); // eslint-disable-line no-underscore-dangle .find(child => child.$options._componentTag === 'recaptcha-modal'); // eslint-disable-line no-underscore-dangle
recaptchaChild.scriptSrc = '//scriptsrc'; recaptchaChild.scriptSrc = '//scriptsrc';
} }
...@@ -302,7 +302,7 @@ describe('Issuable output', () => { ...@@ -302,7 +302,7 @@ describe('Issuable output', () => {
.then(promise) .then(promise)
.then(() => setTimeoutPromise()) .then(() => setTimeoutPromise())
.then(() => { .then(() => {
modal = vm.$el.querySelector('.js-recaptcha-dialog'); modal = vm.$el.querySelector('.js-recaptcha-modal');
expect(modal.style.display).not.toEqual('none'); expect(modal.style.display).not.toEqual('none');
expect(modal.querySelector('.g-recaptcha').textContent).toEqual('recaptcha_html'); expect(modal.querySelector('.g-recaptcha').textContent).toEqual('recaptcha_html');
......
...@@ -54,7 +54,7 @@ describe('Description component', () => { ...@@ -54,7 +54,7 @@ describe('Description component', () => {
it('opens recaptcha dialog if update rejected as spam', (done) => { it('opens recaptcha dialog if update rejected as spam', (done) => {
let modal; let modal;
const recaptchaChild = vm.$children const recaptchaChild = vm.$children
.find(child => child.$options._componentTag === 'recaptcha-dialog'); // eslint-disable-line no-underscore-dangle .find(child => child.$options._componentTag === 'recaptcha-modal'); // eslint-disable-line no-underscore-dangle
recaptchaChild.scriptSrc = '//scriptsrc'; recaptchaChild.scriptSrc = '//scriptsrc';
...@@ -64,7 +64,7 @@ describe('Description component', () => { ...@@ -64,7 +64,7 @@ describe('Description component', () => {
vm.$nextTick() vm.$nextTick()
.then(() => { .then(() => {
modal = vm.$el.querySelector('.js-recaptcha-dialog'); modal = vm.$el.querySelector('.js-recaptcha-modal');
expect(modal.style.display).not.toEqual('none'); expect(modal.style.display).not.toEqual('none');
expect(modal.querySelector('.g-recaptcha').textContent).toEqual('recaptcha_html'); expect(modal.querySelector('.g-recaptcha').textContent).toEqual('recaptcha_html');
......
import Vue from 'vue'; import Vue from 'vue';
import PopupDialog from '~/vue_shared/components/popup_dialog.vue'; import modal from '~/vue_shared/components/modal.vue';
import mountComponent from '../../helpers/vue_mount_component_helper'; import mountComponent from '../../helpers/vue_mount_component_helper';
describe('PopupDialog', () => { describe('Modal', () => {
it('does not render a primary button if no primaryButtonLabel', () => { it('does not render a primary button if no primaryButtonLabel', () => {
const popupDialog = Vue.extend(PopupDialog); const modalComponent = Vue.extend(modal);
const vm = mountComponent(popupDialog); const vm = mountComponent(modalComponent);
expect(vm.$el.querySelector('.js-primary-button')).toBeNull(); expect(vm.$el.querySelector('.js-primary-button')).toBeNull();
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment