@xen-orchestra/web-core 0.4.0 → 0.5.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 (124) hide show
  1. package/lib/assets/css/_colors.pcss +56 -24
  2. package/lib/assets/css/_context.pcss +9 -9
  3. package/lib/assets/css/base.pcss +6 -6
  4. package/lib/components/backup-item/VtsBackupItem.vue +47 -0
  5. package/lib/components/backup-state/{BackupState.vue → VtsBackupState.vue} +4 -4
  6. package/lib/components/{button/ButtonGroup.vue → button-group/VtsButtonGroup.vue} +7 -6
  7. package/lib/components/cell-object/{CellObject.vue → VtsCellObject.vue} +14 -14
  8. package/lib/components/cell-text/{CellText.vue → VtsCellText.vue} +11 -11
  9. package/lib/components/console/{RemoteConsole.vue → VtsRemoteConsole.vue} +12 -18
  10. package/lib/components/donut-chart-with-legend/{DonutChartWithLegend.vue → VtsDonutChartWithLegend.vue} +6 -6
  11. package/lib/components/dropdown/DropdownItem.vue +8 -14
  12. package/lib/components/dropdown/DropdownTitle.vue +3 -3
  13. package/lib/components/icon/VtsIcon.vue +38 -42
  14. package/lib/components/layout/{LayoutSidebar.vue → VtsLayoutSidebar.vue} +31 -30
  15. package/lib/components/legend-group/VtsLegendGroup.vue +44 -0
  16. package/lib/components/{legend/LegendList.vue → legend-list/VtsLegendList.vue} +2 -2
  17. package/lib/components/menu/MenuTrigger.vue +2 -2
  18. package/lib/components/stacked-bar-with-legend/{StackedBarWithLegend.vue → VtsStackedBarWithLegend.vue} +14 -14
  19. package/lib/components/state-hero/VtsComingSoonHero.vue +13 -0
  20. package/lib/components/state-hero/VtsLoadingHero.vue +15 -0
  21. package/lib/components/state-hero/VtsNoDataHero.vue +11 -0
  22. package/lib/components/state-hero/VtsObjectNotFoundHero.vue +13 -0
  23. package/lib/components/state-hero/{StateHero.vue → VtsStateHero.vue} +42 -35
  24. package/lib/components/tab/TabItem.vue +6 -6
  25. package/lib/components/table/ColumnTitle.vue +7 -7
  26. package/lib/components/table/{UiTable.vue → VtsTable.vue} +7 -3
  27. package/lib/components/task/{QuickTaskButton.vue → VtsQuickTaskButton.vue} +8 -7
  28. package/lib/components/task/{QuickTaskList.vue → VtsQuickTaskList.vue} +10 -11
  29. package/lib/components/task/{QuickTaskTabBar.vue → VtsQuickTaskTabBar.vue} +9 -13
  30. package/lib/components/{tooltip/TooltipList.vue → tooltip-list/VtsTooltipList.vue} +2 -3
  31. package/lib/components/tree/{TreeItem.vue → VtsTreeItem.vue} +3 -4
  32. package/lib/components/tree/VtsTreeItemError.vue +18 -0
  33. package/lib/components/tree/{TreeLine.vue → VtsTreeLine.vue} +9 -11
  34. package/lib/components/tree/{TreeList.vue → VtsTreeList.vue} +5 -2
  35. package/lib/components/tree/VtsTreeLoadingItem.vue +61 -0
  36. package/lib/components/ui/account-menu-button/UiAccountMenuButton.vue +64 -0
  37. package/lib/components/ui/actions-title/UiActionsTitle.vue +2 -2
  38. package/lib/components/ui/button/UiButton.vue +532 -0
  39. package/lib/components/ui/button-icon/UiButtonIcon.vue +248 -0
  40. package/lib/components/{UiCard.vue → ui/card/UiCard.vue} +8 -6
  41. package/lib/components/ui/card-numbers/UiCardNumbers.vue +103 -0
  42. package/lib/components/ui/card-subtitle/UiCardSubtitle.vue +24 -0
  43. package/lib/components/ui/card-title/UiCardTitle.vue +56 -0
  44. package/lib/components/ui/checkbox/UiCheckbox.vue +410 -0
  45. package/lib/components/ui/checkbox-group/UiCheckboxGroup.vue +57 -0
  46. package/lib/components/ui/chip/ChipIcon.vue +21 -0
  47. package/lib/components/ui/chip/ChipRemoveIcon.vue +13 -0
  48. package/lib/components/ui/chip/UiChip.vue +135 -0
  49. package/lib/components/{icon/ComplexIcon.vue → ui/complex-icon/UiComplexIcon.vue} +21 -27
  50. package/lib/components/ui/counter/UiCounter.vue +134 -0
  51. package/lib/components/{donut-chart/DonutChart.vue → ui/donut-chart/UiDonutChart.vue} +28 -30
  52. package/lib/components/{head-bar/HeadBar.vue → ui/head-bar/UiHeadBar.vue} +31 -31
  53. package/lib/components/{info/VtsInfo.vue → ui/info/UiInfo.vue} +13 -11
  54. package/lib/components/{input → ui/input}/UiInput.vue +9 -7
  55. package/lib/components/ui/input/UiTextarea.vue +120 -0
  56. package/lib/components/{input/VtsLabel.vue → ui/label/UiLabel.vue} +25 -25
  57. package/lib/components/ui/legend/UiLegend.vue +98 -0
  58. package/lib/components/{LegendTitle.vue → ui/legend-title/UiLegendTitle.vue} +4 -4
  59. package/lib/components/{UiSpinner.vue → ui/loader/UiLoader.vue} +3 -3
  60. package/lib/components/{icon/ObjectIcon.vue → ui/object-icon/UiObjectIcon.vue} +44 -36
  61. package/lib/components/ui/object-link/UiObjectLink.vue +83 -0
  62. package/lib/components/ui/panel/UiPanel.vue +57 -0
  63. package/lib/components/{query-search-bar/QuerySearchBar.vue → ui/query-search-bar/UiQuerySearchBar.vue} +16 -16
  64. package/lib/components/{task/QuickTaskItem.vue → ui/quick-task-item/UiQuickTaskItem.vue} +46 -34
  65. package/lib/components/{task/QuickTaskPanel.vue → ui/quick-task-panel/UiQuickTaskPanel.vue} +8 -7
  66. package/lib/components/ui/radio-button/UiRadioButton.vue +196 -0
  67. package/lib/components/ui/radio-button-group/UiRadioButtonGroup.vue +56 -0
  68. package/lib/components/{stacked-bar → ui/stacked-bar}/StackedBarSegment.vue +23 -26
  69. package/lib/components/{stacked-bar/StackedBar.vue → ui/stacked-bar/UiStackedBar.vue} +6 -6
  70. package/lib/components/ui/table-actions/UiTableActions.vue +46 -0
  71. package/lib/components/ui/tag/UiTag.vue +118 -0
  72. package/lib/components/ui/title/UiTitle.vue +2 -2
  73. package/lib/components/ui/toaster/UiToaster.vue +100 -0
  74. package/lib/components/ui/toggle/UiToggle.vue +117 -0
  75. package/lib/components/{tooltip/TooltipItem.vue → ui/tooltip/UiTooltip.vue} +15 -15
  76. package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +64 -0
  77. package/lib/components/{tree/TreeItemLabel.vue → ui/tree-item-label/UiTreeItemLabel.vue} +60 -59
  78. package/lib/components/ui/user-link/UiUserLink.vue +76 -0
  79. package/lib/components/ui/user-logo/UiUserLogo.vue +50 -0
  80. package/lib/composables/route-query.composable.md +136 -0
  81. package/lib/composables/table.composable.md +159 -0
  82. package/lib/composables/tree/define-tree.ts +1 -1
  83. package/lib/composables/tree/tree-node-base.ts +6 -6
  84. package/lib/composables/tree.composable.md +536 -0
  85. package/lib/layouts/CoreLayout.vue +8 -6
  86. package/lib/locales/de.json +2 -2
  87. package/lib/locales/en.json +6 -3
  88. package/lib/locales/fa.json +2 -2
  89. package/lib/locales/fr.json +6 -3
  90. package/lib/types/color.type.ts +0 -2
  91. package/lib/types/subscribable-store.type.ts +2 -2
  92. package/lib/utils/create-subscribable-store-context.util.ts +1 -1
  93. package/lib/utils/if-else.utils.md +23 -0
  94. package/lib/utils/if-else.utils.ts +2 -2
  95. package/lib/utils/to-variants.util.md +62 -0
  96. package/package.json +7 -7
  97. package/lib/components/CardNumbers.vue +0 -101
  98. package/lib/components/PowerStateIcon.vue +0 -46
  99. package/lib/components/UiTag.vue +0 -101
  100. package/lib/components/backup-item/BackupItem.vue +0 -40
  101. package/lib/components/button/ButtonIcon.vue +0 -220
  102. package/lib/components/button/UiButton.vue +0 -470
  103. package/lib/components/card/CardSubtitle.vue +0 -24
  104. package/lib/components/card/CardTitle.vue +0 -57
  105. package/lib/components/chip/ChipIcon.vue +0 -30
  106. package/lib/components/chip/ChipRemoveIcon.vue +0 -13
  107. package/lib/components/chip/UiChip.vue +0 -137
  108. package/lib/components/counter/VtsCounter.vue +0 -147
  109. package/lib/components/legend/LegendGroup.vue +0 -44
  110. package/lib/components/legend/LegendItem.vue +0 -86
  111. package/lib/components/object-link/ObjectLink.vue +0 -87
  112. package/lib/components/state-hero/ComingSoonHero.vue +0 -13
  113. package/lib/components/state-hero/LoadingHero.vue +0 -15
  114. package/lib/components/state-hero/NoDataHero.vue +0 -11
  115. package/lib/components/state-hero/ObjectNotFoundHero.vue +0 -13
  116. package/lib/components/tree/TreeItemError.vue +0 -13
  117. package/lib/components/tree/TreeLoadingItem.vue +0 -60
  118. package/lib/components/user/UserLink.vue +0 -72
  119. package/lib/components/user/UserLogo.vue +0 -57
  120. package/lib/types/backup.type.ts +0 -11
  121. package/lib/types/size.type.ts +0 -1
  122. package/lib/types/task.type.ts +0 -13
  123. /package/lib/components/backdrop/{Backdrop.vue → VtsBackdrop.vue} +0 -0
  124. /package/lib/components/divider/{Divider.vue → VtsDivider.vue} +0 -0
