ads-nuxt 0.1.1 → 0.1.2

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 (74) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +567 -546
  3. package/app/app.config.ts +25 -25
  4. package/app/assets/ads/checkbox-check.svg +5 -5
  5. package/app/assets/ads/checkbox-minus.svg +5 -5
  6. package/app/assets/brand/farmarcas.svg +6 -6
  7. package/app/assets/brand/radar.svg +9 -9
  8. package/app/assets/css/component-tokens.css +403 -403
  9. package/app/assets/css/main.css +617 -617
  10. package/app/components/AdsBadge.vue +48 -48
  11. package/app/components/AdsBroadcast.vue +45 -45
  12. package/app/components/AdsButton.vue +569 -569
  13. package/app/components/AdsButtonGroup.vue +39 -39
  14. package/app/components/AdsButtonMenu.vue +48 -48
  15. package/app/components/AdsCard.vue +117 -117
  16. package/app/components/AdsCharttip.vue +78 -78
  17. package/app/components/AdsCheckbox.vue +77 -77
  18. package/app/components/AdsDatePicker.vue +473 -473
  19. package/app/components/AdsDropdownMenu.vue +19 -19
  20. package/app/components/AdsEmptyState.vue +58 -58
  21. package/app/components/AdsFarmarcasPill.vue +74 -74
  22. package/app/components/AdsFeatureCard.vue +217 -217
  23. package/app/components/AdsFileCard.vue +101 -101
  24. package/app/components/AdsFilterDropdown.vue +174 -174
  25. package/app/components/AdsFilterOption.vue +72 -72
  26. package/app/components/AdsFilterSelect.vue +202 -202
  27. package/app/components/AdsFooter.vue +25 -25
  28. package/app/components/AdsInput.vue +143 -143
  29. package/app/components/AdsListDropdown.vue +44 -44
  30. package/app/components/AdsLoading.vue +109 -109
  31. package/app/components/AdsMenuBar.vue +103 -103
  32. package/app/components/AdsMetricCard.vue +119 -119
  33. package/app/components/AdsMiniPill.vue +40 -40
  34. package/app/components/AdsModal.vue +157 -157
  35. package/app/components/AdsMonthPicker.vue +80 -80
  36. package/app/components/AdsNavbarApp.vue +67 -67
  37. package/app/components/AdsNavbarDesk.vue +62 -62
  38. package/app/components/AdsNotabilityPill.vue +27 -27
  39. package/app/components/AdsNumberInput.vue +166 -166
  40. package/app/components/AdsPagination.vue +91 -91
  41. package/app/components/AdsProductTag.vue +61 -61
  42. package/app/components/AdsRadio.vue +70 -70
  43. package/app/components/AdsSearchInput.vue +113 -113
  44. package/app/components/AdsSegmentedTabs.vue +28 -28
  45. package/app/components/AdsSideMenu.vue +101 -101
  46. package/app/components/AdsSmalltip.vue +44 -44
  47. package/app/components/AdsSteptip.vue +101 -101
  48. package/app/components/AdsSwitch.vue +59 -59
  49. package/app/components/AdsTable.vue +100 -100
  50. package/app/components/AdsTableToolbar.vue +44 -44
  51. package/app/components/AdsTabs.vue +51 -51
  52. package/app/components/AdsTextarea.vue +109 -109
  53. package/app/components/AdsToast.vue +181 -181
  54. package/app/components/AdsTooltip.vue +66 -66
  55. package/app/components/InvertedTooltip.vue +40 -40
  56. package/app/components/OverlayLoading.vue +173 -173
  57. package/app/components/ProgressBarLoading.vue +256 -256
  58. package/app/composables/useOverlayLoading.ts +66 -66
  59. package/app/locale/pt-br.ts +6 -6
  60. package/app/plugins/ads-toast.client.ts +24 -24
  61. package/app/theme/ads-theme.ts +370 -370
  62. package/app/theme/component-tokens.json +402 -402
  63. package/app/theme/component-tokens.ts +815 -815
  64. package/app/types/overlay-loading.types.ts +26 -26
  65. package/app/utils/ads-filter-select.ts +172 -172
  66. package/app/utils/ads-table.ts +204 -204
  67. package/app/utils/calendar-date.ts +128 -128
  68. package/app/utils/category-role.ts +45 -45
  69. package/app/utils/money.ts +77 -77
  70. package/app/utils/notability.ts +8 -8
  71. package/app/utils/parser.ts +134 -134
  72. package/app/utils/percentage.ts +54 -54
  73. package/nuxt.config.ts +31 -32
  74. package/package.json +48 -46
