defuss-shadcn / Website / Comments / comment-form
Comment FormBLK
Collects a new comment or reply - a growing Textarea beside the avatar, guest name and email fields, native validation, a compact reply form. Part of the Comments blocks.
On this page (7)
§Default
The avatar beside a Textarea that grows with its text (field-sizing: content), a hint and the submit Button. Native validation: required + minlength - submit empty and the browser says so.
§Guest
No avatar - the form takes the full width (:has()). Name and email Inputs for guests sit above the textarea; type=email validates natively.
§Reply
data-variant='reply': compact, under a comment - a small avatar and a cancel button.
§Write and preview
data-variant='framed': one box with Tabs (Write / Preview), a formatting Toggle Group, a Separator and a link Button, the growing textarea and a footer with a Kbd shortcut hint.
§Signed out
No form for guests - an Alert with the actions in its place.
§Review with a rating
A review form: the Rating component (native radios) above the growing textarea - required, so posting without stars is blocked by the browser.
§CSS view file
/* -- Comment Form (website) ----------------------------------------- Collects a new comment or a reply: the writer's avatar beside a Textarea that grows with its text (field-sizing), optional name / email fields for guests, a hint and the submit Button. Native validation (required, minlength) - :user-invalid marks the field only after an attempt. */@layer components { .mk-comment-form { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.75rem; box-sizing: border-box; width: 100%; margin: 0; & > .avatar { margin-block-start: 0.25rem; } /* without an avatar the form takes the full row */ &:not(:has(> .avatar)) { grid-template-columns: minmax(0, 1fr); } } .mk-comment-form-main { display: flex; flex-direction: column; gap: 0.625rem; min-width: 0; & .textarea { field-sizing: content; min-height: 5.5rem; max-height: 20rem; resize: none; } } /* guest fields: name + email side by side */ .mk-comment-form-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 0.625rem; & > div { display: flex; flex-direction: column; gap: 0.375rem; } } .mk-comment-form-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0.5rem; } .mk-comment-form-hint { margin: 0 auto 0 0; color: var(--muted-foreground); font-size: 0.75rem; } /* a formatting row above the text (a Toggle Group, a Separator, Buttons) */ .mk-comment-form-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem; } /* framed: toolbar, text and footer in one bordered box - the textarea loses its own border, the box takes the focus ring */ .mk-comment-form[data-variant="framed"] .mk-comment-form-main { gap: 0; overflow: hidden; border: 1px solid var(--input); border-radius: var(--radius-lg); background: var(--background); transition: border-color 120ms, box-shadow 120ms; &:focus-within { border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring) 25%, transparent); } & .mk-comment-form-toolbar { padding: 0.375rem; border-block-end: 1px solid var(--border); background: color-mix(in oklch, var(--muted) 50%, transparent); } & .textarea { border: 0; border-radius: 0; box-shadow: none; outline: none; background: transparent; } & .mk-comment-form-footer { padding: 0.5rem 0.625rem; border-block-start: 1px solid var(--border); } & .tabs { gap: 0; } & .tab-content { padding: 0; } } /* reply: compact, under a comment */ .mk-comment-form[data-variant="reply"] { gap: 0.5rem; & .mk-comment-form-main .textarea { min-height: 3.5rem; font-size: 0.875rem; } } /* -- Accessibility ------------------------------------------- */ @media (prefers-reduced-motion: reduce) { .mk-comment-form[data-variant="framed"] .mk-comment-form-main { transition: none; } } @media (prefers-contrast: more) { .mk-comment-form-hint { color: var(--foreground); } } @media (forced-colors: active) { .mk-comment-form-main .textarea { border: 1px solid CanvasText; } }}Comments, ideas or improvements? Edit this page's source on GitHub