@@ -15,7 +15,7 @@ export type Subscribe<TDefer extends boolean = false> = (options?: {
15
15
 
16
16
  export type SubscribableStoreConfig<TContext> = {
17
17
  context: TContext
18
- onSubscribe: () => void
19
- onUnsubscribe: () => void
18
+ onSubscribe?: () => void
19
+ onUnsubscribe?: () => void
20
20
  isEnabled?: MaybeRefOrGetter<boolean>
21
21
  }
@@ -60,7 +60,7 @@ export function createSubscribableStoreContext<TContext>(
60
60
  }
61
61
 
62
62
  return {
63
- $context: config.context,
63
+ getContext: () => config.context,
64
64
  subscribe,
65
65
  }
66
66
  }
@@ -0,0 +1,23 @@
1
+ # `ifElse`
2
+
3
+ `ifElse` utility is a wrapper around `watch`.
4
+
5
+ It allows watching a `boolean` source and execute the first callback if the source is `true`, or the second one if the
6
+ source is `false`.
7
+
8
+ ```ts
9
+ ifElse(mySource, doSomething, doSomethingElse)
10
+ ifElse(mySource, doSomething, doSomethingElse, { immediate: true })
11
+ ```
12
+
13
+ ## Example
14
+
15
+ ```ts
16
+ const myValue = ref(5)
17
+
18
+ ifElse(
19
+ () => myValue.value > 10,
20
+ () => console.log('myValue is greater than 10'),
21
+ () => console.log('myValue is less than or equal to 10')
22
+ )
23
+ ```
@@ -6,8 +6,8 @@ export interface IfElseOptions extends Pick<WatchOptions, 'immediate'> {}
6
6
 
7
7
  export function ifElse(
8
8
  source: WatchSource<boolean>,
9
- onTrue: MaybeArray<VoidFunction>,
10
- onFalse: MaybeArray<VoidFunction>,
9
+ onTrue: MaybeArray<VoidFunction> | undefined,
10
+ onFalse: MaybeArray<VoidFunction> | undefined,
11
11
  options?: IfElseOptions
12
12
  ) {
13
13
  const onTrueFunctions = toArray(onTrue)
@@ -0,0 +1,62 @@
1
+ # toVariants utility
2
+
3
+ This utility is used to convert a set of props into a list of CSS variants classes.
4
+
5
+ - No class will be added for _falsy_ values
6
+ - `<key>` class will be added for `true` values
7
+ - `<key>--<value>` class will be added for other values
8
+
9
+ ## Basic usage
10
+
11
+ ```ts
12
+ const props = defineProps<{
13
+ label: string
14
+ color: 'blue' | 'red'
15
+ size: 'small' | 'large'
16
+ disabled?: boolean
17
+ }>()
18
+
19
+ const variants = computed(() =>
20
+ toVariants({
21
+ color: props.color,
22
+ size: props.size,
23
+ disabled: props.disabled,
24
+ })
25
+ )
26
+ ```
27
+
28
+ If `color` is `'blue'`, `size` is `'small'`, and `disabled` is `false`,
29
+ then `variants` will be `['color--blue', 'size--small']`.
30
+
31
+ ## Advanced usage
32
+
33
+ Variants don't have to be based on props, you can define them the way you want.
34
+
35
+ Thanks to the way Vue works, they can also be mixed with other classes.
36
+
37
+ ```ts
38
+ const props = defineProps<{
39
+ label: string
40
+ color: 'blue' | 'red'
41
+ size: 'small' | 'large'
42
+ }>()
43
+
44
+ const isDisabled = inject('isParentDisabled', ref(false))
45
+
46
+ const typoClasses = {
47
+ small: 'typo p3-regular',
48
+ large: 'typo p2-medium',
49
+ }
50
+
51
+ const classes = computed(() => [
52
+ typoClasses[props.size],
53
+ { disabled: isDisabled.value },
54
+ toVariants({
55
+ color: props.color,
56
+ size: props.size.slice(0, 1),
57
+ state: isDisabled.value ? 'off' : 'on',
58
+ }),
59
+ ])
60
+ ```
61
+
62
+ `classes` applied to the component will then look like `typo p3-regular disabled color-blue size-s state-off`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xen-orchestra/web-core",
3
3
  "type": "module",
4
- "version": "0.4.0",
4
+ "version": "0.5.0",
5
5
  "private": false,
6
6
  "exports": {
7
7
  "./*": {
@@ -23,19 +23,19 @@
23
23
  "placement.js": "^1.0.0-beta.5"
24
24
  },
25
25
  "peerDependencies": {
26
- "pinia": "^2.1.7",
27
- "vue": "~3.4.13",
26
+ "pinia": "^2.2.6",
27
+ "vue": "~3.5.12",
28
28
  "vue-i18n": "^9.9.0",
29
- "vue-router": "^4.4.0"
29
+ "vue-router": "^4.4.5"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/lodash-es": "^4.17.12",
33
33
  "@types/novnc__novnc": "^1.5.0",
34
34
  "@vue/tsconfig": "^0.5.1",
35
- "pinia": "^2.1.7",
36
- "vue": "~3.4.13",
35
+ "pinia": "^2.2.6",
36
+ "vue": "~3.5.12",
37
37
  "vue-i18n": "^9.9.0",
38
- "vue-router": "^4.4.0"
38
+ "vue-router": "^4.4.5"
39
39
  },
40
40
  "homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/web-core",
41
41
  "bugs": "https://github.com/vatesfr/xen-orchestra/issues",
@@ -1,101 +0,0 @@
1
- <!-- v1.0 -->
2
- <template>
3
- <div class="card-numbers" :class="size">
4
- <span class="label typo" :class="labelFontClass">{{ label }}</span>
5
- <div class="values" :class="size">
6
- <span v-if="percentValue" class="value typo c2-semi-bold">
7
- {{ percentValue }}
8
- </span>
9
-
10
- <div class="value typo" :class="valueFontClass">
11
- {{ value ?? '-' }}<span class="unit typo" :class="unitFontClass">{{ unit }}</span>
12
- </div>
13
- </div>
14
- </div>
15
- </template>
16
-
17
- <script setup lang="ts" generic="TSize extends 'small' | 'medium'">
18
- import { computed } from 'vue'
19
- import { useI18n } from 'vue-i18n'
20
-
21
- interface CardNumbersProps {
22
- label: string
23
- size: TSize
24
- value?: number
25
- unit?: string
26
- max?: TSize extends 'small' ? number : never
27
- }
28
-
29
- const props = defineProps<CardNumbersProps>()
30
-
31
- const { n } = useI18n()
32
-
33
- const labelFontClass = computed(() => (props.size === 'medium' ? 'c3-semi-bold' : 'c2-semi-bold'))
34
-
35
- const valueFontClass = computed(() => (props.size === 'medium' ? 'h3-semi-bold' : 'c2-semi-bold'))
36
-
37
- const unitFontClass = computed(() => (props.size === 'medium' ? 'p2-medium' : 'c2-semi-bold'))
38
-
39
- const percentValue = computed(() => {
40
- if (props.size !== 'small' || props.max === undefined || props.max === 0) {
41
- return undefined
42
- }
43
-
44
- if (props.value === undefined) {
45
- return n(0, 'percent').replace('0', '-')
46
- }
47
-
48
- return n(props.value / props.max, 'percent')
49
- })
50
- </script>
51
-
52
- <style lang="postcss" scoped>
53
- /* COLOR VARIANTS */
54
- .card-numbers {
55
- &.small {
56
- --label-color: var(--color-neutral-txt-primary);
57
- }
58
-
59
- &.medium {
60
- --label-color: var(--color-neutral-txt-secondary);
61
- }
62
- }
63
-
64
- /* IMPLEMENTATION */
65
- .card-numbers {
66
- display: flex;
67
- gap: 0.8rem;
68
- width: fit-content;
69
-
70
- &.medium {
71
- flex-direction: column;
72
- gap: 0.4rem;
73
- }
74
- }
75
-
76
- .label {
77
- color: var(--label-color);
78
- }
79
-
80
- .values {
81
- display: flex;
82
- flex-direction: column;
83
- gap: 0.8rem;
84
- align-items: flex-end;
85
-
86
- &.medium {
87
- align-items: flex-start;
88
- }
89
- }
90
-
91
- .value {
92
- color: var(--color-neutral-txt-primary);
93
- display: flex;
94
- gap: 0.2rem;
95
- align-items: center;
96
- }
97
-
98
- .unit {
99
- color: var(--color-neutral-txt-primary);
100
- }
101
- </style>
@@ -1,46 +0,0 @@
1
- <!-- v1.0 -->
2
- <template>
3
- <VtsIcon :class="className" accent="current" :icon class="power-state-icon" />
4
- </template>
5
-
6
- <script lang="ts" setup>
7
- import VtsIcon from '@core/components/icon/VtsIcon.vue'
8
- import type { POWER_STATE } from '@core/types/power-state.type'
9
- import { faMoon, faPause, faPlay, faStop } from '@fortawesome/free-solid-svg-icons'
10
- import { computed } from 'vue'
11
-
12
- const props = defineProps<{
13
- state: POWER_STATE
14
- }>()
15
-
16
- const icons = {
17
- running: faPlay,
18
- paused: faPause,
19
- suspended: faMoon,
20
- halted: faStop,
21
- }
22
-
23
- const icon = computed(() => icons[props.state])
24
-
25
- const className = computed(() => `state-${props.state}`)
26
- </script>
27
-
28
- <style lang="postcss" scoped>
29
- .power-state-icon {
30
- &.state-suspended {
31
- color: var(--color-normal-txt-item);
32
- }
33
-
34
- &.state-running {
35
- color: var(--color-success-item-base);
36
- }
37
-
38
- &.state-paused {
39
- color: var(--color-normal-item-active);
40
- }
41
-
42
- &.state-halted {
43
- color: var(--color-danger-item-base);
44
- }
45
- }
46
- </style>
@@ -1,101 +0,0 @@
1
- <!-- v1.2 -->
2
- <template>
3
- <span :class="[color, { light }]" class="ui-tag typo p3-regular">
4
- <slot name="icon">
5
- <VtsIcon :icon accent="current" fixed-width />
6
- </slot>
7
- <span class="text-ellipsis"><slot /></span>
8
- </span>
9
- </template>
10
-
11
- <script lang="ts" setup>
12
- import VtsIcon from '@core/components/icon/VtsIcon.vue'
13
- import type { TagColor } from '@core/types/color.type'
14
- import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
15
-
16
- defineProps<{
17
- color: TagColor
18
- light?: boolean
19
- icon?: IconDefinition
20
- }>()
21
- </script>
22
-
23
- <style lang="postcss" scoped>
24
- /* COLOR VARIANTS */
25
- .ui-tag {
26
- &.primary {
27
- --background-color: var(--color-normal-item-base);
28
- --color: var(--color-normal-txt-item);
29
-
30
- &.light {
31
- --background-color: var(--color-normal-background-selected);
32
- --color: var(--color-normal-txt-base);
33
- }
34
- }
35
-
36
- &.secondary {
37
- --background-color: var(--color-neutral-txt-primary);
38
- --color: var(--color-neutral-background-primary);
39
-
40
- &.light {
41
- --background-color: var(--color-neutral-background-secondary);
42
- --color: var(--color-neutral-txt-primary);
43
- }
44
- }
45
-
46
- &.success {
47
- --background-color: var(--color-success-item-base);
48
- --color: var(--color-success-txt-item);
49
-
50
- &.light {
51
- --background-color: var(--color-success-background-selected);
52
- --color: var(--color-success-txt-base);
53
- }
54
- }
55
-
56
- &.warning {
57
- --background-color: var(--color-warning-item-base);
58
- --color: var(--color-warning-txt-item);
59
-
60
- &.light {
61
- --background-color: var(--color-warning-background-selected);
62
- --color: var(--color-warning-txt-base);
63
- }
64
- }
65
-
66
- &.danger {
67
- --background-color: var(--color-danger-item-base);
68
- --color: var(--color-danger-txt-item);
69
-
70
- &.light {
71
- --background-color: var(--color-danger-background-selected);
72
- --color: var(--color-danger-txt-base);
73
- }
74
- }
75
-
76
- &.disabled {
77
- --background-color: var(--color-neutral-background-disabled);
78
- --color: var(--color-neutral-txt-secondary);
79
-
80
- &.light {
81
- --background-color: var(--color-neutral-background-secondary);
82
- --color: var(--color-neutral-txt-secondary);
83
- }
84
- }
85
- }
86
-
87
- /* IMPLEMENTATION */
88
- .ui-tag {
89
- display: flex;
90
- justify-content: center;
91
- align-items: center;
92
- gap: 0.8rem;
93
- white-space: nowrap;
94
- color: var(--color);
95
- background-color: var(--background-color);
96
- padding: 0.2rem 0.8rem;
97
- border-radius: 0.4rem;
98
- vertical-align: middle;
99
- min-width: 0;
100
- }
101
- </style>
@@ -1,40 +0,0 @@
1
- <!-- v1.0 -->
2
- <template>
3
- <div class="backup-item">
4
- <RouterLink v-if="backup.route !== undefined" :to="backup.route">
5
- {{ backup.label }}
6
- </RouterLink>
7
- <p v-else class="typo p3-medium">
8
- {{ backup.label }}
9
- </p>
10
- <div class="states">
11
- <BackupState v-for="(state, index) in backup.states" :key="index" :state />
12
- </div>
13
- </div>
14
- </template>
15
-
16
- <script lang="ts" setup>
17
- import BackupState from '@core/components/backup-state/BackupState.vue'
18
- import type { Backup } from '@core/types/backup.type'
19
-
20
- defineProps<{
21
- backup: Backup
22
- }>()
23
- </script>
24
-
25
- <style lang="postcss" scoped>
26
- .backup-item {
27
- padding: 0.8rem 0.4rem;
28
- border-top: 0.1rem solid var(--color-neutral-border);
29
- display: flex;
30
- align-items: center;
31
- gap: 0.2rem;
32
- }
33
-
34
- .states {
35
- margin-inline-start: auto;
36
- display: flex;
37
- align-items: center;
38
- gap: 0.2rem;
39
- }
40
- </style>
@@ -1,220 +0,0 @@
1
- <!-- v1.0 -->
2
- <template>
3
- <button :class="[color, size, { disabled, active }]" :disabled class="button-icon" type="button">
4
- <VtsIcon :icon accent="current" />
5
- <span v-if="dot" class="dot" />
6
- </button>
7
- </template>
8
-
9
- <script lang="ts" setup>
10
- import VtsIcon from '@core/components/icon/VtsIcon.vue'
11
- import type { Color } from '@core/types/color.type'
12
- import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
13
- import { computed } from 'vue'
14
-
15
- const props = withDefaults(
16
- defineProps<{
17
- icon: IconDefinition
18
- size?: 'small' | 'medium' | 'large'
19
- color?: Color
20
- disabled?: boolean
21
- active?: boolean
22
- dot?: boolean
23
- targetScale?: number | { x: number; y: number }
24
- }>(),
25
- { color: 'normal', size: 'medium', targetScale: 1 }
26
- )
27
-
28
- const cssTargetScale = computed(() => {
29
- if (typeof props.targetScale === 'number') {
30
- return `scale(${props.targetScale})`
31
- }
32
-
33
- return `scale(${props.targetScale.x}, ${props.targetScale.y})`
34
- })
35
- </script>
36
-
37
- <style lang="postcss" scoped>
38
- /* COLOR VARIANTS */
39
- .button-icon {
40
- &.normal {
41
- & {
42
- --color: var(--color-normal-txt-base);
43
- --background-color: transparent;
44
- --dot-color: var(--color-danger-txt-base);
45
- }
46
-
47
- &:is(.active, .selected) {
48
- --color: var(--color-normal-txt-base);
49
- --background-color: var(--color-normal-background-selected);
50
- }
51
-
52
- &:is(:hover, .hover, :focus-visible) {
53
- --color: var(--color-normal-txt-hover);
54
- --background-color: var(--color-normal-background-hover);
55
- }
56
-
57
- &:is(:active, .pressed) {
58
- --color: var(--color-normal-txt-active);
59
- --background-color: var(--color-normal-background-active);
60
- }
61
-
62
- &:is(:disabled, .disabled) {
63
- --color: var(--color-neutral-txt-secondary);
64
- --background-color: transparent;
65
- }
66
- }
67
-
68
- &.success {
69
- & {
70
- --color: var(--color-success-txt-base);
71
- --background-color: transparent;
72
- --dot-color: var(--color-danger-txt-base);
73
- }
74
-
75
- &:is(.active, .selected) {
76
- --color: var(--color-success-txt-base);
77
- --background-color: var(--color-success-background-selected);
78
- }
79
-
80
- &:is(:hover, .hover, :focus-visible) {
81
- --color: var(--color-success-txt-hover);
82
- --background-color: var(--color-success-background-hover);
83
- }
84
-
85
- &:is(:active, .pressed) {
86
- --color: var(--color-success-txt-active);
87
- --background-color: var(--color-success-background-active);
88
- }
89
-
90
- &:is(:disabled, .disabled) {
91
- --color: var(--color-neutral-txt-secondary);
92
- --background-color: transparent;
93
- }
94
- }
95
-
96
- &.warning {
97
- & {
98
- --color: var(--color-warning-txt-base);
99
- --background-color: transparent;
100
- --dot-color: var(--color-danger-txt-base);
101
- }
102
-
103
- &:is(.active, .selected) {
104
- --color: var(--color-warning-txt-base);
105
- --background-color: var(--color-warning-background-selected);
106
- }
107
-
108
- &:is(:hover, .hover, :focus-visible) {
109
- --color: var(--color-warning-txt-hover);
110
- --background-color: var(--color-warning-background-hover);
111
- }
112
-
113
- &:is(:active, .pressed) {
114
- --color: var(--color-warning-txt-active);
115
- --background-color: var(--color-warning-background-active);
116
- }
117
-
118
- &:is(:disabled, .disabled) {
119
- --color: var(--color-neutral-txt-secondary);
120
- --background-color: transparent;
121
- }
122
- }
123
-
124
- &:is(.danger, .error) {
125
- & {
126
- --color: var(--color-danger-txt-base);
127
- --background-color: transparent;
128
- --dot-color: var(--color-warning-txt-base);
129
- }
130
-
131
- &:is(.active, .selected) {
132
- --color: var(--color-danger-txt-base);
133
- --background-color: var(--color-danger-background-selected);
134
- }
135
-
136
- &:is(:hover, .hover, :focus-visible) {
137
- --color: var(--color-danger-txt-hover);
138
- --background-color: var(--color-danger-background-hover);
139
- }
140
-
141
- &:is(:active, .pressed) {
142
- --color: var(--color-danger-txt-active);
143
- --background-color: var(--color-danger-background-active);
144
- }
145
-
146
- &:is(:disabled, .disabled) {
147
- --color: var(--color-neutral-txt-secondary);
148
- --background-color: transparent;
149
- }
150
- }
151
- }
152
-
153
- /* SIZE VARIANTS */
154
- .button-icon {
155
- &.small {
156
- --size: 1.6rem;
157
- --font-size: 1.2rem;
158
- --dot-size: 0.4rem;
159
- --dot-offset: 0.2rem;
160
- }
161
-
162
- &.medium {
163
- --size: 2.4rem;
164
- --font-size: 1.6rem;
165
- --dot-size: 0.5rem;
166
- --dot-offset: 0.4rem;
167
- }
168
-
169
- &.large {
170
- --size: 4rem;
171
- --font-size: 2.4rem;
172
- --dot-size: 0.8rem;
173
- --dot-offset: 0.8rem;
174
- }
175
- }
176
-
177
- /* IMPLEMENTATION */
178
- .button-icon {
179
- display: inline-flex;
180
- justify-content: center;
181
- align-items: center;
182
- border: none;
183
- padding: 0;
184
- border-radius: 0.2rem;
185
- width: var(--size);
186
- height: var(--size);
187
- font-size: var(--font-size);
188
- color: var(--color);
189
- background-color: var(--background-color);
190
- position: relative;
191
- cursor: pointer;
192
- outline: none;
193
-
194
- &:is(:disabled, .disabled) {
195
- cursor: not-allowed;
196
- }
197
-
198
- .dot {
199
- position: absolute;
200
- display: block;
201
- width: var(--dot-size);
202
- height: var(--dot-size);
203
- border-radius: 50%;
204
- background-color: var(--dot-color);
205
- top: var(--dot-offset);
206
- right: var(--dot-offset);
207
- }
208
- }
209
-
210
- /*
211
- * Increase the size of the clickable area,
212
- * without changing the padding of the ButtonIcon component
213
- */
214
- .button-icon::after {
215
- content: '';
216
- position: absolute;
217
- inset: 0;
218
- transform: v-bind(cssTargetScale);
219
- }
220
- </style>