@gitlab/ui 37.0.0 → 37.3.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/components/base/drawer/drawer.documentation.js +1 -1
  3. package/dist/components/base/form/form_input_group/form_input_group.documentation.js +2 -26
  4. package/dist/components/base/form/form_input_group/form_input_group.js +7 -0
  5. package/dist/components/base/loading_icon/loading_icon.js +1 -1
  6. package/dist/components/base/pagination/pagination.js +23 -2
  7. package/dist/components/base/path/data.js +2 -1
  8. package/dist/components/base/path/path.js +14 -7
  9. package/dist/components/base/tabs/tab/tab.js +4 -0
  10. package/dist/components/base/tabs/tabs/tabs.documentation.js +2 -14
  11. package/dist/components/base/tabs/tabs/tabs.js +8 -0
  12. package/dist/components/charts/legend/legend.js +12 -0
  13. package/dist/directives/safe_html/safe_html.documentation.js +1 -1
  14. package/dist/directives/safe_link/safe_link.documentation.js +2 -3
  15. package/dist/index.css +1 -1
  16. package/dist/index.css.map +1 -1
  17. package/dist/utility_classes.css +1 -1
  18. package/dist/utility_classes.css.map +1 -1
  19. package/documentation/components_documentation.js +0 -2
  20. package/documentation/documented_stories.js +6 -0
  21. package/package.json +1 -1
  22. package/src/components/base/drawer/drawer.documentation.js +1 -1
  23. package/src/components/base/form/form_input_group/form_input_group.documentation.js +0 -28
  24. package/src/components/base/form/form_input_group/form_input_group.md +0 -4
  25. package/src/components/base/form/form_input_group/form_input_group.stories.js +84 -62
  26. package/src/components/base/form/form_input_group/form_input_group.vue +9 -0
  27. package/src/components/base/loading_icon/loading_icon.vue +1 -1
  28. package/src/components/base/pagination/pagination.spec.js +12 -2
  29. package/src/components/base/pagination/pagination.vue +23 -6
  30. package/src/components/base/path/__snapshots__/path.spec.js.snap +6 -0
  31. package/src/components/base/path/data.js +1 -0
  32. package/src/components/base/path/path.scss +6 -1
  33. package/src/components/base/path/path.spec.js +20 -0
  34. package/src/components/base/path/path.vue +18 -7
  35. package/src/components/base/tabs/tab/tab.vue +4 -0
  36. package/src/components/base/tabs/tabs/tabs.documentation.js +0 -12
  37. package/src/components/base/tabs/tabs/tabs.md +2 -7
  38. package/src/components/base/tabs/tabs/tabs.stories.js +219 -161
  39. package/src/components/base/tabs/tabs/tabs.vue +6 -0
  40. package/src/components/charts/legend/legend.stories.js +22 -15
  41. package/src/components/charts/legend/legend.vue +9 -0
  42. package/src/directives/safe_html/safe_html.md +0 -4
  43. package/src/directives/safe_html/safe_html.stories.js +53 -44
  44. package/src/directives/safe_link/safe_link.documentation.js +0 -1
  45. package/src/directives/safe_link/safe_link.md +0 -4
  46. package/src/directives/safe_link/safe_link.stories.js +31 -30
  47. package/src/scss/utilities.scss +8 -0
  48. package/src/scss/utility-mixins/background.scss +4 -0
  49. package/dist/components/base/form/form_input_group/examples/form_input_group.basic.example.js +0 -38
  50. package/dist/components/base/form/form_input_group/examples/form_input_group.predefined_options.example.js +0 -54
  51. package/dist/components/base/form/form_input_group/examples/form_input_group.predefined_reactive.example.js +0 -55
  52. package/dist/components/base/form/form_input_group/examples/form_input_group.reactive.example.js +0 -48
  53. package/dist/components/base/form/form_input_group/examples/index.js +0 -27
  54. package/dist/components/base/tabs/tab/examples/index.js +0 -13
  55. package/dist/components/base/tabs/tab/examples/tab.basic.example.js +0 -38
  56. package/dist/components/base/tabs/tab/tab.documentation.js +0 -18
  57. package/dist/components/base/tabs/tabs/examples/index.js +0 -60
  58. package/dist/components/base/tabs/tabs/examples/tabs.basic.example.js +0 -38
  59. package/dist/components/base/tabs/tabs/examples/tabs.contentless_tab.example.js +0 -38
  60. package/dist/components/base/tabs/tabs/examples/tabs.counterbadges.example.js +0 -38
  61. package/dist/components/base/tabs/tabs/examples/tabs.custom_title.example.js +0 -38
  62. package/dist/components/base/tabs/tabs/examples/tabs.disabled.example.js +0 -38
  63. package/dist/components/base/tabs/tabs/examples/tabs.justified.example.js +0 -38
  64. package/dist/components/base/tabs/tabs/examples/tabs.no_tabs.example.js +0 -38
  65. package/dist/components/base/tabs/tabs/examples/tabs.scrollable.example.js +0 -47
  66. package/dist/components/base/tabs/tabs/examples/tabs.styles_only.example.js +0 -38
  67. package/dist/components/charts/legend/examples/index.js +0 -22
  68. package/dist/components/charts/legend/examples/legend.basic.example.js +0 -93
  69. package/dist/components/charts/legend/examples/legend.toggled.example.js +0 -100
  70. package/dist/components/charts/legend/legend.documentation.js +0 -21
  71. package/src/components/base/form/form_input_group/examples/form_input_group.basic.example.vue +0 -10
  72. package/src/components/base/form/form_input_group/examples/form_input_group.predefined_options.example.vue +0 -25
  73. package/src/components/base/form/form_input_group/examples/form_input_group.predefined_reactive.example.vue +0 -32
  74. package/src/components/base/form/form_input_group/examples/form_input_group.reactive.example.vue +0 -25
  75. package/src/components/base/form/form_input_group/examples/index.js +0 -32
  76. package/src/components/base/tabs/tab/examples/index.js +0 -15
  77. package/src/components/base/tabs/tab/examples/tab.basic.example.vue +0 -5
  78. package/src/components/base/tabs/tab/tab.documentation.js +0 -16
  79. package/src/components/base/tabs/tab/tab.md +0 -3
  80. package/src/components/base/tabs/tab/tab.stories.js +0 -12
  81. package/src/components/base/tabs/tabs/examples/index.js +0 -72
  82. package/src/components/base/tabs/tabs/examples/tabs.basic.example.vue +0 -6
  83. package/src/components/base/tabs/tabs/examples/tabs.contentless_tab.example.vue +0 -17
  84. package/src/components/base/tabs/tabs/examples/tabs.counterbadges.example.vue +0 -28
  85. package/src/components/base/tabs/tabs/examples/tabs.custom_title.example.vue +0 -9
  86. package/src/components/base/tabs/tabs/examples/tabs.disabled.example.vue +0 -7
  87. package/src/components/base/tabs/tabs/examples/tabs.justified.example.vue +0 -6
  88. package/src/components/base/tabs/tabs/examples/tabs.no_tabs.example.vue +0 -8
  89. package/src/components/base/tabs/tabs/examples/tabs.scrollable.example.vue +0 -20
  90. package/src/components/base/tabs/tabs/examples/tabs.styles_only.example.vue +0 -22
  91. package/src/components/charts/legend/examples/index.js +0 -27
  92. package/src/components/charts/legend/examples/legend.basic.example.vue +0 -55
  93. package/src/components/charts/legend/examples/legend.toggled.example.vue +0 -60
  94. package/src/components/charts/legend/legend.documentation.js +0 -19
  95. package/src/components/charts/legend/legend.md +0 -0
