diff --git a/src/components/Layer.tsx b/src/components/Layer.tsx index da4c3aa3..14178590 100644 --- a/src/components/Layer.tsx +++ b/src/components/Layer.tsx @@ -1,5 +1,10 @@ +// this is deprecated and only still used internally for the Toast component (since it's probably more work than it's worth to migrate) +// anything else that needs similar functionality should use a ModalWrapper +import { type UseTransitionProps, useTransition } from '@react-spring/web' import { useOutsideClick } from 'honorable' +import { isNil } from 'lodash-es' import { + type ComponentProps, type MutableRefObject, type PropsWithChildren, forwardRef, @@ -9,8 +14,6 @@ import { useState, } from 'react' import { createPortal } from 'react-dom' -import { type UseTransitionProps, useTransition } from '@react-spring/web' -import { isNil } from 'lodash-es' import styled, { useTheme } from 'styled-components' import usePrevious from '../hooks/usePrevious' @@ -158,6 +161,7 @@ function LayerRef( onClose, onCloseComplete, open, + wrapperProps, }: PropsWithChildren<{ open: boolean position: LayerPositionType @@ -167,6 +171,7 @@ function LayerRef( onClose?: () => void | null | undefined onCloseComplete?: () => void | null | undefined onClickOutside?: () => void | null | undefined + wrapperProps?: ComponentProps<'div'> }>, ref: MutableRefObject ) { @@ -292,6 +297,7 @@ function LayerRef( {transitions((styles) => ( {children} diff --git a/src/components/Markdown.tsx b/src/components/Markdown.tsx index 42eba017..1a1637f9 100644 --- a/src/components/Markdown.tsx +++ b/src/components/Markdown.tsx @@ -1,4 +1,3 @@ -import { Div } from 'honorable' import { Children, useMemo } from 'react' import ReactMarkdown from 'react-markdown' import rehypeRaw from 'rehype-raw' @@ -7,6 +6,8 @@ import styled, { useTheme } from 'styled-components' import { isExternalUrl, removeTrailingSlashes } from '../utils/urls' +import { styledTheme } from '../theme' + import MultilineCode from './Code' import InlineCode from './InlineCode' @@ -43,6 +44,7 @@ function getLastStringChild(children: any, depth = 0): any { } function MarkdownPreformatted({ children, ...props }: any) { + const theme = useTheme() let lang const className = children?.[0]?.props?.className @@ -53,104 +55,143 @@ function MarkdownPreformatted({ children, ...props }: any) { const stringChild = getLastStringChild(children) || '' return ( -
- - {stringChild} - -
+ + {stringChild} + ) } const commonCfg = { shouldForwardProp: () => true } +const spacingReset = { + padding: 0, + margin: 0, + 'hr + &': { + paddingTop: styledTheme.spacing.medium, + }, +} const MdBlockquote = styled.blockquote.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, position: 'relative', ...theme.partials.text.body1, color: theme.colors['text-light'], - margin: 0, + paddingTop: theme.spacing.small, marginLeft: theme.spacing.xlarge - 1, - borderLeft: `2px solid ${theme.colors.border}`, - padding: '0', - paddingLeft: theme.spacing.xlarge - 1, boxShadow: 'none', '& p': { + borderLeft: `2px solid ${theme.colors.border}`, + paddingLeft: theme.spacing.xlarge - 1, ...theme.partials.text.body1, color: theme.colors['text-light'], }, })) const MdUl = styled.ul.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, paddingLeft: theme.spacing.xlarge, - marginBottom: theme.spacing.small, + paddingTop: theme.spacing.medium, + display: 'flex', + flexDirection: 'column', + gap: theme.spacing.xsmall, + 'ul &, ol &': { + paddingTop: theme.spacing.xxsmall, + gap: theme.spacing.xxsmall, + }, })) const MdOl = styled.ol.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, paddingLeft: theme.spacing.xlarge, - marginBottom: theme.spacing.small, + paddingTop: theme.spacing.medium, + display: 'flex', + flexDirection: 'column', + gap: theme.spacing.xsmall, + 'ul &, ol &': { + paddingTop: theme.spacing.xxsmall, + gap: theme.spacing.xxsmall, + }, })) const MdLi = styled.li.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.body2LooseLineHeight, - marginTop: theme.spacing.xxsmall, + color: theme.colors['text-light'], })) const MdH1 = styled.h1.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.title2, color: theme.colors.text, - marginTop: theme.spacing.large, - marginBottom: theme.spacing.small, - '&:first-of-type': { marginTop: 0 }, + margin: 0, + paddingTop: theme.spacing.xlarge, + '&:first-child': { paddingTop: 0 }, })) const MdH2 = styled.h2.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.subtitle1, color: theme.colors.text, - marginTop: theme.spacing.large, - marginBottom: theme.spacing.small, - '&:first-of-type': { marginTop: 0 }, + margin: 0, + paddingTop: theme.spacing.xlarge, + '&:first-child': { paddingTop: 0 }, })) const MdH3 = styled.h3.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.subtitle2, color: theme.colors.text, - marginTop: theme.spacing.large, - marginBottom: theme.spacing.small, - '&:first-of-type': { marginTop: 0 }, + paddingTop: theme.spacing.xlarge, + '&:first-child': { paddingTop: 0 }, })) const MdH4 = styled.h4.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.body1Bold, color: theme.colors.text, - marginTop: theme.spacing.large, - marginBottom: theme.spacing.small, - '&:first-of-type': { marginTop: 0 }, + paddingTop: theme.spacing.large, + '&:first-child': { paddingTop: 0 }, })) const MdH5 = styled.h5.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.body1Bold, color: theme.colors.text, - marginTop: theme.spacing.large, - marginBottom: theme.spacing.small, - '&:first-of-type': { marginTop: 0 }, + paddingTop: theme.spacing.large, + '&:first-child': { paddingTop: 0 }, })) const MdH6 = styled.h6.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.body1Bold, color: theme.colors.text, - marginTop: theme.spacing.large, - marginBottom: theme.spacing.small, - '&:first-of-type': { marginTop: 0 }, + paddingTop: theme.spacing.large, + '&:first-child': { paddingTop: 0 }, })) const MdImg = styled.img(() => ({ display: 'inline', maxWidth: '100%' })) const MdP = styled.p.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, ...theme.partials.text.body2LooseLineHeight, - marginBottom: theme.spacing.medium, + color: theme.colors['text-light'], + paddingTop: theme.spacing.large, + 'h1 + &, h2 + &, h3 + &, h4 + &, h5 + &, h6 + &': { + paddingTop: theme.spacing.small, + }, + '&:first-child': { paddingTop: 0 }, })) const MdDiv = styled.div.withConfig(commonCfg)(({ theme }) => ({ ...theme.partials.text.body2LooseLineHeight, marginBottom: theme.spacing.medium, })) const MdA = styled.a.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, display: 'inline', ...theme.partials.text.inlineLink, })) const MdSpan = styled.span.withConfig(commonCfg)((_p) => ({ + ...spacingReset, verticalAlign: 'bottom', })) const MdHr = styled.hr.withConfig(commonCfg)(({ theme }) => ({ + ...spacingReset, '&::before': { content: '""', display: 'table', @@ -163,8 +204,7 @@ const MdHr = styled.hr.withConfig(commonCfg)(({ theme }) => ({ height: '1px', backgroundColor: theme.colors.border, border: 0, - padding: 0, - margin: `${theme.spacing.xlarge}px ${theme.spacing.large}px`, + margin: `${theme.spacing.medium}px ${theme.spacing.large}px 0`, })) function MarkdownImage({ @@ -257,10 +297,7 @@ function Markdown({ text, gitUrl, mainBranch }: MarkdownProps) { }), span: render({ component: MdSpan }), code: render({ component: InlineCode }), - pre: render({ - component: MarkdownPreformatted, - props: { marginBottom: 'medium' }, - }), + pre: render({ component: MarkdownPreformatted }), hr: render({ component: MdHr }), }} > diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx index d59b4a9e..c50281d5 100644 --- a/src/components/Toast.tsx +++ b/src/components/Toast.tsx @@ -1,4 +1,11 @@ -import { type Ref, forwardRef, useCallback, useEffect, useState } from 'react' +import { + type ComponentProps, + type Ref, + forwardRef, + useCallback, + useEffect, + useState, +} from 'react' import { type Severity } from '../types' import { type Extends } from '../utils/ts-utils' @@ -15,6 +22,7 @@ type ToastProps = { onCloseComplete?: () => void show?: boolean severity?: ToastSeverity + layerProps?: ComponentProps<'div'> } & BannerProps const defaults = { @@ -35,6 +43,7 @@ const Toast = forwardRef( severity = defaults.severity, children, show = true, + layerProps, ...props }: ToastProps, ref: Ref @@ -67,6 +76,7 @@ const Toast = forwardRef( return ( { @@ -76,6 +86,7 @@ const Toast = forwardRef( onCloseComplete() }} ref={ref} + {...layerProps} > setOpen(false)} diff --git a/src/stories/Markdown.stories.tsx b/src/stories/Markdown.stories.tsx index 794137c7..67256b3c 100644 --- a/src/stories/Markdown.stories.tsx +++ b/src/stories/Markdown.stories.tsx @@ -79,6 +79,10 @@ https://google.com ___ +text below a divider + +___ + # Some more stuff from Chatwoot's readme Chat dashboard dark mode Chat dashboard diff --git a/src/theme/zIndexes.ts b/src/theme/zIndexes.ts index eee65242..fc284f97 100644 --- a/src/theme/zIndexes.ts +++ b/src/theme/zIndexes.ts @@ -5,4 +5,5 @@ export const zIndexes = { modal: 1000, selectPopover: 1500, tooltip: 2000, + toast: 2500, } as const satisfies CSSObject