Skip to content

Commit 47bbfcd

Browse files
committed
fix(emerald): apply Figma design feedback round across components
Loader spinner replaces text in EmButton loading state; tooltip opens on hover with delay and cleans up timers on unmount; menu and tooltip popovers no longer clip their drop shadows; accordion height transitions smoothly via grid-rows with visibility-driven a11y; selected tab uses primary fill with white text and inset shadow plus a fade-in panel transition; stepper description renders below the title and the completed-state badge no longer looks wrapped; slider thumb sits inside the track on the primary range; checkbox and radio default to border-only with a focus ring on the whole label; text field error/disabled states match spec; carousel switches to a stacked fade with centered indicator and drops the unused perView and orientation props; loading exposes a real ring spinner; alerts use outline icons; table overflows horizontally with a compact example added; badge count text inherits variant on-color; tag padding refined.
1 parent 1199149 commit 47bbfcd

35 files changed

Lines changed: 445 additions & 169 deletions

packages/emerald/src/components/EmAccordion/EmAccordionContent.vue

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,47 @@
1212
<template>
1313
<ExpansionPanelContent class="emerald-accordion__content">
1414
<template #default="slotProps">
15-
<slot v-bind="slotProps" />
15+
<div class="emerald-accordion__content-inner">
16+
<slot v-bind="slotProps" />
17+
</div>
1618
</template>
1719
</ExpansionPanelContent>
1820
</template>
1921

2022
<style>
2123
.emerald-accordion__content {
22-
display: block;
23-
padding: 12px;
24+
display: grid;
25+
grid-template-rows: 1fr;
26+
transition: grid-template-rows 280ms cubic-bezier(0.4, 0.0, 0.2, 1);
2427
font-family: Manrope, system-ui, -apple-system, sans-serif;
2528
font-weight: 400;
2629
font-size: 12px;
2730
line-height: normal;
2831
color: #000000;
32+
}
33+
34+
.emerald-accordion__content[hidden] {
35+
display: grid;
36+
grid-template-rows: 0fr;
37+
}
38+
39+
.emerald-accordion__content-inner {
40+
min-height: 0;
41+
overflow: hidden;
42+
padding: 12px;
43+
transition: visibility 0s linear 280ms;
44+
}
45+
46+
.emerald-accordion__content[data-selected] .emerald-accordion__content-inner {
47+
visibility: visible;
48+
transition-delay: 0s;
49+
}
50+
51+
.emerald-accordion__content[hidden] .emerald-accordion__content-inner {
52+
visibility: hidden;
53+
}
54+
55+
.emerald-accordion__content[data-selected] .emerald-accordion__content-inner {
2956
border-top: 0.5px solid rgb(var(--emerald-neutral-channels, 26 28 30) / 0.1);
3057
}
3158
</style>

