@appscode/design-system 2.4.4-alpha → 2.4.4

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/main.scss CHANGED
@@ -4,8 +4,8 @@
4
4
 
5
5
  // Third party CSS
6
6
  @import "../node_modules/bulma/bulma.sass";
7
- // @import "bulma-checkradio";
8
- // @import "bulma-switch";
7
+ @import "bulma-checkradio";
8
+ @import "bulma-switch";
9
9
  @import "bulma-tooltip";
10
10
  @import "font-awesome/css/font-awesome.min.css";
11
11
  @import "vue-multiselect/dist/vue-multiselect.css";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appscode/design-system",
3
- "version": "2.4.4-alpha",
3
+ "version": "2.4.4",
4
4
  "description": "A design system for Appscode websites and dashboards made using Bulma",
5
5
  "main": "main.scss",
6
6
  "scripts": {
@@ -1,47 +1,47 @@
1
- // .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label::before,
2
- // .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label:before,
3
- // .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label::after,
4
- // .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label:after {
5
- // background-color: $ac-primary !important;
6
- // }
7
-
8
- // .is-checkradio[type="checkbox"] + label::after,
9
- // .is-checkradio[type="checkbox"] + label:after {
10
- // border-color: $ac-primary;
11
- // }
12
-
13
- // .is-checkradio[type="checkbox"]:checked + label::before,
14
- // .is-checkradio[type="checkbox"]:checked + label:before {
15
- // border: 1px solid $ac-primary;
16
- // }
17
-
18
- // .is-checkradio.is-primary[type="radio"] + label::after,
19
- // .is-checkradio.is-primary[type="radio"] + label:after {
20
- // background: $ac-primary !important;
21
- // }
22
-
23
- // .is-checkradio.is-primary[type="checkbox"]:checked + label::before,
24
- // .is-checkradio.is-primary[type="checkbox"]:checked + label:before,
25
- // .is-checkradio.is-primary[type="radio"]:checked + label::before,
26
- // .is-checkradio.is-primary[type="radio"]:checked + label:before {
27
- // border-color: $ac-primary;
28
- // }
29
-
30
- // .is-checkradio[type="radio"].is-primary:checked + label::after,
31
- // .is-checkradio[type="radio"].is-primary:checked + label:after {
32
- // background-color: $ac-primary !important;
33
- // border-color: $ac-primary;
34
- // }
35
-
36
- // .switch[type="checkbox"].is-primary:checked + label::before,
37
- // .switch[type="checkbox"].is-primary:checked + label:before {
38
- // background-color: $ac-primary;
39
- // }
40
-
41
- // .is-checkradio[type="radio"] + label::after,
42
- // .is-checkradio[type="radio"] + label:after {
43
- // background-color: $ac-primary;
44
- // }
1
+ .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label::before,
2
+ .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label:before,
3
+ .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label::after,
4
+ .is-checkradio.is-primary[type="checkbox"].is-primary:checked.has-background-color + label:after {
5
+ background-color: $ac-primary !important;
6
+ }
7
+
8
+ .is-checkradio[type="checkbox"] + label::after,
9
+ .is-checkradio[type="checkbox"] + label:after {
10
+ border-color: $ac-primary;
11
+ }
12
+
13
+ .is-checkradio[type="checkbox"]:checked + label::before,
14
+ .is-checkradio[type="checkbox"]:checked + label:before {
15
+ border: 1px solid $ac-primary;
16
+ }
17
+
18
+ .is-checkradio.is-primary[type="radio"] + label::after,
19
+ .is-checkradio.is-primary[type="radio"] + label:after {
20
+ background: $ac-primary !important;
21
+ }
22
+
23
+ .is-checkradio.is-primary[type="checkbox"]:checked + label::before,
24
+ .is-checkradio.is-primary[type="checkbox"]:checked + label:before,
25
+ .is-checkradio.is-primary[type="radio"]:checked + label::before,
26
+ .is-checkradio.is-primary[type="radio"]:checked + label:before {
27
+ border-color: $ac-primary;
28
+ }
29
+
30
+ .is-checkradio[type="radio"].is-primary:checked + label::after,
31
+ .is-checkradio[type="radio"].is-primary:checked + label:after {
32
+ background-color: $ac-primary !important;
33
+ border-color: $ac-primary;
34
+ }
35
+
36
+ .switch[type="checkbox"].is-primary:checked + label::before,
37
+ .switch[type="checkbox"].is-primary:checked + label:before {
38
+ background-color: $ac-primary;
39
+ }
40
+
41
+ .is-checkradio[type="radio"] + label::after,
42
+ .is-checkradio[type="radio"] + label:after {
43
+ background-color: $ac-primary;
44
+ }
45
45
 
46
46
  // 2024 AppsCode Custom Checkbox, Radio, Switch style
47
47
  // checkbox
@@ -98,11 +98,6 @@
98
98
  transition: all 0.2s ease;
99
99
  }