@@ -1,8 +1,34 @@
1
- import { withKnobs, boolean } from '@storybook/addon-knobs';
2
1
  import { range } from 'lodash';
3
- import { documentedStoriesOf } from '../../../../../documentation/documented_stories';
4
2
  import { GlTabs, GlTab, GlScrollableTabs } from '../../../../index';
5
- import docs from './tabs.md';
3
+ import readme from './tabs.md';
4
+
5
+ const components = {
6
+ GlTabs,
7
+ GlTab,
8
+ };
9
+
10
+ const generateProps = ({
11
+ justified,
12
+ actionPrimary = null,
13
+ actionSecondary = null,
14
+ actionTertiary = null,
15
+ } = {}) => ({
16
+ justified,
17
+ actionPrimary,
18
+ actionSecondary,
19
+ actionTertiary,
20
+ });
21
+
22
+ const wrap = (template) => `
23
+ <gl-tabs
24
+ :justified="justified"
25
+ :action-primary="actionPrimary"
26
+ :action-secondary="actionSecondary"
27
+ :action-tertiary="actionTertiary"
28
+ >
29
+ ${template}
30
+ </gl-tabs>
31
+ `;
6
32
 
7
33
  const ScrollableTabsGenerator = {
8
34
  components: {
@@ -33,167 +59,199 @@ const ScrollableTabsGenerator = {
33
59
  `,
34
60
  };
35
61
 
36
- const createBaseStory = () => ({
37
- components: {
38
- GlTabs,
39
- GlTab,
62
+ export const Default = (_args, { argTypes }) => ({
63
+ props: Object.keys(argTypes),
64
+ components,
65
+ template: wrap(`
66
+ <gl-tab title="Tab 1">
67
+ Tab panel 1
68
+ </gl-tab>
69
+ <gl-tab title="Tab 2">
70
+ Tab panel 2
71
+ </gl-tab>
72
+ <gl-tab title="Tab 3">
73
+ Tab panel 3
74
+ </gl-tab>
75
+ <gl-tab title="Tab 4">
76
+ Tab panel 4
77
+ </gl-tab>
78
+ <gl-tab title="Tab 5">
79
+ Tab panel 5
80
+ </gl-tab>
81
+ <gl-tab title="Tab 6">
82
+ Tab panel 6
83
+ </gl-tab>
84
+ <gl-tab title="Tab 7">
85
+ Tab panel 7
86
+ </gl-tab>
87
+ <gl-tab title="Tab 8">
88
+ Tab panel 8
89
+ </gl-tab>
90
+ <gl-tab title="Tab 9">
91
+ Tab panel 9
92
+ </gl-tab>
93
+ <gl-tab title="Tab 10">
94
+ Tab panel 10
95
+ </gl-tab>
96
+ <gl-tab title="Tab 11">
97
+ Tab panel 11
98
+ </gl-tab>
99
+ <gl-tab title="Tab 12">
100
+ Tab panel 12
101
+ </gl-tab>
102
+ <gl-tab title="Tab 13" query-param-value="thirteenth">
103
+ Tab panel 13
104
+ </gl-tab>
105
+ <gl-tab title="Tab 14">
106
+ Tab panel 14
107
+ </gl-tab>`),
108
+ });
109
+ Default.args = generateProps();
110
+
111
+ export const ContentlessTab = (_args, { argTypes }) => ({
112
+ props: Object.keys(argTypes),
113
+ components,
114
+ template: wrap(`
115
+ <gl-tab title="Regular tab">
116
+ <p>Regular tab content.</p>
117
+ <p>The contentless tab is not selectable, as it has no content. This is useful for displaying things that aren't really tabs after the list of tabs.</p>
118
+ </gl-tab>
119
+ <gl-tab title="Another tab">
120
+ <p>Another tab's content.</p>
121
+ </gl-tab>
122
+ <template #tabs-end>
123
+ <li class="gl-tab-nav-item">
124
+ Contentless tab
125
+ </li>
126
+ </template>`),
127
+ });
128
+
129
+ export const EmptyState = (_args, { argTypes }) => ({
130
+ props: Object.keys(argTypes),
131
+ components,
132
+ template: wrap(`
133
+ <template #empty>
134
+ This content is only displayed when there are no tabs. Useful for dynamically added/removed tabs.
135
+ </template>`),
136
+ });
137
+
138
+ export const JustifiedTabs = (_args, { argTypes }) => ({
139
+ props: Object.keys(argTypes),
140
+ components,
141
+ template: wrap(`
142
+ <gl-tab title="Tab 1">
143
+ <p>Tab panel 1</p>
144
+ </gl-tab>
145
+ <gl-tab title="Tab 2">
146
+ <p>Tab panel 2</p>
147
+ </gl-tab>`),
148
+ });
149
+ JustifiedTabs.args = generateProps({ justified: true });
150
+
151
+ export const WithCounterBadges = (_args, { argTypes }) => ({
152
+ props: Object.keys(argTypes),
153
+ components,
154
+ template: wrap(`
155
+ <gl-tab>
156
+ <template #title>
157
+ <span>Tab</span>
158
+ <gl-badge size="sm" class="gl-tab-counter-badge">500</gl-badge>
159
+ <span class="sr-only">items</span>
160
+ </template>
161
+ Tab panel 1
162
+ </gl-tab>
163
+ <gl-tab>
164
+ <template #title>
165
+ <span>Tab</span>
166
+ <gl-badge size="sm" class="gl-tab-counter-badge">250</gl-badge>
167
+ <span class="sr-only">items</span>
168
+ </template>
169
+ Tab panel 2
170
+ </gl-tab>
171
+ <gl-tab>
172
+ <template #title>
173
+ <span>Tab</span>
174
+ </template>
175
+ Tab panel 3
176
+ </gl-tab>`),
177
+ });
178
+
179
+ export const WithActions = (_args, { argTypes }) => ({
180
+ props: Object.keys(argTypes),
181
+ components,
182
+ template: wrap(`
183
+ <gl-tab title="Tab 1">
184
+ Tab panel 1
185
+ </gl-tab>`),
186
+ });
187
+ WithActions.args = generateProps({
188
+ actionPrimary: {
189
+ attributes: {
190
+ variant: 'danger',
191
+ },
192
+ text: 'Primary action',
40
193
  },
41
- props: {
42
- syncActiveTabWithQueryParams: {
43
- type: Boolean,
44
- default: boolean('sync-active-tab-with-query-params', false),
194
+ actionSecondary: {
195
+ attributes: {
196
+ variant: 'success',
45
197
  },
198
+ text: 'Secondary action',
199
+ },
200
+ actionTertiary: {
201
+ attributes: {
202
+ variant: 'default',
203
+ },
204
+ text: 'Tertiary action',
46
205
  },
47
206
  });
48
207
 
49
- documentedStoriesOf('base/tabs/tabs', docs)
50
- .addDecorator(withKnobs)
51
- .add('default', () => ({
52
- ...createBaseStory(),
53
- template: `
54
- <gl-tabs :sync-active-tab-with-query-params="syncActiveTabWithQueryParams">
55
- <gl-tab title="Tab 1">
56
- Tab panel 1
57
- </gl-tab>
58
- <gl-tab title="Tab 2">
59
- Tab panel 2
60
- </gl-tab>
61
- <gl-tab title="Tab 3">
62
- Tab panel 3
63
- </gl-tab>
64
- <gl-tab title="Tab 4">
65
- Tab panel 4
66
- </gl-tab>
67
- <gl-tab title="Tab 5">
68
- Tab panel 5
69
- </gl-tab>
70
- <gl-tab title="Tab 6">
71
- Tab panel 6
72
- </gl-tab>
73
- <gl-tab title="Tab 7">
74
- Tab panel 7
75
- </gl-tab>
76
- <gl-tab title="Tab 8">
77
- Tab panel 8
78
- </gl-tab>
79
- <gl-tab title="Tab 9">
80
- Tab panel 9
81
- </gl-tab>
82
- <gl-tab title="Tab 10">
83
- Tab panel 10
84
- </gl-tab>
85
- <gl-tab title="Tab 11">
86
- Tab panel 11
87
- </gl-tab>
88
- <gl-tab title="Tab 12">
89
- Tab panel 12
90
- </gl-tab>
91
- <gl-tab title="Tab 13" query-param-value="thirteenth">
92
- Tab panel 13
93
- </gl-tab>
94
- <gl-tab title="Tab 14">
95
- Tab panel 14
96
- </gl-tab>
97
- </gl-tabs>
98
- `,
99
- }))
100
- .add('contentless tab', () => ({
101
- ...createBaseStory(),
102
- template: `
103
- <gl-tabs>
104
- <gl-tab title="Regular tab">
105
- <p>Regular tab content.</p>
106
- <p>The contentless tab is not selectable, as it has no content. This is useful for displaying things that aren't really tabs after the list of tabs.</p>
107
- </gl-tab>
108
- <gl-tab title="Another tab">
109
- <p>Another tab's content.</p>
110
- </gl-tab>
111
- <template #tabs-end>
112
- <li class="gl-tab-nav-item">
113
- Contentless tab
114
- </li>
115
- </template>
116
- </gl-tabs>
117
- `,
118
- }))
119
- .add('empty state', () => ({
120
- ...createBaseStory(),
121
- template: `
122
- <gl-tabs>
123
- <template #empty>
124
- This content is only displayed when there are no tabs. Useful for dynamically added/removed tabs.
125
- </template>
126
- </gl-tabs>
127
- `,
128
- }))
129
- .add('justified tabs', () => ({
130
- ...createBaseStory(),
131
- template: `
132
- <gl-tabs justified>
133
- <gl-tab title="Tab 1">
134
- <p>Tab panel 1</p>
135
- </gl-tab>
136
- <gl-tab title="Tab 2">
137
- <p>Tab panel 2</p>
138
- </gl-tab>
139
- </gl-tabs>
140
- `,
141
- }))
142
- .add('with counter badges', () => ({
143
- ...createBaseStory(),
144
- template: `
145
- <gl-tabs>
146
- <gl-tab>
147
- <template #title>
148
- <span>Tab</span>
149
- <gl-badge size="sm" class="gl-tab-counter-badge">500</gl-badge>
150
- <span class="sr-only">items</span>
151
- </template>
152
- Tab panel 1
153
- </gl-tab>
154
- <gl-tab>
155
- <template #title>
156
- <span>Tab</span>
157
- <gl-badge size="sm" class="gl-tab-counter-badge">250</gl-badge>
158
- <span class="sr-only">items</span>
159
- </template>
160
- Tab panel 2
161
- </gl-tab>
162
- <gl-tab>
163
- <template #title>
164
- <span>Tab</span>
165
- </template>
166
- Tab panel 3
167
- </gl-tab>
168
- </gl-tabs>
169
- `,
170
- }))
171
- .add('with scroll', () => ({
172
- ...createBaseStory(),
173
- components: {
174
- ScrollableTabsGenerator,
175
- },
176
- template: '<scrollable-tabs-generator :count="50" />',
177
- }))
178
- .add(
179
- 'with scroll and growing',
180
- () => ({
181
- ...createBaseStory(),
182
- components: {
183
- ScrollableTabsGenerator,
184
- },
185
- data() {
186
- return {
187
- count: 2,
188
- intervalId: 0,
189
- };
190
- },
191
- mounted() {
192
- this.intervalId = setInterval(() => {
193
- this.count += 1;
194
- }, 2000);
208
+ export const WithScroll = (_args, { argTypes }) => ({
209
+ props: Object.keys(argTypes),
210
+ components: {
211
+ ScrollableTabsGenerator,
212
+ },
213
+ template: '<scrollable-tabs-generator :count="50" />',
214
+ });
215
+
216
+ export const WithScrollAndGrowing = (_args, { argTypes }) => ({
217
+ props: Object.keys(argTypes),
218
+ components: {
219
+ ScrollableTabsGenerator,
220
+ },
221
+ data() {
222
+ return {
223
+ count: 2,
224
+ intervalId: 0,
225
+ };
226
+ },
227
+ mounted() {
228
+ this.intervalId = setInterval(() => {
229
+ this.count += 1;
230
+ }, 2000);
231
+ },
232
+ template: '<scrollable-tabs-generator :count="count" />',
233
+ });
234
+ WithScrollAndGrowing.parameters = {
235
+ storyshots: { disable: true },
236
+ };
237
+
238
+ export default {
239
+ title: 'base/tabs',
240
+ component: GlTabs,
241
+ subcomponents: { GlTab, GlScrollableTabs },
242
+ parameters: {
243
+ bootstrapComponent: 'b-tabs',
244
+ docs: {
245
+ description: {
246
+ component: readme,
195
247
  },
196
- template: '<scrollable-tabs-generator :count="count" />',
197
- }),
198
- { storyshots: false }
199
- );
248
+ },
249
+ },
250
+ argTypes: {
251
+ contentClass: { control: { disable: true } },
252
+ navClass: { control: { disable: true } },
253
+ syncActiveTabWithQueryParams: { control: { disable: true } },
254
+ queryParamName: { control: { disable: true } },
255
+ value: { control: { disable: true } },
256
+ },
257
+ };
@@ -46,11 +46,17 @@ export default {
46
46
  required: false,
47
47
  default: false,
48
48
  },
49
+ /**
50
+ * Sync active tab with query string parameters. Allows for deep linking into specific tabs.
51
+ */
49
52
  syncActiveTabWithQueryParams: {
50
53
  type: Boolean,
51
54
  required: false,
52
55
  default: false,
53
56
  },
57
+ /**
58
+ * Name to use for query string parameter.
59
+ */
54
60
  queryParamName: {
55
61
  type: String,
56
62
  required: false,
@@ -1,5 +1,4 @@
1
1
  import { GlChart, GlChartLegend } from '../../../charts';
2
- import { documentedStoriesOf } from '../../../../documentation/documented_stories';
3
2
  import { LEGEND_LAYOUT_TABLE } from '../../../utils/charts/constants';
4
3
  import { generateSeriesData } from '../../../utils/charts/story_config';
5
4
  import {
@@ -7,7 +6,6 @@ import {
7
6
  SERIES_NAME_LONG,
8
7
  SERIES_NAME_LONG_WITHOUT_SPACES,
9
8
  } from '../../../utils/stories_utils';
10
- import readme from './legend.md';
11
9
 
12
10
  const generateOptions = (seriesLength, seriesNameType) => {
13
11
  return {
@@ -89,16 +87,25 @@ const getStoryOptions = (seriesLength, seriesNameType, legendLayoutType) => {
89
87
  };
90
88
  };
91
89
 
92
- documentedStoriesOf('charts/chart-legend', readme)
93
- .add('default', () => getStoryOptions(10, SERIES_NAME_SHORT))
94
- .add('default with long series names', () => getStoryOptions(10, SERIES_NAME_LONG))
95
- .add('default with long series names and no spaces', () =>
96
- getStoryOptions(10, SERIES_NAME_LONG_WITHOUT_SPACES)
97
- )
98
- .add('with tabular layout', () => getStoryOptions(10, SERIES_NAME_SHORT, LEGEND_LAYOUT_TABLE))
99
- .add('with tabular layout and long series names', () =>
100
- getStoryOptions(10, SERIES_NAME_LONG, LEGEND_LAYOUT_TABLE)
101
- )
102
- .add('with tabular layout and long series names with no spaces', () =>
103
- getStoryOptions(10, SERIES_NAME_LONG_WITHOUT_SPACES, LEGEND_LAYOUT_TABLE)
104
- );
90
+ export const Default = () => getStoryOptions(10, SERIES_NAME_SHORT);
91
+
92
+ export const DefaultWithLongSeriesNames = () => getStoryOptions(10, SERIES_NAME_LONG);
93
+
94
+ export const DefaultWithLongSeriesNamesAndNoSpaces = () =>
95
+ getStoryOptions(10, SERIES_NAME_LONG_WITHOUT_SPACES);
96
+
97
+ export const WithTabularLayout = () => getStoryOptions(10, SERIES_NAME_SHORT, LEGEND_LAYOUT_TABLE);
98
+ export const WithTabularLayoutAndLongSeriesNames = () =>
99
+ getStoryOptions(10, SERIES_NAME_LONG, LEGEND_LAYOUT_TABLE);
100
+
101
+ export const WithTabularLayoutAndLongSeriesNamesWithNoSpaces = () =>
102
+ getStoryOptions(10, SERIES_NAME_LONG_WITHOUT_SPACES, LEGEND_LAYOUT_TABLE);
103
+
104
+ export default {
105
+ title: 'charts/chart-legend',
106
+ component: GlChartLegend,
107
+ parameters: {
108
+ controls: { disable: true },
109
+ knobs: { disable: true },
110
+ },
111
+ };
@@ -39,6 +39,9 @@ export default {
39
39
  required: false,
40
40
  default: () => ({}),
41
41
  },
42
+ /**
43
+ * Text for data average (overridden by prop if needed for internationalization)
44
+ */
42
45
  averageText: {
43
46
  type: String,
44
47
  required: false,
@@ -54,11 +57,17 @@ export default {
54
57
  required: false,
55
58
  default: LEGEND_MIN_TEXT,
56
59
  },
60
+ /**
61
+ * Text for max amount (overridden by prop if needed for internationalization)
62
+ */
57
63
  maxText: {
58
64
  type: String,
59
65
  required: false,
60
66
  default: LEGEND_MAX_TEXT,
61
67
  },
68
+ /**
69
+ * Sets the display layout
70
+ */
62
71
  layout: {
63
72
  type: String,
64
73
  required: false,
@@ -1,9 +1,5 @@
1
- # Safe Html
2
-
3
1
  A Vue Directive to sanitize HTML to avoid any XSS vulnerabilities.
4
2
 
5
- <!-- STORY -->
6
-
7
3
  ## Usage
8
4
 
9
5
  This directive can be used to sanitize HTML code which may contain user input, to prevent cross-site
@@ -1,50 +1,59 @@
1
- import { withKnobs, text } from '@storybook/addon-knobs';
2
1
  import { sanitize } from 'dompurify';
3
- import { escape } from 'lodash';
4
- import { documentedStoriesOf } from '../../../documentation/documented_stories';
5
- import { GlSafeHtmlDirective } from '../../index';
2
+ import { GlSafeHtmlDirective as GlSafeHtml } from '../../index';
6
3
  import readme from './safe_html.md';
7
4
 
8
- documentedStoriesOf('directives/safe-html-directive', readme)
9
- .addDecorator(withKnobs)
10
- .addParameters({ storyshots: false, knobs: { escapeHTML: false } })
11
- .add('default', () => ({
12
- directives: {
13
- 'gl-safe-html': GlSafeHtmlDirective,
14
- },
15
- props: {
16
- unsafeHTML: {
17
- type: String,
18
- default: text('Unsafe HTML', '<a href="javascript:alert(document.domain)">Click me</a>'),
19
- },
5
+ const generateProps = ({
6
+ unsafeHTML = '<a href="javascript:alert(document.domain)">Click me</a>',
7
+ } = {}) => ({
8
+ unsafeHTML,
9
+ });
10
+
11
+ export const Default = (_args, { argTypes }) => ({
12
+ directives: {
13
+ GlSafeHtml,
14
+ },
15
+ props: Object.keys(argTypes),
16
+ computed: {
17
+ sanitizedHtml() {
18
+ return sanitize(this.unsafeHTML);
20
19
  },
21
- computed: {
22
- sanitizedHtml() {
23
- return sanitize(this.unsafeHTML);
20
+ },
21
+ template: `
22
+ <table class="gl-table">
23
+ <thead>
24
+ <tr>
25
+ <th>Directive</th>
26
+ <th>Output</th>
27
+ <th>Rendered</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td><strong>v-html</strong></td>
33
+ <td><code>{{ unsafeHTML }}</code></td>
34
+ <td>N/A for security reasons</td>
35
+ </tr>
36
+ <tr>
37
+ <td><strong>v-safe-html</strong></td>
38
+ <td><code>{{ sanitizedHtml }}</code></td>
39
+ <td v-gl-safe-html="unsafeHTML"></td>
40
+ </tr>
41
+ </tbody>
42
+ </table>
43
+ `,
44
+ });
45
+ Default.args = generateProps();
46
+
47
+ export default {
48
+ title: 'directives/safe-html-directive',
49
+ component: GlSafeHtml,
50
+ parameters: {
51
+ storyshots: { disable: true },
52
+ knobs: { disable: true },
53
+ docs: {
54
+ description: {
55
+ component: readme,
24
56
  },
25
57
  },
26
- escape,
27
- template: `
28
- <table class="gl-table">
29
- <thead>
30
- <tr>
31
- <th>Directive</th>
32
- <th>Output</th>
33
- <th>Rendered</th>
34
- </tr>
35
- </thead>
36
- <tbody>
37
- <tr>
38
- <td><strong>v-html</strong></td>
39
- <td><code v-html="$options.escape(unsafeHTML)"></code></td>
40
- <td>N/A for security reasons</td>
41
- </tr>
42
- <tr>
43
- <td><strong>v-safe-html</strong></td>
44
- <td><code v-html="$options.escape(sanitizedHtml)"></code></td>
45
- <td v-gl-safe-html="unsafeHTML"></td>
46
- </tr>
47
- </tbody>
48
- </table>
49
- `,
50
- }));
58
+ },
59
+ };
@@ -3,5 +3,4 @@ import description from './safe_link.md';
3
3
  export default {
4
4
  followsDesignSystem: false,
5
5
  description,
6
- examples: false,
7
6
  };
@@ -1,9 +1,5 @@
1
- # Safe Link Directive
2
-
3
1
  A Vue directive to make the hyperlinks secure by default.
4
2
 
5
- <!-- STORY -->
6
-
7
3
  ## Security measures
8
4
 
9
5
  ### rel