packages/emerald/src/components/EmBadge/EmBadge.vue

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@
107107
padding: 0 4px;
108108
font-size: 10px;
109109
font-weight: 700;
110-
color: #000;
111110
}
112111
113112
/* Variants — background color only; border/shadow handled above */
@@ -141,8 +140,8 @@
141140
color: var(--emerald-neutral-800);
142141
}
143142
144-
/* Count content keeps black text regardless of variant (per Figma) */
145-
.emerald-badge[data-shape="count"] {
146-
color: #000;
143+
/* Neutral count keeps darker text since the surface is light. */
144+
.emerald-badge[data-shape="count"][data-variant="neutral"] {
145+
color: var(--emerald-neutral-800);
147146
}
148147
</style>

packages/emerald/src/components/EmButton/EmButton.vue

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<script lang="ts">
22
import { V0Paper } from '@vuetify/paper'
33
4+
import EmButtonLoader from './EmButtonLoader.vue'
5+
46
// Types
57
import type { V0PaperProps } from '@vuetify/paper'
68
@@ -53,7 +55,12 @@
5355
:type="href ? undefined : type"
5456
@click="onClick"
5557
>
56-
<slot />
58+
<span v-if="loading" class="emerald-button__loading">
59+
<EmButtonLoader />
60+
</span>
61+
<span :class="['emerald-button__content', loading && 'emerald-button__content--hidden']">
62+
<slot />
63+
</span>
5764
</V0Paper>
5865
</template>
5966

@@ -63,12 +70,15 @@
6370
align-items: center;
6471
justify-content: center;
6572
font-family: Manrope, system-ui, -apple-system, sans-serif;
66-
font-weight: 600;
73+
font-weight: 500;
6774
border: none;
6875
cursor: pointer;
6976
user-select: none;
7077
background: var(--emerald-primary-500);
7178
color: var(--emerald-primary-100);
79+
box-shadow:
80+
0 1px 2px 0 rgb(var(--emerald-primary-500-channels) / 0.25),
81+
0 1px 3px 0 rgb(var(--emerald-primary-500-channels) / 0.18);
7282
transition: background-color 120ms ease, box-shadow 120ms ease, transform 80ms ease;
7383
}
7484
@@ -100,8 +110,8 @@
100110
background: var(--emerald-primary-700);
101111
color: var(--emerald-primary-200);
102112
box-shadow:
103-
0 1px 3px 0 var(--emerald-primary-700),
104-
0 1px 5px 0 rgb(var(--emerald-primary-700-channels) / 0.2);
113+
0 2px 4px 0 rgb(var(--emerald-primary-700-channels) / 0.32),
114+
0 3px 8px 0 rgb(var(--emerald-primary-700-channels) / 0.22);
105115
}
106116
107117
.emerald-button:active:not([data-disabled]) {
@@ -121,4 +131,28 @@
121131
cursor: not-allowed;
122132
pointer-events: none;
123133
}
134+
135+
.emerald-button[data-loading] {
136+
position: relative;
137+
cursor: progress;
138+
box-shadow: none;
139+
}
140+
141+
.emerald-button__content {
142+
display: inline-flex;
143+
align-items: center;
144+
gap: inherit;
145+
}
146+
147+
.emerald-button__content--hidden {
148+
visibility: hidden;
149+
}
150+
151+
.emerald-button__loading {
152+
position: absolute;
153+
inset: 0;
154+
display: inline-flex;
155+
align-items: center;
156+
justify-content: center;
157+
}
124158
</style>

packages/emerald/src/components/EmButton/EmButtonLoader.vue

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,31 @@
88

99
<template>
1010
<span aria-hidden="true" class="emerald-button__loader">
11-
<slot />
11+
<slot>
12+
<span class="emerald-button__spinner" />
13+
</slot>
1214
</span>
1315
</template>
16+
17+
<style>
18+
.emerald-button__loader {
19+
display: inline-flex;
20+
align-items: center;
21+
justify-content: center;
22+
line-height: 0;
23+
}
24+
25+
.emerald-button__spinner {
26+
display: inline-block;
27+
width: 1em;
28+
height: 1em;
29+
border-radius: 50%;
30+
border: 2px solid currentColor;
31+
border-top-color: transparent;
32+
animation: emerald-button-spin 700ms linear infinite;
33+
}
34+
35+
@keyframes emerald-button-spin {
36+
to { transform: rotate(360deg); }
37+
}
38+
</style>

