| 1 | import type { ReactNode } from "react"; |
| 2 | import { Tooltip } from "./Tooltip"; |
| 3 | |
| 4 | export function SettingsSection({ |
| 5 | title, |
| 6 | className, |
| 7 | description, |
| 8 | actions, |
| 9 | children, |
| 10 | }: { |
| 11 | title?: ReactNode; |
| 12 | className?: string; |
| 13 | description?: ReactNode; |
| 14 | actions?: ReactNode; |
| 15 | children: ReactNode; |
| 16 | }) { |
| 17 | const hasHead = Boolean(title || description || actions); |
| 18 | return ( |
| 19 | <section className={`settings-section${className ? ` ${className}` : ""}`}> |
| 20 | {hasHead && ( |
| 21 | <div className="settings-section__head"> |
| 22 | <div> |
| 23 | {title && <div className="settings-section__title">{title}</div>} |
| 24 | {description && ( |
| 25 | <div className="settings-section__desc"> |
| 26 | <SettingsHint hint={description} /> |
| 27 | </div> |
| 28 | )} |
| 29 | </div> |
| 30 | {actions && <div className="settings-section__actions">{actions}</div>} |
| 31 | </div> |
| 32 | )} |
| 33 | <div className="settings-section__body">{children}</div> |
| 34 | </section> |
| 35 | ); |
| 36 | } |
| 37 | |
| 38 | export function SettingsField({ |
| 39 | label, |
| 40 | hint, |
| 41 | icon, |
| 42 | children, |
| 43 | className, |
| 44 | stacked = false, |
| 45 | }: { |
| 46 | label: ReactNode; |
| 47 | hint?: ReactNode; |
| 48 | icon?: ReactNode; |
| 49 | children: ReactNode; |
| 50 | className?: string; |
| 51 | stacked?: boolean; |
| 52 | }) { |
| 53 | return ( |
| 54 | <div className={`settings-field${stacked ? " settings-field--stacked" : ""}${className ? ` ${className}` : ""}`}> |
| 55 | <div className={`settings-field__copy${icon ? " settings-field__copy--icon" : ""}`}> |
| 56 | {icon && <span className="settings-field__icon" aria-hidden="true">{icon}</span>} |
| 57 | <div className="settings-field__copy-body"> |
| 58 | <div className="settings-field__label">{label}</div> |
| 59 | {hint && ( |
| 60 | <div className="settings-field__hint"> |
| 61 | <SettingsHint hint={hint} /> |
| 62 | </div> |
| 63 | )} |
| 64 | </div> |
| 65 | </div> |
| 66 | <div className="settings-field__control">{children}</div> |
| 67 | </div> |
| 68 | ); |
| 69 | } |
| 70 | |
| 71 | function SettingsHint({ hint }: { hint: ReactNode }) { |
| 72 | if (typeof hint === "string" || typeof hint === "number") { |
| 73 | const label = String(hint); |
| 74 | return ( |
| 75 | <Tooltip label={label} fill block className="settings-field__hint-tooltip"> |
| 76 | <span className="settings-field__hint-line">{label}</span> |
| 77 | </Tooltip> |
| 78 | ); |
| 79 | } |
| 80 | return hint; |
| 81 | } |
| 82 |