@softize/opus 29.0.0 → 30.0.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.
@@ -18,6 +18,10 @@ import {
18
18
  } from "react";
19
19
  import { cn } from "../../lib/cn.ts";
20
20
 
21
+ /** Metadados contextuais, separados da orientação textual e da linha de ações. */
22
+ export const structuralMetaClasses =
23
+ "mt-3 flex min-w-0 flex-wrap items-center gap-x-3 gap-y-2 text-sm text-muted-foreground [overflow-wrap:anywhere] [&>*]:max-w-full";
24
+
21
25
  export type StructuralHeaderVariant = "page" | "section";
22
26
 
23
27
  /** As classes por slot, por hierarquia visual — PageTitle e SurfaceTitle no nível 1 são o mesmo. */
@@ -46,6 +50,7 @@ interface StructuralHeaderSlots {
46
50
  title: ElementType;
47
51
  count?: ElementType;
48
52
  description?: ElementType;
53
+ meta?: ElementType;
49
54
  actions?: ElementType;
50
55
  }
51
56
 
@@ -127,6 +132,7 @@ export function StructuralHeader({
127
132
  const counts = slots.count === undefined ? [] : of(slots.count);
128
133
  const descriptions =
129
134
  slots.description === undefined ? [] : of(slots.description);
135
+ const metas = slots.meta === undefined ? [] : of(slots.meta);
130
136
  const actionSlots = slots.actions === undefined ? [] : of(slots.actions);
131
137
  const slotTypes = [
132
138
  ...leadingTypes,
@@ -134,6 +140,7 @@ export function StructuralHeader({
134
140
  slots.title,
135
141
  slots.count,
136
142
  slots.description,
143
+ slots.meta,
137
144
  slots.actions,
138
145
  ].filter((type): type is ElementType => type !== undefined);
139
146
  const free = allowFreeContent
@@ -151,6 +158,7 @@ export function StructuralHeader({
151
158
  titles.length +
152
159
  counts.length +
153
160
  descriptions.length +
161
+ metas.length +
154
162
  actionSlots.length;
155
163
 
156
164
  if (
@@ -159,6 +167,7 @@ export function StructuralHeader({
159
167
  medias.length > 1 ||
160
168
  counts.length > 1 ||
161
169
  descriptions.length > 1 ||
170
+ metas.length > 1 ||
162
171
  actionSlots.length > 1 ||
163
172
  recognized !== nodes.length
164
173
  ) {
@@ -170,6 +179,7 @@ export function StructuralHeader({
170
179
  ...leadingTypes,
171
180
  slots.media,
172
181
  slots.description,
182
+ slots.meta,
173
183
  slots.count,
174
184
  slots.actions,
175
185
  ]
@@ -193,6 +203,10 @@ export function StructuralHeader({
193
203
  );
194
204
  }
195
205
 
206
+ if (metas.length > 0 && titles.length === 0) {
207
+ throw new Error(`${name} exige título para exibir metadados.`);
208
+ }
209
+
196
210
  const titleLine = titles.length + counts.length > 0 && (
197
211
  <Wrapper className="flex items-baseline gap-2">
198
212
  {titles}
@@ -342,11 +356,19 @@ export function StructuralHeader({
342
356
  </>
343
357
  );
344
358
 
359
+ const withMeta = (
360
+ <>
361
+ {layout}
362
+ {metas}
363
+ </>
364
+ );
365
+
345
366
  return (
346
367
  <Root
347
368
  data-slot={`${slot}-header`}
348
369
  className={cn(
349
- contentClassName === undefined &&
370
+ metas.length === 0 &&
371
+ contentClassName === undefined &&
350
372
  leadingPlacement !== "inline" &&
351
373
  leading.length === 0 &&
352
374
  actionSlots.length > 0 &&
@@ -359,13 +381,13 @@ export function StructuralHeader({
359
381
  {...props}
360
382
  >
361
383
  {contentClassName === undefined ? (
362
- layout
384
+ withMeta
363
385
  ) : (
364
386
  <Wrapper
365
387
  data-slot={`${slot}-header-content`}
366
388
  className={contentClassName}
367
389
  >
368
- {layout}
390
+ {withMeta}
369
391
  </Wrapper>
370
392
  )}
371
393
  </Root>
@@ -42,6 +42,7 @@ import { headingTags, type HeadingLevel } from "./heading-level.ts";
42
42
  import { usePageHeadingPresence } from "./page-heading-context.tsx";
43
43
  import {
44
44
  StructuralHeader,
45
+ structuralMetaClasses,
45
46
  structuralHeaderClasses,
46
47
  } from "./structural-header.tsx";
47
48
  import {
@@ -113,6 +114,8 @@ interface SurfaceHeaderShorthandProps {
113
114
  count?: number;
114
115
  /** Forma curta: frase de apoio sob o título. */
115
116
  description?: ReactNode;
117
+ /** Forma curta: badges, datas e autoria sob a orientação. */
118
+ meta?: ReactNode;
116
119
  /** Forma curta: ações sobre a superfície inteira, no extremo oposto ao título. */
117
120
  actions?: ReactNode;
118
121
  }
@@ -124,6 +127,7 @@ interface SurfaceLegendShorthandProps {
124
127
  media?: ReactNode;
125
128
  count?: never;
126
129
  description?: never;
130
+ meta?: never;
127
131
  actions?: never;
128
132
  }
129
133
 
@@ -132,6 +136,7 @@ interface SurfaceNoShorthandProps {
132
136
  media?: never;
133
137
  count?: never;
134
138
  description?: never;
139
+ meta?: never;
135
140
  actions?: never;
136
141
  }
137
142
 
@@ -204,6 +209,7 @@ export function Surface({
204
209
  media,
205
210
  count,
206
211
  description,
212
+ meta,
207
213
  actions,
208
214
  className,
209
215
  children,
@@ -230,10 +236,11 @@ export function Surface({
230
236
  (hasMedia(media) ||
231
237
  count !== undefined ||
232
238
  description !== undefined ||
239
+ meta !== undefined ||
233
240
  actions !== undefined)
234
241
  ) {
235
242
  throw new Error(
236
- "Surface exige title para usar media, count, description ou actions.",
243
+ "Surface exige title para usar media, count, description, meta ou actions.",
237
244
  );
238
245
  }
239
246
  if (asChild && shorthand) {
@@ -303,10 +310,11 @@ export function Surface({
303
310
  <SurfaceHeader>
304
311
  {hasMedia(media) && <SurfaceMedia>{media}</SurfaceMedia>}
305
312
  <SurfaceTitle>{title}</SurfaceTitle>
306
- {count !== undefined && <SurfaceMeta>{count}</SurfaceMeta>}
313
+ {count !== undefined && <SurfaceCount>{count}</SurfaceCount>}
307
314
  {description !== undefined && (
308
315
  <SurfaceDescription>{description}</SurfaceDescription>
309
316
  )}
317
+ {meta !== undefined && <SurfaceMeta>{meta}</SurfaceMeta>}
310
318
  {actions !== undefined && <SurfaceActions>{actions}</SurfaceActions>}
311
319
  </SurfaceHeader>
312
320
  {regions > 0
@@ -370,7 +378,7 @@ export function Surface({
370
378
  export type SurfaceHeaderProps = Omit<HTMLAttributes<HTMLDivElement>, "title">;
371
379
 
372
380
  const legendInvalidMessage =
373
- "SurfaceHeader de fieldset aceita somente SurfaceMedia e SurfaceTitle; contador, descrição e ações ficam fora da legenda.";
381
+ "SurfaceHeader de fieldset aceita somente SurfaceMedia e SurfaceTitle; contador, descrição, metadados e ações ficam fora da legenda.";
374
382
 
375
383
  /**
376
384
  * Header da superfície; não existe fora dela. Monta a linha sozinho — mídia, título com
@@ -401,7 +409,8 @@ export function SurfaceHeader({
401
409
  : {
402
410
  media: SurfaceMedia,
403
411
  title: SurfaceTitle,
404
- count: SurfaceMeta,
412
+ count: SurfaceCount,
413
+ meta: SurfaceMeta,
405
414
  description: SurfaceDescription,
406
415
  actions: SurfaceActions,
407
416
  }
@@ -509,25 +518,44 @@ export function SurfaceDescription({
509
518
  );
510
519
  }
511
520
 
512
- /** Metadado ao lado do título — o slot do `count` da forma curta. */
513
- export function SurfaceMeta({
521
+ /** Contador ao lado do título — o slot do `count` da forma curta. */
522
+ export function SurfaceCount({
514
523
  className,
515
524
  ...props
516
525
  }: HTMLAttributes<HTMLSpanElement>): ReactElement {
517
526
  const surface = requiredContext(
518
527
  useContext(SurfaceHeaderContext),
519
- "SurfaceMeta",
528
+ "SurfaceCount",
520
529
  "SurfaceHeader",
521
530
  );
522
531
  return (
523
532
  <span
524
- data-slot="surface-meta"
533
+ data-slot="surface-count"
525
534
  className={cn(structuralHeaderClasses[surface.variant].count, className)}
526
535
  {...props}
527
536
  />
528
537
  );
529
538
  }
530
539
 
540
+ /** Badges, datas e autoria sob o título e a orientação da superfície. */
541
+ export function SurfaceMeta({
542
+ className,
543
+ ...props
544
+ }: HTMLAttributes<HTMLDivElement>): ReactElement {
545
+ requiredContext(
546
+ useContext(SurfaceHeaderContext),
547
+ "SurfaceMeta",
548
+ "SurfaceHeader",
549
+ );
550
+ return (
551
+ <div
552
+ data-slot="surface-meta"
553
+ className={cn(structuralMetaClasses, className)}
554
+ {...props}
555
+ />
556
+ );
557
+ }
558
+
531
559
  /** Ações do header — a família as posiciona no extremo oposto ao título. */
532
560
  export function SurfaceActions({
533
561
  className,
@@ -16,6 +16,7 @@ import { FillBoundary } from "../patterns/fill-region.ts";
16
16
  import { headingTags, type HeadingLevel } from "../patterns/heading-level.ts";
17
17
  import {
18
18
  StructuralHeader,
19
+ structuralMetaClasses,
19
20
  structuralHeaderClasses,
20
21
  validateSurfaceIntro,
21
22
  } from "../patterns/structural-header.tsx";
@@ -67,6 +68,7 @@ const DialogContentContext = React.createContext<DialogContentContextValue>({
67
68
  closeSize: "sm",
68
69
  });
69
70
 
71
+ const DialogMetaContext = React.createContext(false);
70
72
  const DialogIntroContext = React.createContext(false);
71
73
 
72
74
  /**
@@ -589,33 +591,36 @@ export function DialogHeader({
589
591
  }
590
592
 
591
593
  return (
592
- <StructuralHeader
593
- name="DialogHeader"
594
- slot="dialog"
595
- slots={{
596
- leading: DialogNavigation,
597
- media: DialogMedia,
598
- title: DialogTitle,
599
- description: DialogDescription,
600
- actions: DialogActions,
601
- }}
602
- leadingPlacement="inline"
603
- titleRequired={false}
604
- rowClassName={surfaceHeaderRowClasses("dialog")}
605
- className={cn(
606
- "text-left",
607
- surfaceRegionClasses("dialog", layout, "header"),
608
- className,
609
- )}
610
- trailing={
611
- showCloseButton ? (
612
- <DialogCloseButton disabled={closeDisabled} size={closeSize} />
613
- ) : undefined
614
- }
615
- {...props}
616
- >
617
- {children}
618
- </StructuralHeader>
594
+ <DialogMetaContext.Provider value>
595
+ <StructuralHeader
596
+ name="DialogHeader"
597
+ slot="dialog"
598
+ slots={{
599
+ leading: DialogNavigation,
600
+ media: DialogMedia,
601
+ title: DialogTitle,
602
+ description: DialogDescription,
603
+ meta: DialogMeta,
604
+ actions: DialogActions,
605
+ }}
606
+ leadingPlacement="inline"
607
+ titleRequired={false}
608
+ rowClassName={surfaceHeaderRowClasses("dialog")}
609
+ className={cn(
610
+ "text-left",
611
+ surfaceRegionClasses("dialog", layout, "header"),
612
+ className,
613
+ )}
614
+ trailing={
615
+ showCloseButton ? (
616
+ <DialogCloseButton disabled={closeDisabled} size={closeSize} />
617
+ ) : undefined
618
+ }
619
+ {...props}
620
+ >
621
+ {children}
622
+ </StructuralHeader>
623
+ </DialogMetaContext.Provider>
619
624
  );
620
625
  }
621
626
 
@@ -655,25 +660,52 @@ export function DialogIntro({
655
660
  }: React.ComponentProps<"div">) {
656
661
  return (
657
662
  <DialogIntroContext.Provider value>
658
- <StructuralHeader
659
- name="DialogIntro"
660
- slot="dialog-intro"
661
- slots={{
662
- title: DialogTitle,
663
- description: DialogDescription,
664
- actions: DialogIntroActions,
665
- }}
666
- leadingPlacement="inline"
667
- titleRequired
668
- className={cn("text-left", className)}
669
- {...props}
670
- >
671
- {children}
672
- </StructuralHeader>
663
+ <DialogMetaContext.Provider value>
664
+ <StructuralHeader
665
+ name="DialogIntro"
666
+ slot="dialog-intro"
667
+ slots={{
668
+ title: DialogTitle,
669
+ description: DialogDescription,
670
+ meta: DialogMeta,
671
+ actions: DialogIntroActions,
672
+ }}
673
+ leadingPlacement="inline"
674
+ titleRequired
675
+ className={cn("text-left", className)}
676
+ {...props}
677
+ >
678
+ {children}
679
+ </StructuralHeader>
680
+ </DialogMetaContext.Provider>
673
681
  </DialogIntroContext.Provider>
674
682
  );
675
683
  }
676
684
 
685
+ /** Badges, datas e autoria abaixo do título e da orientação. */
686
+ export function DialogMeta({
687
+ className,
688
+ ...props
689
+ }: React.ComponentProps<"div">) {
690
+ const { mode } = useDialogContext();
691
+ const inside = React.useContext(DialogMetaContext);
692
+ if (mode === "alert")
693
+ throw new Error(
694
+ 'DialogMeta não está disponível em Dialog com mode="alert"; coloque as informações no corpo do alerta.',
695
+ );
696
+ if (!inside)
697
+ throw new Error(
698
+ "DialogMeta deve estar dentro de DialogHeader ou DialogIntro.",
699
+ );
700
+ return (
701
+ <div
702
+ data-slot="dialog-meta"
703
+ className={cn(structuralMetaClasses, className)}
704
+ {...props}
705
+ />
706
+ );
707
+ }
708
+
677
709
  /** Ações relacionadas ao título do conteúdo, separadas das ações de chrome do header. */
678
710
  export function DialogIntroActions({
679
711
  className,
@@ -15,6 +15,7 @@ import {
15
15
  import { headingTags, type HeadingLevel } from "../patterns/heading-level.ts";
16
16
  import {
17
17
  StructuralHeader,
18
+ structuralMetaClasses,
18
19
  structuralHeaderClasses,
19
20
  validateSurfaceIntro,
20
21
  } from "../patterns/structural-header.tsx";
@@ -50,6 +51,7 @@ const DrawerContentContext = React.createContext<DrawerContentContextValue>({
50
51
  closeSize: "sm",
51
52
  });
52
53
 
54
+ const DrawerMetaContext = React.createContext(false);
53
55
  const DrawerIntroContext = React.createContext(false);
54
56
 
55
57
  /** Estado de aberto que a pilha de modais da camada flutuante acompanha (ADR 0052). */
@@ -257,33 +259,36 @@ function DrawerHeader({
257
259
  const { showCloseButton, closeDisabled, closeSize } =
258
260
  React.useContext(DrawerContentContext);
259
261
  return (
260
- <StructuralHeader
261
- name="DrawerHeader"
262
- slot="drawer"
263
- slots={{
264
- leading: DrawerNavigation,
265
- media: DrawerMedia,
266
- title: DrawerTitle,
267
- description: DrawerDescription,
268
- actions: DrawerActions,
269
- }}
270
- leadingPlacement="inline"
271
- titleRequired={false}
272
- rowClassName={surfaceHeaderRowClasses("drawer")}
273
- className={cn(
274
- "text-left",
275
- surfaceRegionClasses("drawer", layout, "header"),
276
- className,
277
- )}
278
- trailing={
279
- showCloseButton ? (
280
- <DrawerCloseButton disabled={closeDisabled} size={closeSize} />
281
- ) : undefined
282
- }
283
- {...props}
284
- >
285
- {children}
286
- </StructuralHeader>
262
+ <DrawerMetaContext.Provider value>
263
+ <StructuralHeader
264
+ name="DrawerHeader"
265
+ slot="drawer"
266
+ slots={{
267
+ leading: DrawerNavigation,
268
+ media: DrawerMedia,
269
+ title: DrawerTitle,
270
+ description: DrawerDescription,
271
+ meta: DrawerMeta,
272
+ actions: DrawerActions,
273
+ }}
274
+ leadingPlacement="inline"
275
+ titleRequired={false}
276
+ rowClassName={surfaceHeaderRowClasses("drawer")}
277
+ className={cn(
278
+ "text-left",
279
+ surfaceRegionClasses("drawer", layout, "header"),
280
+ className,
281
+ )}
282
+ trailing={
283
+ showCloseButton ? (
284
+ <DrawerCloseButton disabled={closeDisabled} size={closeSize} />
285
+ ) : undefined
286
+ }
287
+ {...props}
288
+ >
289
+ {children}
290
+ </StructuralHeader>
291
+ </DrawerMetaContext.Provider>
287
292
  );
288
293
  }
289
294
 
@@ -325,25 +330,47 @@ function DrawerIntro({
325
330
  }: React.ComponentProps<"div">) {
326
331
  return (
327
332
  <DrawerIntroContext.Provider value>
328
- <StructuralHeader
329
- name="DrawerIntro"
330
- slot="drawer-intro"
331
- slots={{
332
- title: DrawerTitle,
333
- description: DrawerDescription,
334
- actions: DrawerIntroActions,
335
- }}
336
- leadingPlacement="inline"
337
- titleRequired
338
- className={cn("text-left", className)}
339
- {...props}
340
- >
341
- {children}
342
- </StructuralHeader>
333
+ <DrawerMetaContext.Provider value>
334
+ <StructuralHeader
335
+ name="DrawerIntro"
336
+ slot="drawer-intro"
337
+ slots={{
338
+ title: DrawerTitle,
339
+ description: DrawerDescription,
340
+ meta: DrawerMeta,
341
+ actions: DrawerIntroActions,
342
+ }}
343
+ leadingPlacement="inline"
344
+ titleRequired
345
+ className={cn("text-left", className)}
346
+ {...props}
347
+ >
348
+ {children}
349
+ </StructuralHeader>
350
+ </DrawerMetaContext.Provider>
343
351
  </DrawerIntroContext.Provider>
344
352
  );
345
353
  }
346
354
 
355
+ /** Badges, datas e autoria abaixo do título e da orientação. */
356
+ export function DrawerMeta({
357
+ className,
358
+ ...props
359
+ }: React.ComponentProps<"div">) {
360
+ const inside = React.useContext(DrawerMetaContext);
361
+ if (!inside)
362
+ throw new Error(
363
+ "DrawerMeta deve estar dentro de DrawerHeader ou DrawerIntro.",
364
+ );
365
+ return (
366
+ <div
367
+ data-slot="drawer-meta"
368
+ className={cn(structuralMetaClasses, className)}
369
+ {...props}
370
+ />
371
+ );
372
+ }
373
+
347
374
  /** Ações relacionadas ao título do conteúdo, separadas das ações de chrome do header. */
348
375
  function DrawerIntroActions({
349
376
  className,
@@ -24,7 +24,7 @@ function Table({
24
24
  data-slot="table-container"
25
25
  data-variant={variant}
26
26
  className={cn(
27
- "relative w-full overflow-x-auto",
27
+ "relative w-full min-w-0 max-w-full overflow-x-auto",
28
28
  variant === "framed" && "rounded-lg border border-border",
29
29
  containerClassName,
30
30
  )}
@@ -95,7 +95,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
95
95
  <th
96
96
  data-slot="table-head"
97
97
  className={cn(
98
- "h-10 px-3 text-left align-middle font-medium whitespace-nowrap text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[0.125rem]",
98
+ "h-10 px-3 text-left align-middle font-medium whitespace-normal text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[0.125rem]",
99
99
  className,
100
100
  )}
101
101
  {...props}
@@ -108,7 +108,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
108
108
  <td
109
109
  data-slot="table-cell"
110
110
  className={cn(
111
- "px-3 py-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[0.125rem]",
111
+ "px-3 py-2 align-middle whitespace-normal wrap-break-word [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[0.125rem]",
112
112
  className,
113
113
  )}
114
114
  {...props}
@@ -10,13 +10,20 @@ limites visuais da coleção; use [`Table`](/ui/table) diretamente quando a comp
10
10
  variante `framed`. Carregamento, erro e vazio usam o mesmo [`DataState`](/ui/data-state) das
11
11
  demais coleções.
12
12
 
13
- A barra mantém em uma única linha os controles declarados como `inline`: ela não quebra e não move
14
- filtros para o modal por falta de espaço. Seletores de valor único acompanham o valor escolhido até
15
- `20rem` e truncam o excedente; a busca varia entre `8rem` e `16rem` conforme a largura
16
- disponível. Quando a barra ficar longa demais, declare como `advanced` os filtros que não precisam
17
- ficar sempre à vista, como descreve a seção “Onde cada filtro aparece”. Recarregar e
18
- exibição formam um `ButtonGroup` espaçado; `toolbarActions` acrescenta, depois deles, operações
19
- ligadas ao recorte atual.
13
+ A tabela usa a largura disponível e permite quebra em células textuais. Colunas com `fit`
14
+ preservam valores compactos sem quebra. A largura das colunas de dados considera cabeçalhos e
15
+ valores, sem comprimir todas as colunas `fit` para ampliar a primeira. Os cabeçalhos quebram
16
+ quando falta espaço; seleção, ações de linha e células contendo apenas um switch
17
+ (direto ou envolvido por TooltipTrigger) mantêm a largura compacta.
18
+ Se identificadores sem espaços ou larguras mínimas explícitas excederem o espaço, a rolagem
19
+ fica nos resultados, sem alargar a toolbar ou o rodapé. Em `layout="fill"`, o cabeçalho continua fixo nessa região.
20
+
21
+ A barra distribui os controles `inline` em mais de uma linha quando necessário, preservando sua
22
+ ordem. Ela não move filtros automaticamente para o modal. Seletores de valor único acompanham o
23
+ valor escolhido até `20rem` e truncam o excedente; a busca varia entre `8rem` e `16rem`.
24
+ Declare como `advanced` os filtros que não precisam ficar sempre à vista, como descreve a seção
25
+ “Onde cada filtro aparece”. Recarregar e exibição formam um `ButtonGroup` espaçado;
26
+ `toolbarActions` acrescenta, depois deles, operações ligadas ao recorte atual.
20
27
 
21
28
  ```tsx preview col
22
29
  render(
@@ -460,6 +460,32 @@ botão. O texto informa o efeito real, como `Excluir`, `Revogar acesso` ou `Arqu
460
460
  age onde a pessoa está. O modo `alert` cobre a camada até a resposta.
461
461
  - `DialogHost` apresenta uma solicitação por vez para que cada resposta tenha um alvo inequívoco.
462
462
 
463
+ ## Metadados junto à identidade
464
+
465
+ Use `DialogMeta` para badges, autoria e datas relacionados ao registro. A faixa fica
466
+ abaixo da linha de título e ações, com espaço próprio; `DialogDescription` continua
467
+ reservado à orientação textual breve. Os itens quebram em várias linhas quando necessário.
468
+
469
+ ```tsx
470
+ <Dialog defaultOpen>
471
+ <DialogContent>
472
+ <DialogHeader />
473
+ <DialogBody>
474
+ <DialogIntro>
475
+ <DialogTitle>Manual de atendimento</DialogTitle>
476
+ <DialogDescription>Orientações para a equipe.</DialogDescription>
477
+ <DialogMeta><Badge>Publicado</Badge><span>Por Ana</span></DialogMeta>
478
+ </DialogIntro>
479
+ <p>Conteúdo do manual.</p>
480
+ </DialogBody>
481
+ </DialogContent>
482
+ </Dialog>
483
+ ```
484
+
485
+ A composição aceita um único `DialogMeta` e exige um `DialogTitle`. Na forma explícita, coloque-o em `DialogIntro` ou no `DialogHeader` compacto. Não coloque o slot solto no corpo.
486
+
487
+ O modo `alert` conserva sua composição especializada e não recebe `DialogMeta`.
488
+
463
489
  ## Propriedades de Dialog
464
490
 
465
491
  | Propriedade | Tipo | Padrão | Descrição |
@@ -668,3 +694,16 @@ Use `flush` quando o conteúdo controlar seus próprios recuos.
668
694
 
669
695
  Na intro, `DialogTitle` usa a mesma escala de `PageTitle` (`1.875rem`). No header
670
696
  compacto, o título conserva a escala de `1.125rem`. O nível semântico não altera essas medidas.
697
+
698
+ ## Propriedades de DialogMeta
699
+
700
+ | Propriedade | Tipo | Descrição |
701
+ | --- | --- | --- |
702
+ | `children` | `ReactNode` | Badges, datas, autoria ou outros metadados do registro. |
703
+ | `className` | `string` | Ajusta a faixa de metadados. |
704
+
705
+ Aceita atributos nativos de `div`. O intervalo superior é de 0,75rem; os itens têm
706
+ 0,75rem entre colunas e 0,5rem entre linhas. O componente não insere separadores nem
707
+ carrega dados. Omitir o slot não reserva espaço. Metadados não substituem orientações
708
+ ou condições necessárias à decisão e não são anunciados como descrição do modal.
709
+ `DialogMeta` não se aplica a `mode="alert"`; informações necessárias à resposta ficam no corpo do alerta.