packages/emerald/src/components/EmCarousel/EmCarousel.vue

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,10 @@
77
// Types
88
import type { V0PaperProps } from '@vuetify/paper'
99
10-
export type EmCarouselOrientation = 'horizontal' | 'vertical'
11-
1210
export interface EmCarouselProps extends V0PaperProps {
1311
label?: string
1412
disabled?: boolean
1513
circular?: boolean
16-
orientation?: EmCarouselOrientation
17-
perView?: number
1814
autoplay?: number
1915
}
2016
</script>
@@ -26,8 +22,6 @@
2622
label,
2723
disabled = false,
2824
circular = false,
29-
orientation = 'horizontal',
30-
perView = 1,
3125
autoplay = 0,
3226
...paperProps
3327
} = defineProps<EmCarouselProps>()
@@ -41,16 +35,13 @@
4135
as="div"
4236
class="emerald-carousel"
4337
:data-disabled="disabled || undefined"
44-
:data-orientation="orientation"
4538
>
4639
<CarouselRoot
4740
v-model="model"
4841
:autoplay
4942
:circular
5043
:disabled
5144
:label
52-
:orientation
53-
:per-view
5445
renderless
5546
>
5647
<template #default="slotProps">
@@ -65,18 +56,14 @@
6556
position: relative;
6657
display: grid;
6758
grid-template-columns: auto 1fr auto;
68-
grid-template-rows: 1fr auto;
59+
grid-template-rows: minmax(280px, auto) auto;
60+
justify-items: center;
6961
align-items: center;
7062
gap: 14px 12px;
7163
font-family: Manrope, system-ui, -apple-system, sans-serif;
7264
color: #000000;
7365
}
7466
75-
.emerald-carousel[data-orientation="vertical"] {
76-
grid-template-columns: 1fr;
77-
grid-template-rows: auto 1fr auto auto;
78-
}
79-
8067
.emerald-carousel[data-disabled] {
8168
opacity: 0.6;
8269
pointer-events: none;

packages/emerald/src/components/EmCarousel/EmCarouselItem.vue

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,35 @@
3030

3131
<style>
3232
.emerald-carousel__item {
33-
flex: 0 0 60%;
33+
position: absolute;
34+
top: 0;
35+
left: 50%;
3436
display: flex;
3537
align-items: center;
3638
justify-content: center;
37-
padding: 0 8px;
38-
min-width: 0;
39-
scroll-snap-align: center;
39+
width: 60%;
40+
height: 100%;
4041
background: #ffffff;
4142
border: 1px solid rgb(var(--emerald-neutral-channels) / 0.1);
4243
border-radius: 8px;
4344
overflow: hidden;
44-
filter: blur(1px);
45-
transition: filter 160ms ease, box-shadow 160ms ease, transform 160ms ease;
46-
transform: scale(0.94);
47-
box-shadow: none;
45+
opacity: 0;
46+
transform: translateX(-50%) scale(0.92) translateY(8px);
47+
transition:
48+
opacity 280ms cubic-bezier(0.4, 0.0, 0.2, 1),
49+
transform 280ms cubic-bezier(0.4, 0.0, 0.2, 1),
50+
box-shadow 280ms ease;
51+
pointer-events: none;
4852
}
4953
5054
.emerald-carousel__item[data-selected] {
51-
filter: none;
52-
transform: scale(1);
55+
opacity: 1;
56+
transform: translateX(-50%) scale(1) translateY(0);
5357
box-shadow:
54-
0 1px 3px 0 rgb(5 0 18 / 0.12),
55-
0 1px 5px 0 rgb(5 0 18 / 0.20);
58+
0 4px 10px 0 rgb(5 0 18 / 0.12),
59+
0 8px 24px 0 rgb(5 0 18 / 0.16);
5660
z-index: 1;
61+
pointer-events: auto;
5762
}
5863
5964
.emerald-carousel__item[data-disabled] {

packages/emerald/src/components/EmCarousel/EmCarouselViewport.vue

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,21 @@
1919

2020
<style>
2121
.emerald-carousel__viewport {
22+
position: relative;
2223
grid-column: 2;
2324
grid-row: 1;
25+
justify-self: stretch;
2426
align-self: stretch;
25-
padding: 8px 20%;
26-
gap: 12px;
27+
width: 100%;
28+
height: 100%;
29+
display: block;
30+
padding: 0;
31+
gap: 0;
32+
overflow: visible;
2733
}
2834
2935
.emerald-carousel__viewport[data-orientation="vertical"] {
3036
grid-column: 1;
3137
grid-row: 2;
32-
padding: 20% 8px;
33-
}
34-
35-
.emerald-carousel__viewport[data-dragging] {
36-
cursor: grabbing;
3738
}
3839
</style>

packages/emerald/src/components/EmCheckbox/EmCheckbox.vue

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,16 @@
6565
.emerald-checkbox {
6666
display: inline-flex;
6767
align-items: center;
68-
gap: 8px;
68+
gap: 10px;
6969
font-family: Manrope, system-ui, -apple-system, sans-serif;
7070
color: var(--emerald-on-background);
7171
font-size: 14px;
7272
line-height: 1.4;
7373
cursor: pointer;
7474
user-select: none;
75+
border-radius: 6px;
76+
padding: 2px 6px 2px 2px;
77+
transition: box-shadow 120ms ease;
7578
}
7679
7780
.emerald-checkbox[data-disabled] {
@@ -92,12 +95,8 @@
9295
flex-shrink: 0;
9396
}
9497
95-
.emerald-checkbox__root:focus-visible::after {
96-
content: '';
97-
position: absolute;
98-
inset: -3px;
99-
border: 1px solid var(--emerald-primary-500, #7c5cf6);
100-
border-radius: 5px;
101-
pointer-events: none;
98+
/* Focus ring on the whole label (control + text) */
99+
.emerald-checkbox:has(.emerald-checkbox__root:focus-visible) {
100+
box-shadow: 0 0 0 2px rgb(var(--emerald-primary-500-channels, 124 92 246) / 0.35);
102101
}
103102
</style>

0 commit comments

Comments
 (0)