@@ -1,181 +1,181 @@
1
- <template>
2
- <div
3
- v-if="appearance === 'status'"
4
- class="flex w-[var(--ads-toast-status-width)] max-w-full items-center justify-between gap-3 rounded-[var(--ads-toast-radius)] bg-[var(--ads-toast-status-bg)] p-3 text-[var(--ads-toast-status-text)] shadow-[var(--ads-shadow-level-1)]"
5
- role="status"
6
- >
7
- <div class="flex min-w-0 items-center gap-3">
8
- <UIcon
9
- :name="statusIcon"
10
- class="size-[var(--ads-toast-status-icon)] shrink-0"
11
- :class="[statusIconClass, status === 'loading' ? 'animate-spin' : '']"
12
- aria-hidden="true"
13
- />
14
- <div class="min-w-0">
15
- <p class="text-[length:var(--ads-toast-status-title-size)] leading-[1.3] font-bold">{{ title || resolvedMessage }}</p>
16
- <p v-if="subtitle" class="text-[length:var(--ads-toast-status-subtitle-size)] leading-[1.1]">{{ subtitle }}</p>
17
- </div>
18
- </div>
19
- <button
20
- v-if="closable"
21
- type="button"
22
- class="flex size-[18px] shrink-0 items-center justify-center text-[var(--ads-text-contrast)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--ads-text-contrast)]"
23
- aria-label="Fechar"
24
- @click="emit('close')"
25
- >
26
- <UIcon name="i-lucide-x" class="size-[18px]" />
27
- </button>
28
- </div>
29
- <div
30
- v-else
31
- class="flex flex-wrap items-center gap-[var(--ads-toast-gap)] rounded-[var(--ads-toast-radius)] p-[var(--ads-toast-padding)]"
32
- :class="[surfaceClass, app ? 'w-[331px] max-w-full' : 'w-full']"
33
- role="status"
34
- >
35
- <div class="flex min-w-0 flex-1 basis-full items-start gap-2 sm:basis-auto">
36
- <UIcon
37
- :name="resolvedIcon"
38
- class="size-[var(--ads-toast-icon)] shrink-0"
39
- :class="iconClass"
40
- aria-hidden="true"
41
- />
42
- <div class="min-w-0 flex-1">
43
- <slot>
44
- <p class="text-[length:var(--ads-toast-font-size)] [font-weight:var(--ads-toast-weight)] leading-[1.3] text-[var(--ads-toast-text)]">
45
- {{ resolvedMessage }}
46
- </p>
47
- </slot>
48
- </div>
49
- </div>
50
- <div
51
- v-if="actionLabel || closable"
52
- class="ml-auto flex shrink-0 items-center gap-2"
53
- >
54
- <AdsButton
55
- v-if="actionLabel"
56
- size="sm"
57
- :color="actionColor"
58
- :leading="Boolean(actionIcon)"
59
- :icon="actionIcon"
60
- :label="actionLabel"
61
- @click="emit('action')"
62
- />
63
- <button
64
- v-if="closable"
65
- type="button"
66
- class="flex size-6 shrink-0 items-center justify-center rounded text-[var(--ads-text-primary)] hover:bg-black/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--ads-text-primary)]"
67
- aria-label="Fechar"
68
- @click="emit('close')"
69
- >
70
- <UIcon name="i-lucide-x" class="size-[18px]" />
71
- </button>
72
- </div>
73
- </div>
74
- </template>
75
-
76
- <script setup lang="ts">
77
- import { computed } from "vue";
78
- import AdsButton from "./AdsButton.vue";
79
- import type { AdsButtonColor } from "./AdsButton.vue";
80
-
81
- export type AdsToastStatus = "primary" | "success" | "error" | "warning" | "neutral" | "loading";
82
- export type AdsToastAppearance = "banner" | "status";
83
-
84
- const props = withDefaults(
85
- defineProps<{
86
- status?: AdsToastStatus;
87
- /** `banner` é a faixa clara. `status` é o reporte escuro (Figma Status Toast). */
88
- appearance?: AdsToastAppearance;
89
- /** Faixa estreita de 331px, a variação `App` do ADS. */
90
- app?: boolean;
91
- message?: string;
92
- title?: string;
93
- subtitle?: string;
94
- icon?: string;
95
- /** Quando falso, o aviso permanece sem a ação de fechar. */
96
- closable?: boolean;
97
- /** Recuperação na própria faixa, como tentar de novo. */
98
- actionLabel?: string;
99
- /** Ícone da ação. Vazio esconde o ícone. */
100
- actionIcon?: string;
101
- }>(),
102
- {
103
- status: "error",
104
- appearance: "banner",
105
- app: false,
106
- message: undefined,
107
- title: undefined,
108
- subtitle: undefined,
109
- icon: undefined,
110
- closable: true,
111
- actionLabel: undefined,
112
- actionIcon: "i-lucide-refresh-cw",
113
- },
114
- );
115
-
116
- const emit = defineEmits<{
117
- close: [];
118
- action: [];
119
- }>();
120
-
121
- const actionColor = computed((): AdsButtonColor => {
122
- if (props.status === "success") return "success";
123
- if (props.status === "warning") return "attention";
124
- if (props.status === "primary") return "primary";
125
- if (props.status === "neutral") return "neutral";
126
- return "warning";
127
- });
128
-
129
- const surfaceClass = computed(() => {
130
- if (props.status === "primary") return "bg-[var(--ads-toast-primary-bg)]";
131
- if (props.status === "success") return "bg-[var(--ads-status-success-100)]";
132
- if (props.status === "warning") return "bg-[var(--ads-toast-warning-bg)]";
133
- if (props.status === "neutral") return "bg-[var(--ads-toast-neutral-bg)]";
134
- if (props.status === "loading") return "bg-[var(--ads-toast-primary-bg)]";
135
- return "bg-[var(--ads-toast-error-bg)]";
136
- });
137
-
138
- const iconClass = computed(() => {
139
- if (props.status === "primary") return "text-[var(--ads-toast-primary-icon)]";
140
- if (props.status === "success") return "text-[var(--ads-toast-success-icon)]";
141
- if (props.status === "warning") return "text-[var(--ads-toast-warning-icon)]";
142
- if (props.status === "neutral") return "text-[var(--ads-toast-neutral-icon)]";
143
- if (props.status === "loading") return "text-ads-oportunidade-300";
144
- return "text-[var(--ads-toast-error-icon)]";
145
- });
146
-
147
- const resolvedIcon = computed(() => {
148
- if (props.icon) return props.icon;
149
- if (props.status === "primary") return "i-lucide-info";
150
- if (props.status === "success") return "i-lucide-circle-check";
151
- if (props.status === "warning") return "i-lucide-triangle-alert";
152
- if (props.status === "neutral") return "i-lucide-calendar-fold";
153
- if (props.status === "loading") return "i-lucide-loader-circle";
154
- return "i-lucide-circle-x";
155
- });
156
-
157
- const statusIcon = computed(() => {
158
- if (props.icon) return props.icon;
159
- if (props.status === "success") return "i-lucide-circle-check";
160
- if (props.status === "warning") return "i-lucide-triangle-alert";
161
- if (props.status === "loading") return "i-lucide-loader-circle";
162
- return "i-lucide-circle-x";
163
- });
164
-
165
- const statusIconClass = computed(() => {
166
- if (props.status === "success") return "text-[var(--ads-toast-status-success)]";
167
- if (props.status === "warning") return "text-[var(--ads-toast-status-warning)]";
168
- if (props.status === "loading") return "text-[var(--ads-toast-status-loading)]";
169
- return "text-[var(--ads-toast-status-error)]";
170
- });
171
-
172
- const resolvedMessage = computed(() => {
173
- if (props.message) return props.message;
174
- if (props.status === "primary") return "Mensagem informativa";
175
- if (props.status === "success") return "Mensagem de sucesso";
176
- if (props.status === "warning") return "Mensagem de alerta";
177
- if (props.status === "neutral") return "Mensagem de lembrete";
178
- if (props.status === "loading") return "Mensagem de reporte";
179
- return "Mensagem de erro";
180
- });
181
- </script>
1
+ <template>
2
+ <div
3
+ v-if="appearance === 'status'"
4
+ class="flex w-[var(--ads-toast-status-width)] max-w-full items-center justify-between gap-3 rounded-[var(--ads-toast-radius)] bg-[var(--ads-toast-status-bg)] p-3 text-[var(--ads-toast-status-text)] shadow-[var(--ads-shadow-level-1)]"
5
+ role="status"
6
+ >
7
+ <div class="flex min-w-0 items-center gap-3">
8
+ <UIcon
9
+ :name="statusIcon"
10
+ class="size-[var(--ads-toast-status-icon)] shrink-0"
11
+ :class="[statusIconClass, status === 'loading' ? 'animate-spin' : '']"
12
+ aria-hidden="true"
13
+ />
14
+ <div class="min-w-0">
15
+ <p class="text-[length:var(--ads-toast-status-title-size)] leading-[1.3] font-bold">{{ title || resolvedMessage }}</p>
16
+ <p v-if="subtitle" class="text-[length:var(--ads-toast-status-subtitle-size)] leading-[1.1]">{{ subtitle }}</p>
17
+ </div>
18
+ </div>
19
+ <button
20
+ v-if="closable"
21
+ type="button"
22
+ class="flex size-[18px] shrink-0 items-center justify-center text-[var(--ads-text-contrast)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--ads-text-contrast)]"
23
+ aria-label="Fechar"
24
+ @click="emit('close')"
25
+ >
26
+ <UIcon name="i-lucide-x" class="size-[18px]" />
27
+ </button>
28
+ </div>
29
+ <div
30
+ v-else
31
+ class="flex flex-wrap items-center gap-[var(--ads-toast-gap)] rounded-[var(--ads-toast-radius)] p-[var(--ads-toast-padding)]"
32
+ :class="[surfaceClass, app ? 'w-[331px] max-w-full' : 'w-full']"
33
+ role="status"
34
+ >
35
+ <div class="flex min-w-0 flex-1 basis-full items-start gap-2 sm:basis-auto">
36
+ <UIcon
37
+ :name="resolvedIcon"
38
+ class="size-[var(--ads-toast-icon)] shrink-0"
39
+ :class="iconClass"
40
+ aria-hidden="true"
41
+ />
42
+ <div class="min-w-0 flex-1">
43
+ <slot>
44
+ <p class="text-[length:var(--ads-toast-font-size)] [font-weight:var(--ads-toast-weight)] leading-[1.3] text-[var(--ads-toast-text)]">
45
+ {{ resolvedMessage }}
46
+ </p>
47
+ </slot>
48
+ </div>
49
+ </div>
50
+ <div
51
+ v-if="actionLabel || closable"
52
+ class="ml-auto flex shrink-0 items-center gap-2"
53
+ >
54
+ <AdsButton
55
+ v-if="actionLabel"
56
+ size="sm"
57
+ :color="actionColor"
58
+ :leading="Boolean(actionIcon)"
59
+ :icon="actionIcon"
60
+ :label="actionLabel"
61
+ @click="emit('action')"
62
+ />
63
+ <button
64
+ v-if="closable"
65
+ type="button"
66
+ class="flex size-6 shrink-0 items-center justify-center rounded text-[var(--ads-text-primary)] hover:bg-black/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--ads-text-primary)]"
67
+ aria-label="Fechar"
68
+ @click="emit('close')"
69
+ >
70
+ <UIcon name="i-lucide-x" class="size-[18px]" />
71
+ </button>
72
+ </div>
73
+ </div>
74
+ </template>
75
+
76
+ <script setup lang="ts">
77
+ import { computed } from "vue";
78
+ import AdsButton from "./AdsButton.vue";
79
+ import type { AdsButtonColor } from "./AdsButton.vue";
80
+
81
+ export type AdsToastStatus = "primary" | "success" | "error" | "warning" | "neutral" | "loading";
82
+ export type AdsToastAppearance = "banner" | "status";
83
+
84
+ const props = withDefaults(
85
+ defineProps<{
86
+ status?: AdsToastStatus;
87
+ /** `banner` é a faixa clara. `status` é o reporte escuro (Figma Status Toast). */
88
+ appearance?: AdsToastAppearance;
89
+ /** Faixa estreita de 331px, a variação `App` do ADS. */
90
+ app?: boolean;
91
+ message?: string;
92
+ title?: string;
93
+ subtitle?: string;
94
+ icon?: string;
95
+ /** Quando falso, o aviso permanece sem a ação de fechar. */
96
+ closable?: boolean;
97
+ /** Recuperação na própria faixa, como tentar de novo. */
98
+ actionLabel?: string;
99
+ /** Ícone da ação. Vazio esconde o ícone. */
100
+ actionIcon?: string;
101
+ }>(),
102
+ {
103
+ status: "error",
104
+ appearance: "banner",
105
+ app: false,
106
+ message: undefined,
107
+ title: undefined,
108
+ subtitle: undefined,
109
+ icon: undefined,
110
+ closable: true,
111
+ actionLabel: undefined,
112
+ actionIcon: "i-lucide-refresh-cw",
113
+ },
114
+ );
115
+
116
+ const emit = defineEmits<{
117
+ close: [];
118
+ action: [];
119
+ }>();
120
+
121
+ const actionColor = computed((): AdsButtonColor => {
122
+ if (props.status === "success") return "success";
123
+ if (props.status === "warning") return "attention";
124
+ if (props.status === "primary") return "primary";
125
+ if (props.status === "neutral") return "neutral";
126
+ return "warning";
127
+ });
128
+
129
+ const surfaceClass = computed(() => {
130
+ if (props.status === "primary") return "bg-[var(--ads-toast-primary-bg)]";
131
+ if (props.status === "success") return "bg-[var(--ads-status-success-100)]";
132
+ if (props.status === "warning") return "bg-[var(--ads-toast-warning-bg)]";
133
+ if (props.status === "neutral") return "bg-[var(--ads-toast-neutral-bg)]";
134
+ if (props.status === "loading") return "bg-[var(--ads-toast-primary-bg)]";
135
+ return "bg-[var(--ads-toast-error-bg)]";
136
+ });
137
+
138
+ const iconClass = computed(() => {
139
+ if (props.status === "primary") return "text-[var(--ads-toast-primary-icon)]";
140
+ if (props.status === "success") return "text-[var(--ads-toast-success-icon)]";
141
+ if (props.status === "warning") return "text-[var(--ads-toast-warning-icon)]";
142
+ if (props.status === "neutral") return "text-[var(--ads-toast-neutral-icon)]";
143
+ if (props.status === "loading") return "text-ads-oportunidade-300";
144
+ return "text-[var(--ads-toast-error-icon)]";
145
+ });
146
+
147
+ const resolvedIcon = computed(() => {
148
+ if (props.icon) return props.icon;
149
+ if (props.status === "primary") return "i-lucide-info";
150
+ if (props.status === "success") return "i-lucide-circle-check";
151
+ if (props.status === "warning") return "i-lucide-triangle-alert";
152
+ if (props.status === "neutral") return "i-lucide-calendar-fold";
153
+ if (props.status === "loading") return "i-lucide-loader-circle";
154
+ return "i-lucide-circle-x";
155
+ });
156
+
157
+ const statusIcon = computed(() => {
158
+ if (props.icon) return props.icon;
159
+ if (props.status === "success") return "i-lucide-circle-check";
160
+ if (props.status === "warning") return "i-lucide-triangle-alert";
161
+ if (props.status === "loading") return "i-lucide-loader-circle";
162
+ return "i-lucide-circle-x";
163
+ });
164
+
165
+ const statusIconClass = computed(() => {
166
+ if (props.status === "success") return "text-[var(--ads-toast-status-success)]";
167
+ if (props.status === "warning") return "text-[var(--ads-toast-status-warning)]";
168
+ if (props.status === "loading") return "text-[var(--ads-toast-status-loading)]";
169
+ return "text-[var(--ads-toast-status-error)]";
170
+ });
171
+
172
+ const resolvedMessage = computed(() => {
173
+ if (props.message) return props.message;
174
+ if (props.status === "primary") return "Mensagem informativa";
175
+ if (props.status === "success") return "Mensagem de sucesso";
176
+ if (props.status === "warning") return "Mensagem de alerta";
177
+ if (props.status === "neutral") return "Mensagem de lembrete";
178
+ if (props.status === "loading") return "Mensagem de reporte";
179
+ return "Mensagem de erro";
180
+ });
181
+ </script>
@@ -1,66 +1,66 @@
1
- <template>
2
- <UTooltip
3
- v-if="hasTrigger"
4
- arrow
5
- :delay-duration="delayDuration"
6
- :content="{ side, align: 'center', sideOffset: 8 }"
7
- :ui="tooltipUi"
8
- >
9
- <slot />
10
- <template #content>
11
- <div class="flex max-w-[328px] flex-col gap-1 text-[var(--ads-text-contrast)]">
12
- <p v-if="showTitle" class="text-[length:var(--ads-tooltip-title-size)] leading-[1.3] font-bold text-[var(--ads-tooltip-title)]">{{ title }}</p>
13
- <p v-if="showDescription" class="text-[length:var(--ads-tooltip-font-size)] leading-[1.3] text-[var(--ads-tooltip-title)]">{{ description }}</p>
14
- </div>
15
- </template>
16
- </UTooltip>
17
- <div
18
- v-else
19
- class="flex max-w-[var(--ads-steptip-width)] flex-col gap-1 rounded-[var(--ads-tooltip-radius)] bg-[var(--ads-tooltip-bg)] px-[var(--ads-tooltip-padding-x)] py-[var(--ads-tooltip-padding-y)] text-[var(--ads-tooltip-title)] shadow-[var(--ads-shadow-level-1)]"
20
- >
21
- <p v-if="showTitle" class="text-[length:var(--ads-tooltip-title-size)] leading-[1.3] font-bold">{{ title }}</p>
22
- <p v-if="showDescription" class="text-[length:var(--ads-tooltip-font-size)] leading-[1.3]">{{ description }}</p>
23
- </div>
24
- </template>
25
-
26
- <script setup lang="ts">
27
- import { computed, useSlots } from "vue";
28
-
29
- type Wing = "up" | "down" | "left" | "right";
30
-
31
- const props = withDefaults(
32
- defineProps<{
33
- title?: string;
34
- description?: string;
35
- showTitle?: boolean;
36
- showDescription?: boolean;
37
- /** Figma `Wing Position`. */
38
- wing?: Wing;
39
- delayDuration?: number;
40
- }>(),
41
- {
42
- title: "Título",
43
- description: "Descrição do tooltip.",
44
- showTitle: true,
45
- showDescription: true,
46
- wing: "up",
47
- delayDuration: 150,
48
- },
49
- );
50
-
51
- const slots = useSlots();
52
- const hasTrigger = computed(() => Boolean(slots.default));
53
-
54
- const side = computed(() => {
55
- if (props.wing === "down") return "bottom" as const;
56
- if (props.wing === "left") return "left" as const;
57
- if (props.wing === "right") return "right" as const;
58
- return "top" as const;
59
- });
60
-
61
- const tooltipUi = {
62
- content:
63
- "z-[70] h-auto max-w-[328px] rounded-[var(--ads-tooltip-radius)] bg-[var(--ads-tooltip-bg)] px-4 py-3 shadow-[var(--ads-shadow-level-1)] ring-0",
64
- arrow: "fill-[var(--ads-tooltip-bg)]",
65
- };
66
- </script>
1
+ <template>
2
+ <UTooltip
3
+ v-if="hasTrigger"
4
+ arrow
5
+ :delay-duration="delayDuration"
6
+ :content="{ side, align: 'center', sideOffset: 8 }"
7
+ :ui="tooltipUi"
8
+ >
9
+ <slot />
10
+ <template #content>
11
+ <div class="flex max-w-[328px] flex-col gap-1 text-[var(--ads-text-contrast)]">
12
+ <p v-if="showTitle" class="text-[length:var(--ads-tooltip-title-size)] leading-[1.3] font-bold text-[var(--ads-tooltip-title)]">{{ title }}</p>
13
+ <p v-if="showDescription" class="text-[length:var(--ads-tooltip-font-size)] leading-[1.3] text-[var(--ads-tooltip-title)]">{{ description }}</p>
14
+ </div>
15
+ </template>
16
+ </UTooltip>
17
+ <div
18
+ v-else
19
+ class="flex max-w-[var(--ads-steptip-width)] flex-col gap-1 rounded-[var(--ads-tooltip-radius)] bg-[var(--ads-tooltip-bg)] px-[var(--ads-tooltip-padding-x)] py-[var(--ads-tooltip-padding-y)] text-[var(--ads-tooltip-title)] shadow-[var(--ads-shadow-level-1)]"
20
+ >
21
+ <p v-if="showTitle" class="text-[length:var(--ads-tooltip-title-size)] leading-[1.3] font-bold">{{ title }}</p>
22
+ <p v-if="showDescription" class="text-[length:var(--ads-tooltip-font-size)] leading-[1.3]">{{ description }}</p>
23
+ </div>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { computed, useSlots } from "vue";
28
+
29
+ type Wing = "up" | "down" | "left" | "right";
30
+
31
+ const props = withDefaults(
32
+ defineProps<{
33
+ title?: string;
34
+ description?: string;
35
+ showTitle?: boolean;
36
+ showDescription?: boolean;
37
+ /** Figma `Wing Position`. */
38
+ wing?: Wing;
39
+ delayDuration?: number;
40
+ }>(),
41
+ {
42
+ title: "Título",
43
+ description: "Descrição do tooltip.",
44
+ showTitle: true,
45
+ showDescription: true,
46
+ wing: "up",
47
+ delayDuration: 150,
48
+ },
49
+ );
50
+
51
+ const slots = useSlots();
52
+ const hasTrigger = computed(() => Boolean(slots.default));
53
+
54
+ const side = computed(() => {
55
+ if (props.wing === "down") return "bottom" as const;
56
+ if (props.wing === "left") return "left" as const;
57
+ if (props.wing === "right") return "right" as const;
58
+ return "top" as const;
59
+ });
60
+
61
+ const tooltipUi = {
62
+ content:
63
+ "z-[70] h-auto max-w-[328px] rounded-[var(--ads-tooltip-radius)] bg-[var(--ads-tooltip-bg)] px-4 py-3 shadow-[var(--ads-shadow-level-1)] ring-0",
64
+ arrow: "fill-[var(--ads-tooltip-bg)]",
65
+ };
66
+ </script>
@@ -1,40 +1,40 @@
1
- <template>
2
- <UTooltip
3
- :text="text"
4
- arrow
5
- :delay-duration="delayDuration"
6
- :disabled="disabled || !text"
7
- :content="content"
8
- :ui="tooltipUi"
9
- >
10
- <slot />
11
- </UTooltip>
12
- </template>
13
-
14
- <script setup lang="ts">
15
- withDefaults(
16
- defineProps<{
17
- text: string;
18
- delayDuration?: number;
19
- disabled?: boolean;
20
- content?: {
21
- side?: "top" | "right" | "bottom" | "left";
22
- align?: "start" | "center" | "end";
23
- sideOffset?: number;
24
- };
25
- }>(),
26
- {
27
- delayDuration: 150,
28
- disabled: false,
29
- content: () => ({ side: "top", align: "start", sideOffset: 8 }),
30
- },
31
- );
32
-
33
- /** Tooltip padrão escuro do produto (`bg-inverted`). */
34
- const tooltipUi = {
35
- content:
36
- "z-[70] h-auto max-w-xs rounded-[var(--ads-tooltip-radius)] bg-[var(--ads-tooltip-bg)] px-[var(--ads-tooltip-padding-x)] py-[var(--ads-tooltip-padding-y)] text-[length:var(--ads-tooltip-font-size)] text-[var(--ads-tooltip-text)] shadow-lg ring-0",
37
- text: "whitespace-normal",
38
- arrow: "fill-[var(--ads-tooltip-bg)]",
39
- };
40
- </script>
1
+ <template>
2
+ <UTooltip
3
+ :text="text"
4
+ arrow
5
+ :delay-duration="delayDuration"
6
+ :disabled="disabled || !text"
7
+ :content="content"
8
+ :ui="tooltipUi"
9
+ >
10
+ <slot />
11
+ </UTooltip>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ withDefaults(
16
+ defineProps<{
17
+ text: string;
18
+ delayDuration?: number;
19
+ disabled?: boolean;
20
+ content?: {
21
+ side?: "top" | "right" | "bottom" | "left";
22
+ align?: "start" | "center" | "end";
23
+ sideOffset?: number;
24
+ };
25
+ }>(),
26
+ {
27
+ delayDuration: 150,
28
+ disabled: false,
29
+ content: () => ({ side: "top", align: "start", sideOffset: 8 }),
30
+ },
31
+ );
32
+
33
+ /** Tooltip padrão escuro do produto (`bg-inverted`). */
34
+ const tooltipUi = {
35
+ content:
36
+ "z-[70] h-auto max-w-xs rounded-[var(--ads-tooltip-radius)] bg-[var(--ads-tooltip-bg)] px-[var(--ads-tooltip-padding-x)] py-[var(--ads-tooltip-padding-y)] text-[length:var(--ads-tooltip-font-size)] text-[var(--ads-tooltip-text)] shadow-lg ring-0",
37
+ text: "whitespace-normal",
38
+ arrow: "fill-[var(--ads-tooltip-bg)]",
39
+ };
40
+ </script>