work-in-progress atproto PDS
typescript atproto pds atcute
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: clean up dialog styling

mary.my.id 2a33763f e2cef19c

verified
+109 -180
+8 -27
packages/danaus/src/web/primitives/dialog-actions.tsx
··· 3 3 4 4 const root = cva({ 5 5 base: [ 6 - 'box-border pt-2', 7 - 'h-fit', 8 - // grid position: row 3 9 - 'row-start-3 row-end-3', 10 - // mobile-first: stacked on mobile, inline on larger 11 - 'flex flex-col gap-2 justify-self-stretch', 12 - 'sm:flex-row sm:justify-self-auto', 6 + 'pt-2', 7 + // stacked on small containers, inline row on larger 8 + 'flex flex-col gap-2', 9 + '@sm/dialog-body:flex-row @sm/dialog-body:items-center', 13 10 ], 14 11 variants: { 15 12 position: { 16 - start: ['col-start-1 col-end-4 row-start-3', 'sm:col-end-2 sm:justify-self-start'], 17 - end: ['col-start-1 col-end-4 row-start-4', 'sm:col-start-2 sm:row-start-3 sm:justify-self-end'], 18 - }, 19 - fluid: { 20 - true: [], 13 + start: '@sm/dialog-body:justify-start', 14 + end: '@sm/dialog-body:justify-end', 21 15 }, 22 16 }, 23 - compoundVariants: [ 24 - { 25 - position: 'start', 26 - fluid: true, 27 - class: 'sm:col-end-4', 28 - }, 29 - { 30 - position: 'end', 31 - fluid: true, 32 - class: 'sm:col-start-1', 33 - }, 34 - ], 35 17 }); 36 18 37 19 export interface DialogActionsProps extends VariantProps<typeof root> { ··· 42 24 /** 43 25 * footer container for dialog action buttons 44 26 * @param props.position alignment of actions ('start' or 'end') 45 - * @param props.fluid whether actions should span full width 46 27 * @param props.class additional CSS classes 47 28 */ 48 29 const DialogActions = (props: DialogActionsProps) => { 49 - const { position = 'end', fluid = false, class: className, children } = props; 30 + const { position = 'end', class: className, children } = props; 50 31 51 - return <div class={root({ position, fluid, className })}>{children}</div>; 32 + return <div class={root({ position, className })}>{children}</div>; 52 33 }; 53 34 54 35 export default DialogActions;
+1 -7
packages/danaus/src/web/primitives/dialog-body.tsx
··· 2 2 import type { Child } from 'hono/jsx'; 3 3 4 4 const root = cva({ 5 - base: [ 6 - 'box-border', 7 - 'grid gap-2', 8 - 'grid-cols-[1fr_1fr_auto]', 9 - // mobile-first: extra row for stacked actions 10 - 'grid-rows-[auto_1fr_auto_auto] sm:grid-rows-[auto_1fr_auto]', 11 - ], 5 + base: ['grid gap-2', '@container/dialog-body'], 12 6 }); 13 7 14 8 export interface DialogBodyProps {
+1 -6
packages/danaus/src/web/primitives/dialog-content.tsx
··· 2 2 import type { Child } from 'hono/jsx'; 3 3 4 4 const root = cva({ 5 - base: [ 6 - // grid position: row 2, col 1-3 7 - 'col-start-1 col-end-4 row-start-2 row-end-2', 8 - 'overflow-y-auto', 9 - 'text-base-300', 10 - ], 5 + base: ['min-h-8 overflow-y-auto', 'text-base-300'], 11 6 }); 12 7 13 8 export interface DialogContentProps {
+18 -10
packages/danaus/src/web/primitives/dialog-surface.tsx
··· 1 - import { cva } from 'cva'; 1 + import { cva, type VariantProps } from 'cva'; 2 2 import type { Child } from 'hono/jsx'; 3 3 4 4 import { useDialogContext } from './utils/dialog-context'; ··· 9 9 'border-none p-0', 10 10 'bg-transparent', 11 11 'overflow-visible', 12 - // reset dialog defaults 13 - 'open:flex open:items-center open:justify-center', 12 + 'open:flex', 13 + // bottom-aligned on mobile, centered on larger screens 14 + 'items-end justify-center', 15 + 'sm:items-center', 14 16 // backdrop 15 17 'backdrop:bg-background-overlay', 16 18 ], ··· 24 26 base: [ 25 27 'relative z-10', 26 28 'box-border', 29 + 'w-full', 27 30 'max-h-[calc(100dvh-48px)]', 28 31 'p-6', 29 - 'rounded-xl', 32 + // rounded top on mobile, all corners on larger screens 33 + 'rounded-t-xl sm:rounded-xl', 30 34 'bg-neutral-background-1 text-neutral-foreground-1', 31 35 'shadow-64', 32 - // mobile-first: full width on mobile, constrained on larger 33 - 'max-w-full sm:max-w-150', 34 36 ], 37 + variants: { 38 + size: { 39 + small: 'max-w-120', 40 + medium: 'max-w-150', 41 + }, 42 + }, 35 43 }); 36 44 37 - export interface DialogSurfaceProps { 45 + export interface DialogSurfaceProps extends VariantProps<typeof surface> { 38 46 children?: Child; 39 47 } 40 48 41 49 /** 42 50 * visual container for dialog content 43 - * @param props.class additional CSS classes 51 + * @param props.size dialog width ('small' or 'medium') 44 52 */ 45 53 const DialogSurface = (props: DialogSurfaceProps) => { 46 - const { children } = props; 54 + const { size = 'small', children } = props; 47 55 48 56 const { dialogId, titleId } = useDialogContext(); 49 57 50 58 return ( 51 59 <dialog id={dialogId} aria-labelledby={titleId} class={root()}> 52 - <div class={surface()}>{children}</div> 60 + <div class={surface({ size })}>{children}</div> 53 61 54 62 <button 55 63 type="button"
+5 -20
packages/danaus/src/web/primitives/dialog-title.tsx
··· 4 4 import { useDialogContext } from './utils/dialog-context.tsx'; 5 5 6 6 const root = cva({ 7 - base: [ 8 - 'm-0 pb-2', 9 - 'text-base-500 font-semibold', 10 - // grid position: row 1, col 1-2 (leaves col 3 for action) 11 - 'col-start-1 col-end-3 row-start-1 row-end-1', 12 - ], 13 - variants: { 14 - hasAction: { 15 - false: 'col-end-4', 16 - }, 17 - }, 7 + base: ['m-0 flex items-start gap-2', 'text-base-500 font-semibold'], 18 8 }); 19 9 20 10 const action = cva({ 21 - base: [ 22 - // grid position: row 1, col 3 23 - 'col-start-3 row-start-1 row-end-1', 24 - 'self-start justify-self-end', 25 - ], 11 + base: ['ml-auto shrink-0'], 26 12 }); 27 13 28 14 export interface DialogTitleProps { ··· 41 27 const { action: actionSlot, class: className, children } = props; 42 28 43 29 const context = useDialogContext(null); 44 - const hasAction = actionSlot !== undefined; 45 30 46 31 return ( 47 - <> 48 - <h2 id={context?.titleId} class={root({ hasAction, className })}> 32 + <div class={root({ className })}> 33 + <h2 id={context?.titleId} class="m-0 grow"> 49 34 {children} 50 35 </h2> 51 36 52 37 {actionSlot && <div class={action()}>{actionSlot}</div>} 53 - </> 38 + </div> 54 39 ); 55 40 }; 56 41
+11 -4
packages/danaus/src/web/styles/main.css
··· 289 289 } 290 290 } 291 291 292 - :where(body) { 293 - background: var(--color-neutral-background-2); 294 - color: var(--color-neutral-foreground-1); 295 - color-scheme: light dark; 292 + @layer base { 293 + :where(body) { 294 + background: var(--color-neutral-background-2); 295 + color: var(--color-neutral-foreground-1); 296 + color-scheme: light dark; 297 + } 298 + 299 + /* prevent body scroll when modal dialog is open */ 300 + :where(body:has(dialog:modal)) { 301 + overflow: hidden; 302 + } 296 303 } 297 304 298 305 /* #region anchor positioning */
+65 -106
packages/danaus/src/web/styles/main.out.css
··· 238 238 } 239 239 } 240 240 @layer utilities { 241 + .\@container\/dialog-body { 242 + container-type: inline-size; 243 + container-name: dialog-body; 244 + } 241 245 .pointer-events-none { 242 246 pointer-events: none; 243 247 } ··· 291 295 .z-10 { 292 296 z-index: 10; 293 297 } 294 - .col-start-1 { 295 - grid-column-start: 1; 296 - } 297 - .col-start-3 { 298 - grid-column-start: 3; 299 - } 300 - .col-end-3 { 301 - grid-column-end: 3; 302 - } 303 - .col-end-4 { 304 - grid-column-end: 4; 305 - } 306 - .row-start-1 { 307 - grid-row-start: 1; 308 - } 309 - .row-start-2 { 310 - grid-row-start: 2; 311 - } 312 - .row-start-3 { 313 - grid-row-start: 3; 314 - } 315 - .row-start-4 { 316 - grid-row-start: 4; 317 - } 318 - .row-end-1 { 319 - grid-row-end: 1; 320 - } 321 - .row-end-2 { 322 - grid-row-end: 2; 323 - } 324 - .row-end-3 { 325 - grid-row-end: 3; 326 - } 327 298 .container { 328 299 width: 100%; 329 300 @media (width >= 40rem) { ··· 378 349 .ml-2 { 379 350 margin-left: calc(var(--spacing) * 2); 380 351 } 352 + .ml-auto { 353 + margin-left: auto; 354 + } 381 355 .box-border { 382 356 box-sizing: border-box; 383 357 } ··· 426 400 } 427 401 .h-dvh { 428 402 height: 100dvh; 429 - } 430 - .h-fit { 431 - height: fit-content; 432 403 } 433 404 .h-full { 434 405 height: 100%; ··· 439 410 .max-h-dvh { 440 411 max-height: 100dvh; 441 412 } 413 + .min-h-8 { 414 + min-height: calc(var(--spacing) * 8); 415 + } 442 416 .min-h-9 { 443 417 min-height: calc(var(--spacing) * 9); 444 418 } ··· 481 455 .max-w-96 { 482 456 max-width: calc(var(--spacing) * 96); 483 457 } 458 + .max-w-120 { 459 + max-width: calc(var(--spacing) * 120); 460 + } 461 + .max-w-150 { 462 + max-width: calc(var(--spacing) * 150); 463 + } 484 464 .max-w-dvw { 485 465 max-width: 100dvw; 486 466 } 487 467 .max-w-fit { 488 468 max-width: fit-content; 489 - } 490 - .max-w-full { 491 - max-width: 100%; 492 469 } 493 470 .min-w-0 { 494 471 min-width: calc(var(--spacing) * 0); ··· 517 494 .grid-cols-2 { 518 495 grid-template-columns: repeat(2, minmax(0, 1fr)); 519 496 } 520 - .grid-cols-\[1fr_1fr_auto\] { 521 - grid-template-columns: 1fr 1fr auto; 522 - } 523 497 .grid-cols-\[auto_1fr_auto\] { 524 498 grid-template-columns: auto 1fr auto; 525 499 } 526 500 .grid-cols-\[auto_1fr_auto_auto\] { 527 501 grid-template-columns: auto 1fr auto auto; 528 502 } 529 - .grid-rows-\[auto_1fr_auto_auto\] { 530 - grid-template-rows: auto 1fr auto auto; 531 - } 532 503 .flex-col { 533 504 flex-direction: column; 534 505 } ··· 540 511 } 541 512 .items-center { 542 513 align-items: center; 514 + } 515 + .items-end { 516 + align-items: flex-end; 543 517 } 544 518 .items-start { 545 519 align-items: flex-start; ··· 597 571 .self-start { 598 572 align-self: flex-start; 599 573 } 600 - .justify-self-end { 601 - justify-self: flex-end; 602 - } 603 - .justify-self-stretch { 604 - justify-self: stretch; 605 - } 606 574 .truncate { 607 575 overflow: hidden; 608 576 text-overflow: ellipsis; ··· 634 602 } 635 603 .rounded-xl { 636 604 border-radius: 8px; 605 + } 606 + .rounded-t-xl { 607 + border-top-left-radius: 8px; 608 + border-top-right-radius: 8px; 637 609 } 638 610 .border { 639 611 border-style: var(--tw-border-style); ··· 1135 1107 display: flex; 1136 1108 } 1137 1109 } 1138 - .open\:items-center { 1110 + .open\:items-end { 1139 1111 &:is([open], :popover-open, :open) { 1140 - align-items: center; 1112 + align-items: flex-end; 1141 1113 } 1142 1114 } 1143 1115 .open\:justify-center { ··· 1363 1335 color: var(--color-neutral-foreground-disabled); 1364 1336 } 1365 1337 } 1366 - .sm\:col-start-1 { 1367 - @media (width >= 40rem) { 1368 - grid-column-start: 1; 1369 - } 1370 - } 1371 - .sm\:col-start-2 { 1372 - @media (width >= 40rem) { 1373 - grid-column-start: 2; 1374 - } 1375 - } 1376 - .sm\:col-end-2 { 1377 - @media (width >= 40rem) { 1378 - grid-column-end: 2; 1379 - } 1380 - } 1381 - .sm\:col-end-4 { 1382 - @media (width >= 40rem) { 1383 - grid-column-end: 4; 1384 - } 1385 - } 1386 - .sm\:row-start-3 { 1387 - @media (width >= 40rem) { 1388 - grid-row-start: 3; 1389 - } 1390 - } 1391 1338 .sm\:ml-0 { 1392 1339 @media (width >= 40rem) { 1393 1340 margin-left: calc(var(--spacing) * 0); ··· 1398 1345 display: none; 1399 1346 } 1400 1347 } 1401 - .sm\:max-w-150 { 1402 - @media (width >= 40rem) { 1403 - max-width: calc(var(--spacing) * 150); 1404 - } 1405 - } 1406 1348 .sm\:grid-cols-3 { 1407 1349 @media (width >= 40rem) { 1408 1350 grid-template-columns: repeat(3, minmax(0, 1fr)); ··· 1413 1355 grid-template-columns: repeat(4, minmax(0, 1fr)); 1414 1356 } 1415 1357 } 1416 - .sm\:grid-rows-\[auto_1fr_auto\] { 1417 - @media (width >= 40rem) { 1418 - grid-template-rows: auto 1fr auto; 1419 - } 1420 - } 1421 - .sm\:flex-row { 1422 - @media (width >= 40rem) { 1423 - flex-direction: row; 1424 - } 1425 - } 1426 - .sm\:justify-self-auto { 1427 - @media (width >= 40rem) { 1428 - justify-self: auto; 1429 - } 1430 - } 1431 - .sm\:justify-self-end { 1358 + .sm\:items-center { 1432 1359 @media (width >= 40rem) { 1433 - justify-self: flex-end; 1360 + align-items: center; 1434 1361 } 1435 1362 } 1436 - .sm\:justify-self-start { 1363 + .sm\:rounded-xl { 1437 1364 @media (width >= 40rem) { 1438 - justify-self: flex-start; 1365 + border-radius: 8px; 1439 1366 } 1440 1367 } 1441 1368 .sm\:p-16 { ··· 1448 1375 padding-top: calc(var(--spacing) * 24); 1449 1376 } 1450 1377 } 1378 + .open\:sm\:items-center { 1379 + &:is([open], :popover-open, :open) { 1380 + @media (width >= 40rem) { 1381 + align-items: center; 1382 + } 1383 + } 1384 + } 1451 1385 .lg\:grid { 1452 1386 @media (width >= 64rem) { 1453 1387 display: grid; ··· 1466 1400 .lg\:justify-center { 1467 1401 @media (width >= 64rem) { 1468 1402 justify-content: center; 1403 + } 1404 + } 1405 + .\@sm\/dialog-body\:flex-row { 1406 + @container dialog-body (width >= 24rem) { 1407 + flex-direction: row; 1408 + } 1409 + } 1410 + .\@sm\/dialog-body\:items-center { 1411 + @container dialog-body (width >= 24rem) { 1412 + align-items: center; 1413 + } 1414 + } 1415 + .\@sm\/dialog-body\:justify-end { 1416 + @container dialog-body (width >= 24rem) { 1417 + justify-content: flex-end; 1418 + } 1419 + } 1420 + .\@sm\/dialog-body\:justify-start { 1421 + @container dialog-body (width >= 24rem) { 1422 + justify-content: flex-start; 1469 1423 } 1470 1424 } 1471 1425 } ··· 1633 1587 --shadow-64: 0 0 8px rgba(0, 0, 0, 0.24), 0 32px 64px rgba(0, 0, 0, 0.28); 1634 1588 } 1635 1589 } 1636 - :where(body) { 1637 - background: var(--color-neutral-background-2); 1638 - color: var(--color-neutral-foreground-1); 1639 - color-scheme: light dark; 1590 + @layer base { 1591 + :where(body) { 1592 + background: var(--color-neutral-background-2); 1593 + color: var(--color-neutral-foreground-1); 1594 + color-scheme: light dark; 1595 + } 1596 + :where(body:has(dialog:modal)) { 1597 + overflow: hidden; 1598 + } 1640 1599 } 1641 1600 @property --tw-divide-y-reverse { 1642 1601 syntax: "*";