diff --git a/README.md b/README.md index 33ece02..43aaf61 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ The following command would forward the API keys from the specified shell enviro ```bash export ANTHROPIC_API_KEY=xxx export OPENAI_API_KEY=xxx -docker run --name openui -p 7878:7878 -e OPENAI_API_KEY -e ANTHROPIC_API_KEY -e OLLAMA_HOST=http://host.docker.internal:11434 gchr.io/wandb/openui +docker run --rm --name openui -p 7878:7878 -e OPENAI_API_KEY -e ANTHROPIC_API_KEY -e OLLAMA_HOST=http://host.docker.internal:11434 gchr.io/wandb/openui ``` Now you can goto [http://localhost:7878](http://localhost:7878) and generate new UI's! diff --git a/assets/demo.gif b/assets/demo.gif index e6c41b2..2ba0c9a 100644 Binary files a/assets/demo.gif and b/assets/demo.gif differ diff --git a/backend/openui/dist/annotator/index.html b/backend/openui/dist/annotator/index.html index 734fed2..118b84c 100644 --- a/backend/openui/dist/annotator/index.html +++ b/backend/openui/dist/annotator/index.html @@ -621,7 +621,9 @@

How do you want this to change?

return } const isDark = document.documentElement.classList.contains('dark') - const newModeDark = event.data.mode === 'dark' || !isDark + const newModeDark = + event.data.mode === 'dark' || + (!isDark && event.data.mode !== 'light') if (newModeDark) { document.documentElement.classList.add('dark') } else { diff --git a/frontend/public/annotator/index.html b/frontend/public/annotator/index.html index 734fed2..118b84c 100644 --- a/frontend/public/annotator/index.html +++ b/frontend/public/annotator/index.html @@ -621,7 +621,9 @@

How do you want this to change?

return } const isDark = document.documentElement.classList.contains('dark') - const newModeDark = event.data.mode === 'dark' || !isDark + const newModeDark = + event.data.mode === 'dark' || + (!isDark && event.data.mode !== 'light') if (newModeDark) { document.documentElement.classList.add('dark') } else { diff --git a/frontend/src/api/openai.ts b/frontend/src/api/openai.ts index 53bf8af..890ab54 100644 --- a/frontend/src/api/openai.ts +++ b/frontend/src/api/openai.ts @@ -68,6 +68,7 @@ Prefer using these colors when appropriate, for example: \`\`\` *Implementation Rules:* +- Only implement elements within the \`\` tag, don't bother with \`\` or \`\` tags. - Avoid using SVGs directly. Instead, use the \`\` tag with a descriptive title as the alt attribute and add .svg to the placehold.co url, for example: \`\`\`html diff --git a/frontend/src/components/Settings.tsx b/frontend/src/components/Settings.tsx index ca57950..2bea780 100644 --- a/frontend/src/components/Settings.tsx +++ b/frontend/src/components/Settings.tsx @@ -134,7 +134,7 @@ export default function Settings({ trigger }: { trigger: JSX.Element }) {

Settings

Model:{' '} - {slugToNiceName(model, false)} + {slugToNiceName(model.split('/').at(-1), false)}

Temperature: {temperature} diff --git a/frontend/src/components/VersionPreview.tsx b/frontend/src/components/VersionPreview.tsx index 2e13f87..fc25bb4 100644 --- a/frontend/src/components/VersionPreview.tsx +++ b/frontend/src/components/VersionPreview.tsx @@ -1,6 +1,7 @@ import { TrashIcon } from '@radix-ui/react-icons' import { useVersion } from 'hooks' import { useAtomValue } from 'jotai' +import { themes } from 'lib/themes' import { cn } from 'lib/utils' import { nanoid } from 'nanoid' import { useEffect, useMemo, useRef, useState } from 'react' @@ -8,6 +9,8 @@ import { darkModeAtom, historySidebarStateAtom, imageDB, + uiStateAtom, + uiThemeAtom, useSaveHistory, type ItemWrapper } from 'state' @@ -27,6 +30,10 @@ export default function VersionPreview({ const iframeRef = useRef(null) const [isFrameReady, setIsFrameReady] = useState(false) const isVisible = useAtomValue(historySidebarStateAtom) === 'versions' + const uiState = useAtomValue(uiStateAtom) + const isRendering = uiState.rendering + const uiTheme = useAtomValue(uiThemeAtom) + const theme = themes.find(t => t.name === uiTheme) ?? themes[0] const [html, setHtml] = useState() const id = useMemo(() => nanoid(8), []) const saveHistory = useSaveHistory() @@ -50,7 +57,11 @@ export default function VersionPreview({ '*' ) } - }, [darkMode, previewDarkMode]) + iframeRef.current?.contentWindow?.postMessage( + { action: 'theme', theme }, + '*' + ) + }, [darkMode, previewDarkMode, theme]) useEffect(() => { item @@ -80,12 +91,17 @@ export default function VersionPreview({ html, js: [], darkMode: previewDarkMode === 'dark', - action: 'hydrate' + action: 'hydrate', + rendering: isRendering }, '*' ) + iframeRef.current?.contentWindow?.postMessage( + { action: 'theme', theme }, + '*' + ) } - }, [isFrameReady, html, isVisible, previewDarkMode, id]) + }, [isFrameReady, html, isVisible, previewDarkMode, id, isRendering, theme]) const W = 1524 const H = 960 diff --git a/frontend/src/lib/constants.ts b/frontend/src/lib/constants.ts index e47835a..69b22bc 100644 --- a/frontend/src/lib/constants.ts +++ b/frontend/src/lib/constants.ts @@ -1,5 +1,5 @@ export const EXAMPLES = [ - // 'Make me a flashy landing page for an AI SaaS startup. Use some gradients and animations on hover. Come up with an exciting name and create a navigation bar up top.', + 'Make me a flashy landing page for an AI SaaS startup. Come up with an exciting name and create a navigation bar up top.', 'Create a responsive navigation bar with dropdown menus, using a dark theme.', 'I need a user profile card with an avatar, name, and social media links in Tailwind CSS.', 'Generate a modal popup for user feedback, including text area and submit button.', diff --git a/frontend/src/lib/markdown.ts b/frontend/src/lib/markdown.ts index 9016b06..603b15b 100644 --- a/frontend/src/lib/markdown.ts +++ b/frontend/src/lib/markdown.ts @@ -70,7 +70,6 @@ export function parseMarkdown( } /* This is supposed to prevent us from writing frontmatter to the UI TODO: this is brittle, and doesn't seem to work consistently :/ - */ if (rendering && cleanMarkdown.slice(0, 1000).includes('---')) { const offset = cleanMarkdown.split('---').slice(0, -1).join('---').length cleanMarkdown = cleanMarkdown.slice(offset) @@ -78,6 +77,7 @@ export function parseMarkdown( cleanMarkdown = '' } } + */ const parsed = unified().use(remarkParse).parse(cleanMarkdown) @@ -103,7 +103,7 @@ export function parseMarkdown( !rendering && htmlBlocks.filter(h => h.value.trim() !== '').length === 0 ) { - console.warn('No HTML found, parse results:', parsed) + console.warn('No HTML found, parse results:', parsed.children) htmlBlocks = [ { type: 'code', diff --git a/frontend/src/state/atoms/history.ts b/frontend/src/state/atoms/history.ts index 6da52ce..e686873 100644 --- a/frontend/src/state/atoms/history.ts +++ b/frontend/src/state/atoms/history.ts @@ -497,20 +497,34 @@ export const useSaveHistory = () => { } safeValue = JSON.stringify(parsed) } + // TODO: move this shit to indexed DB!!! for (const key of Object.keys(parsed.historyMap)) { const item = parsed.historyMap[key] as HistoryItem const html = item.html ?? '' if (html !== '') { delete item.html - localStorage.setItem(`${key}.html`, html) + try { + localStorage.setItem(`${key}.html`, html) + } catch (error) { + console.error('Error saving HTML', error) + } } const markdown = item.markdown ?? '' if (markdown !== '') { delete item.markdown - localStorage.setItem(`${key}.md`, markdown) + try { + localStorage.setItem(`${key}.md`, markdown) + } catch (error) { + console.error('Error saving markdown', error) + } } } - localStorage.setItem('serializedHistory', safeValue) + console.log('Saving history', safeValue.length) + try { + localStorage.setItem('serializedHistory', safeValue) + } catch (error) { + console.error('Error saving history', error) + } } }) } diff --git a/frontend/src/state/index.ts b/frontend/src/state/index.ts index 66d48ba..002e755 100644 --- a/frontend/src/state/index.ts +++ b/frontend/src/state/index.ts @@ -21,7 +21,8 @@ export const historySidebarStateAtom = atom<'closed' | 'history' | 'versions'>( export const screenshotAtom = atom('') export const facetsAtom = atomWithStorage('facets', []) export const commentsAtom = atom([]) -export const uiThemeAtom = atomWithStorage('uiTheme', 'zinc') +const theme = undefined +export const uiThemeAtom = atomWithStorage('uiTheme', theme) export const darkModeAtom = atomWithStorage('darkMode', 'system') export const beastModeAtom = atom(false) export const draggingAtom = atom(false)