@gitlab/ui 114.8.0 → 115.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import { IS_BROWSER } from '../../constants/env';
4
4
  import { EVENT_NAME_CLICK, EVENT_NAME_FIRST, EVENT_NAME_PREV, EVENT_NAME_LAST, EVENT_NAME_NEXT, EVENT_NAME_CHANGED, EVENT_NAME_ACTIVATE_TAB } from '../../constants/events';
5
5
  import { CODE_SPACE, CODE_UP, CODE_LEFT, CODE_HOME, CODE_DOWN, CODE_RIGHT, CODE_END } from '../../constants/key-codes';
6
6
  import { PROP_TYPE_NUMBER, PROP_TYPE_STRING, PROP_TYPE_BOOLEAN, PROP_TYPE_ARRAY_OBJECT_STRING } from '../../constants/props';
7
- import { SLOT_NAME_TITLE, SLOT_NAME_TABS_START, SLOT_NAME_TABS_END, SLOT_NAME_EMPTY } from '../../constants/slots';
7
+ import { SLOT_NAME_TITLE, SLOT_NAME_TABS_START, SLOT_NAME_TABS_END, SLOT_NAME_TOOLBAR_START, SLOT_NAME_TOOLBAR_END, SLOT_NAME_EMPTY } from '../../constants/slots';
8
8
  import { arrayIncludes } from '../../utils/array';
9
9
  import { BvEvent } from '../../utils/bv-event.class';
10
10
  import { attemptFocus, selectAll, requestAF } from '../../utils/dom';
@@ -561,7 +561,7 @@ const BTabs = /*#__PURE__*/extend({
561
561
  $nav = h('div', {
562
562
  class: this.navWrapperClass,
563
563
  key: 'bv-tabs-nav'
564
- }, [$nav]);
564
+ }, [this.normalizeSlot(SLOT_NAME_TOOLBAR_START) || h(), $nav, this.normalizeSlot(SLOT_NAME_TOOLBAR_END) || h()]);
565
565
  const $children = this.normalizeSlot() || [];
566
566
  let $empty = h();
