@appscode/design-system 2.17.26-alpha → 2.17.26-alpha-1

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": "@appscode/design-system",
3
- "version": "2.17.26-alpha",
3
+ "version": "2.17.26-alpha-1",
4
4
  "description": "A design system for Appscode websites and dashboards made using Bulma",
5
5
  "main": "main.scss",
6
6
  "scripts": {
@@ -0,0 +1,140 @@
1
+ /* ========== Variables ========== */
2
+ $cool-gray: #eff1f1;
3
+ $secondary-light-gray: #f7f9fa;
4
+ $scroll-highlight: darken($cool-gray, 10%);
5
+
6
+ /* ========== Mixins ========== */
7
+ @mixin hide-scrollbars {
8
+ -ms-overflow-style: none; // IE 10+
9
+ scrollbar-width: none; // Firefox
10
+ &::-webkit-scrollbar {
11
+ display: none;
12
+ }
13
+ }
14
+
15
+ /* ========== Container ========== */
16
+ .picker-wrapper {
17
+ background: white;
18
+ box-shadow: 0 0.5vw 2vw -5px rgba(0, 0, 0, 0.2);
19
+ display: inline-flex;
20
+ flex-direction: column;
21
+ border-radius: 8px;
22
+ }
23
+
24
+ /* ========== Header ========== */
25
+ .duration-header {
26
+ background-color: $secondary-light-gray;
27
+ text-align: center;
28
+ height: 36px;
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+
33
+ h6 {
34
+ font-size: 13px;
35
+ margin: 0;
36
+ font-weight: 600;
37
+ }
38
+ }
39
+
40
+ /* ========== Title Labels ========== */
41
+ .d-title {
42
+ display: inline-grid;
43
+ grid-template-columns: repeat(3, fit-content(100px));
44
+ justify-content: end;
45
+ gap: 0.5em;
46
+ font-weight: bold;
47
+ font-size: 11px;
48
+ padding: 8px 1rem 0;
49
+
50
+ span {
51
+ width: 40px;
52
+ text-align: center;
53
+ margin-right: 1em;
54
+ }
55
+ }
56
+
57
+ /* ========== Picker Section ========== */
58
+ .picker {
59
+ position: relative;
60
+ display: inline-grid;
61
+ grid-template-columns: repeat(3, fit-content(80px));
62
+ justify-content: end;
63
+ padding: 0 1rem;
64
+ font-size: 13px;
65
+ font-weight: 500;
66
+ font-feature-settings: "tnum";
67
+
68
+ &::before,
69
+ &::after {
70
+ content: "";
71
+ position: absolute;
72
+ width: 100%;
73
+ pointer-events: none;
74
+ z-index: 1;
75
+ }
76
+
77
+ &::before {
78
+ top: 0;
79
+ height: 50%;
80
+ background: linear-gradient(white, rgba(255, 255, 255, 0));
81
+ }
82
+
83
+ &::after {
84
+ bottom: 0;
85
+ height: 50%;
86
+ background: linear-gradient(rgba(255, 255, 255, 0), white);
87
+ }
88
+
89
+ ul {
90
+ @include hide-scrollbars();
91
+ max-height: 190px;
92
+ overflow-y: scroll;
93
+ padding: 1.5em 0;
94
+ margin-right: 1em;
95
+ scroll-snap-type: y mandatory;
96
+ scroll-behavior: smooth;
97
+
98
+ li {
99
+ scroll-snap-align: center;
100
+ height: 2.35em;
101
+ width: 40px;
102
+ text-align: center;
103
+ user-select: none;
104
+ cursor: pointer;
105
+ line-height: 2.35em;
106
+ border-radius: 4px;
107
+
108
+ &:hover {
109
+ background: #f0f0f0;
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ /* ========== Highlight Window ========== */
116
+ .picker-window {
117
+ position: absolute;
118
+ top: 50%;
119
+ left: 0;
120
+ width: 100%;
121
+ height: 2.4em;
122
+ transform: translateY(-52%);
123
+ border-top: 1px solid $scroll-highlight;
124
+ border-bottom: 1px solid $scroll-highlight;
125
+ pointer-events: none;
126
+ z-index: 2;
127
+ }
128
+
129
+ /* ========== Footer Buttons ========== */
130
+ .duration-footer {
131
+ padding: 0 1rem 1rem;
132
+ display: flex;
133
+ justify-content: flex-end;
134
+ gap: 0.5rem;
135
+
136
+ .buttons {
137
+ display: flex;
138
+ gap: 0.5rem;
139
+ }
140
+ }
@@ -517,7 +517,8 @@
517
517
  padding: 0;
518
518
  }
519
519
 
520
- .ac-search:focus {
520
+ .ac-search:focus,
521
+ .ac-search:not(:placeholder-shown) {
521
522
  width: 200px !important;
522
523
  padding-right: 10px;
523
524
  }
@@ -1,6 +1,9 @@
1
1
  <script setup lang="ts">
2
- import { defineProps, type Component } from "vue";
2
+ import { defineProps, defineEmits, type Component, defineAsyncComponent } from "vue";
3
3
  import AcButton from "../../v3/button/Button.vue";
4
+ const Skeletons = defineAsyncComponent(() => import("../skeleton/Skeletons.vue"));
5
+ const Skeleton = defineAsyncComponent(() => import("../skeleton/Skeleton.vue"));
6
+
4
7
  interface UsageRow {
5
8
  icon?: Component;
6
9
  label: string;
@@ -14,20 +17,30 @@ withDefaults(
14
17
  title?: string;
15
18
  thead?: Header[];
16
19
  tbody?: UsageRow[];
20
+ isLoaderActive?: boolean;
17
21
  }>(),
18
22
  {
19
23
  title: "Total Usage Data",
20
24
  thead: () => [],
21
25
  tbody: () => [],
26
+ isLoaderActive: false,
22
27
  },
23
28
  );
29
+
30
+ const emit = defineEmits<{
31
+ "header-button-click": [index: number];
32
+ }>();
33
+
34
+ const handleHeaderButtonClick = (index: number) => {
35
+ emit("header-button-click", index);
36
+ };
24
37
  </script>
25
38
 
26
39
  <template>
27
40
  <h5 class="mb-8">{{ title }}</h5>
28
41
  <div class="usage-table-card">
29
42
  <div class="table-row thead">
30
- <div v-for="(header, index) in thead" :key="index" class="table-cell">
43
+ <div v-for="(header, index) in thead" :key="index" class="table-cell has-text-weight-normal">
31
44
  <template v-if="typeof header === 'string'">
32
45
  {{ header }}
33
46
  </template>
@@ -37,7 +50,7 @@ withDefaults(
37
50
  <ac-button
38
51
  modifier-classes="is-text has-text-primary p-0 height-auto"
39
52
  v-if="header.button"
40
- @click="$emit('total-click')"
53
+ @click="handleHeaderButtonClick(1)"
41
54
  >({{ header.text }})</ac-button
42
55
  >
43
56
  </div>
@@ -45,6 +58,15 @@ withDefaults(
45
58
  </div>
46
59
  </div>
47
60
 
61
+ <div v-if="tbody.length === 0 && !isLoaderActive" class="table-row">
62
+ <div class="table-cell" :style="{ gridColumn: `1 / -1`, textAlign: 'center' }">
63
+ <strong>
64
+ Resource Not Found
65
+ <i class="pl-5 fa fa-exclamation-circle" aria-hidden="true"></i>
66
+ </strong>
67
+ </div>
68
+ </div>
69
+
48
70
  <div v-for="(row, rowIndex) in tbody" :key="rowIndex" class="table-row">
49
71
  <div class="table-cell">
50
72
  <div class="is-flex gap-8">
@@ -54,8 +76,17 @@ withDefaults(
54
76
  <span>{{ row.label }}</span>
55
77
  </div>
56
78
  </div>
57
- <div v-for="(val, valIndex) in row.values" :key="valIndex" class="table-cell">
58
- {{ val }}
79
+ <div v-for="(val, valIndex) in row.values" :key="valIndex" class="table-cell has-text-weight-normal">
80
+ <div v-if="isLoaderActive">
81
+ <skeletons>
82
+ <template #default>
83
+ <Skeleton />
84
+ </template>
85
+ </skeletons>
86
+ </div>
87
+ <div v-else>
88
+ {{ val }}
89
+ </div>
59
90
  </div>
60
91
  </div>
61
92
  </div>
@@ -0,0 +1,162 @@
1
+ <script setup lang="ts">
2
+ import { defineProps, defineEmits, type Component, defineAsyncComponent, ref } from "vue";
3
+ import AcButton from "../../v3/button/Button.vue";
4
+ const Skeletons = defineAsyncComponent(() => import("../skeleton/Skeletons.vue"));
5
+ const Skeleton = defineAsyncComponent(() => import("../skeleton/Skeleton.vue"));
6
+ const LinkIcon = defineAsyncComponent(() => import("../icons/BillableInfo.vue"));
7
+ interface UsageRow {
8
+ icon?: Component;
9
+ label: string;
10
+ values: (string | number)[];
11
+ }
12
+
13
+ type Header = string | { label: string; button?: boolean; text?: string };
14
+
15
+ withDefaults(
16
+ defineProps<{
17
+ title?: string;
18
+ thead?: Header[];
19
+ tbody?: UsageRow[];
20
+ isLoaderActive?: boolean;
21
+ }>(),
22
+ {
23
+ title: "Total Usage Data",
24
+ thead: () => [],
25
+ tbody: () => [],
26
+ isLoaderActive: false,
27
+ },
28
+ );
29
+
30
+ const emit = defineEmits<{
31
+ "header-button-click": [index: number];
32
+ }>();
33
+
34
+ const handleHeaderButtonClick = (index: number) => {
35
+ emit("header-button-click", index);
36
+ };
37
+
38
+ const hoveredRow = ref<number | null>(null);
39
+ </script>
40
+
41
+ <template>
42
+ <div class="columns is-multiline">
43
+ <div class="column is-12">
44
+ <h5>{{ title }}</h5>
45
+ <div class="usage-table-card">
46
+ <div class="table-row thead">
47
+ <div class="table-cell has-text-weight-normal">{{ thead[0] }}</div>
48
+ <div class="table-cell has-text-weight-normal">{{ thead[1] }}</div>
49
+ <div
50
+ class="table-cell has-text-weight-normal has-background-white has-text-centered is-flex is-justify-content-center b-1 ml-40"
51
+ >
52
+ <span class="width-70 is-flex is-align-items-center is-justify-content-flex-end">{{ thead[2] }}</span>
53
+ <span class="b-r-1 mx-4"></span>
54
+ <span class="width-70 is-flex is-align-items-center">{{ thead[3] }}</span>
55
+ <span class="b-l-1 px-2 is-flex is-align-items-center is-clickable">
56
+ <ac-button @click="handleHeaderButtonClick(2)" modifier-classes="is-text has-text-primary p-0 height-16">
57
+ <LinkIcon />
58
+ </ac-button>
59
+ </span>
60
+ </div>
61
+ <div class="table-cell has-text-weight-normal is-flex is-justify-content-end gap-5">
62
+ <div>{{ thead[4] }}</div>
63
+ <div class="is-flex is-clickable">
64
+ <ac-button modifier-classes="is-text has-text-primary p-0 height-16" @click="handleHeaderButtonClick(1)">
65
+ <LinkIcon />
66
+ </ac-button>
67
+ </div>
68
+ </div>
69
+ </div>
70
+
71
+ <div v-for="(row, rowIndex) in tbody" :key="rowIndex" class="table-row">
72
+ <div class="table-cell">
73
+ <div class="is-flex gap-8">
74
+ <span class="icon" v-if="row.icon">
75
+ <component :is="row.icon" />
76
+ </span>
77
+ <span>{{ row.label }}</span>
78
+ </div>
79
+ </div>
80
+
81
+ <div class="table-cell has-text-weight-normal">
82
+ <div v-if="isLoaderActive">
83
+ <skeletons>
84
+ <template #default>
85
+ <Skeleton />
86
+ </template>
87
+ </skeletons>
88
+ </div>
89
+ <div v-else @mouseenter="hoveredRow = rowIndex" @mouseleave="hoveredRow = null">
90
+ <span>{{ row.values[0] }}</span>
91
+ </div>
92
+ </div>
93
+
94
+ <div
95
+ class="table-cell has-text-weight-normal has-background-white has-text-centered is-flex is-justify-content-center b-1 ml-40 relative-cell"
96
+ :class="{ 'highlighted-cell': hoveredRow === rowIndex }"
97
+ >
98
+ <div v-if="hoveredRow === rowIndex" class="tooltip">Sum = ({{ row.values[1] }} + {{ row.values[2] }})</div>
99
+
100
+ <span class="width-70 is-flex is-justify-content-flex-end">
101
+ <Skeleton v-if="isLoaderActive" />
102
+ <template v-else>{{ row.values[1] }}</template>
103
+ </span>
104
+ <span class="b-r-1 mx-4"></span>
105
+ <span class="width-70 is-flex">
106
+ <Skeleton v-if="isLoaderActive" />
107
+ <template v-else>{{ row.values[2] }}</template>
108
+ </span>
109
+ <span class="width-30"></span>
110
+ </div>
111
+ <div class="table-cell has-text-weight-normal">
112
+ <div v-if="isLoaderActive">
113
+ <skeletons>
114
+ <template #default>
115
+ <Skeleton />
116
+ </template>
117
+ </skeletons>
118
+ </div>
119
+ <div v-else>{{ row.values[3] }}</div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </template>
126
+
127
+ <style scoped>
128
+ .highlighted-cell {
129
+ border: 1px dashed #333 !important;
130
+ background-color: #f1f1f1 !important;
131
+ position: relative;
132
+ }
133
+
134
+ .relative-cell {
135
+ position: relative;
136
+ }
137
+
138
+ .tooltip {
139
+ position: absolute;
140
+ top: -26px;
141
+ left: 50%;
142
+ transform: translateX(-50%);
143
+ background: #333;
144
+ color: #fff;
145
+ padding: 4px 8px;
146
+ font-size: 12px;
147
+ border-radius: 4px;
148
+ white-space: nowrap;
149
+ z-index: 10;
150
+ }
151
+
152
+ .tooltip::after {
153
+ content: "";
154
+ position: absolute;
155
+ bottom: -4px;
156
+ left: 50%;
157
+ transform: translateX(-50%);
158
+ border-width: 5px;
159
+ border-style: solid;
160
+ border-color: #333 transparent transparent;
161
+ }
162
+ </style>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
3
+ <!-- Icon from Lucide by Lucide Contributors - https://github.com/lucide-icons/lucide/blob/main/LICENSE -->
4
+ <path
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-linecap="round"
8
+ stroke-linejoin="round"
9
+ stroke-width="2"
10
+ d="M15 3h6v6m-11 5L21 3m-3 10v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"
11
+ />
12
+ </svg>
13
+ </template>
@@ -131,7 +131,7 @@ const handleClick = (name: string) => {
131
131
  <navbar-item-content class="navbar-dropdown-wrapper" style="right: -30px">
132
132
  <ul class="ac-scrollbar p-0 app-drawer">
133
133
  <li v-for="app in filteredAppList" :key="app.url">
134
- <a :href="app.url" target="_blank" @click="handleClick(app.name)">
134
+ <a :href="app.url" @click="handleClick(app.name)">
135
135
  <article class="media">
136
136
  <figure class="media-left">
137
137
  <p class="image">