@citizenplane/pimp 8.16.1 → 8.17.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@citizenplane/pimp",
3
- "version": "8.16.1",
3
+ "version": "8.17.0",
4
4
  "scripts": {
5
5
  "dev": "storybook dev -p 8080",
6
6
  "build-storybook": "storybook build --output-dir ./docs",
@@ -1,5 +1,6 @@
1
1
  // CitizenPlane colors
2
2
  $astronaut: #3e3e5b;
3
+
3
4
  $gray-1: #8b8b9d;
4
5
  $gray-2: #b2b2bd;
5
6
  $gray-3: #c6c6ce;
@@ -7,15 +8,44 @@ $gray-4: #d8d8de;
7
8
  $gray-5: #ececef;
8
9
 
9
10
  $red: #eb0505;
10
- $orange: #ffa800;
11
+ $red-100: #ffe5e5;
12
+ $red-200: #ffb3b3;
13
+ $red-500: #fc5959;
14
+
15
+ $blue: #144dc2;
16
+ $blue-100: #e3f2ff;
17
+ $blue-200: #B3D4FF;
18
+ $blue-500: #144DC2;
19
+
20
+ $green: #00895c;
21
+ $green-100: #E6FFF4;
22
+ $green-200: #B8FFDF;
23
+ $green-500: #00895C;
24
+
11
25
  $yellow: #ffd00b;
26
+ $yellow-100: #FFF9E3;
27
+ $yellow-200: #FFEA82;
28
+ $yellow-500: #998700;
29
+
30
+ $orange: #ffa800;
31
+ $orange-100: #FFF4E3;
32
+ $orange-200: #FFE1B3;
33
+ $orange-500: #FFA800;
34
+
35
+ $purple: #5341f9;
36
+ $purple-100: #E5E3FF;
37
+ $purple-200: #C8C4FF;
38
+ $purple-500: #5341F9;
39
+
40
+ $pink: #ff7dc1;
41
+ $pink-100: #FFE6F2;
42
+ $pink-200: #FFCCE6;
43
+ $pink-500: #FF7DC1;
44
+
12
45
  $green-2: #00c582;
13
46
  $green-1: #00f8a4;
14
47
 
15
- $purple: #5341f9;
16
- $blue: #144dc2;
17
48
  $blue-1: #56c1fe;
18
- $pink: #ff7dc1;
19
49
 
20
50
  // Main colors
21
51
  $primary-color: $purple;
@@ -0,0 +1,145 @@
1
+ <template>
2
+ <div class="cpBadgeNew" :class="componentDynamicClasses">
3
+ <slot name="leading-icon">
4
+ <cp-icon v-if="leadingIcon" :type="leadingIcon" class="cpBadgeNew__icon" />
5
+ </slot>
6
+
7
+ <span class="cpBadgeNew__label">
8
+ <slot>{{ label }}</slot>
9
+ </span>
10
+
11
+ <slot v-if="!isClearable" name="trailing-icon">
12
+ <cp-icon v-if="trailingIcon" :type="trailingIcon" class="cpBadgeNew__icon" />
13
+ </slot>
14
+
15
+ <button v-if="isClearable" class="cpBadgeNew__clear" @click="onClear">
16
+ <cp-icon type="x" class="cpBadgeNew__icon" />
17
+ </button>
18
+ </div>
19
+ </template>
20
+
21
+ <script setup>
22
+ import { computed } from 'vue'
23
+
24
+ import { Colors } from '@/constants'
25
+
26
+ import { Sizes } from '@/utils/constants'
27
+
28
+ import { capitalizeFirstLetter } from '@/helpers'
29
+
30
+ const props = defineProps({
31
+ color: {
32
+ type: String,
33
+ default: Colors.GRAY,
34
+ validator: (value) => Object.values(Colors).includes(value),
35
+ },
36
+ size: {
37
+ type: String,
38
+ required: false,
39
+ default: Sizes.MD,
40
+ validator(value) {
41
+ return Object.values(Sizes).includes(value)
42
+ },
43
+ },
44
+ label: {
45
+ type: String,
46
+ default: '',
47
+ },
48
+ leadingIcon: {
49
+ type: String,
50
+ default: '',
51
+ },
52
+ trailingIcon: {
53
+ type: String,
54
+ default: '',
55
+ },
56
+ isStroked: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
60
+ isClearable: {
61
+ type: Boolean,
62
+ default: false,
63
+ },
64
+ })
65
+
66
+ const componentDynamicClasses = computed(() => {
67
+ return [
68
+ `cpBadgeNew--${props.size}`,
69
+ `cpBadgeNew--is${capitalizeFirstLetter(props.color)}`,
70
+ { 'cpBadgeNew--isStroked': props.isStroked },
71
+ { 'cpBadgeNew--isClearable': props.isClearable },
72
+ ]
73
+ })
74
+ </script>
75
+
76
+ <style lang="scss">
77
+ @mixin cp-badge-new-themed($className, $color, $bg-color, $outline-color) {
78
+ &--is#{$className} {
79
+ color: $color;
80
+ background-color: $bg-color;
81
+ outline-color: $outline-color;
82
+
83
+ .cpBadgeNew__clear:hover,
84
+ .cpBadgeNew__clear:focus-visible {
85
+ background-color: $color;
86
+ }
87
+ }
88
+ }
89
+
90
+ .cpBadgeNew {
91
+ display: inline-flex;
92
+ padding: sp.$space-sm sp.$space;
93
+ align-items: center;
94
+ border-radius: fn.px-to-rem(8);
95
+ background-color: colors.$neutral-dark-5;
96
+ font-size: fn.px-to-em(14);
97
+ color: colors.$neutral-dark;
98
+ gap: sp.$space-sm;
99
+
100
+ &--isStroked {
101
+ outline: 1px solid currentColor;
102
+ }
103
+
104
+ @include cp-badge-new-themed('Blue', colors.$blue, colors.$blue-100, colors.$blue-200);
105
+ @include cp-badge-new-themed('Gray', colors.$astronaut, colors.$gray-5, colors.$gray-4);
106
+ @include cp-badge-new-themed('Green', colors.$green, colors.$green-100, colors.$green-200);
107
+ @include cp-badge-new-themed('Orange', colors.$orange, colors.$orange-100, colors.$orange-200);
108
+ @include cp-badge-new-themed('Pink', colors.$pink, colors.$pink-100, colors.$pink-200);
109
+ @include cp-badge-new-themed('Purple', colors.$purple, colors.$purple-100, colors.$purple-200);
110
+ @include cp-badge-new-themed('Red', colors.$red, colors.$red-100, colors.$red-200);
111
+ @include cp-badge-new-themed('Yellow', colors.$yellow-500, colors.$yellow-100, colors.$yellow-200);
112
+
113
+ &--sm {
114
+ font-size: fn.px-to-em(12);
115
+
116
+ .cpBadgeNew__label {
117
+ line-height: fn.px-to-rem(16);
118
+ }
119
+ }
120
+
121
+ &__icon {
122
+ width: fn.px-to-rem(16);
123
+ height: fn.px-to-rem(16);
124
+ aspect-ratio: 1/1;
125
+ }
126
+
127
+ &__label {
128
+ line-height: fn.px-to-rem(20);
129
+ }
130
+
131
+ &__clear {
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ padding: sp.$space-xs;
136
+ border-radius: 50%;
137
+ color: inherit;
138
+
139
+ &:hover,
140
+ &:focus-visible {
141
+ color: colors.$neutral-light;
142
+ }
143
+ }
144
+ }
145
+ </style>
@@ -20,7 +20,7 @@ const props = defineProps({
20
20
  size: {
21
21
  type: String,
22
22
  required: false,
23
- default: 'md',
23
+ default: Sizes.MD,
24
24
  validator(value) {
25
25
  return Object.values(Sizes).includes(value)
26
26
  },
@@ -1,7 +1,10 @@
1
1
  export default {
2
2
  BLUE: 'blue',
3
- PURPLE: 'purple',
3
+ GRAY: 'gray',
4
4
  GREEN: 'green',
5
5
  ORANGE: 'orange',
6
+ PINK: 'pink',
7
+ PURPLE: 'purple',
6
8
  RED: 'red',
9
+ YELLOW: 'yellow',
7
10
  }
@@ -0,0 +1,148 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+
3
+ import CpBadgeNew from '@/components/atomic-elements/CpBadgeNew.vue'
4
+
5
+ const meta = {
6
+ title: 'CpBadgeNew',
7
+ component: CpBadgeNew,
8
+ argTypes: {
9
+ color: {
10
+ control: 'select',
11
+ options: ['gray', 'blue', 'green', 'red', 'orange', 'purple', 'pink', 'yellow'],
12
+ description: 'The color variant of the badge',
13
+ },
14
+ size: {
15
+ control: 'select',
16
+ options: ['sm', 'md'],
17
+ description: 'The size of the badge',
18
+ },
19
+ isStroked: {
20
+ control: 'boolean',
21
+ description: 'Whether the badge has a stroked border',
22
+ },
23
+ leadingIcon: {
24
+ control: 'select',
25
+ options: ['check', 'arrow-right', 'arrow-left', 'arrow-up', 'arrow-down'],
26
+ description: 'Type of leading icon (if any)',
27
+ },
28
+ trailingIcon: {
29
+ control: 'select',
30
+ options: ['check', 'arrow-right', 'arrow-left', 'arrow-up', 'arrow-down'],
31
+ description: 'Type of trailing icon (if any)',
32
+ },
33
+ label: {
34
+ control: 'text',
35
+ description: 'The label text',
36
+ },
37
+ },
38
+ } satisfies Meta<typeof CpBadgeNew>
39
+
40
+ export default meta
41
+
42
+ type Story = StoryObj<typeof meta>
43
+
44
+ export const Default: Story = {
45
+ args: {
46
+ color: 'gray',
47
+ size: 'md',
48
+ isStroked: false,
49
+ leadingIcon: '',
50
+ trailingIcon: '',
51
+ label: 'Badge',
52
+ },
53
+ render: (args) => ({
54
+ components: { CpBadgeNew },
55
+ setup() {
56
+ return { args }
57
+ },
58
+ template: '<CpBadgeNew v-bind="args" />',
59
+ }),
60
+ }
61
+
62
+ export const WithColors: Story = {
63
+ render: () => ({
64
+ components: { CpBadgeNew },
65
+ template: `
66
+ <div style="display: flex; gap: 8px; flex-wrap: wrap;">
67
+ <CpBadgeNew color="gray" label="Gray" />
68
+ <CpBadgeNew color="blue" label="Blue" />
69
+ <CpBadgeNew color="green" label="Green" />
70
+ <CpBadgeNew color="red" label="Red" />
71
+ <CpBadgeNew color="orange" label="Orange" />
72
+ <CpBadgeNew color="purple" label="Purple" />
73
+ <CpBadgeNew color="pink" label="Pink" />
74
+ <CpBadgeNew color="yellow" label="Yellow" />
75
+ </div>
76
+ `,
77
+ }),
78
+ }
79
+
80
+ export const WithSizes: Story = {
81
+ render: () => ({
82
+ components: { CpBadgeNew },
83
+ template: `
84
+ <div style="display: flex; gap: 8px; align-items: center;">
85
+ <CpBadgeNew size="sm" label="Small" />
86
+ <CpBadgeNew size="md" label="Medium" />
87
+ </div>
88
+ `,
89
+ }),
90
+ }
91
+
92
+ export const IsStroked: Story = {
93
+ render: () => ({
94
+ components: { CpBadgeNew },
95
+ template: `
96
+ <div style="display: flex; gap: 8px; flex-wrap: wrap;">
97
+ <CpBadgeNew color="blue" isStroked label="Stroked" />
98
+ <CpBadgeNew color="green" isStroked label="Stroked" />
99
+ <CpBadgeNew color="red" isStroked label="Stroked" />
100
+ </div>
101
+ `,
102
+ }),
103
+ }
104
+
105
+ export const WithIcons: Story = {
106
+ render: () => ({
107
+ components: { CpBadgeNew },
108
+ template: `
109
+ <div style="display: flex; gap: 8px; align-items: center;">
110
+ <CpBadgeNew color="blue" leading-icon="check" label="Leading Icon" />
111
+ <CpBadgeNew color="green" trailing-icon="arrow-right" label="Trailing Icon" />
112
+ <CpBadgeNew color="red" leading-icon="check" trailing-icon="arrow-right" label="Both Icons" />
113
+ </div>
114
+ `,
115
+ }),
116
+ }
117
+
118
+ export const IsClearable: Story = {
119
+ render: () => ({
120
+ components: { CpBadgeNew },
121
+ template: `
122
+ <div style="display: flex; gap: 8px; align-items: center;">
123
+ <CpBadgeNew color="blue" isClearable label="Clearable" />
124
+ <CpBadgeNew color="green" isClearable label="Clearable" />
125
+ <CpBadgeNew color="red" isClearable label="Clearable" />
126
+ </div>
127
+ `,
128
+ }),
129
+ }
130
+
131
+ export const WithSlot: Story = {
132
+ render: () => ({
133
+ components: { CpBadgeNew },
134
+ template: `
135
+ <CpBadgeNew color="purple">
136
+ <template #leading-icon>
137
+ <span style="font-size: 16px; margin-right: 4px;">🌟</span>
138
+ </template>
139
+ <div>
140
+ Custom div inside default slot
141
+ </div>
142
+ <template #trailing-icon>
143
+ <span style="font-size: 16px; margin-left: 4px;">🚀</span>
144
+ </template>
145
+ </CpBadgeNew>
146
+ `,
147
+ }),
148
+ }