diff --git a/.changeset/fix-react-popup-and-overlays.md b/.changeset/fix-react-popup-and-overlays.md new file mode 100644 index 00000000..5bf480ca --- /dev/null +++ b/.changeset/fix-react-popup-and-overlays.md @@ -0,0 +1,5 @@ +--- +"@tiny-design/react": patch +--- + +Fix popup positioning and interaction regressions across overlay-based React components, and align related input, table, tree, tour, and upload behaviors diff --git a/apps/docs/public/llms.txt b/apps/docs/public/llms.txt index a98fce60..5f0da6f8 100644 --- a/apps/docs/public/llms.txt +++ b/apps/docs/public/llms.txt @@ -62,7 +62,7 @@ Components that accept sizes use: `'sm' | 'md' | 'lg'` - **Button** — Trigger operations. Props: `btnType` (`'default'|'primary'|'outline'|'ghost'|'link'|'info'|'danger'|'warning'|'success'`), `loading`, `disabled`, `block`, `size`, `round`, `icon`. Also: `Button.Group`. - **Image** — Display images with preview support. - **Link** — Styled anchor element. -- **Typography** — Headings, body text, lists. Subcomponents: `Typography.Title`, `Typography.Text`, `Typography.Paragraph`. +- **Typography** — Headings, body text, lists. Prefer `Heading`, `Text`, `Paragraph`; compatibility entrypoints: `Typography.Heading`, `Typography.Text`, `Typography.Paragraph`. ### Layout - **AspectRatio** — Maintain width-to-height proportional relationship. diff --git a/apps/docs/src/containers/home/theme-showcase.tsx b/apps/docs/src/containers/home/theme-showcase.tsx index 7d20075d..8c0fb5a2 100644 --- a/apps/docs/src/containers/home/theme-showcase.tsx +++ b/apps/docs/src/containers/home/theme-showcase.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Typography, Button, Marquee } from '@tiny-design/react'; +import { Button, Heading, Marquee, Paragraph } from '@tiny-design/react'; import { buildThemeDocumentFromDraft, getPresetDraft, @@ -76,12 +76,12 @@ export const ThemeShowcase = (): React.ReactElement => { return (
- + {s.home.themeShowcase} - - + + {s.home.themeShowcaseDesc} - +
diff --git a/apps/docs/src/containers/theme-studio/defaults.ts b/apps/docs/src/containers/theme-studio/defaults.ts index b3f26112..d8ecb58d 100644 --- a/apps/docs/src/containers/theme-studio/defaults.ts +++ b/apps/docs/src/containers/theme-studio/defaults.ts @@ -49,15 +49,25 @@ export const DEFAULT_FIELDS: ThemeEditorFields = { h1Size: '40px', h2Size: '32px', letterSpacing: '-0.02em', - radius: '14px', + radius: '0.3rem', shadowCard: '0 20px 55px rgba(17, 24, 39, 0.08)', shadowFocus: '0 0 0 3px rgba(110, 65, 191, 0.22)', - buttonRadius: '999px', - inputRadius: '14px', - cardRadius: '22px', - buttonPaddingX: '18px', - inputHeight: '40px', - cardPadding: '24px', + buttonRadius: '0.3rem', + inputRadius: '0.3rem', + cardRadius: '0.3rem', + fieldPaddingSm: '8px', + fieldPaddingMd: '8px', + fieldPaddingLg: '8px', + buttonPaddingSm: '8px', + buttonPaddingMd: '15px', + buttonPaddingLg: '20px', + fieldHeightSm: '24px', + fieldHeightMd: '35px', + fieldHeightLg: '44px', + buttonHeightSm: '24px', + buttonHeightMd: '35px', + buttonHeightLg: '44px', + cardPadding: '18px', }; export function createDraft( diff --git a/apps/docs/src/containers/theme-studio/editor-draft.ts b/apps/docs/src/containers/theme-studio/editor-draft.ts index 52838ecb..ac88092a 100644 --- a/apps/docs/src/containers/theme-studio/editor-draft.ts +++ b/apps/docs/src/containers/theme-studio/editor-draft.ts @@ -126,8 +126,18 @@ export function buildPreviewVars(fields: ThemeEditorFields): React.CSSProperties '--editor-button-radius': fields.buttonRadius, '--editor-input-radius': fields.inputRadius, '--editor-card-radius': fields.cardRadius, - '--editor-button-padding-x': fields.buttonPaddingX, - '--editor-input-height': fields.inputHeight, + '--editor-field-padding-sm': fields.fieldPaddingSm, + '--editor-field-padding-md': fields.fieldPaddingMd, + '--editor-field-padding-lg': fields.fieldPaddingLg, + '--editor-button-padding-sm': fields.buttonPaddingSm, + '--editor-button-padding-md': fields.buttonPaddingMd, + '--editor-button-padding-lg': fields.buttonPaddingLg, + '--editor-field-height-sm': fields.fieldHeightSm, + '--editor-field-height-md': fields.fieldHeightMd, + '--editor-field-height-lg': fields.fieldHeightLg, + '--editor-button-height-sm': fields.buttonHeightSm, + '--editor-button-height-md': fields.buttonHeightMd, + '--editor-button-height-lg': fields.buttonHeightLg, '--editor-card-padding': fields.cardPadding, } as React.CSSProperties; } diff --git a/apps/docs/src/containers/theme-studio/editor-fields.tsx b/apps/docs/src/containers/theme-studio/editor-fields.tsx index df668c10..008d82fb 100644 --- a/apps/docs/src/containers/theme-studio/editor-fields.tsx +++ b/apps/docs/src/containers/theme-studio/editor-fields.tsx @@ -9,7 +9,7 @@ export function swatchTextStyle(background: string, foreground: string): React.C }; } -function parseSliderValue(value: string, unit?: 'px' | 'em'): number | undefined { +function parseSliderValue(value: string, unit?: 'px' | 'em' | 'rem'): number | undefined { if (unit === 'px') { const match = /^(-?\d+(?:\.\d+)?)px$/.exec(value.trim()); return match ? Number(match[1]) : undefined; @@ -20,11 +20,16 @@ function parseSliderValue(value: string, unit?: 'px' | 'em'): number | undefined return match ? Number(match[1]) : undefined; } + if (unit === 'rem') { + const match = /^(-?\d+(?:\.\d+)?)rem$/.exec(value.trim()); + return match ? Number(match[1]) : undefined; + } + const parsed = Number(value); return Number.isNaN(parsed) ? undefined : parsed; } -function formatSliderValue(value: number, unit?: 'px' | 'em'): string { +function formatSliderValue(value: number, unit?: 'px' | 'em' | 'rem'): string { if (!unit) return String(value); return `${value}${unit}`; } diff --git a/apps/docs/src/containers/theme-studio/index.tsx b/apps/docs/src/containers/theme-studio/index.tsx index b634583c..00129dcf 100644 --- a/apps/docs/src/containers/theme-studio/index.tsx +++ b/apps/docs/src/containers/theme-studio/index.tsx @@ -1,13 +1,15 @@ import React, { useEffect, useMemo, useState } from 'react'; import type { ThemeDocument } from '@tiny-design/react'; +import { validateThemeDocument } from '@tiny-design/tokens/validate-theme'; import { Button, ConfigProvider, Modal, + Paragraph, Segmented, Select, + Text, Textarea, - Typography, useTheme, } from '@tiny-design/react'; import { @@ -115,10 +117,16 @@ const ThemeStudioPage = (): React.ReactElement => { const handleImport = () => { try { const parsed = JSON.parse(importText) as ThemeDocument; - setDraft(buildDraftFromThemeDocument(parsed)); + const validation = validateThemeDocument(parsed); + if (!validation.valid) { + setImportError(validation.errors.join('\n')); + return; + } + + setDraft(buildDraftFromThemeDocument(validation.normalizedDocument as ThemeDocument)); setImportVisible(false); setImportError(null); - setStatus('Imported theme document'); + setStatus(validation.warnings.length > 0 ? 'Imported theme document with validation warnings' : 'Imported theme document'); } catch { setImportError('Invalid theme document JSON'); } @@ -137,7 +145,7 @@ const ThemeStudioPage = (): React.ReactElement => { >
- Theme Editor + Theme Editor
{activePreset.name} {THEME_EDITOR_PRESETS.length} presets @@ -194,9 +202,7 @@ const ThemeStudioPage = (): React.ReactElement => {
-
- {renderPreview(draft.activeTemplate, draft.fields, draft.activeSection)} -
+ {renderPreview(draft.activeTemplate, draft.fields, draft.activeSection)}
@@ -215,10 +221,10 @@ const ThemeStudioPage = (): React.ReactElement => { }} >
- + Paste a Tiny theme document JSON export to replace the current global theme. - - Preset selection and all editor controls will sync to the imported values. + + Preset selection and all editor controls will sync to the imported values.