@bethinkpl/design-system 26.10.2 → 26.11.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.
- package/.eslintrc.cjs +2 -3
- package/dist/design-system.umd.cjs +18 -18
- package/dist/design-system.umd.cjs.map +1 -1
- package/dist/lib/js/components/Avatar/Avatar.consts.d.ts +16 -1
- package/dist/lib/js/components/Avatar/Avatar.vue.d.ts +10 -21
- package/dist/lib/js/components/Badge/Badge.consts.d.ts +24 -0
- package/dist/lib/js/components/Badge/Badge.vue.d.ts +28 -0
- package/dist/lib/js/components/Badge/index.d.ts +4 -0
- package/dist/lib/js/components/BadgeScore/BadgeScore.vue.d.ts +2 -2
- package/dist/lib/js/components/Banner/Banner.vue.d.ts +7 -7
- package/dist/lib/js/components/Buttons/Button/Button.vue.d.ts +2 -2
- package/dist/lib/js/components/Buttons/IconButton/IconButton.vue.d.ts +4 -4
- package/dist/lib/js/components/Cards/CardExpandable/CardExpandable.vue.d.ts +1 -1
- package/dist/lib/js/components/Chip/Chip.vue.d.ts +5 -5
- package/dist/lib/js/components/DatePickers/DateBox/DateBox.vue.d.ts +1 -1
- package/dist/lib/js/components/DatePickers/DatePicker/DatePicker.vue.d.ts +4 -4
- package/dist/lib/js/components/DatePickers/DateRangePicker/DateRangePicker.vue.d.ts +1 -1
- package/dist/lib/js/components/Drawer/DrawerHeader/DrawerHeader.vue.d.ts +12 -12
- package/dist/lib/js/components/Drawer/DrawerListItem/DrawerListItem.vue.d.ts +1 -1
- package/dist/lib/js/components/Drawer/DrawerSection/DrawerSection.vue.d.ts +7 -7
- package/dist/lib/js/components/Drawer/DrawerTile/DrawerTile.vue.d.ts +1 -1
- package/dist/lib/js/components/Form/Checkbox/Checkbox.vue.d.ts +1 -1
- package/dist/lib/js/components/Form/RadioButton/RadioButton.vue.d.ts +1 -1
- package/dist/lib/js/components/Form/SelectionControl/SelectionControl.vue.d.ts +1 -1
- package/dist/lib/js/components/Headers/OverlayHeader/OverlayHeader.vue.d.ts +4 -4
- package/dist/lib/js/components/Headers/SectionHeader/SectionHeader.vue.d.ts +6 -6
- package/dist/lib/js/components/IconText/IconText.vue.d.ts +1 -1
- package/dist/lib/js/components/Icons/FeatureIcon/FeatureIcon.vue.d.ts +2 -2
- package/dist/lib/js/components/Icons/Icon/Icon.vue.d.ts +1 -1
- package/dist/lib/js/components/Modal/Modal.vue.d.ts +1 -1
- package/dist/lib/js/components/Modals/Modal/Modal.vue.d.ts +11 -11
- package/dist/lib/js/components/Modals/ModalDialog/ModalDialog.vue.d.ts +11 -11
- package/dist/lib/js/components/Outline/OutlineItem/OutlineItem.vue.d.ts +1 -1
- package/dist/lib/js/components/Pagination/Pagination.vue.d.ts +5 -5
- package/dist/lib/js/components/ProgressBar/ProgressBar.vue.d.ts +1 -1
- package/dist/lib/js/components/ProgressDonutChart/ProgressDonutChart.vue.d.ts +1 -1
- package/dist/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.vue.d.ts +6 -6
- package/dist/lib/js/components/RichList/RichListItem/RichListItem.vue.d.ts +4 -4
- package/dist/lib/js/components/SelectList/SelectListItem/SelectListItem.vue.d.ts +1 -1
- package/dist/lib/js/components/SelectList/SelectListItemTile/SelectListItemTile.vue.d.ts +1 -1
- package/dist/lib/js/components/SelectList/SelectListItemToggle/SelectListItemToggle.vue.d.ts +1 -1
- package/dist/lib/js/components/SelectionTile/SelectionTile.vue.d.ts +5 -5
- package/dist/lib/js/components/Statuses/AccessStatus/AccessStatus.vue.d.ts +1 -1
- package/dist/lib/js/components/Statuses/BlockadeStatus/BlockadeStatus.vue.d.ts +1 -1
- package/dist/lib/js/components/SurveyQuestions/SurveyQuestionOpenEnded/SurveyQuestionOpenEnded.vue.d.ts +7 -7
- package/dist/lib/js/components/SurveyQuestions/SurveyQuestionScale/SurveyQuestionScale.vue.d.ts +8 -8
- package/dist/lib/js/components/SurveyToggle/SurveyToggle.vue.d.ts +1 -1
- package/dist/lib/js/components/Switch/Switch.vue.d.ts +1 -1
- package/dist/lib/js/components/TabItem/TabItem.vue.d.ts +2 -2
- package/dist/lib/js/components/Tile/Tile.sb.shared.d.ts +9 -9
- package/dist/lib/js/components/Tile/Tile.vue.d.ts +1 -1
- package/dist/lib/js/components/Toast/Toast.vue.d.ts +4 -4
- package/dist/lib/js/components/Toggles/CounterToggle/CounterToggle.vue.d.ts +1 -1
- package/dist/lib/js/components/Toggles/ToggleButton/ToggleButton.vue.d.ts +1 -1
- package/dist/lib/js/index.d.ts +2 -0
- package/docs/assets/Avatar-BY2FHjur.js +1 -0
- package/docs/assets/Avatar.stories-CHgyprX4.js +37 -0
- package/docs/assets/Badge-DWUXekFu.js +1 -0
- package/docs/assets/Badge.stories-B90k4kes.js +21 -0
- package/docs/assets/{BasicRichListItem.stories-CJLLsCH2.js → BasicRichListItem.stories-Cq_2y-ip.js} +2 -2
- package/docs/assets/{Color-ERTF36HU-06Iq2w_Z.js → Color-ERTF36HU-gYu0mrgM.js} +1 -1
- package/docs/assets/{DateBox.stories-DL_j7ydW.js → DateBox.stories-2Z3tCp_1.js} +1 -1
- package/docs/assets/{DatePicker-CcKDLhxp.js → DatePicker-C2ooefT-.js} +1 -1
- package/docs/assets/{DatePicker.stories-CK6I-6c-.js → DatePicker.stories-CwMU6bVO.js} +1 -1
- package/docs/assets/{DateRangePicker-laHPjs-v.js → DateRangePicker-BbtTUk2P.js} +1 -1
- package/docs/assets/{DateRangePicker.stories-BtP6-oba.js → DateRangePicker.stories-DLDTFPz3.js} +1 -1
- package/docs/assets/{DocsRenderer-CFRXHY34-D86268a8.js → DocsRenderer-CFRXHY34-CCozPr0-.js} +5 -5
- package/docs/assets/{RichListItem.stories-xEDsV2D_.js → RichListItem.stories-Bjn9_BVO.js} +2 -2
- package/docs/assets/{SelectionTile-DSpUGzPs.js → SelectionTile-BKeLO5-6.js} +1 -1
- package/docs/assets/{SelectionTile.stories-WMHY5FHJ.js → SelectionTile.stories-BSF1jx58.js} +1 -1
- package/docs/assets/{iframe-DJBrrd4-.js → iframe-DM9VVuiu.js} +4 -3
- package/docs/assets/{index-C_7Ic1-A.js → index-BLJge5bw.js} +1 -1
- package/docs/assets/{index-nq_4YiNl.js → index-GQAS3BWp.js} +1 -1
- package/docs/assets/{preview-TdvdvCat.js → preview-Bx8DeNCo.js} +2 -2
- package/docs/assets/preview-IY5bCRtO.js +64 -0
- package/docs/iframe.html +1 -1
- package/docs/index.json +1 -1
- package/docs/project.json +1 -1
- package/lib/js/components/Avatar/Avatar.consts.ts +20 -1
- package/lib/js/components/Avatar/Avatar.spec.ts +83 -3
- package/lib/js/components/Avatar/Avatar.stories.ts +24 -4
- package/lib/js/components/Avatar/Avatar.vue +210 -46
- package/lib/js/components/Badge/Badge.consts.ts +29 -0
- package/lib/js/components/Badge/Badge.spec.ts +168 -0
- package/lib/js/components/Badge/Badge.stories.ts +99 -0
- package/lib/js/components/Badge/Badge.vue +297 -0
- package/lib/js/components/Badge/index.ts +4 -0
- package/lib/js/components/Chip/Chip.stories.ts +1 -1
- package/lib/js/index.ts +2 -0
- package/package.json +3 -2
- package/docs/assets/Avatar-OqeGv3bT.js +0 -1
- package/docs/assets/Avatar.stories-Ran7nhCi.js +0 -35
- package/docs/assets/preview-hR283N6x.js +0 -64
- /package/lib/{js/components/Chip → images}/logo-badge.svg +0 -0
|
@@ -19,6 +19,22 @@
|
|
|
19
19
|
<img v-if="!!avatarUrl" :src="avatarUrl" :alt="username" class="ds-avatar__image" />
|
|
20
20
|
<span v-else class="ds-avatar__initials">{{ initials }}</span>
|
|
21
21
|
</div>
|
|
22
|
+
<div v-if="activityStatus" class="ds-avatar__activityStatus">
|
|
23
|
+
<ds-badge
|
|
24
|
+
:color="activityStatusColor"
|
|
25
|
+
:elevation="BADGE_ELEVATIONS.X_SMALL"
|
|
26
|
+
:size="activityStatusSize"
|
|
27
|
+
/>
|
|
28
|
+
</div>
|
|
29
|
+
<div v-if="accessStatus" class="ds-avatar__accessStatus">
|
|
30
|
+
<ds-badge
|
|
31
|
+
:color="accessStatusColor"
|
|
32
|
+
:elevation="BADGE_ELEVATIONS.SMALL"
|
|
33
|
+
:icon="accessStatusIcon"
|
|
34
|
+
:size="accessStatusSize"
|
|
35
|
+
:image-url="accessStatusImage"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
22
38
|
</div>
|
|
23
39
|
</template>
|
|
24
40
|
|
|
@@ -31,6 +47,7 @@
|
|
|
31
47
|
$root: &;
|
|
32
48
|
|
|
33
49
|
display: flex;
|
|
50
|
+
position: relative;
|
|
34
51
|
|
|
35
52
|
&.-ds-xx-small {
|
|
36
53
|
height: 24px;
|
|
@@ -117,62 +134,209 @@
|
|
|
117
134
|
height: 100%;
|
|
118
135
|
width: 100%;
|
|
119
136
|
}
|
|
137
|
+
|
|
138
|
+
&__accessStatus {
|
|
139
|
+
@at-root {
|
|
140
|
+
.ds-avatar.-ds-xx-small & {
|
|
141
|
+
bottom: -2px;
|
|
142
|
+
right: -2px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ds-avatar.-ds-large & {
|
|
146
|
+
bottom: 1px;
|
|
147
|
+
right: 1px;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
bottom: 0;
|
|
152
|
+
display: flex;
|
|
153
|
+
position: absolute;
|
|
154
|
+
right: 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
&__activityStatus {
|
|
158
|
+
display: flex;
|
|
159
|
+
left: -4px;
|
|
160
|
+
position: absolute;
|
|
161
|
+
top: -4px;
|
|
162
|
+
|
|
163
|
+
.ds-avatar.-ds-xx-small &,
|
|
164
|
+
.ds-avatar.-ds-x-small &,
|
|
165
|
+
.ds-avatar.-ds-small & {
|
|
166
|
+
left: -3px;
|
|
167
|
+
top: -3px;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
120
170
|
}
|
|
121
171
|
</style>
|
|
122
172
|
|
|
123
173
|
<script setup lang="ts">
|
|
124
|
-
import {
|
|
174
|
+
import {
|
|
175
|
+
AVATAR_ACCESS_STATUSES,
|
|
176
|
+
AVATAR_ACTIVITY_STATUSES,
|
|
177
|
+
AVATAR_SIZES,
|
|
178
|
+
AvatarAccessStatus,
|
|
179
|
+
AvatarActivityStatus,
|
|
180
|
+
AvatarSize,
|
|
181
|
+
} from './Avatar.consts';
|
|
182
|
+
import DsBadge, { BADGE_ELEVATIONS, BADGE_SIZES, BADGE_COLORS } from '../Badge';
|
|
125
183
|
import { computed } from 'vue';
|
|
184
|
+
import { ICONS } from '../Icons/Icon';
|
|
185
|
+
|
|
186
|
+
const {
|
|
187
|
+
size = AVATAR_SIZES.X_SMALL,
|
|
188
|
+
username,
|
|
189
|
+
avatarUrl,
|
|
190
|
+
activityStatus,
|
|
191
|
+
accessStatus,
|
|
192
|
+
teamMemberImageUrl,
|
|
193
|
+
} = defineProps<{
|
|
194
|
+
username: string;
|
|
195
|
+
avatarUrl?: string;
|
|
196
|
+
size?: AvatarSize;
|
|
197
|
+
activityStatus?: AvatarActivityStatus;
|
|
198
|
+
accessStatus?: AvatarAccessStatus;
|
|
199
|
+
teamMemberImageUrl?: string;
|
|
200
|
+
}>();
|
|
201
|
+
|
|
202
|
+
const { initials, initialBackgroundColor } = useInitials();
|
|
203
|
+
const { accessStatusColor, accessStatusIcon, accessStatusSize, accessStatusImage } =
|
|
204
|
+
useAccessStatus();
|
|
205
|
+
const { activityStatusColor, activityStatusSize } = useActivityStatus();
|
|
206
|
+
function useInitials() {
|
|
207
|
+
const initialsBackgrounds = [
|
|
208
|
+
'#1abc9c',
|
|
209
|
+
'#2ecc71',
|
|
210
|
+
'#3498db',
|
|
211
|
+
'#9b59b6',
|
|
212
|
+
'#34495e',
|
|
213
|
+
'#16a085',
|
|
214
|
+
'#27ae60',
|
|
215
|
+
'#2980b9',
|
|
216
|
+
'#8e44ad',
|
|
217
|
+
'#2c3e50',
|
|
218
|
+
'#f1c40f',
|
|
219
|
+
'#e67e22',
|
|
220
|
+
'#e74c3c',
|
|
221
|
+
'#f39c12',
|
|
222
|
+
'#d35400',
|
|
223
|
+
'#c0392b',
|
|
224
|
+
];
|
|
126
225
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
avatarUrl: undefined,
|
|
136
|
-
},
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
const initialsBackgrounds = [
|
|
140
|
-
'#1abc9c',
|
|
141
|
-
'#2ecc71',
|
|
142
|
-
'#3498db',
|
|
143
|
-
'#9b59b6',
|
|
144
|
-
'#34495e',
|
|
145
|
-
'#16a085',
|
|
146
|
-
'#27ae60',
|
|
147
|
-
'#2980b9',
|
|
148
|
-
'#8e44ad',
|
|
149
|
-
'#2c3e50',
|
|
150
|
-
'#f1c40f',
|
|
151
|
-
'#e67e22',
|
|
152
|
-
'#e74c3c',
|
|
153
|
-
'#f39c12',
|
|
154
|
-
'#d35400',
|
|
155
|
-
'#c0392b',
|
|
156
|
-
];
|
|
157
|
-
|
|
158
|
-
function getInitials(username: string) {
|
|
159
|
-
const [first, second] = username.split(/\s+/);
|
|
160
|
-
|
|
161
|
-
if (first && second) {
|
|
162
|
-
return `${first[0]}${second[0]}`.toUpperCase();
|
|
226
|
+
function getInitials(username: string) {
|
|
227
|
+
const [first, second] = username.split(/\s+/);
|
|
228
|
+
|
|
229
|
+
if (first && second) {
|
|
230
|
+
return `${first[0]}${second[0]}`.toUpperCase();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return first.substring(0, 2).toUpperCase();
|
|
163
234
|
}
|
|
164
235
|
|
|
165
|
-
|
|
236
|
+
const initialBackgroundColor = computed(() => {
|
|
237
|
+
if (avatarUrl) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const colorIndex = (username.charCodeAt(0) - 65) % 16;
|
|
242
|
+
|
|
243
|
+
return initialsBackgrounds[colorIndex];
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const initials = computed(() => getInitials(username));
|
|
247
|
+
|
|
248
|
+
return { initials, initialBackgroundColor };
|
|
166
249
|
}
|
|
167
250
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
251
|
+
function useAccessStatus() {
|
|
252
|
+
const accessStatusColor = computed(() => {
|
|
253
|
+
switch (accessStatus) {
|
|
254
|
+
case AVATAR_ACCESS_STATUSES.ACTIVE:
|
|
255
|
+
return BADGE_COLORS.SUCCESS;
|
|
256
|
+
case AVATAR_ACCESS_STATUSES.INACTIVE:
|
|
257
|
+
case AVATAR_ACCESS_STATUSES.AWAITING:
|
|
258
|
+
return BADGE_COLORS.NEUTRAL;
|
|
259
|
+
case AVATAR_ACCESS_STATUSES.BLOCKED:
|
|
260
|
+
return BADGE_COLORS.DANGER;
|
|
261
|
+
default:
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
172
265
|
|
|
173
|
-
const
|
|
266
|
+
const accessStatusIcon = computed(() => {
|
|
267
|
+
switch (accessStatus) {
|
|
268
|
+
case AVATAR_ACCESS_STATUSES.ACTIVE:
|
|
269
|
+
return ICONS.FA_UNLOCK_KEYHOLE;
|
|
270
|
+
case AVATAR_ACCESS_STATUSES.BLOCKED:
|
|
271
|
+
case AVATAR_ACCESS_STATUSES.INACTIVE:
|
|
272
|
+
return ICONS.FA_LOCK_KEYHOLE;
|
|
273
|
+
case AVATAR_ACCESS_STATUSES.AWAITING:
|
|
274
|
+
return ICONS.FA_HOURGLASS_START;
|
|
275
|
+
default:
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
});
|
|
174
279
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
280
|
+
const accessStatusSize = computed(() => {
|
|
281
|
+
// Casting to AvatarSize to work around an IDE issue (PhpStorm incorrectly flags some case branches as unreachable)
|
|
282
|
+
switch (size as AvatarSize) {
|
|
283
|
+
case AVATAR_SIZES.XX_SMALL:
|
|
284
|
+
return BADGE_SIZES.SMALL;
|
|
285
|
+
case AVATAR_SIZES.X_SMALL:
|
|
286
|
+
return BADGE_SIZES.SMALL;
|
|
287
|
+
case AVATAR_SIZES.SMALL:
|
|
288
|
+
return BADGE_SIZES.SMALL;
|
|
289
|
+
case AVATAR_SIZES.MEDIUM:
|
|
290
|
+
return BADGE_SIZES.MEDIUM;
|
|
291
|
+
case AVATAR_SIZES.LARGE:
|
|
292
|
+
return BADGE_SIZES.MEDIUM;
|
|
293
|
+
case AVATAR_SIZES.X_LARGE:
|
|
294
|
+
default:
|
|
295
|
+
return BADGE_SIZES.X_LARGE;
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const accessStatusImage = computed(() => {
|
|
300
|
+
if (accessStatus !== AVATAR_ACCESS_STATUSES.TEAM_MEMBER) {
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return teamMemberImageUrl;
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
return { accessStatusColor, accessStatusIcon, accessStatusSize, accessStatusImage };
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function useActivityStatus() {
|
|
311
|
+
const activityStatusColor = computed(() => {
|
|
312
|
+
switch (activityStatus) {
|
|
313
|
+
case AVATAR_ACTIVITY_STATUSES.ACTIVE:
|
|
314
|
+
return BADGE_COLORS.SUCCESS;
|
|
315
|
+
default:
|
|
316
|
+
case AVATAR_ACTIVITY_STATUSES.INACTIVE:
|
|
317
|
+
return BADGE_COLORS.NEUTRAL;
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const activityStatusSize = computed(() => {
|
|
322
|
+
// Casting to AvatarSize to work around an IDE issue (PhpStorm incorrectly flags some case branches as unreachable)
|
|
323
|
+
switch (size as AvatarSize) {
|
|
324
|
+
case AVATAR_SIZES.XX_SMALL:
|
|
325
|
+
return BADGE_SIZES.X_SMALL;
|
|
326
|
+
case AVATAR_SIZES.X_SMALL:
|
|
327
|
+
return BADGE_SIZES.SMALL;
|
|
328
|
+
case AVATAR_SIZES.SMALL:
|
|
329
|
+
return BADGE_SIZES.SMALL;
|
|
330
|
+
case AVATAR_SIZES.MEDIUM:
|
|
331
|
+
return BADGE_SIZES.MEDIUM;
|
|
332
|
+
case AVATAR_SIZES.LARGE:
|
|
333
|
+
return BADGE_SIZES.MEDIUM;
|
|
334
|
+
case AVATAR_SIZES.X_LARGE:
|
|
335
|
+
default:
|
|
336
|
+
return BADGE_SIZES.MEDIUM;
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
return { activityStatusColor, activityStatusSize };
|
|
341
|
+
}
|
|
178
342
|
</script>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Value } from '../../utils/type.utils';
|
|
2
|
+
|
|
3
|
+
export const BADGE_SIZES = {
|
|
4
|
+
X_SMALL: 'x-small',
|
|
5
|
+
SMALL: 'small',
|
|
6
|
+
MEDIUM: 'medium',
|
|
7
|
+
LARGE: 'large',
|
|
8
|
+
X_LARGE: 'x-large',
|
|
9
|
+
} as const;
|
|
10
|
+
|
|
11
|
+
export type BadgeSize = Value<typeof BADGE_SIZES>;
|
|
12
|
+
|
|
13
|
+
export const BADGE_COLORS = {
|
|
14
|
+
PRIMARY: 'primary',
|
|
15
|
+
SUCCESS: 'success',
|
|
16
|
+
DANGER: 'danger',
|
|
17
|
+
FAIL: 'fail',
|
|
18
|
+
NEUTRAL: 'neutral',
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
export type BadgeColor = Value<typeof BADGE_COLORS>;
|
|
22
|
+
|
|
23
|
+
export const BADGE_ELEVATIONS = {
|
|
24
|
+
NONE: 'none',
|
|
25
|
+
X_SMALL: 'x-small',
|
|
26
|
+
SMALL: 'small',
|
|
27
|
+
} as const;
|
|
28
|
+
|
|
29
|
+
export type BadgeElevation = Value<typeof BADGE_ELEVATIONS>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import Badge from './Badge.vue';
|
|
3
|
+
import { BADGE_COLORS, BADGE_ELEVATIONS, BADGE_SIZES } from './Badge.consts';
|
|
4
|
+
import { ICONS } from '../Icons/Icon';
|
|
5
|
+
|
|
6
|
+
describe('Badge', () => {
|
|
7
|
+
it('should render with label', () => {
|
|
8
|
+
const wrapper = mount(Badge, {
|
|
9
|
+
props: {
|
|
10
|
+
label: '1',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
expect(wrapper.find('.ds-badge__content').text()).toBe('1');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should render with icon', () => {
|
|
18
|
+
const wrapper = mount(Badge, {
|
|
19
|
+
props: {
|
|
20
|
+
icon: ICONS.FA_BELL,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect(wrapper.find('.ds-icon .fa-bell').exists()).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('does not render label if icon is present', () => {
|
|
28
|
+
const wrapper = mount(Badge, {
|
|
29
|
+
props: {
|
|
30
|
+
label: '1',
|
|
31
|
+
icon: ICONS.FA_BELL,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
expect(wrapper.find('.ds-badge__content').exists()).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should render image', () => {
|
|
39
|
+
const imageUrl = 'https://via.placeholder.com/150';
|
|
40
|
+
const wrapper = mount(Badge, {
|
|
41
|
+
props: {
|
|
42
|
+
imageUrl,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
expect(wrapper.find('.ds-badge__image').exists()).toBe(true);
|
|
47
|
+
expect(wrapper.find('.ds-badge__image').attributes('src')).toBe(imageUrl);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should not render icon if image is present', () => {
|
|
51
|
+
const wrapper = mount(Badge, {
|
|
52
|
+
props: {
|
|
53
|
+
icon: ICONS.FA_BELL,
|
|
54
|
+
imageUrl: 'https://via.placeholder.com/150',
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(wrapper.find('.ds-badge__image').exists()).toBe(true);
|
|
59
|
+
expect(wrapper.find('.ds-icon').exists()).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should not render label if image is present', () => {
|
|
63
|
+
const wrapper = mount(Badge, {
|
|
64
|
+
props: {
|
|
65
|
+
label: '1',
|
|
66
|
+
imageUrl: 'https://via.placeholder.com/150',
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(wrapper.find('.ds-badge__image').exists()).toBe(true);
|
|
71
|
+
expect(wrapper.find('.ds-badge__content').exists()).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it.each([
|
|
75
|
+
{
|
|
76
|
+
size: BADGE_SIZES.X_LARGE,
|
|
77
|
+
color: undefined,
|
|
78
|
+
expectedClassName: '-ds-x-large',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
size: BADGE_SIZES.LARGE,
|
|
82
|
+
color: undefined,
|
|
83
|
+
expectedClassName: '-ds-large',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
size: BADGE_SIZES.MEDIUM,
|
|
87
|
+
color: undefined,
|
|
88
|
+
expectedClassName: '-ds-medium',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
size: BADGE_SIZES.SMALL,
|
|
92
|
+
color: undefined,
|
|
93
|
+
expectedClassName: '-ds-small',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
size: BADGE_SIZES.X_SMALL,
|
|
97
|
+
color: undefined,
|
|
98
|
+
expectedClassName: '-ds-x-small',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
size: undefined,
|
|
102
|
+
color: BADGE_COLORS.PRIMARY,
|
|
103
|
+
expectedClassName: '-ds-color-primary',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
size: undefined,
|
|
107
|
+
color: BADGE_COLORS.SUCCESS,
|
|
108
|
+
expectedClassName: '-ds-color-success',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
size: undefined,
|
|
112
|
+
color: BADGE_COLORS.DANGER,
|
|
113
|
+
expectedClassName: '-ds-color-danger',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
size: undefined,
|
|
117
|
+
color: BADGE_COLORS.FAIL,
|
|
118
|
+
expectedClassName: '-ds-color-fail',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
size: undefined,
|
|
122
|
+
color: BADGE_COLORS.NEUTRAL,
|
|
123
|
+
expectedClassName: '-ds-color-neutral',
|
|
124
|
+
},
|
|
125
|
+
])(
|
|
126
|
+
'should have valid class names for size: $size, color: $color',
|
|
127
|
+
({ size, color, expectedClassName }) => {
|
|
128
|
+
const wrapper = mount(Badge, {
|
|
129
|
+
props: {
|
|
130
|
+
size,
|
|
131
|
+
color,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
expect(wrapper.find('.ds-badge').classes()).toContain(expectedClassName);
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
it('should have -ds-no-elevation class when elevation is none', () => {
|
|
140
|
+
const wrapper = mount(Badge, {
|
|
141
|
+
props: {
|
|
142
|
+
elevation: BADGE_ELEVATIONS.NONE,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(wrapper.find('.ds-badge__elevation').classes()).toContain('-ds-no-elevation');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should have -ds-elevation-s class when elevation is small', () => {
|
|
150
|
+
const wrapper = mount(Badge, {
|
|
151
|
+
props: {
|
|
152
|
+
elevation: BADGE_ELEVATIONS.SMALL,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
expect(wrapper.find('.ds-badge__elevation').classes()).toContain('-ds-elevation-s');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should not have elevation modifier class when elevation is x-small', () => {
|
|
160
|
+
const wrapper = mount(Badge, {
|
|
161
|
+
props: {
|
|
162
|
+
elevation: BADGE_ELEVATIONS.X_SMALL,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
expect(wrapper.find('.ds-badge__elevation').classes()).toEqual(['ds-badge__elevation']);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ComponentProps } from 'vue-component-type-helpers';
|
|
2
|
+
import { Meta, StoryObj } from '@storybook/vue3';
|
|
3
|
+
|
|
4
|
+
import Badge from './Badge.vue';
|
|
5
|
+
import { BADGE_COLORS, BADGE_ELEVATIONS, BADGE_SIZES } from './Badge.consts';
|
|
6
|
+
import { IconKey, ICONS } from '../Icons/Icon';
|
|
7
|
+
import DsBanner, { BANNER_COLORS } from '../Banner';
|
|
8
|
+
|
|
9
|
+
type BadgeProps = ComponentProps<typeof Badge>;
|
|
10
|
+
|
|
11
|
+
function wrapWithContainer(template: string): string {
|
|
12
|
+
// line-height: 0; is to remove extra space below the badge (as it's an inline element)
|
|
13
|
+
return `<div style="display: inline-flex; background: #ccc; padding: 16px; line-height: 0; margin-bottom: 16px;">${template}</div>
|
|
14
|
+
<ds-banner :color="BANNER_COLORS.WARNING" title="Taka kombinacja jest niezgodna z design systemem!" v-if="invalidUsage" />
|
|
15
|
+
`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const meta: Meta<typeof Badge> = {
|
|
19
|
+
title: 'Components/Badges/Badge',
|
|
20
|
+
component: Badge,
|
|
21
|
+
render: (args: BadgeProps) => ({
|
|
22
|
+
components: { Badge, DsBanner },
|
|
23
|
+
setup() {
|
|
24
|
+
return {
|
|
25
|
+
BANNER_COLORS,
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
computed: {
|
|
29
|
+
invalidUsage() {
|
|
30
|
+
const invalidSizeWithLabel =
|
|
31
|
+
(args.size === BADGE_SIZES.X_SMALL || args.size === BADGE_SIZES.SMALL) &&
|
|
32
|
+
args.label;
|
|
33
|
+
|
|
34
|
+
const invalidSizeWithIconOrImage =
|
|
35
|
+
args.size === BADGE_SIZES.X_SMALL && (args.icon || args.imageUrl);
|
|
36
|
+
|
|
37
|
+
return invalidSizeWithLabel || invalidSizeWithIconOrImage;
|
|
38
|
+
},
|
|
39
|
+
props() {
|
|
40
|
+
return {
|
|
41
|
+
...args,
|
|
42
|
+
icon: ICONS[args.icon as IconKey],
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
// line-height: 0; is to remove extra space below the badge (as it's an inline element)
|
|
47
|
+
template: wrapWithContainer('<Badge v-bind="props" />'),
|
|
48
|
+
}),
|
|
49
|
+
argTypes: {
|
|
50
|
+
color: {
|
|
51
|
+
control: 'select',
|
|
52
|
+
options: Object.values(BADGE_COLORS),
|
|
53
|
+
},
|
|
54
|
+
size: {
|
|
55
|
+
control: 'select',
|
|
56
|
+
options: Object.values(BADGE_SIZES),
|
|
57
|
+
},
|
|
58
|
+
icon: {
|
|
59
|
+
control: 'select',
|
|
60
|
+
options: [null, ...Object.keys(ICONS)],
|
|
61
|
+
},
|
|
62
|
+
elevation: {
|
|
63
|
+
control: 'select',
|
|
64
|
+
options: Object.values(BADGE_ELEVATIONS),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
export default meta;
|
|
69
|
+
|
|
70
|
+
type Story = StoryObj<typeof Badge>;
|
|
71
|
+
|
|
72
|
+
export const Interactive: Story = {
|
|
73
|
+
args: {
|
|
74
|
+
color: BADGE_COLORS.PRIMARY,
|
|
75
|
+
size: BADGE_SIZES.SMALL,
|
|
76
|
+
label: '',
|
|
77
|
+
icon: undefined,
|
|
78
|
+
imageUrl: '',
|
|
79
|
+
elevation: BADGE_ELEVATIONS.X_SMALL,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
Interactive.parameters = {
|
|
84
|
+
design: {
|
|
85
|
+
type: 'figma',
|
|
86
|
+
url: 'https://www.figma.com/design/izQdYyiBR1GQgFkaOIfIJI/LMS---DS-Components?node-id=12364-10601&m=dev',
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const InteractiveWithImage: Story = {
|
|
91
|
+
args: {
|
|
92
|
+
color: BADGE_COLORS.PRIMARY,
|
|
93
|
+
size: BADGE_SIZES.SMALL,
|
|
94
|
+
label: '',
|
|
95
|
+
icon: undefined,
|
|
96
|
+
imageUrl: 'https://lek.wiecejnizlek.pl/images/lek/logo-badge.svg',
|
|
97
|
+
elevation: BADGE_ELEVATIONS.X_SMALL,
|
|
98
|
+
},
|
|
99
|
+
};
|