Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-react-popup-and-overlays.md
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion apps/docs/public/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions apps/docs/src/containers/home/theme-showcase.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -76,12 +76,12 @@ export const ThemeShowcase = (): React.ReactElement => {

return (
<div className="home__section home__theme-showcase">
<Typography.Heading level={1} className="home__feature-title">
<Heading level={1} className="home__feature-title">
{s.home.themeShowcase}
</Typography.Heading>
<Typography.Paragraph className="home__theme-showcase-desc">
</Heading>
<Paragraph className="home__theme-showcase-desc">
{s.home.themeShowcaseDesc}
</Typography.Paragraph>
</Paragraph>

<div className="home__marquee-container">
<Marquee duration={50} pauseOnHover>
Expand Down
24 changes: 17 additions & 7 deletions apps/docs/src/containers/theme-studio/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
14 changes: 12 additions & 2 deletions apps/docs/src/containers/theme-studio/editor-draft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
9 changes: 7 additions & 2 deletions apps/docs/src/containers/theme-studio/editor-fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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}`;
}
Expand Down
32 changes: 19 additions & 13 deletions apps/docs/src/containers/theme-studio/index.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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');
}
Expand All @@ -137,7 +145,7 @@ const ThemeStudioPage = (): React.ReactElement => {
>
<div className="theme-studio__topbar">
<div className="theme-studio__topbar-copy">
<Typography.Text className="theme-studio__eyebrow">Theme Editor</Typography.Text>
<Text className="theme-studio__eyebrow">Theme Editor</Text>
<div className="theme-studio__topbar-meta">
<span>{activePreset.name}</span>
<span>{THEME_EDITOR_PRESETS.length} presets</span>
Expand Down Expand Up @@ -194,9 +202,7 @@ const ThemeStudioPage = (): React.ReactElement => {
</div>
</div>

<div className={`theme-studio__preview theme-studio__preview_${draft.mode}`}>
{renderPreview(draft.activeTemplate, draft.fields, draft.activeSection)}
</div>
{renderPreview(draft.activeTemplate, draft.fields, draft.activeSection)}
</main>
</div>

Expand All @@ -215,18 +221,18 @@ const ThemeStudioPage = (): React.ReactElement => {
}}
>
<div className="theme-studio__modal-copy">
<Typography.Paragraph>
<Paragraph>
Paste a Tiny theme document JSON export to replace the current global theme.
</Typography.Paragraph>
<Typography.Text type="secondary">Preset selection and all editor controls will sync to the imported values.</Typography.Text>
</Paragraph>
<Text type="secondary">Preset selection and all editor controls will sync to the imported values.</Text>
</div>
<Textarea
rows={16}
className="theme-studio__import-textarea"
value={importText}
onChange={(next) => setImportText(next)}
/>
{importError ? <Typography.Paragraph className="theme-studio__error">{importError}</Typography.Paragraph> : null}
{importError ? <Paragraph className="theme-studio__error">{importError}</Paragraph> : null}
</Modal>

<Modal
Expand All @@ -247,8 +253,8 @@ const ThemeStudioPage = (): React.ReactElement => {
>
<div className="theme-studio__code-head">
<div>
<Typography.Text strong>Output</Typography.Text>
<Typography.Text type="secondary">{activePreset.name} · {status}</Typography.Text>
<Text strong>Output</Text>
<Text type="secondary">{activePreset.name} · {status}</Text>
</div>
<Segmented
options={CODE_VIEW_OPTIONS}
Expand Down
Loading
Loading