100
100
  }
101
- &:hover {
102
- .checkmark {
103
- border: 1px solid $ac-primary;
104
- }
105
- }
106
101
  }
107
102
 
108
103
  // radio button
@@ -136,7 +131,6 @@
136
131
  border: 1px solid $color-border-dark;
137
132
  border-radius: 50%; // Full circle
138
133
  background: #fff;
139
- transition: 0.2s ease-in-out;
140
134
  }
141
135
 
142
136
  // Inner dot for selected radio button
@@ -162,16 +156,6 @@
162
156
  opacity: 1;
163
157
  transform: scale(1);
164
158
  }
165
- [type="radio"]:checked + label::before {
166
- border: 1px solid $ac-primary;
167
- }
168
- &:hover {
169
- [type="radio"] + label {
170
- &::before {
171
- border: 1px solid $ac-primary;
172
- }
173
- }
174
- }
175
159
  }
176
160
 
177
161
  .ac-switch {
@@ -224,7 +208,7 @@
224
208
  }
225
209
 
226
210
  input:checked + .slider {
227
- background-color: $ac-primary;
211
+ background-color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-light));
228
212
  }
229
213
 
230
214
  input:checked + .slider:before {
@@ -232,7 +216,7 @@
232
216
  }
233
217
 
234
218
  input:focus-visible + .slider {
235
- box-shadow: 0 0 3px $ac-primary;
219
+ box-shadow: 0 0 3px hsl(var(--primary-hue), var(--primary-saturation), var(--primary-light));
236
220
  }
237
221
  }
238
222
  }
@@ -2,11 +2,43 @@
2
2
  position: relative;
3
3
  z-index: 9;
4
4
 
5
+ &.is-disabled {
6
+ pointer-events: none;
7
+ }
8
+
5
9
  input[type="text"] {
6
10
  padding-right: 32px;
7
11
  }
8
12
 
