@1doc/1ds-react 2.13.0 → 2.15.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.
- package/CHANGELOG.md +62 -59
- package/dist/components/AILabel/AILabel.css +1 -1
- package/dist/components/Alert/Alert.css +1 -1
- package/dist/components/AppShell/AppShell.css +4 -0
- package/dist/components/AttachmentCard/AttachmentCard.css +2 -2
- package/dist/components/Avatar/Avatar.d.ts +8 -3
- package/dist/components/Avatar/Avatar.js +28 -4
- package/dist/components/BottomNavigation/BottomNavigation.css +2 -2
- package/dist/components/BottomSheet/BottomSheet.css +2 -2
- package/dist/components/Box/Box.css +3 -3
- package/dist/components/Button/Button.css +6 -1
- package/dist/components/Button/Button.d.ts +11 -2
- package/dist/components/Button/Button.js +15 -3
- package/dist/components/Card/Card.css +5 -5
- package/dist/components/Chart/Chart.css +1 -1
- package/dist/components/Coachmark/Coachmark.css +1 -1
- package/dist/components/Combobox/Combobox.css +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.css +1 -1
- package/dist/components/Counter/Counter.css +43 -0
- package/dist/components/Counter/Counter.d.ts +57 -0
- package/dist/components/Counter/Counter.js +99 -0
- package/dist/components/DatePicker/DatePicker.css +1 -1
- package/dist/components/Drawer/Drawer.css +2 -2
- package/dist/components/Dropdown/Dropdown.css +3 -1
- package/dist/components/Dropdown/Dropdown.d.ts +17 -0
- package/dist/components/Dropdown/Dropdown.js +22 -2
- package/dist/components/EmptyState/EmptyState.css +12 -0
- package/dist/components/EmptyState/EmptyState.d.ts +3 -0
- package/dist/components/EmptyState/EmptyState.js +1 -0
- package/dist/components/Kanban/Kanban.css +2 -2
- package/dist/components/Kanban/KanbanCard.css +2 -2
- package/dist/components/List/List.css +83 -0
- package/dist/components/List/List.d.ts +3 -0
- package/dist/components/List/List.js +6 -2
- package/dist/components/List/ListItem.d.ts +19 -0
- package/dist/components/List/ListItem.js +5 -1
- package/dist/components/Modal/Modal.css +3 -4
- package/dist/components/MultiSelect/MultiSelect.css +1 -1
- package/dist/components/OrgChart/OrgChart.css +2 -2
- package/dist/components/PhoneInput/PhoneInput.css +2 -2
- package/dist/components/Popover/Popover.css +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.css +1 -1
- package/dist/components/Select/Select.css +1 -1
- package/dist/components/StatCard/StatCard.css +99 -5
- package/dist/components/StatCard/StatCard.d.ts +12 -6
- package/dist/components/StatCard/StatCard.js +6 -2
- package/dist/components/Switch/Switch.css +2 -2
- package/dist/components/Text/Text.d.ts +6 -0
- package/dist/components/TimePicker/TimePicker.css +1 -1
- package/dist/components/Toast/Toast.css +2 -2
- package/dist/components/Tooltip/Tooltip.css +23 -3
- package/dist/components/Tooltip/Tooltip.js +33 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/teste/PedidosMatheus.test.d.ts +1 -0
- package/dist/teste/PedidosMatheus.test.js +91 -0
- package/dist/teste/PedidosMatheus2.test.d.ts +1 -0
- package/dist/teste/PedidosMatheus2.test.js +82 -0
- package/dist/teste/SegmentedControlSuperficie.test.js +1 -1
- package/dist/teste/StatCardTamanhoSm.test.js +8 -0
- package/package.json +3 -3
- package/src/index.ts +2 -0
- package/src/teste/PedidosMatheus.test.tsx +129 -0
- package/src/teste/PedidosMatheus2.test.tsx +102 -0
- package/src/teste/SegmentedControlSuperficie.test.tsx +1 -1
- package/src/teste/StatCardTamanhoSm.test.tsx +9 -0
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
box-sizing: border-box;
|
|
105
105
|
padding-bottom: var(--umds-primitive-spacing-quarck); /* 4px */
|
|
106
106
|
border-top: none;
|
|
107
|
-
box-shadow: var(--umds-semantic-shadow-
|
|
107
|
+
box-shadow: var(--umds-semantic-shadow-top-sm);
|
|
108
108
|
/* o disco ultrapassa o topo da barra: sem isto ele seria recortado */
|
|
109
109
|
overflow: visible;
|
|
110
110
|
}
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
espaço, para o rótulo não descer junto e a linha de rótulos ficar reta. */
|
|
132
132
|
margin-top: -12px;
|
|
133
133
|
margin-bottom: -4px;
|
|
134
|
-
box-shadow: var(--umds-semantic-shadow-sm);
|
|
134
|
+
box-shadow: var(--umds-semantic-shadow-bottom-sm);
|
|
135
135
|
flex-shrink: 0;
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
background-color: var(--umds-semantic-color-background-elevated);
|
|
46
46
|
border-top-left-radius: var(--umds-primitive-border-radius-sm);
|
|
47
47
|
border-top-right-radius: var(--umds-primitive-border-radius-sm);
|
|
48
|
-
box-shadow: var(--umds-semantic-shadow-
|
|
48
|
+
box-shadow: var(--umds-semantic-shadow-top-sm);
|
|
49
49
|
outline: none;
|
|
50
50
|
animation: umds-bottomsheet-entrada var(--umds-semantic-motion-duration-base)
|
|
51
51
|
var(--umds-semantic-motion-easing-standard);
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
margin: 0 calc(-1 * var(--umds-primitive-spacing-xxxs))
|
|
154
154
|
calc(-1 * var(--umds-primitive-spacing-xxxs));
|
|
155
155
|
background-color: var(--umds-semantic-color-background-elevated);
|
|
156
|
-
box-shadow: var(--umds-semantic-shadow-
|
|
156
|
+
box-shadow: var(--umds-semantic-shadow-top-sm);
|
|
157
157
|
flex-shrink: 0;
|
|
158
158
|
}
|
|
159
159
|
|
|
@@ -96,9 +96,9 @@
|
|
|
96
96
|
.umds-box--radius-circular { border-radius: var(--umds-primitive-border-radius-circular); }
|
|
97
97
|
|
|
98
98
|
/* ── Elevação ── */
|
|
99
|
-
.umds-box--shadow-level1 { box-shadow: var(--umds-
|
|
100
|
-
.umds-box--shadow-level2 { box-shadow: var(--umds-
|
|
101
|
-
.umds-box--shadow-level3 { box-shadow: var(--umds-
|
|
99
|
+
.umds-box--shadow-level1 { box-shadow: var(--umds-semantic-shadow-bottom-md); }
|
|
100
|
+
.umds-box--shadow-level2 { box-shadow: var(--umds-semantic-shadow-bottom-lg); }
|
|
101
|
+
.umds-box--shadow-level3 { box-shadow: var(--umds-semantic-shadow-bottom-xl); }
|
|
102
102
|
|
|
103
103
|
/* ── Layout flex (direction, gap, align, justify, wrap) ──
|
|
104
104
|
Liga quando qualquer uma das props é passada; mesmos nomes e valores do Stack. */
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
line-height: 1;
|
|
23
23
|
white-space: nowrap;
|
|
24
24
|
text-decoration: none;
|
|
25
|
+
box-sizing: border-box; /* com href o Button é <a>, que nasce content-box */
|
|
25
26
|
|
|
26
27
|
transition:
|
|
27
28
|
background-color var(--umds-semantic-motion-duration-fast) var(--umds-semantic-motion-easing-standard),
|
|
@@ -210,8 +211,12 @@
|
|
|
210
211
|
.umds-button--icon.umds-button--md { width: var(--umds-primitive-spacing-sm); } /* 40px */
|
|
211
212
|
.umds-button--icon.umds-button--lg { width: var(--umds-primitive-spacing-md); } /* 48px */
|
|
212
213
|
|
|
214
|
+
/* Camada de estado translúcida, da cor do próprio ícone: funciona sobre
|
|
215
|
+
qualquer fundo (o ⋮ num item azul selecionado não vira um quadrado branco).
|
|
216
|
+
12% de neutral-dark-down (#565656) sobre o branco dá #EBEBEB, o mesmo
|
|
217
|
+
neutral-light-medium de antes: no fundo claro o visual não muda. */
|
|
213
218
|
.umds-button--icon:hover:not(:disabled) {
|
|
214
|
-
background-color:
|
|
219
|
+
background-color: color-mix(in srgb, currentColor 12%, transparent);
|
|
215
220
|
}
|
|
216
221
|
|
|
217
222
|
.umds-button--icon:disabled {
|
|
@@ -22,8 +22,11 @@ import './Button.css';
|
|
|
22
22
|
* @property {boolean} autoFocus - Foca o botão automaticamente ao montar
|
|
23
23
|
* @property {number} tabIndex - Ordem de tabulação nativa
|
|
24
24
|
* @property {object} style - Estilos inline aplicados ao botão (objeto no React, string/objeto no Vue)
|
|
25
|
-
* @
|
|
26
|
-
* @
|
|
25
|
+
* @property {string} href - Botão que NAVEGA: com `href` o Button vira `<a>` com a mesma aparência (Ctrl+clique e "abrir em nova aba" funcionam). Desabilitado, volta a ser `<button disabled>`.
|
|
26
|
+
* @property {string} target - Destino do link (`_blank` ganha `rel="noopener noreferrer"`)
|
|
27
|
+
* @property {string} rel - Relação do link; sobrescreve o padrão do `target`
|
|
28
|
+
* @quandoUsar AÇÃO que muda estado: salvar, enviar, abrir modal, confirmar. Use `variant="icon"` para ação só com ícone (sempre com `ariaLabel`). Para navegação com cara de botão (o "Ver todos" de um rodapé de card), passe `href`: sai um `<a>` de verdade.
|
|
29
|
+
* @quandoNaoUsar Para navegar com cara de texto, no meio de uma frase, use `Link`. Nunca navegue por `onClick`: sem `href` não há Ctrl+clique nem "abrir em nova aba".
|
|
27
30
|
*/
|
|
28
31
|
export interface ButtonProps {
|
|
29
32
|
variant?: "primary" | "secondary" | "neutral" | "neutral-text" | "text" | "negative" | "negative-outlined" | "icon";
|
|
@@ -48,6 +51,12 @@ export interface ButtonProps {
|
|
|
48
51
|
form?: string;
|
|
49
52
|
autoFocus?: boolean;
|
|
50
53
|
tabIndex?: number;
|
|
54
|
+
/** Botão que navega: vira `<a>` com a mesma aparência. Desabilitado, volta a ser `<button>`. */
|
|
55
|
+
href?: string;
|
|
56
|
+
/** Destino do link. `_blank` ganha `rel="noopener noreferrer"`. */
|
|
57
|
+
target?: string;
|
|
58
|
+
/** Relação do link. Sobrescreve o padrão do `target`. */
|
|
59
|
+
rel?: string;
|
|
51
60
|
}
|
|
52
61
|
import { IconProp } from "../Icon/Icon";
|
|
53
62
|
declare function Button(props: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -63,15 +63,27 @@ function Button(props) {
|
|
|
63
63
|
function endIconIsIcon() {
|
|
64
64
|
return isIconValue(props.endIcon);
|
|
65
65
|
}
|
|
66
|
+
function isLink() {
|
|
67
|
+
return !!props.href && !props.disabled;
|
|
68
|
+
}
|
|
69
|
+
function relValue() {
|
|
70
|
+
if (props.rel)
|
|
71
|
+
return props.rel;
|
|
72
|
+
return props.target === "_blank" ? "noopener noreferrer" : undefined;
|
|
73
|
+
}
|
|
66
74
|
function handleClick(event) {
|
|
67
75
|
// Clique bloqueado durante o carregamento — evita dupla submissão
|
|
68
|
-
// sem mudar o visual (o botão não fica disabled).
|
|
69
|
-
|
|
76
|
+
// sem mudar o visual (o botão não fica disabled). No `<a>`, segura
|
|
77
|
+
// também a navegação.
|
|
78
|
+
if (props.loading) {
|
|
79
|
+
if (event && event.preventDefault)
|
|
80
|
+
event.preventDefault();
|
|
70
81
|
return;
|
|
82
|
+
}
|
|
71
83
|
if (props.onClick) {
|
|
72
84
|
props.onClick(event);
|
|
73
85
|
}
|
|
74
86
|
}
|
|
75
|
-
return (_jsxs("button", { type: props.type || "button", disabled: props.disabled, id: props.id, name: props.name, value: props.value, form: props.form, autoFocus: props.autoFocus || undefined, tabIndex: props.tabIndex, "aria-label": props.ariaLabel, "aria-busy": props.loading, onClick: (event) => handleClick(event), className: classes(), children: [showLoadingAtStart() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null, showStartIcon() ? (_jsx(_Fragment, { children: startIconIsIcon() ? (_jsx(Icon, { variant: "inherit", icon: props.startIcon, size: iconSize() })) : (_jsx(_Fragment, { children: _jsx(_Fragment, { children: props.startIcon }) })) })) : null, showLoadingAtCenter() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null, showLoadingAtCenter() ? (_jsx("span", { className: "umds-button__visually-hidden", children: props.children })) : null, showChildren() ? _jsx(_Fragment, { children: props.children }) : null, showEndIcon() ? (_jsx(_Fragment, { children: endIconIsIcon() ? (_jsx(Icon, { variant: "inherit", icon: props.endIcon, size: iconSize() })) : (_jsx(_Fragment, { children: _jsx(_Fragment, { children: props.endIcon }) })) })) : null, showLoadingAtEnd() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null] }));
|
|
87
|
+
return (_jsx(_Fragment, { children: isLink() ? (_jsx(_Fragment, { children: _jsxs("a", { href: props.href, target: props.target, rel: relValue(), id: props.id, tabIndex: props.tabIndex, "aria-label": props.ariaLabel, "aria-busy": props.loading, onClick: (event) => handleClick(event), className: classes(), children: [showLoadingAtStart() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null, showStartIcon() ? (_jsx(_Fragment, { children: startIconIsIcon() ? (_jsx(Icon, { variant: "inherit", icon: props.startIcon, size: iconSize() })) : (_jsx(_Fragment, { children: _jsx(_Fragment, { children: props.startIcon }) })) })) : null, showLoadingAtCenter() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null, showLoadingAtCenter() ? (_jsx("span", { className: "umds-button__visually-hidden", children: props.children })) : null, showChildren() ? _jsx(_Fragment, { children: props.children }) : null, showEndIcon() ? (_jsx(_Fragment, { children: endIconIsIcon() ? (_jsx(Icon, { variant: "inherit", icon: props.endIcon, size: iconSize() })) : (_jsx(_Fragment, { children: _jsx(_Fragment, { children: props.endIcon }) })) })) : null, showLoadingAtEnd() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null] }) })) : (_jsx(_Fragment, { children: _jsxs("button", { type: props.type || "button", disabled: props.disabled, id: props.id, name: props.name, value: props.value, form: props.form, autoFocus: props.autoFocus || undefined, tabIndex: props.tabIndex, "aria-label": props.ariaLabel, "aria-busy": props.loading, onClick: (event) => handleClick(event), className: classes(), children: [showLoadingAtStart() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null, showStartIcon() ? (_jsx(_Fragment, { children: startIconIsIcon() ? (_jsx(Icon, { variant: "inherit", icon: props.startIcon, size: iconSize() })) : (_jsx(_Fragment, { children: _jsx(_Fragment, { children: props.startIcon }) })) })) : null, showLoadingAtCenter() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null, showLoadingAtCenter() ? (_jsx("span", { className: "umds-button__visually-hidden", children: props.children })) : null, showChildren() ? _jsx(_Fragment, { children: props.children }) : null, showEndIcon() ? (_jsx(_Fragment, { children: endIconIsIcon() ? (_jsx(Icon, { variant: "inherit", icon: props.endIcon, size: iconSize() })) : (_jsx(_Fragment, { children: _jsx(_Fragment, { children: props.endIcon }) })) })) : null, showLoadingAtEnd() ? (_jsx("span", { "aria-hidden": "true", className: "umds-button__loading", children: _jsx(Icon, { variant: "inherit", icon: props.loadingIcon || faRefresh, size: iconSize() }) })) : null] }) })) }));
|
|
76
88
|
}
|
|
77
89
|
export default Button;
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
/* ── Sombras (tokens semânticos oficiais — TOKEN-MAP §3b) ── */
|
|
17
17
|
.umds-card--shadow-none { box-shadow: none; }
|
|
18
|
-
.umds-card--shadow-xs { box-shadow: var(--umds-semantic-shadow-xs); }
|
|
19
|
-
.umds-card--shadow-sm { box-shadow: var(--umds-semantic-shadow-sm); }
|
|
20
|
-
.umds-card--shadow-md { box-shadow: var(--umds-semantic-shadow-md); }
|
|
21
|
-
.umds-card--shadow-lg { box-shadow: var(--umds-semantic-shadow-lg); }
|
|
18
|
+
.umds-card--shadow-xs { box-shadow: var(--umds-semantic-shadow-bottom-xs); }
|
|
19
|
+
.umds-card--shadow-sm { box-shadow: var(--umds-semantic-shadow-bottom-sm); }
|
|
20
|
+
.umds-card--shadow-md { box-shadow: var(--umds-semantic-shadow-bottom-md); }
|
|
21
|
+
.umds-card--shadow-lg { box-shadow: var(--umds-semantic-shadow-bottom-lg); }
|
|
22
22
|
|
|
23
23
|
/* ── Padding ── */
|
|
24
24
|
.umds-card--padding-none { padding: 0; }
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
.umds-card--hoverable:hover {
|
|
39
39
|
border-color: var(--umds-semantic-color-primary-medium); /* #6393DB */
|
|
40
|
-
box-shadow: var(--umds-semantic-shadow-md); /* protótipo --shadow-md */
|
|
40
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md); /* protótipo --shadow-md */
|
|
41
41
|
transform: translateY(-1px);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
border: var(--umds-primitive-border-width-hairline) solid var(--umds-semantic-color-neutral-light-medium);
|
|
216
216
|
border-radius: var(--umds-primitive-border-radius-sm);
|
|
217
217
|
background-color: var(--umds-semantic-color-neutral-light-pure);
|
|
218
|
-
box-shadow: var(--umds-
|
|
218
|
+
box-shadow: var(--umds-semantic-shadow-bottom-lg);
|
|
219
219
|
font-size: var(--umds-primitive-font-size-xxxs); /* 12px */
|
|
220
220
|
line-height: var(--umds-primitive-font-line-height-lg);
|
|
221
221
|
white-space: nowrap;
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
background: var(--umds-semantic-color-background-white);
|
|
65
65
|
color: var(--umds-semantic-color-neutral-dark-pure);
|
|
66
66
|
border-radius: var(--umds-primitive-border-radius-md); /* 16px */
|
|
67
|
-
box-shadow: var(--umds-
|
|
67
|
+
box-shadow: var(--umds-semantic-shadow-bottom-xl);
|
|
68
68
|
outline: none;
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -231,7 +231,7 @@
|
|
|
231
231
|
background-color: var(--umds-semantic-color-background-elevated);
|
|
232
232
|
border: 1px solid var(--umds-semantic-color-neutral-light-down);
|
|
233
233
|
border-radius: var(--umds-primitive-border-radius-sm);
|
|
234
|
-
box-shadow: var(--umds-semantic-shadow-md);
|
|
234
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md);
|
|
235
235
|
z-index: var(--umds-semantic-layer-popover);
|
|
236
236
|
max-height: 300px; /* literal, igual ao Select — candidato a novo token */
|
|
237
237
|
display: flex;
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
.umds-confirm-dialog {
|
|
40
40
|
background: var(--umds-semantic-color-background-elevated); /* superfície elevada: igual ao white no light; mais clara no dark (decisão 25/07) */
|
|
41
41
|
border-radius: var(--umds-primitive-border-radius-sm); /* 8px universal (rodada ago/2026) — era md */
|
|
42
|
-
box-shadow: var(--umds-semantic-shadow-
|
|
42
|
+
box-shadow: var(--umds-semantic-shadow-center-xl); /* modal: mesma sombra do Modal */
|
|
43
43
|
width: 100%;
|
|
44
44
|
max-width: 440px;
|
|
45
45
|
overflow: hidden;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────
|
|
2
|
+
COUNTER
|
|
3
|
+
Número que conta até o valor. Herda fonte, tamanho e cor de onde está.
|
|
4
|
+
A reserva (cópia invisível do valor final) e o número que corre ocupam a
|
|
5
|
+
mesma célula da grade: a largura é a do valor final desde o primeiro quadro.
|
|
6
|
+
───────────────────────────────────────────── */
|
|
7
|
+
|
|
8
|
+
.umds-counter {
|
|
9
|
+
/* Contém a cópia escondida (__leitura, absolute): sem isso ela escapa do
|
|
10
|
+
overflow de uma área que rola (o mesmo bug corrigido no Tooltip). */
|
|
11
|
+
position: relative;
|
|
12
|
+
display: inline-grid;
|
|
13
|
+
font-variant-numeric: tabular-nums;
|
|
14
|
+
white-space: nowrap;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.umds-counter__reserva,
|
|
18
|
+
.umds-counter__numero {
|
|
19
|
+
grid-area: 1 / 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.umds-counter__reserva {
|
|
23
|
+
visibility: hidden;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.umds-counter__numero {
|
|
27
|
+
justify-self: end;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Valor final para o leitor de tela. Receita visually-hidden; os 1px não são
|
|
31
|
+
medida de design. */
|
|
32
|
+
.umds-counter__leitura {
|
|
33
|
+
position: absolute;
|
|
34
|
+
width: 1px;
|
|
35
|
+
height: 1px;
|
|
36
|
+
margin: -1px;
|
|
37
|
+
padding: 0;
|
|
38
|
+
border: 0;
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
clip: rect(0, 0, 0, 0);
|
|
41
|
+
clip-path: inset(50%);
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import './Counter.css';
|
|
2
|
+
/**
|
|
3
|
+
* Counter — número que conta até o valor.
|
|
4
|
+
*
|
|
5
|
+
* Ao aparecer, o número sobe de `from` (0) até `value`; quando `value` muda,
|
|
6
|
+
* conta do valor atual até o novo. É o número do painel ("1.284 processos") e o
|
|
7
|
+
* total de páginas da caixa de entrada. Herda fonte, tamanho e cor de onde
|
|
8
|
+
* está, então serve dentro de um título, de um `StatCard` ou no meio do texto.
|
|
9
|
+
*
|
|
10
|
+
* Três decisões que valem saber:
|
|
11
|
+
*
|
|
12
|
+
* - **O leitor de tela lê só o valor final.** O número que corre é
|
|
13
|
+
* `aria-hidden`; uma cópia escondida com o valor final é o que se anuncia.
|
|
14
|
+
* Ninguém ouve "1, 37, 210, 1.284".
|
|
15
|
+
* - **A largura não pula.** Uma cópia invisível do valor final reserva o
|
|
16
|
+
* espaço, e os algarismos são tabulares: o texto em volta não dança enquanto
|
|
17
|
+
* o número conta.
|
|
18
|
+
* - **Movimento reduzido é respeitado.** Com `prefers-reduced-motion` (ou
|
|
19
|
+
* `disableAnimation`) o número aparece direto no valor final.
|
|
20
|
+
*
|
|
21
|
+
* O formato é o do `Intl.NumberFormat` em `locale` (pt-BR: "1.284", "22,31").
|
|
22
|
+
* As casas decimais seguem as do `value`, a menos que `decimals` diga outra
|
|
23
|
+
* coisa.
|
|
24
|
+
* @property {number} value - Valor final (número ou texto numérico)
|
|
25
|
+
* @property {number} from - De onde a contagem começa ao montar (padrão 0)
|
|
26
|
+
* @property {number} duration - Duração da contagem em ms (padrão 1000)
|
|
27
|
+
* @property {number} decimals - Casas decimais (padrão: as do `value`)
|
|
28
|
+
* @property {string} locale - Idioma do formato (padrão "pt-BR")
|
|
29
|
+
* @property {string} prefix - Texto antes do número ("R$ ")
|
|
30
|
+
* @property {string} suffix - Texto depois do número ("%", " páginas")
|
|
31
|
+
* @property {boolean} disableAnimation - Mostra o valor final direto, sem contar
|
|
32
|
+
* @property {string} className - Classes CSS adicionais
|
|
33
|
+
* @quandoUsar Número de destaque que merece atenção ao aparecer: KPI de painel, total de páginas ou de itens de uma caixa de entrada, contadores de resultado.
|
|
34
|
+
* @quandoNaoUsar Para contagem pequena presa a outro elemento (não lidos de uma aba), use `Badge`. Para número que muda o tempo todo (cronômetro, campo editável), mostre o texto direto: a animação a cada mudança cansa. Em tabela (`DataTable`), número não anima.
|
|
35
|
+
*/
|
|
36
|
+
export interface CounterProps {
|
|
37
|
+
/** Valor final. Aceita número ou texto numérico ("1284", "22.31"). */
|
|
38
|
+
value: number | string;
|
|
39
|
+
/** De onde a contagem começa ao montar. @default 0 */
|
|
40
|
+
from?: number;
|
|
41
|
+
/** Duração da contagem, em milissegundos. @default 1000 */
|
|
42
|
+
duration?: number;
|
|
43
|
+
/** Casas decimais. Sem a prop, as do `value`. */
|
|
44
|
+
decimals?: number;
|
|
45
|
+
/** Idioma do formato do número. @default 'pt-BR' */
|
|
46
|
+
locale?: string;
|
|
47
|
+
/** Texto antes do número ("R$ "). */
|
|
48
|
+
prefix?: string;
|
|
49
|
+
/** Texto depois do número ("%", " páginas"). */
|
|
50
|
+
suffix?: string;
|
|
51
|
+
/** Mostra o valor final direto, sem contar. @default false */
|
|
52
|
+
disableAnimation?: boolean;
|
|
53
|
+
/** Classes CSS adicionais. */
|
|
54
|
+
className?: string;
|
|
55
|
+
}
|
|
56
|
+
declare function Counter(props: CounterProps): import("react/jsx-runtime").JSX.Element;
|
|
57
|
+
export default Counter;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import './Counter.css';
|
|
4
|
+
import { useState, useRef, useEffect } from "react";
|
|
5
|
+
function Counter(props) {
|
|
6
|
+
const quadroRef = useRef(null);
|
|
7
|
+
const ultimoRef = useRef(null);
|
|
8
|
+
const alvoRef = useRef(null);
|
|
9
|
+
const [exibido, setExibido] = useState(() => null);
|
|
10
|
+
function alvo() {
|
|
11
|
+
const numero = Number(props.value);
|
|
12
|
+
return isFinite(numero) ? numero : 0;
|
|
13
|
+
}
|
|
14
|
+
function casas() {
|
|
15
|
+
if (typeof props.decimals === "number")
|
|
16
|
+
return props.decimals;
|
|
17
|
+
const texto = String(props.value);
|
|
18
|
+
const ponto = texto.indexOf(".");
|
|
19
|
+
return ponto < 0 ? 0 : Math.min(texto.length - ponto - 1, 4);
|
|
20
|
+
}
|
|
21
|
+
function formatar(numero) {
|
|
22
|
+
const digitos = casas();
|
|
23
|
+
const formatado = new Intl.NumberFormat(props.locale || "pt-BR", {
|
|
24
|
+
minimumFractionDigits: digitos,
|
|
25
|
+
maximumFractionDigits: digitos,
|
|
26
|
+
}).format(numero);
|
|
27
|
+
return (props.prefix || "") + formatado + (props.suffix || "");
|
|
28
|
+
}
|
|
29
|
+
function semAnimacao() {
|
|
30
|
+
if (props.disableAnimation)
|
|
31
|
+
return true;
|
|
32
|
+
if (typeof window === "undefined" || !window.matchMedia)
|
|
33
|
+
return false;
|
|
34
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
35
|
+
}
|
|
36
|
+
function parar() {
|
|
37
|
+
if (quadroRef.current !== null && typeof window !== "undefined") {
|
|
38
|
+
window.cancelAnimationFrame(quadroRef.current);
|
|
39
|
+
}
|
|
40
|
+
quadroRef.current = null;
|
|
41
|
+
}
|
|
42
|
+
function animar(de, para) {
|
|
43
|
+
parar();
|
|
44
|
+
const duracao = typeof props.duration === "number" ? props.duration : 1000;
|
|
45
|
+
if (semAnimacao() ||
|
|
46
|
+
duracao <= 0 ||
|
|
47
|
+
de === para ||
|
|
48
|
+
typeof window === "undefined") {
|
|
49
|
+
ultimoRef.current = para;
|
|
50
|
+
setExibido(para);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const inicio = performance.now();
|
|
54
|
+
const passo = (agora) => {
|
|
55
|
+
const progresso = Math.min(1, (agora - inicio) / duracao);
|
|
56
|
+
// ease-out cúbico: rápido no começo, assenta devagar no valor.
|
|
57
|
+
const suave = 1 - Math.pow(1 - progresso, 3);
|
|
58
|
+
const atual = progresso >= 1 ? para : de + (para - de) * suave;
|
|
59
|
+
ultimoRef.current = atual;
|
|
60
|
+
setExibido(atual);
|
|
61
|
+
quadroRef.current =
|
|
62
|
+
progresso < 1 ? window.requestAnimationFrame(passo) : null;
|
|
63
|
+
};
|
|
64
|
+
quadroRef.current = window.requestAnimationFrame(passo);
|
|
65
|
+
}
|
|
66
|
+
function textoNaTela() {
|
|
67
|
+
if (exibido !== null)
|
|
68
|
+
return formatar(exibido);
|
|
69
|
+
if (props.disableAnimation)
|
|
70
|
+
return formatar(alvo());
|
|
71
|
+
return formatar(typeof props.from === "number" ? props.from : 0);
|
|
72
|
+
}
|
|
73
|
+
function textoFinal() {
|
|
74
|
+
return formatar(alvo());
|
|
75
|
+
}
|
|
76
|
+
function classes() {
|
|
77
|
+
return ["umds-counter", props.className].filter(Boolean).join(" ");
|
|
78
|
+
}
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const para = alvo();
|
|
81
|
+
alvoRef.current = para;
|
|
82
|
+
animar(typeof props.from === "number" ? props.from : 0, para);
|
|
83
|
+
}, []);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const para = alvo();
|
|
86
|
+
// O React roda este efeito também na montagem: o onMount já cuidou dela.
|
|
87
|
+
if (ultimoRef.current === null || alvoRef.current === para)
|
|
88
|
+
return;
|
|
89
|
+
alvoRef.current = para;
|
|
90
|
+
animar(ultimoRef.current, para);
|
|
91
|
+
}, [props.value]);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
return () => {
|
|
94
|
+
parar();
|
|
95
|
+
};
|
|
96
|
+
}, []);
|
|
97
|
+
return (_jsxs("span", { className: classes(), children: [_jsx("span", { className: "umds-counter__reserva", "aria-hidden": "true", children: textoFinal() }), _jsx("span", { className: "umds-counter__numero", "aria-hidden": "true", children: textoNaTela() }), _jsx("span", { className: "umds-counter__leitura", children: textoFinal() })] }));
|
|
98
|
+
}
|
|
99
|
+
export default Counter;
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
background: var(--umds-semantic-color-background-elevated); /* superfície elevada: igual ao white no light; mais clara no dark (decisão 25/07) */
|
|
179
179
|
border: 1px solid var(--umds-semantic-color-neutral-light-down); /* #D5D5D5 */
|
|
180
180
|
border-radius: var(--umds-primitive-border-radius-sm); /* 8px */
|
|
181
|
-
box-shadow: var(--umds-semantic-shadow-md);
|
|
181
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md);
|
|
182
182
|
padding: var(--umds-primitive-spacing-xxxs); /* 16px */
|
|
183
183
|
gap: var(--umds-primitive-spacing-xxxs); /* 16px */
|
|
184
184
|
box-sizing: border-box;
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
box-sizing: border-box;
|
|
72
72
|
padding: var(--umds-primitive-spacing-xxxs);
|
|
73
73
|
background-color: var(--umds-semantic-color-background-elevated);
|
|
74
|
-
box-shadow: var(--umds-semantic-shadow-lg);
|
|
74
|
+
box-shadow: var(--umds-semantic-shadow-bottom-lg);
|
|
75
75
|
outline: none;
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
margin: 0 calc(-1 * var(--umds-primitive-spacing-xxxs))
|
|
190
190
|
calc(-1 * var(--umds-primitive-spacing-xxxs));
|
|
191
191
|
background-color: var(--umds-semantic-color-background-elevated);
|
|
192
|
-
box-shadow: var(--umds-semantic-shadow-md);
|
|
192
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md);
|
|
193
193
|
flex-shrink: 0;
|
|
194
194
|
}
|
|
195
195
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
background: var(--umds-semantic-color-background-elevated); /* superfície elevada: igual ao white no light; mais clara no dark (decisão 25/07) */
|
|
36
36
|
border: 1px solid var(--umds-semantic-color-neutral-light-down); /* #D5D5D5 */
|
|
37
37
|
border-radius: var(--umds-primitive-border-radius-sm); /* era 12px (protótipo --radius-lg) — snap 14/07: painel overlay → md */
|
|
38
|
-
box-shadow: var(--umds-semantic-shadow-md); /* era 0 4px 16px rgba(0,0,0,0.12) — mapeado para shadow-md 14/07 */
|
|
38
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md); /* era 0 4px 16px rgba(0,0,0,0.12) — mapeado para shadow-md 14/07 */
|
|
39
39
|
font-family: var(--umds-semantic-font-family-base);
|
|
40
40
|
min-width: 160px; /* dimensão do protótipo sem token 1DS */
|
|
41
41
|
transition: opacity var(--umds-semantic-motion-duration-fast) var(--umds-semantic-motion-easing-standard);
|
|
@@ -55,10 +55,12 @@
|
|
|
55
55
|
align-items: center;
|
|
56
56
|
gap: var(--umds-primitive-spacing-nano); /* 8px */
|
|
57
57
|
width: 100%;
|
|
58
|
+
box-sizing: border-box; /* o item com href é <a>, que nasce content-box */
|
|
58
59
|
padding: var(--umds-primitive-spacing-nano) var(--umds-primitive-spacing-xxxs); /* 8px 16px */
|
|
59
60
|
background: none;
|
|
60
61
|
border: none;
|
|
61
62
|
text-align: left;
|
|
63
|
+
text-decoration: none;
|
|
62
64
|
font-family: var(--umds-semantic-font-family-base);
|
|
63
65
|
font-size: var(--umds-primitive-font-size-xxs); /* 14px */
|
|
64
66
|
font-weight: 400;
|
|
@@ -7,14 +7,31 @@ import './Dropdown.css';
|
|
|
7
7
|
* @property {boolean} disabled - Desabilita o item (não selecionável).
|
|
8
8
|
* @property {boolean} danger - Aplica o estilo destrutivo (vermelho).
|
|
9
9
|
* @property {boolean} dividerAfter - Adiciona um divisor abaixo do item.
|
|
10
|
+
* @property {string} href - Item que navega: vira `<a>` de verdade (Ctrl+clique e "abrir em nova aba" funcionam). O `onSelect` continua sendo chamado.
|
|
11
|
+
* @property {string} target - Destino do link (`_blank` ganha `rel="noopener noreferrer"`).
|
|
12
|
+
* @property {string} rel - Relação do link; sobrescreve o padrão do `target`.
|
|
13
|
+
* @property {function} onSelect - Ação deste item: chamada ao escolhê-lo, antes do `onSelect` do Dropdown. Dispensa o switch por `key` e o cast para um tipo próprio.
|
|
14
|
+
*
|
|
15
|
+
* O item aceita campos próprios (`command`, `id`, `payload`...), que voltam
|
|
16
|
+
* intactos no `onSelect`: não é preciso converter para outro tipo.
|
|
10
17
|
*/
|
|
11
18
|
export interface DropdownItem {
|
|
19
|
+
/** Ação deste item, chamada ao escolhê-lo (antes do `onSelect` do Dropdown). */
|
|
20
|
+
onSelect?: (item: DropdownItem) => void;
|
|
21
|
+
/** Campos próprios do produto (`command`, `payload`...) voltam intactos no `onSelect`. */
|
|
22
|
+
[campo: string]: any;
|
|
12
23
|
key: string;
|
|
13
24
|
label: string;
|
|
14
25
|
icon?: IconProp;
|
|
15
26
|
disabled?: boolean;
|
|
16
27
|
danger?: boolean;
|
|
17
28
|
dividerAfter?: boolean;
|
|
29
|
+
/** Item que navega: vira `<a>` (Ctrl+clique e nova aba funcionam). Desabilitado, volta a ser botão. */
|
|
30
|
+
href?: string;
|
|
31
|
+
/** Destino do link. `_blank` ganha `rel="noopener noreferrer"`. */
|
|
32
|
+
target?: string;
|
|
33
|
+
/** Relação do link. Sobrescreve o padrão do `target`. */
|
|
34
|
+
rel?: string;
|
|
18
35
|
}
|
|
19
36
|
/**
|
|
20
37
|
* Dropdown component — menu de ações ancorado a um trigger.
|
|
@@ -211,6 +211,8 @@ function Dropdown(props) {
|
|
|
211
211
|
function handleSelect(item) {
|
|
212
212
|
if (item.disabled)
|
|
213
213
|
return;
|
|
214
|
+
if (item.onSelect)
|
|
215
|
+
item.onSelect(item);
|
|
214
216
|
if (props.onSelect) {
|
|
215
217
|
props.onSelect(item);
|
|
216
218
|
}
|
|
@@ -302,8 +304,21 @@ function Dropdown(props) {
|
|
|
302
304
|
activateIndex(nextEnabledIndex(total, -1));
|
|
303
305
|
}
|
|
304
306
|
else if (key === "Enter" || key === " ") {
|
|
305
|
-
event.preventDefault();
|
|
306
307
|
const item = itemList()[focusedIndex()];
|
|
308
|
+
// Item com href é <a>: o Enter fica com o navegador, que dispara o
|
|
309
|
+
// clique do link (e respeita Ctrl/Shift para nova aba/janela). O
|
|
310
|
+
// onClick do <a> chama o handleSelect. Espaço não ativa link no
|
|
311
|
+
// navegador, então vira um clique de verdade.
|
|
312
|
+
if (item && item.href && !item.disabled) {
|
|
313
|
+
if (key === " ") {
|
|
314
|
+
event.preventDefault();
|
|
315
|
+
const alvo = event.target;
|
|
316
|
+
if (alvo && alvo.click)
|
|
317
|
+
alvo.click();
|
|
318
|
+
}
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
event.preventDefault();
|
|
307
322
|
if (item)
|
|
308
323
|
handleSelect(item);
|
|
309
324
|
}
|
|
@@ -312,6 +327,11 @@ function Dropdown(props) {
|
|
|
312
327
|
close();
|
|
313
328
|
}
|
|
314
329
|
}
|
|
330
|
+
function relDoItem(item) {
|
|
331
|
+
if (item.rel)
|
|
332
|
+
return item.rel;
|
|
333
|
+
return item.target === "_blank" ? "noopener noreferrer" : undefined;
|
|
334
|
+
}
|
|
315
335
|
function itemClasses(item) {
|
|
316
336
|
return [
|
|
317
337
|
"umds-dropdown__item",
|
|
@@ -370,6 +390,6 @@ function Dropdown(props) {
|
|
|
370
390
|
}, []);
|
|
371
391
|
return (_jsxs("span", { ref: triggerRef, className: triggerClasses(), style: {
|
|
372
392
|
display: "inline-flex",
|
|
373
|
-
}, children: [_jsx("span", { className: "umds-dropdown__trigger", ref: triggerButtonRef, role: triggerIsInteractive ? undefined : "button", tabIndex: triggerIsInteractive ? undefined : 0, "aria-haspopup": triggerIsInteractive ? undefined : "menu", "aria-expanded": triggerIsInteractive ? undefined : ariaExpandedText(), onClick: (event) => toggle(), onKeyDown: (event) => handleTriggerKeydown(event), children: _jsx(_Fragment, { children: props.children }) }), _jsx(Portal, { children: mounted ? (_jsx("span", { className: "umds-dropdown__floating", ref: floatingRef, style: floatingStyle(), children: _jsx("ul", { className: "umds-dropdown__menu", role: "menu", ref: menuRef, "aria-label": props.ariaLabel, tabIndex: -1, style: menuStyle(), onKeyDown: (event) => handleMenuKeydown(event), children: itemList()?.map((item, index) => (_jsx("li", { role: "none", children: _jsxs("button", { type: "button", role: "menuitem", className: itemClasses(item), tabIndex: index === activeIndex ? 0 : -1, "data-active": index === activeIndex, disabled: item.disabled, onClick: (event) => handleSelect(item), children: [item.icon ? (_jsx("span", { className: "umds-dropdown__item-icon", "aria-hidden": "true", children: _jsx(Icon, { size: "sm", variant: "inherit", icon: item.icon }) })) : null, _jsx("span", { className: "umds-dropdown__item-label", children: item.label })] }) }, item.key))) }) })) : null })] }));
|
|
393
|
+
}, children: [_jsx("span", { className: "umds-dropdown__trigger", ref: triggerButtonRef, role: triggerIsInteractive ? undefined : "button", tabIndex: triggerIsInteractive ? undefined : 0, "aria-haspopup": triggerIsInteractive ? undefined : "menu", "aria-expanded": triggerIsInteractive ? undefined : ariaExpandedText(), onClick: (event) => toggle(), onKeyDown: (event) => handleTriggerKeydown(event), children: _jsx(_Fragment, { children: props.children }) }), _jsx(Portal, { children: mounted ? (_jsx("span", { className: "umds-dropdown__floating", ref: floatingRef, style: floatingStyle(), children: _jsx("ul", { className: "umds-dropdown__menu", role: "menu", ref: menuRef, "aria-label": props.ariaLabel, tabIndex: -1, style: menuStyle(), onKeyDown: (event) => handleMenuKeydown(event), children: itemList()?.map((item, index) => (_jsx("li", { role: "none", children: item.href && !item.disabled ? (_jsxs("a", { role: "menuitem", href: item.href, target: item.target, rel: relDoItem(item), className: itemClasses(item), tabIndex: index === activeIndex ? 0 : -1, "data-active": index === activeIndex, onClick: (event) => handleSelect(item), children: [item.icon ? (_jsx("span", { className: "umds-dropdown__item-icon", "aria-hidden": "true", children: _jsx(Icon, { size: "sm", variant: "inherit", icon: item.icon }) })) : null, _jsx("span", { className: "umds-dropdown__item-label", children: item.label })] })) : (_jsx(_Fragment, { children: _jsxs("button", { type: "button", role: "menuitem", className: itemClasses(item), tabIndex: index === activeIndex ? 0 : -1, "data-active": index === activeIndex, disabled: item.disabled, onClick: (event) => handleSelect(item), children: [item.icon ? (_jsx("span", { className: "umds-dropdown__item-icon", "aria-hidden": "true", children: _jsx(Icon, { size: "sm", variant: "inherit", icon: item.icon }) })) : null, _jsx("span", { className: "umds-dropdown__item-label", children: item.label })] }) })) }, item.key))) }) })) : null })] }));
|
|
374
394
|
}
|
|
375
395
|
export default Dropdown;
|
|
@@ -130,3 +130,15 @@
|
|
|
130
130
|
outline: 2px solid var(--umds-semantic-color-primary-pure);
|
|
131
131
|
outline-offset: 2px;
|
|
132
132
|
}
|
|
133
|
+
|
|
134
|
+
/* ── fill: ocupa e centraliza no espaço disponível ──
|
|
135
|
+
Para o vazio de uma coluna que rola: cresce no pai flex (flex: 1) e, num pai
|
|
136
|
+
com altura definida, ocupa a altura toda (min-height). O conteúdo continua
|
|
137
|
+
centralizado pela regra base. */
|
|
138
|
+
.umds-empty-state--fill {
|
|
139
|
+
flex: 1 1 auto;
|
|
140
|
+
align-self: stretch;
|
|
141
|
+
box-sizing: border-box;
|
|
142
|
+
width: 100%;
|
|
143
|
+
min-height: 100%;
|
|
144
|
+
}
|
|
@@ -11,6 +11,7 @@ import './EmptyState.css';
|
|
|
11
11
|
* @property {function} onAction - Callback acionado ao clicar no botão de ação
|
|
12
12
|
* @property {string} size - Tamanho do bloco: 'sm' | 'md' | 'lg'
|
|
13
13
|
* @property {string} className - Classes CSS adicionais
|
|
14
|
+
* @property {boolean} fill - Ocupa e centraliza no espaço disponível: cresce no pai flex e, num pai com altura definida, fica no meio dele (o vazio de uma coluna que rola)
|
|
14
15
|
* @quandoUsar Quando NÃO HÁ dados para mostrar: lista vazia, busca sem resultado, área ainda não configurada. Traz ícone, mensagem e ação opcional.
|
|
15
16
|
* @quandoNaoUsar Enquanto os dados ainda estão CARREGANDO — use `Skeleton` ou `Spinner`. Estado vazio é resposta definitiva, não espera.
|
|
16
17
|
*/
|
|
@@ -22,6 +23,8 @@ export interface EmptyStateProps {
|
|
|
22
23
|
actionLabel?: string;
|
|
23
24
|
onAction?: () => void;
|
|
24
25
|
size?: "sm" | "md" | "lg";
|
|
26
|
+
/** Ocupa e centraliza no espaço disponível (coluna que rola, painel). @default false */
|
|
27
|
+
fill?: boolean;
|
|
25
28
|
className?: string;
|
|
26
29
|
}
|
|
27
30
|
import { IconProp } from "../Icon/Icon";
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
|
|
66
66
|
.umds-kanban__handle:hover .umds-kanban-card {
|
|
67
67
|
border-color: var(--umds-semantic-color-primary-medium);
|
|
68
|
-
box-shadow: var(--umds-semantic-shadow-md);
|
|
68
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
.umds-kanban__handle:focus {
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
/* Pego pelo teclado: o cartão "levanta". */
|
|
81
81
|
.umds-kanban__item--pego .umds-kanban-card {
|
|
82
82
|
border-color: var(--umds-semantic-color-primary-pure);
|
|
83
|
-
box-shadow: var(--umds-semantic-shadow-lg);
|
|
83
|
+
box-shadow: var(--umds-semantic-shadow-bottom-lg);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/* Origem do arrasto com o ponteiro: fica o lugar, esmaecido. */
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
border: 1px solid var(--umds-semantic-color-neutral-light-medium);
|
|
19
19
|
border-radius: var(--umds-primitive-border-radius-sm);
|
|
20
20
|
background-color: var(--umds-semantic-color-background-elevated);
|
|
21
|
-
box-shadow: var(--umds-semantic-shadow-xs);
|
|
21
|
+
box-shadow: var(--umds-semantic-shadow-bottom-xs);
|
|
22
22
|
font-family: var(--umds-semantic-font-family-base);
|
|
23
23
|
color: var(--umds-semantic-color-neutral-dark-pure);
|
|
24
24
|
text-align: left;
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
.umds-kanban-card--interativo:hover {
|
|
35
35
|
border-color: var(--umds-semantic-color-primary-medium);
|
|
36
|
-
box-shadow: var(--umds-semantic-shadow-md);
|
|
36
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.umds-kanban-card--interativo:focus-visible {
|