567
567
  if ($children.length === 0) {
@@ -24,6 +24,8 @@ const SLOT_NAME_TABLE_CAPTION = 'table-caption';
24
24
  const SLOT_NAME_TABLE_COLGROUP = 'table-colgroup';
25
25
  const SLOT_NAME_TABS_END = 'tabs-end';
26
26
  const SLOT_NAME_TABS_START = 'tabs-start';
27
+ const SLOT_NAME_TOOLBAR_END = 'toolbar-end';
28
+ const SLOT_NAME_TOOLBAR_START = 'toolbar-start';
27
29
  const SLOT_NAME_TEXT = 'text';
28
30
  const SLOT_NAME_THEAD_TOP = 'thead-top';
29
31
  const SLOT_NAME_TITLE = 'title';
@@ -31,4 +33,4 @@ const SLOT_NAME_TOAST_TITLE = 'toast-title';
31
33
  const SLOT_NAME_TOP_ROW = 'top-row';
32
34
  const SLOT_NAME_VALID_FEEDBACK = 'valid-feedback';
33
35
 
34
- export { SLOT_NAME_APPEND, SLOT_NAME_BOTTOM_ROW, SLOT_NAME_BUTTON_CONTENT, SLOT_NAME_CUSTOM_FOOT, SLOT_NAME_DEFAULT, SLOT_NAME_DESCRIPTION, SLOT_NAME_EMPTY, SLOT_NAME_EMPTYFILTERED, SLOT_NAME_FIRST, SLOT_NAME_HEADER, SLOT_NAME_INVALID_FEEDBACK, SLOT_NAME_LABEL, SLOT_NAME_MODAL_BACKDROP, SLOT_NAME_MODAL_CANCEL, SLOT_NAME_MODAL_FOOTER, SLOT_NAME_MODAL_HEADER, SLOT_NAME_MODAL_HEADER_CLOSE, SLOT_NAME_MODAL_OK, SLOT_NAME_MODAL_TITLE, SLOT_NAME_PREPEND, SLOT_NAME_ROW_DETAILS, SLOT_NAME_TABLE_BUSY, SLOT_NAME_TABLE_CAPTION, SLOT_NAME_TABLE_COLGROUP, SLOT_NAME_TABS_END, SLOT_NAME_TABS_START, SLOT_NAME_TEXT, SLOT_NAME_THEAD_TOP, SLOT_NAME_TITLE, SLOT_NAME_TOAST_TITLE, SLOT_NAME_TOP_ROW, SLOT_NAME_VALID_FEEDBACK };
36
+ export { SLOT_NAME_APPEND, SLOT_NAME_BOTTOM_ROW, SLOT_NAME_BUTTON_CONTENT, SLOT_NAME_CUSTOM_FOOT, SLOT_NAME_DEFAULT, SLOT_NAME_DESCRIPTION, SLOT_NAME_EMPTY, SLOT_NAME_EMPTYFILTERED, SLOT_NAME_FIRST, SLOT_NAME_HEADER, SLOT_NAME_INVALID_FEEDBACK, SLOT_NAME_LABEL, SLOT_NAME_MODAL_BACKDROP, SLOT_NAME_MODAL_CANCEL, SLOT_NAME_MODAL_FOOTER, SLOT_NAME_MODAL_HEADER, SLOT_NAME_MODAL_HEADER_CLOSE, SLOT_NAME_MODAL_OK, SLOT_NAME_MODAL_TITLE, SLOT_NAME_PREPEND, SLOT_NAME_ROW_DETAILS, SLOT_NAME_TABLE_BUSY, SLOT_NAME_TABLE_CAPTION, SLOT_NAME_TABLE_COLGROUP, SLOT_NAME_TABS_END, SLOT_NAME_TABS_START, SLOT_NAME_TEXT, SLOT_NAME_THEAD_TOP, SLOT_NAME_TITLE, SLOT_NAME_TOAST_TITLE, SLOT_NAME_TOOLBAR_END, SLOT_NAME_TOOLBAR_START, SLOT_NAME_TOP_ROW, SLOT_NAME_VALID_FEEDBACK };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "114.8.0",
3
+ "version": "115.0.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -81,7 +81,7 @@
81
81
  "dependencies": {
82
82
  "@floating-ui/dom": "1.7.1",
83
83
  "echarts": "^5.6.0",
84
- "iframe-resizer": "^4.3.2",
84
+ "iframe-resizer": "^4.4.5",
85
85
  "lodash": "^4.17.21",
86
86
  "popper.js": "^1.16.1",
87
87
  "portal-vue": "^2.1.7",
@@ -103,7 +103,7 @@
103
103
  "postcss": "8.5.3",
104
104
  "json5": "2.2.3",
105
105
  "rollup-plugin-vue/@vue/component-compiler/postcss-modules-sync/generic-names/loader-utils": "1.4.2",
106
- "eslint-plugin-import": "2.31.0"
106
+ "eslint-plugin-import": "2.32.0"
107
107
  },
108
108
  "devDependencies": {
109
109
  "@babel/core": "^7.27.4",
@@ -114,13 +114,13 @@
114
114
  "@cypress/grep": "^4.0.1",
115
115
  "@eslint/eslintrc": "^3.3.1",
116
116
  "@eslint/js": "^9.29.0",
117
- "@gitlab/eslint-plugin": "20.7.1",
117
+ "@gitlab/eslint-plugin": "21.1.0",
118
118
  "@gitlab/fonts": "^1.3.0",
119
119
  "@gitlab/stylelint-config": "6.2.2",
120
120
  "@gitlab/svgs": "3.131.0",
121
- "@jest/test-sequencer": "^29.7.0",
122
- "@rollup/plugin-commonjs": "^11.1.0",
123
- "@rollup/plugin-node-resolve": "^7.1.3",
121
+ "@jest/test-sequencer": "^30.0.2",
122
+ "@rollup/plugin-commonjs": "^21.1.0",
123
+ "@rollup/plugin-node-resolve": "^9.0.0",
124
124
  "@rollup/plugin-replace": "^2.4.2",
125
125
  "@storybook/addon-a11y": "^7.6.20",
126
126
  "@storybook/addon-docs": "^7.6.20",
@@ -151,18 +151,18 @@
151
151
  "axe-playwright": "^2.1.0",
152
152
  "babel-jest": "29.7.0",
153
153
  "babel-loader": "^8.4.1",
154
- "cypress": "14.3.3",
154
+ "cypress": "14.5.0",
155
155
  "cypress-real-events": "^1.14.0",
156
156
  "dompurify": "^3.1.2",
157
157
  "emoji-regex": "^10.4.0",
158
158
  "entities": "^4.5.0",
159
159
  "esbuild": "^0.18.0",
160
- "eslint": "9.28.0",
161
- "eslint-formatter-gitlab": "^6.0.0",
160
+ "eslint": "9.29.0",
161
+ "eslint-formatter-gitlab": "^6.0.1",
162
162
  "eslint-import-resolver-jest": "3.0.2",
163
- "eslint-plugin-cypress": "5.0.1",
163
+ "eslint-plugin-cypress": "5.1.0",
164
164
  "eslint-plugin-storybook": "0.12.0",
165
- "fuse.js": "^7.0.0",
165
+ "fuse.js": "^7.1.0",
166
166
  "gitlab-api-async-iterator": "^1.3.1",
167
167
  "glob": "10.4.5",
168
168
  "globby": "^11.1.0",
@@ -179,14 +179,14 @@
179
179
  "npm-run-all": "^4.1.5",
180
180
  "patch-package": "^8.0.0",
181
181
  "pikaday": "^1.8.0",
182
- "playwright": "^1.52.0",
183
- "playwright-core": "^1.52.0",
182
+ "playwright": "^1.53.1",
183
+ "playwright-core": "^1.53.1",
184
184
  "postcss": "8.5.3",
185
185
  "postcss-loader": "8.1.1",
186
186
  "postcss-scss": "4.0.9",
187
187
  "prettier": "3.5.3",
188
188
  "prettier-plugin-tailwindcss": "^0.6.5",
189
- "react": "^18.2.0",
189
+ "react": "^18.3.1",
190
190
  "react-dom": "^18.3.1",
191
191
  "rollup": "^2.79.2",
192
192
  "rollup-plugin-babel": "^4.4.0",
@@ -195,22 +195,22 @@
195
195
  "rollup-plugin-svg": "^2.0.0",
196
196
  "rollup-plugin-vue": "^5.1.9",
197
197
  "sass": "^1.49.9",
198
- "sass-loader": "^10.2.0",
198
+ "sass-loader": "^10.5.2",
199
199
  "sass-true": "^6.1.0",
200
- "start-server-and-test": "^1.10.6",
200
+ "start-server-and-test": "^1.15.4",
201
201
  "storybook": "^7.6.20",
202
202
  "storybook-dark-mode": "4.0.2",
203
- "style-dictionary": "^4.4.0",
204
- "stylelint": "16.8.1",
203
+ "style-dictionary": "^5.0.0",
204
+ "stylelint": "16.21.0",
205
205
  "tailwind-config-viewer": "2.0.4",
206
206
  "tailwindcss": "3.4.17",
207
207
  "vue": "2.7.16",
208
208
  "vue-loader": "^15.11.1",
209
- "vue-loader-vue3": "npm:vue-loader@17",
209
+ "vue-loader-vue3": "npm:vue-loader@17.4.2",
210
210
  "vue-router": "^3.5.1",
211
211
  "vue-template-compiler": "2.7.16",
212
212
  "vue-test-utils-compat": "^0.0.15",
213
- "webpack": "^5.9.0",
213
+ "webpack": "^5.99.9",
214
214
  "yargs": "^17.7.2",
215
215
  "yarn-deduplicate": "^6.0.2"
216
216
  }
@@ -14,8 +14,8 @@ $clear-button-size: 24px;
14
14
  padding-right: calc(#{$gl-spacing-scale-6} + #{$gl-spacing-scale-2});
15
15
  @apply gl-py-4;
16
16
  @apply gl-text-base;
17
+ @apply gl-text-default;
17
18
  background-color: var(--gl-dropdown-search-background-color);
18
- color: var(--gl-control-text-color);
19
19
 
20
20
  &:focus {
21
21
  @include gl-focus($inset: true);
@@ -2,6 +2,7 @@
2
2
  import debounce from 'lodash/debounce';
3
3
  import { GlResizeObserverDirective } from '../../../../directives/resize_observer/resize_observer';
4
4
  import GlIcon from '../../icon/icon.vue';
5
+ import { translate } from '../../../../utils/i18n';
5
6
  import GlTabs from './tabs.vue';
6
7
 
7
8
  const NAV_CLASS = 'gl-scrollable-tabs-nav';
@@ -16,6 +17,24 @@ export default {
16
17
  GlResizeObserverDirective,
17
18
  },
18
19
  inheritAttrs: false,
20
+ props: {
21
+ /**
22
+ * The aria-label that will be rendered inside for the scroll to left button.
23
+ */
24
+ scrollLeftLabel: {
25
+ type: String,
26
+ required: false,
27
+ default: translate('GlTabs.GlScrollableTabs.scrollLeftLabel', 'Scroll left'),
28
+ },
29
+ /**
30
+ * The aria-label that will be rendered inside for the scroll to right button.
31
+ */
32
+ scrollRightLabel: {
33
+ type: String,
34
+ required: false,
35
+ default: translate('GlTabs.GlScrollableTabs.scrollRightLabel', 'Scroll right'),
36
+ },
37
+ },
19
38
  data() {
20
39
  return {
21
40
  width: 0,
@@ -112,29 +131,27 @@ export default {
112
131
  <template v-for="slot in Object.keys($slots)" #[slot]>
113
132
  <slot :name="slot"></slot>
114
133
  </template>
115
- <template #tabs-start>
116
- <li v-show="displayScrollLeft" class="gl-tabs-fade gl-tabs-fade-left">
134
+ <template #toolbar-start>
135
+ <div v-show="displayScrollLeft" class="gl-tabs-fade gl-tabs-fade-left">
117
136
  <button
118
137
  class="gl-tabs-fade-icon-button"
119
- aria-label="Scroll left"
120
- tabindex="-1"
138
+ :aria-label="scrollLeftLabel"
121
139
  @click="scrollTabsLeft"
122
140
  >
123
141
  <gl-icon :size="16" name="chevron-lg-left" />
124
142
  </button>
125
- </li>
143
+ </div>
126
144
  </template>
127
- <template #tabs-end>
128
- <li v-show="displayScrollRight" class="gl-tabs-fade gl-tabs-fade-right">
145
+ <template #toolbar-end>
146
+ <div v-show="displayScrollRight" class="gl-tabs-fade gl-tabs-fade-right">
129
147
  <button
130
148
  class="gl-tabs-fade-icon-button"
131
- aria-label="Scroll right"
132
- tabindex="-1"
149
+ :aria-label="scrollRightLabel"
133
150
  @click="scrollTabsRight"
134
151
  >
135
152
  <gl-icon :size="16" name="chevron-lg-right" />
136
153
  </button>
137
- </li>
154
+ </div>
138
155
  </template>
139
156
  </gl-tabs>
140
157
  </template>
@@ -41,7 +41,8 @@ tab, when active, will reveal it’s own unique content.
41
41
 
42
42
  ## Adding Action Buttons to the Tabs
43
43
 
44
- Tabs start and end slot can be populated via props: `action-primary`, `action-secondary` and
44
+ Action buttons are rendered in separate toolbar slots (`#toolbar-start` & `#toolbar-end`) and can
45
+ be populated via props: `action-primary`, `action-secondary` and
45
46
  `action-tertiary`. These props allow you to handle how a primary, secondary and tertiary button will
46
47
  behave and look. The props receive an object as such:
47
48
 
@@ -70,7 +71,10 @@ component. This is a separate Vue component because of some limitations:
70
71
  exceptions).
71
72
 
72
73
  ~~~html
73
- <gl-scrollable-tabs>
74
+ <gl-scrollable-tabs
75
+ scroll-left-label="Custom scroll left text"
76
+ scroll-right-label="Custom scroll right text"
77
+ >
74
78
  <gl-tab v-for="tab in tabs" :key="tab.key" :title="tab.title"> {{ tab.content }} </gl-tab>
75
79
  </gl-scrollable-tabs>
76
80
  ~~~
@@ -1,5 +1,9 @@
1
+ .gl-tabs-wrapper {
2
+ @apply gl-relative gl-flex gl-flex-wrap gl-border-b;
3
+ }
4
+
1
5
  .gl-tabs-nav {
2
- @apply gl-border-b;
6
+ @apply gl-grow;
3
7
  }
4
8
 
5
9
  .gl-tab-nav-item {
@@ -107,13 +111,14 @@
107
111
  @apply gl-w-full;
108
112
  @apply gl-flex;
109
113
  @apply gl-flex-col;
114
+ @apply gl-grow-0;
110
115
  @apply gl-mt-3;
111
116
  @apply md:gl-hidden;
112
117
  }
113
118
 
114
119
  .gl-actions-tabs-end {
115
120
  @apply gl-hidden;
116
- @apply gl-grow;
121
+ @apply gl-grow-0;
117
122
  @apply gl-justify-end;
118
123
  @apply gl-items-center;
119
124
  @apply gl-flex-row;
@@ -135,19 +140,19 @@
135
140
  }
136
141
 
137
142
  .gl-tabs-fade {
143
+ @apply gl-absolute gl-top-0 gl-bottom-0 gl-z-2;
138
144
  @apply gl-w-8;
139
- bottom: 0;
140
- position: sticky;
141
145
  @apply gl-p-2;
146
+ @apply gl-flex;
142
147
  }
143
148
 
144
149
  .gl-tabs-fade-left {
145
- left: 0;
150
+ @apply gl-left-0;
146
151
  @include gl-bg-gradient-blur(left, var(--gl-background-color-default));
147
152
  }
148
153
 
149
154
  .gl-tabs-fade-right {
150
- right: 0;
155
+ @apply gl-justify-end gl-right-0;
151
156
  @include gl-bg-gradient-blur(right, var(--gl-background-color-default));
152
157
  }
153
158
 
@@ -210,6 +210,7 @@ export default {
210
210
  :no-fade="true"
211
211
  active-nav-item-class="gl-tab-nav-item-active"
212
212
  :content-class="[contentClass, 'gl-tab-content']"
213
+ nav-wrapper-class="gl-tabs-wrapper"
213
214
  :nav-class="[navClass, 'gl-tabs-nav']"
214
215
  :justified="justified"
215
216
  :value="activeTabIndex"
@@ -222,8 +223,8 @@ export default {
222
223
  <slot :name="slot"></slot>
223
224
  </template>
224
225
 
225
- <template v-if="hasActions" #tabs-start>
226
- <div data-testid="actions-tabs-start" class="gl-actions-tabs-start">
226
+ <template v-if="hasActions" #toolbar-start>
227
+ <div role="toolbar" data-testid="actions-tabs-start" class="gl-actions-tabs-start">
227
228
  <gl-button
228
229
  v-if="actionPrimary"
229
230
  data-testid="action-primary"
@@ -250,8 +251,8 @@ export default {
250
251
  </gl-button>
251
252
  </div>
252
253
  </template>
253
- <template v-if="hasActions" #tabs-end>
254
- <div data-testid="actions-tabs-end" class="gl-actions-tabs-end">
254
+ <template v-if="hasActions" #toolbar-end>
255
+ <div role="toolbar" data-testid="actions-tabs-end" class="gl-actions-tabs-end">
255
256
  <gl-button
256
257
  v-if="actionPrimary"
257
258
  data-testid="action-primary"