13
+ .custom-select-placeholder {
14
+ border: 1px solid $color-border-dark;
15
+ padding: 8px 15px;
16
+ border-radius: 4px;
17
+ line-height: 1;
18
+ // cursor: pointer;
19
+ display: flex;
20
+ align-items: center;
21
+ height: 36px;
22
+ span {
23
+ line-height: 1.2;
24
+ }
25
+
26
+ &:hover {
27
+ border: 1px solid $ac-primary;
28
+ }
29
+ }
30
+
9
31
  &.is-extra-small {
32
+ height: 32px;
33
+
34
+ .custom-select-placeholder {
35
+ height: 32px;
36
+ }
37
+
38
+ .ac-field {
39
+ top: 5px;
40
+ }
41
+
10
42
  .buttons {
11
43
  .button {
12
44
  height: 28px;
@@ -34,6 +66,7 @@
34
66
  right: 2px;
35
67
  top: 2px;
36
68
  margin: 0;
69
+ z-index: 9;
37
70
 
38
71
  .button {
39
72
  margin: 0 !important;
@@ -54,7 +87,7 @@
54
87
  width: 100%;
55
88
  max-height: 500px;
56
89
  overflow-y: auto;
57
- transition: 0.3s ease-in-out;
90
+ // transition: 0.2s ease-in-out;
58
91
  opacity: 0;
59
92
  visibility: hidden;
60
93
 
@@ -75,7 +108,7 @@
75
108
  li {
76
109
  display: flex;
77
110
 
78
- &:hover:not(.is-active) {
111
+ &:hover:not(.is-active, .is-disabled) {
79
112
  background-color: $primary-light-gray;
80
113
  color: $color-heading;
81
114
 
@@ -103,7 +136,7 @@
103
136
  cursor: pointer;
104
137
  }
105
138
 
106
- &:hover:not(.group li, .is-active) {
139
+ &:hover:not(.group li, .is-active, .is-disabled) {
107
140
  background-color: $primary-light-gray;
108
141
  color: $color-heading;
109
142
 
@@ -129,6 +162,9 @@
129
162
  &.is-disabled {
130
163
  opacity: 0.6;
131
164
  cursor: not-allowed;
165
+ label {
166
+ cursor: not-allowed;
167
+ }
132
168
  }
133
169
  }
134
170
  }
@@ -284,7 +284,7 @@
284
284
  color: $color-heading;
285
285
  position: absolute;
286
286
  z-index: 2;
287
- transition: 0.3s ease-in-out;
287
+ transition: 0.1s ease-in-out;
288
288
 
289
289
  .is-required {
290
290
  color: $danger;
@@ -19,14 +19,18 @@ const model = defineModel({ type: Array });
19
19
  </script>
20
20
 
21
21
  <template>
22
- <div v-for="option in options" :key="name + option.label" class="mb-8">
23
- <label class="ac-checkbox" :for="name + option.label">
24
- <input :class="modifierClasses" :id="name + option.label" :value="option.value" type="checkbox" v-model="model" />
25
- <span class="checkmark"></span>
26
- <span>{{ option.label }}</span>
27
- </label>
22
+ <div v-for="option in options" :key="name + option.label" class="field">
23
+ <input
24
+ class="is-checkradio has-background-color"
25
+ :class="modifierClasses"
26
+ :id="name + option.label"
27
+ :value="option.value"
28
+ type="checkbox"
29
+ v-model="model"
30
+ />
31
+ <label :for="name + option.label">{{ option.label }}</label>
28
32
  </div>
29
- <p v-show="errorMsg" class="is-danger mb-16">
33
+ <p v-show="errorMsg" class="is-danger">
30
34
  {{ errorMsg }}
31
35
  </p>
32
36
  </template>
@@ -18,9 +18,10 @@ const model = defineModel();
18
18
  </script>
19
19
 
20
20
  <template>
21
- <div class="ac-radio" v-for="option in options" :key="name + option.label">
21
+ <div v-for="option in options" :key="name + option.label" class="field">
22
22
  <input
23
23
  v-model="model"
24
+ class="is-checkradio"
24
25
  :class="modifierClasses"
25
26
  :id="name + option.label"
26
27
  type="radio"
@@ -33,7 +34,7 @@ const model = defineModel();
33
34
  <slot name="message" />
34
35
  </p>
35
36
  </div>
36
- <p v-show="errorMsg" class="is-danger mb-16">
37
+ <p v-show="errorMsg" class="is-danger">
37
38
  {{ errorMsg }}
38
39
  </p>
39
40
  </template>
@@ -27,7 +27,13 @@ const CloseIcon = defineAsyncComponent(() => import("../icons/CloseIcon.vue"));
27
27
  <div class="ac-single-input is-small is-selectbox" :class="[isOpen ? 'is-open' : '']" style="z-index: 2">
28
28
  <!-- add 'show-label' class for move top -->
29
29
  <label for="custom-select" class="ac-label show-label">Select Option</label>
30
- <input type="text" value="Select" />
30
+
31
+ <!-- <input type="text" value="Select" /> -->
32
+ <p class="custom-select-placeholder">
33
+ <span class="is-ellipsis-1">
34
+ Select Value Select ValueSelect ValueSelect ValueSelect ValueSelect ValueSelect Value
35
+ </span>
36
+ </p>
31
37
 
32
38
  <div v-if="multiselect" class="ac-field field is-grouped is-clipped">
33
39
  <div class="control">
@@ -18,21 +18,17 @@ const model = defineModel({ type: Boolean });
18
18
  </script>
19
19
 
20
20
  <template>
21
- <div class="ac-switch is-flex is-align-items-center gap-8">
21
+ <div class="field">
22
+ <input
23
+ v-model="model"
24
+ :id="name"
25
+ type="checkbox"
26
+ :name="name"
27
+ class="switch is-rounded is-primary"
28
+ :class="modifierClasses"
29
+ :data-testid="dataTestId"
30
+ />
22
31
  <label :for="name">{{ label }}</label>
23
- <label class="switch">
24
- <input
25
- v-model="model"
26
- :id="name"
27
- type="checkbox"
28
- :name="name"
29
- class="switch is-rounded is-primary"
30
- :class="modifierClasses"
31
- :data-testid="dataTestId"
32
- />
33
- <span class="slider round"></span>
34
- </label>
35
-
36
32
  <p v-show="errorMsg" class="is-danger">
37
33
  {{ errorMsg }}
38
34
  </p>
@@ -1,3 +1,9 @@
1
+ <script setup lang="ts">
2
+ withDefaults(defineProps<{ direction?: "up" | "down" }>(), {
3
+ direction: "up",
4
+ });
5
+ </script>
6
+
1
7
  <template>
2
8
  <svg
3
9
  xmlns="http://www.w3.org/2000/svg"
@@ -8,6 +14,7 @@
8
14
  stroke-width="1.5"
9
15
  stroke="currentColor"
10
16
  class="size-6"
17
+ :style="direction === 'up' ? 'transform: rotate(0deg)' : 'transform: rotate(-180deg)'"
11
18
  >
12
19
  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
13
20
  </svg>
@@ -1,3 +1,9 @@
1
+ <script setup lang="ts">
2
+ withDefaults(defineProps<{ direction?: "up" | "down" }>(), {
3
+ direction: "up",
4
+ });
5
+ </script>
6
+
1
7
  <template>
2
8
  <svg
3
9
  xmlns="http://www.w3.org/2000/svg"
@@ -8,6 +14,7 @@
8
14
  stroke-width="1.5"
9
15
  stroke="currentColor"
10
16
  class="size-6"
17
+ :style="direction === 'up' ? 'transform: rotate(0deg)' : 'transform: rotate(-180deg)'"
11
18
  >
12
19
  <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
13
20
  </svg>
@@ -0,0 +1,134 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineAsyncComponent, ref, watch } from "vue";
3
+ import { onClickOutside, useFocus } from "@vueuse/core";
4
+
5
+ import AcButton from "../button/Button.vue";
6
+ import AcButtons from "../button/Buttons.vue";
7
+
8
+ const ArrowDownIcon = defineAsyncComponent(() => import("../icons/ArrowDownIcon.vue"));
9
+ const RefreshIcon = defineAsyncComponent(() => import("../icons/RefreshIcon.vue"));
10
+ const CloseIcon = defineAsyncComponent(() => import("../icons/CloseIcon.vue"));
11
+
12
+ type Option = { text: string; value: string };
13
+ interface prop {
14
+ custom?: boolean;
15
+ options?: Array<Option>;
16
+ isLoading?: boolean;
17
+ optionType?: "simple" | "custom";
18
+ }
19
+
20
+ const props = withDefaults(defineProps<prop>(), {
21
+ custom: false,
22
+ options: () => [],
23
+ isLoading: false,
24
+ optionType: "simple",
25
+ });
26
+
27
+ defineEmits(["onRefreshClick"]);
28
+
29
+ const selectedValue = ref<Option>();
30
+ const labelHoisted = ref(false);
31
+ const searchText = ref("");
32
+ const isOpen = ref(false);
33
+
34
+ // handle outside box
35
+ const selectBox = ref(null);
36
+ onClickOutside(selectBox, () => (isOpen.value = false));
37
+
38
+ // handle input click
39
+ const searchInput = ref(null);
40
+ const { focused } = useFocus(searchInput, { initialValue: true });
41
+
42
+ // filter options based on search text
43
+ const filteredOptions = computed(() => {
44
+ if (searchText.value) {
45
+ return props.options.filter((op) => op.text.includes(searchText.value));
46
+ } else return props.options || [];
47
+ });
48
+
49
+ // handle selection
50
+ const onLabelClick = (op: Option) => {
51
+ selectedValue.value = op;
52
+ isOpen.value = false;
53
+ };
54
+
55
+ // handle label click
56
+ const selectClick = () => {
57
+ isOpen.value = true;
58
+ focused.value = true;
59
+ };
60
+
61
+ // handle clear btn
62
+ const handleClear = () => {
63
+ selectedValue.value = undefined;
64
+ searchText.value = "";
65
+ };
66
+
67
+ // handle depend on selected data
68
+ watch(selectedValue, (n) => {
69
+ if (n) labelHoisted.value = true;
70
+ else labelHoisted.value = false;
71
+ });
72
+
73
+ watch(isOpen, (n) => {
74
+ if (n) searchText.value = "";
75
+ else {
76
+ if (!selectedValue.value?.value) labelHoisted.value = false;
77
+ }
78
+ });
79
+ </script>
80
+
81
+ <template>
82
+ <div
83
+ ref="selectBox"
84
+ class="ac-single-input is-small is-selectbox"
85
+ :class="{ 'is-open': isOpen, 'is-disabled': isLoading }"
86
+ :style="[isOpen ? { 'z-index': 2 } : '']"
87
+ >
88
+ <label for="custom-select" class="ac-label" :class="{ 'show-label': labelHoisted || isOpen }" @click="selectClick">
89
+ Select Option
90
+ </label>
91
+
92
+ <input
93
+ v-if="isOpen"
94
+ v-model="searchText"
95
+ type="text"
96
+ ref="searchInput"
97
+ placeholder="Select One"
98
+ @click="selectClick"
99
+ />
100
+
101
+ <p v-else class="custom-select-placeholder" @click="selectClick">
102
+ <span class="is-ellipsis-1">{{ selectedValue?.text }}</span>
103
+ </p>
104
+
105
+ <ac-buttons>
106
+ <button class="button ac-button is-white" @click="handleClear">
107
+ <ArrowDownIcon />
108
+ </button>
109
+
110
+ <ac-button modifier-classes="is-white" @click="$emit('onRefreshClick')">
111
+ <RefreshIcon :class="{ 'is-spin': isLoading }" />
112
+ </ac-button>
113
+
114
+ <ac-button modifier-classes="is-white" @click="isOpen = !isOpen">
115
+ <CloseIcon :direction="isOpen ? 'down' : 'up'" />
116
+ </ac-button>
117
+ </ac-buttons>
118
+
119
+ <div v-if="optionType === 'custom'" class="custom-select options">
120
+ <slot />
121
+ </div>
122
+
123
+ <ul v-else class="options">
124
+ <template v-for="op in filteredOptions" :key="op.value">
125
+ <li @click="onLabelClick(op)" :class="{ 'is-active': selectedValue?.value === op.value }">
126
+ <label for="opt-one">{{ op.text }}</label>
127
+ </li>
128
+ </template>
129
+ <li v-if="filteredOptions.length <= 0" class="is-disabled">
130
+ <label>No element found. Consider changing the search text</label>
131
+ </li>
132
+ </ul>
133
+ </div>
134
+ </template>