diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..d487eb0 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [once-ui-system, lorant-one] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..670a6ca --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,45 @@ +--- +name: Bug report +about: Create a report to help us improve Once UI +title: '[BUG] ' +labels: 'bug' +assignees: '' +--- + +## Describe the bug +A clear and concise description of what the bug is. + +## To reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '...' +3. Scroll down to '...' +4. See error + +## Expected behavior +A clear and concise description of what you expected to happen. + +## Screenshots +If applicable, add screenshots to help explain your problem. + +## Environment +Please complete the following information: +- **OS**: [e.g. macOS, Windows, Linux] +- **Browser**: [e.g. Chrome 120, Safari 17, Firefox 121] +- **Once UI Version**: [e.g. 1.5.0] +- **Next.js Version**: [e.g. 14.0.0] +- **Node.js Version**: [e.g. 18.17.0] + +## Code Sample +```tsx +// Please provide a minimal code example that reproduces the issue +``` + +## Additional context +Add any other context about the problem here. For example: +- Does this happen consistently or intermittently? +- Did this work in a previous version? +- Are there any console errors or warnings? + +## Possible solution +If you have an idea of what might be causing the issue or how to fix it, please share it here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..9ddabc1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: ๐Ÿ“š Documentation + url: https://docs.once-ui.com + about: Check out our documentation for guides and API references + - name: ๐Ÿ’ฌ Discord Community + url: https://discord.com/invite/5EyAQ4eNdS + about: Join our Discord for help, support and discussion with the community + - name: ๐Ÿ” Discussions + url: https://github.com/once-ui-system/core/discussions + about: Ask questions and discuss ideas with the community diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..b0d8a98 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,37 @@ +--- +name: Feature request +about: Suggest an idea for Once UI +title: '[FEATURE] ' +labels: 'feature request' +assignees: '' +--- + +## Is your feature request related to a problem? Please describe. +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +## Describe the solution you'd like +A clear and concise description of what you want to happen. + +## Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +## Use Case +Describe the use case for this feature. How would it benefit Once UI users? + +## Example API (if applicable) +```tsx +// Show how you envision the feature being used + + Content + +``` + +## Additional context +Add any other context, screenshots, or examples about the feature request here. + +## Would you be willing to contribute? +- [ ] Yes, I'd like to work on this feature +- [ ] No, but I can help test it +- [ ] No, just suggesting the idea diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..534762a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,31 @@ +--- +name: Question or Help +about: Ask a question about using Once UI +title: '[QUESTION] ' +labels: 'question' +assignees: '' +--- + +## Your Question +A clear and concise description of what you're trying to achieve or understand. + +## What I've tried +Describe what you've already attempted: +- [ ] Checked the [documentation](https://docs.once-ui.com) +- [ ] Searched existing issues +- [ ] Asked in Discord + +## Code Example +```tsx +// Share relevant code if applicable +``` + +## Expected outcome +What are you trying to accomplish? + +## Additional context +Add any other context, screenshots, or links that might help us understand your question. + +--- + +๐Ÿ’ก **Tip**: For faster responses, consider asking in our [Discord community](https://discord.com/invite/5EyAQ4eNdS) where community members can help! diff --git a/.npmrc b/.npmrc index 993ee2a..26e9efd 100644 --- a/.npmrc +++ b/.npmrc @@ -1,11 +1,5 @@ -# Use symlinks instead of junctions on Windows -symlink=true - # Disable strict peer dependencies strict-peer-dependencies=false -# Hoist all dependencies to the root node_modules -shamefully-hoist=false - -# Use node-linker=hoisted to avoid Windows symlink issues -node-linker=hoisted +# Use shamefully-hoist for better Windows compatibility +shamefully-hoist=true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 447973b..d872d25 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,7 +51,7 @@ Before submitting a PR: ### Best practices -- Follow our [component conventions](https://docs.once-ui.com/once-ui/components) and file structure. +- Follow our [component conventions](https://docs.once-ui.com/once-ui/basics/components) and file structure. - Use the naming system and design tokens already defined in the project. ## Join the community diff --git a/packages/core/LICENSE b/LICENSE.md similarity index 99% rename from packages/core/LICENSE rename to LICENSE.md index 89c5370..e0e5a17 100644 --- a/packages/core/LICENSE +++ b/LICENSE.md @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 882a159..8281d86 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,54 @@ -## Once UI monorepo +
-This monorepo hosts the official Once UI package and its internal development sandbox. It is designed for testing, development, and contributionโ€”not for production deployment. +
+ + + + Once UI Logo + + + + Once UI Wordmark + -## Developer notice +
-It includes: + The indie design system for Next.js apps -- `packages/core`: the published [@once-ui-system/core](https://www.npmjs.com/package/@once-ui-system/core) package -- `apps/docs`: the official documentation of Once UI and Magic templates built with [Magic Docs](https://once-ui.com/products/magic-docs) -- `apps/dev`: a simple sandbox app wired via symlink for testing components + [![npm version](https://img.shields.io/npm/v/@once-ui-system/core.svg)](https://www.npmjs.com/package/@once-ui-system/core) + [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE.md) + [![npm downloads](https://img.shields.io/npm/dm/@once-ui-system/core.svg)](https://www.npmjs.com/package/@once-ui-system/core) + [![Discord](https://img.shields.io/discord/1083398120035074148?color=7289da&logo=discord&logoColor=white)](https://discord.com/invite/5EyAQ4eNdS) +
-This setup is intended for contributors and maintainers. -If you're building a real project, we recommend using: -1. [Once UI Starter](https://github.com/once-ui-system/nextjs-starter) -2. or install via your package manager: -```bash -npm install @once-ui-system/core -# or -yarn add @once-ui-system/core -# or -pnpm add @once-ui-system/core -``` - -### For contributors - -Fork this repo, install dependencies, and run apps: - -```bash -pnpm install -pnpm dev -``` - -The components will update automatically when you make changes to the Core library. If you modify the CSS modules, you'll have to run `pnpm build` in the `packages/core` directory. +
## Documentation -Start here: [docs.once-ui.com](https://docs.once-ui.com/once-ui/quick-start). - -## Creators +Learn how to set up and build with Once UI at [docs.once-ui.com](https://docs.once-ui.com/once-ui/quick-start). -**Lorant One**: [Portfolio](https://lorant.one) / [Threads](https://www.threads.net/@lorant.one) / [LinkedIn](https://www.linkedin.com/in/lorant-one/) +## Installation -**Collaborators**: [Once UI Frontiers](https://once-ui.com/about) +```bash +npm install @once-ui-system/core +``` -## Join the movement +## Authors -![Design Engineers Club](https://docs.once-ui.com/images/docs/vibe-coding-dark.jpg) +Built and maintained by [**Lorant One**](https://lorant.one). -Join the [Design Engineers Club](https://discord.com/invite/5EyAQ4eNdS) on Discord. Build with intention. Share with integrity. +## Community -## Feedback & Bugs +Join the [Design Engineers Club](https://discord.com/invite/5EyAQ4eNdS) for help, support and discussion. -Found a bug? [Report it](https://github.com/once-ui-system/core/issues/new?labels=bug&template=bug_report.md) -Got an idea? [Submit a request](https://github.com/once-ui-system/core/issues/new?labels=feature%20request&template=feature_request.md) +Found a bug? Report it [here](https://github.com/once-ui-system/core/issues/new?labels=bug&template=bug_report.md). Got a feature request? Submit it [here](https://github.com/once-ui-system/core/issues/new?labels=feature%20request&template=feature_request.md). -## Support us +## Contributing -Once UI is an indie project. [Sponsor us](https://github.com/sponsors/once-ui-system) and get featured on our site! +Please read our [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to Once UI. -## License +## Sponsors -Distributed under the MIT License. See `LICENSE.txt`. \ No newline at end of file +Once UI is an indie project. [Sponsor us](https://github.com/sponsors/once-ui-system) and get featured on our site! \ No newline at end of file diff --git a/apps/dev/src/app/(main)/page.tsx b/apps/dev/src/app/(main)/page.tsx index 55225c5..f347d75 100644 --- a/apps/dev/src/app/(main)/page.tsx +++ b/apps/dev/src/app/(main)/page.tsx @@ -52,7 +52,9 @@ import { MasonryGrid, TagInput, Avatar, + Background, } from "@once-ui-system/core"; +import { style } from "@/resources/once-ui.config"; export default function Home() { const [selectedEmoji, setSelectedEmoji] = React.useState(""); @@ -113,16 +115,39 @@ export default function Home() { return ( + hide by default, show on l - hide by default, show on m + hide by default, show on l + hide by default, show on m + hide by default, show on m + hide by default, show on s hide by default, show on s hide by default, show on xs + hide by default, show on xs + + + + + + } + dropdown={ + + + + + + } + /> + - + diff --git a/apps/dev/src/components/UIBenchmark.tsx b/apps/dev/src/components/UIBenchmark.tsx new file mode 100644 index 0000000..9e05207 --- /dev/null +++ b/apps/dev/src/components/UIBenchmark.tsx @@ -0,0 +1,273 @@ +"use client"; + +import React, {useState, useEffect, useCallback, JSX} from "react"; +import { + Button, + Flex, + Text, + Heading, + Column, + Badge, + Input, + Card, + Spinner, + ProgressBar, + Avatar, + Chip, + IconButton, + Grid, + Row, +} from "@once-ui-system/core"; + +interface BenchmarkResult { + testName: string; + renderTime: number; + componentsCount: number; + fps?: number; +} + +interface PerformanceMetrics { + memoryUsage?: number; + renderTime: number; + componentCount: number; +} + +export const UIBenchmark: React.FC = () => { + const [isRunning, setIsRunning] = useState(false); + const [results, setResults] = useState([]); + const [currentTest, setCurrentTest] = useState(""); + const [componentsCount, setComponentsCount] = useState(100); + + // Function for measuring performance + const measurePerformance = useCallback( + (testName: string, renderFunction: () => JSX.Element, count: number): Promise => { + return new Promise((resolve) => { + const startTime = performance.now(); + let frameCount = 0; + const fpsStart = performance.now(); + + // Render components + const renderStart = performance.now(); + renderFunction(); + const renderEnd = performance.now(); + + // Measure FPS + const measureFPS = () => { + frameCount++; + if (performance.now() - fpsStart < 1000) { + requestAnimationFrame(measureFPS); + } else { + const fps = frameCount; + const endTime = performance.now(); + + resolve({ + testName, + renderTime: renderEnd - renderStart, + componentsCount: count, + fps, + }); + } + }; + + requestAnimationFrame(measureFPS); + }); + }, + [] + ); + + // Test simple components (Button, Badge, Text) + const testSimpleComponents = useCallback(() => { + const components = []; + for (let i = 0; i < componentsCount; i++) { + components.push( + + + + Text {i} + + ); + } + return
{components}
; + }, [componentsCount]); + + // Test complex components (Card with multiple elements) + const testComplexComponents = useCallback(() => { + const components = []; + for (let i = 0; i < Math.floor(componentsCount / 5); i++) { + components.push( + + + Card {i} + Description for card {i} + + + + + + + + + ); + } + return
{components}
; + }, [componentsCount]); + + // Test Grid components + const testGridComponents = useCallback(() => { + const components = []; + for (let i = 0; i < componentsCount; i++) { + components.push( + + + Grid Item {i} + + + ); + } + return {components}; + }, [componentsCount]); + + // Test interactive components + const testInteractiveComponents = useCallback(() => { + const components = []; + for (let i = 0; i < Math.floor(componentsCount / 3); i++) { + components.push( + + + + + + ); + } + return
{components}
; + }, [componentsCount]); + + // Function to run all tests + const runBenchmark = useCallback(async () => { + setIsRunning(true); + setResults([]); + + const tests = [ + { name: "Simple Components", fn: testSimpleComponents, count: componentsCount }, + { name: "Complex Components", fn: testComplexComponents, count: Math.floor(componentsCount / 5) }, + { name: "Grid Layout", fn: testGridComponents, count: componentsCount }, + { name: "Interactive Components", fn: testInteractiveComponents, count: Math.floor(componentsCount / 3) }, + ]; + + for (const test of tests) { + setCurrentTest(test.name); + + // Small pause between tests + await new Promise(resolve => setTimeout(resolve, 100)); + + try { + const result = await measurePerformance(test.name, test.fn, test.count); + setResults(prev => [...prev, result]); + } catch (error) { + console.error(`Error in test ${test.name}:`, error); + } + } + + setCurrentTest(""); + setIsRunning(false); + }, [componentsCount, measurePerformance, testSimpleComponents, testComplexComponents, testGridComponents, testInteractiveComponents]); + + // Function to get result color based on performance + const getPerformanceColor = (renderTime: number): "success-strong" | "warning-strong" | "danger-strong" => { + if (renderTime < 5) return "success-strong"; + if (renderTime < 15) return "warning-strong"; + return "danger-strong"; + }; + + return ( + + UI Kit Performance Benchmark + + + + + This benchmark tests the performance of various UI kit components + + + + setComponentsCount(Number(e.target.value))} + min="10" + max="1000" + /> + + + + {isRunning && ( + + + + Running: {currentTest || "Preparing..."} + + + )} + + + + + Test Results + + + + {results.map((result, index) => ( + + + + {result.testName} + + Components: {result.componentsCount} + + + + + + + {result.renderTime.toFixed(2)}ms + + Render Time + + + {result.fps && ( + + 55 ? "success-strong" : result.fps > 30 ? "warning-strong" : "danger-strong"}> + {result.fps}fps + + FPS + + )} + + + + ))} + + + + Result Interpretation: + + Green- Excellent performance (<5ms) + Yellow- Good performance (5-15ms) + Red- Needs optimization (>15ms) + โ€ข FPS shows animation smoothness (60fps is ideal) + + + + + + ); +}; diff --git a/apps/docs/LICENSE b/apps/docs/LICENSE deleted file mode 100644 index d475385..0000000 --- a/apps/docs/LICENSE +++ /dev/null @@ -1,17 +0,0 @@ -Creative Commons Attribution-NonCommercial 4.0 International -CC BY-NC 4.0 - -By using this work, you agree to the following terms: - -You are free to: -- **Share** โ€” copy and redistribute the material in any medium or format -- **Adapt** โ€” remix, transform, and build upon the material - -Under the following conditions: -- **Attribution** โ€” You must give appropriate credit, provide a link to the license, and indicate if changes were made. -- **NonCommercial** โ€” You may not use the material for **commercial purposes**. - -No additional restrictions โ€” You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. - -Full license text available at: -[creativecommons.org](https://creativecommons.org/licenses/by-nc/4.0/legalcode) \ No newline at end of file diff --git a/apps/docs/README.md b/apps/docs/README.md deleted file mode 100644 index 305f181..0000000 --- a/apps/docs/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Once UI Documentation - -The official documentation of Once UI and Magic products. - -## Creators - -**Lorant One**: [Site](https://lorant.one) / [Threads](https://www.threads.net/@lorant.one) / [LinkedIn](https://www.linkedin.com/in/lorant-one/) - -## Become a Oncer - -![Design Engineers Club](https://docs.once-ui.com/images/docs/vibe-coding-dark.jpg) - -Join the [Design Engineers Club](https://discord.com/invite/5EyAQ4eNdS) on Discord to connect with us and share your projects. - -## Magic Docs - -This project is built with [Magic Docs](https://once-ui.com/products/magic-docs). Build your own documentation with Magic Docs for free! - -## License - -Distributed under the CC BY-NC 4.0 License. -- Attribution is required. -- Commercial usage is not allowed. -- You can extend the license to [Dopler CC](https://dopler.app/license) by purchasing a [Once UI Pro](https://once-ui.com/pricing) license. - -See `LICENSE.txt` for more information. \ No newline at end of file diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index 3b4374b..c1f3dfc 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -68,6 +68,41 @@ const nextConfig = { destination: '/:slug*', permanent: true, }, + { + source: '/magic-portfolio/:slug*', + destination: '/products/magic-portfolio/:slug*', + permanent: true, + }, + { + source: '/magic-docs/:slug*', + destination: '/products/magic-docs/:slug*', + permanent: true, + }, + { + source: '/magic-bio/:slug*', + destination: '/products/magic-bio/:slug*', + permanent: true, + }, + { + source: '/magic-agent/:slug*', + destination: '/products/magic-agent/:slug*', + permanent: true, + }, + { + source: '/magic-convert/:slug*', + destination: '/products/magic-convert/:slug*', + permanent: true, + }, + { + source: '/magic-store/:slug*', + destination: '/products/magic-store/:slug*', + permanent: true, + }, + { + source: '/supabase-starter/:slug*', + destination: '/products/supabase-starter/:slug*', + permanent: true, + }, ]; }, }; diff --git a/apps/docs/public/fonts/Inter.ttf b/apps/docs/public/fonts/Inter.ttf deleted file mode 100644 index 15e908f..0000000 Binary files a/apps/docs/public/fonts/Inter.ttf and /dev/null differ diff --git a/apps/docs/public/images/avatar.jpg b/apps/docs/public/images/avatar.jpg index 3237e58..cb9c70c 100644 Binary files a/apps/docs/public/images/avatar.jpg and b/apps/docs/public/images/avatar.jpg differ diff --git a/apps/docs/public/images/changelog/once-ui-1-5.jpg b/apps/docs/public/images/changelog/once-ui-1-5.jpg new file mode 100644 index 0000000..e014553 Binary files /dev/null and b/apps/docs/public/images/changelog/once-ui-1-5.jpg differ diff --git a/apps/docs/public/images/docs/magic-agent.jpg b/apps/docs/public/images/docs/magic-agent.jpg index e73ae7c..1a3de21 100644 Binary files a/apps/docs/public/images/docs/magic-agent.jpg and b/apps/docs/public/images/docs/magic-agent.jpg differ diff --git a/apps/docs/public/images/docs/magic-convert.jpg b/apps/docs/public/images/docs/magic-convert.jpg index 2e091c7..38cdbe8 100644 Binary files a/apps/docs/public/images/docs/magic-convert.jpg and b/apps/docs/public/images/docs/magic-convert.jpg differ diff --git a/apps/docs/public/images/docs/magic-docs.jpg b/apps/docs/public/images/docs/magic-docs.jpg index 6f9d1d7..85d3ed9 100644 Binary files a/apps/docs/public/images/docs/magic-docs.jpg and b/apps/docs/public/images/docs/magic-docs.jpg differ diff --git a/apps/docs/public/images/docs/magic-portfolio.jpg b/apps/docs/public/images/docs/magic-portfolio.jpg index 144405f..245b9e3 100644 Binary files a/apps/docs/public/images/docs/magic-portfolio.jpg and b/apps/docs/public/images/docs/magic-portfolio.jpg differ diff --git a/apps/docs/public/images/docs/magic-store.jpg b/apps/docs/public/images/docs/magic-store.jpg index bc9a032..cd01f00 100644 Binary files a/apps/docs/public/images/docs/magic-store.jpg and b/apps/docs/public/images/docs/magic-store.jpg differ diff --git a/apps/docs/public/images/docs/once-ui.jpg b/apps/docs/public/images/docs/once-ui.jpg index 209ce66..67718e1 100644 Binary files a/apps/docs/public/images/docs/once-ui.jpg and b/apps/docs/public/images/docs/once-ui.jpg differ diff --git a/apps/docs/public/images/docs/supabase-starter.jpg b/apps/docs/public/images/docs/supabase-starter.jpg new file mode 100644 index 0000000..60dddb5 Binary files /dev/null and b/apps/docs/public/images/docs/supabase-starter.jpg differ diff --git a/apps/docs/public/images/docs/swag-promo-01.png b/apps/docs/public/images/docs/swag-promo-01.png new file mode 100644 index 0000000..2271b55 Binary files /dev/null and b/apps/docs/public/images/docs/swag-promo-01.png differ diff --git a/apps/docs/public/images/docs/swag-promo-02.png b/apps/docs/public/images/docs/swag-promo-02.png new file mode 100644 index 0000000..ec8d491 Binary files /dev/null and b/apps/docs/public/images/docs/swag-promo-02.png differ diff --git a/apps/docs/public/trademark/dopler-icon-dark.svg b/apps/docs/public/trademarks/dopler-icon-dark.svg similarity index 100% rename from apps/docs/public/trademark/dopler-icon-dark.svg rename to apps/docs/public/trademarks/dopler-icon-dark.svg diff --git a/apps/docs/public/trademark/dopler-icon-light.svg b/apps/docs/public/trademarks/dopler-icon-light.svg similarity index 100% rename from apps/docs/public/trademark/dopler-icon-light.svg rename to apps/docs/public/trademarks/dopler-icon-light.svg diff --git a/apps/docs/public/trademark/icon-dark.svg b/apps/docs/public/trademarks/icon-dark.svg similarity index 100% rename from apps/docs/public/trademark/icon-dark.svg rename to apps/docs/public/trademarks/icon-dark.svg diff --git a/apps/docs/public/trademark/icon-light.svg b/apps/docs/public/trademarks/icon-light.svg similarity index 100% rename from apps/docs/public/trademark/icon-light.svg rename to apps/docs/public/trademarks/icon-light.svg diff --git a/apps/docs/public/trademark/type-dark.svg b/apps/docs/public/trademarks/type-dark.svg similarity index 100% rename from apps/docs/public/trademark/type-dark.svg rename to apps/docs/public/trademarks/type-dark.svg diff --git a/apps/docs/public/trademark/type-light.svg b/apps/docs/public/trademarks/type-light.svg similarity index 100% rename from apps/docs/public/trademark/type-light.svg rename to apps/docs/public/trademarks/type-light.svg diff --git a/apps/docs/src/app/(docs)/[...slug]/page.tsx b/apps/docs/src/app/(docs)/[...slug]/page.tsx index 615beab..55dc0d7 100644 --- a/apps/docs/src/app/(docs)/[...slug]/page.tsx +++ b/apps/docs/src/app/(docs)/[...slug]/page.tsx @@ -55,8 +55,8 @@ export default async function Docs({ return ( <> - - + + {sectionTitle} {doc.metadata.title} - Last update: {formatDate(doc.metadata.updatedAt)} + Updated: {formatDate(doc.metadata.updatedAt)} {doc.metadata.github && ( + + )} + + ); + })} +
+ + ))} + + ); }; diff --git a/apps/docs/src/app/layout.tsx b/apps/docs/src/app/layout.tsx index f39c3e2..6044974 100644 --- a/apps/docs/src/app/layout.tsx +++ b/apps/docs/src/app/layout.tsx @@ -1,14 +1,15 @@ import '@once-ui-system/core/css/styles.css'; import '@once-ui-system/core/css/tokens.css'; +import '../resources/custom.scss'; import classNames from "classnames"; -import { Footer, Header } from "@/product"; +import { Footer, Header, Sidebar } from "@/product"; import { baseURL } from "@/resources"; import { Analytics } from "@vercel/analytics/react" -import { Background, Column, Flex, Meta } from "@once-ui-system/core"; +import { Background, Column, Flex, Meta, Row } from "@once-ui-system/core"; import { dataStyle, effects, layout, schema, style } from "../resources/once-ui.config"; import { meta } from "@/resources"; import { RouteGuard } from "@/product/RouteGuard"; @@ -158,7 +159,8 @@ export default function RootLayout({ /> - + - {children} + + + {children} + diff --git a/apps/docs/src/app/page.tsx b/apps/docs/src/app/page.tsx index 63e0979..0810b18 100644 --- a/apps/docs/src/app/page.tsx +++ b/apps/docs/src/app/page.tsx @@ -12,12 +12,13 @@ import { Tag, Meta, Schema, - Background, - RevealFx + MatrixFx, + Background } from "@once-ui-system/core"; -import { baseURL, meta, schema, changelog, roadmap } from "@/resources"; +import { baseURL, meta, schema, changelog, roadmap, layout } from "@/resources"; import { formatDate } from "./utils/formatDate"; import { Products } from "@/product"; +import { PromoCard } from "@/components/PromoCard"; export async function generateMetadata() { return Meta.generate({ @@ -66,272 +67,309 @@ const latestChangelogEntry = changelog[0]; export default function Home() { return ( - - - - - - - - - {/* Hero Section */} - - - + + + + + + {/* Hero Section */} + + + + NEW - - Once UI 1.4 release + + Once UI 1.5 โ€” Curiosity in code - + Once UI Docs - Get started with our premium, plug-and-play solutions built for vibe coding + Open-source design system and
app templates for indie builders
-
-
- - - - - Products - - - Deploy fully functional apps in minutes - - - - - {/* Latest Update Section */} - - - - - Latest Update - - - - - {formatDate(latestChangelogEntry.date)} - + + + + + Products + + + Deploy fully functional apps in minutes + + + - - {latestChangelogEntry.image && ( - - )} - - - {latestChangelogEntry.title} - - - {latestChangelogEntry.description && ( - - {latestChangelogEntry.description} - + {/* Latest Update Section */} + + + + + Latest Update + + + + + {formatDate(latestChangelogEntry.date)} + + + + + {latestChangelogEntry.image && ( + )} + + + {latestChangelogEntry.title} + + + {latestChangelogEntry.description && ( + + {latestChangelogEntry.description} + + )} + - - - {/* Roadmap Progress Section */} - - - - - Q2 2025 Roadmap - - - - - Progress and task status - - - - - {/* Overall Progress */} - - - - - {roadmapStats.progressPercentage}% - - - Overall progress - - - - - - - - - {/* Task Status */} - - {/* Planned Tasks */} - - - {roadmapStats.totalTasks - roadmapStats.completedTasks - roadmapStats.inProgressTasks} - - - + {/* Roadmap Progress Section */} + + + + + Q4 2025 Roadmap + + + + + Progress and task status + + + + + + {/* Overall Progress */} + + + + + {roadmapStats.progressPercentage}% + - Planned + Overall progress + + + + - {/* In Progress Tasks */} - - + {/* Planned Tasks */} + - {roadmapStats.inProgressTasks} - - - - In progress + {roadmapStats.totalTasks - roadmapStats.completedTasks - roadmapStats.inProgressTasks} - - + + + + Planned + + + + + {/* In Progress Tasks */} + + + {roadmapStats.inProgressTasks} + + + + + In progress + + + - {/* Completed Tasks */} - - - {roadmapStats.completedTasks} - - - - Completed + {roadmapStats.completedTasks} - - - - + + + + Completed + + + + + +
- +
- + + + + + + + Support our recent launch! + + + {[ + { + href: "https://store.dopler.app/product/curiosity-in-code-hooded-long-sleeve", + image: "/images/docs/swag-promo-01.png", + }, + { + href: "https://store.dopler.app/product/curiosity-in-code-desk-mat", + image: "/images/docs/swag-promo-02.png", + } + ].map((product, index) => ( + + ))} + + ); } diff --git a/apps/docs/src/app/roadmap/layout.tsx b/apps/docs/src/app/roadmap/layout.tsx deleted file mode 100644 index b10be95..0000000 --- a/apps/docs/src/app/roadmap/layout.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Row } from "@once-ui-system/core"; -import { Sidebar } from "@/product"; -import React, { memo } from "react"; - -const DocsLayout = memo(({ - children, -}: { - children: React.ReactNode; -}) => { - return ( - - - {children} - - ); -}); - -DocsLayout.displayName = 'RoadmapLayout'; - -export default DocsLayout; \ No newline at end of file diff --git a/apps/docs/src/app/roadmap/page.tsx b/apps/docs/src/app/roadmap/page.tsx index 650f8ad..0519c96 100644 --- a/apps/docs/src/app/roadmap/page.tsx +++ b/apps/docs/src/app/roadmap/page.tsx @@ -66,7 +66,7 @@ const RoadmapTask = ({ task: taskItem }: { task: Task }) => ( export default function RoadmapPage() { return ( - + - List of features planned for Q3 2025 + List of features planned for Q4 2025 diff --git a/apps/docs/src/components/PromoCard.tsx b/apps/docs/src/components/PromoCard.tsx new file mode 100644 index 0000000..fd4dc2b --- /dev/null +++ b/apps/docs/src/components/PromoCard.tsx @@ -0,0 +1,99 @@ +"use client"; + +import { useRef, useState, useEffect } from "react"; +import { + Row, + Button, + Card, + Animation, + Hover, + LetterFx, + Background, + Media, + Text +} from "@once-ui-system/core"; + +export interface PromoCardProps { + href: string; + image: string; + buttonText?: string; + showOverlay?: boolean; +} + +export function PromoCard({ + href, + image, +}: PromoCardProps) { + const triggerLetterFxRef = useRef<(() => void) | null>(null); + const [isHovered, setIsHovered] = useState(false); + + // Trigger animation when hovered and ref is available + useEffect(() => { + if (isHovered && triggerLetterFxRef.current) { + // Small delay to ensure overlay is mounted + const timer = setTimeout(() => { + triggerLetterFxRef.current?.(); + }, 50); + return () => clearTimeout(timer); + } + }, [isHovered]); + + const cardContent = ( + + + + + + ); + + return ( + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > + + + + + + + + + + } + /> + + ); +} diff --git a/apps/docs/src/content/once-ui/basics/border.mdx b/apps/docs/src/content/once-ui/basics/border.mdx index 9cac148..990e008 100644 --- a/apps/docs/src/content/once-ui/basics/border.mdx +++ b/apps/docs/src/content/once-ui/basics/border.mdx @@ -1,6 +1,6 @@ --- title: "Border" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "Adjusting shape language with border radius and border style." updatedAt: "2025-05-04" docs: "once-ui/basics/border.mdx" navLabel: "Border" diff --git a/apps/docs/src/content/once-ui/basics/color.mdx b/apps/docs/src/content/once-ui/basics/color.mdx index 40a1d73..7e0c5c9 100644 --- a/apps/docs/src/content/once-ui/basics/color.mdx +++ b/apps/docs/src/content/once-ui/basics/color.mdx @@ -1,6 +1,6 @@ --- title: "Color" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "Design harmonious and accessible interfaces with Once UI's flexible color system." updatedAt: "2025-05-04" docs: "once-ui/basics/color.mdx" navLabel: "Color" diff --git a/apps/docs/src/content/once-ui/components.mdx b/apps/docs/src/content/once-ui/basics/components.mdx similarity index 93% rename from apps/docs/src/content/once-ui/components.mdx rename to apps/docs/src/content/once-ui/basics/components.mdx index c277a05..0f624fb 100644 --- a/apps/docs/src/content/once-ui/components.mdx +++ b/apps/docs/src/content/once-ui/basics/components.mdx @@ -1,10 +1,10 @@ --- title: "Components" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "The anatomy and architecture of Once UI components: props, states, and more." updatedAt: "2025-05-04" docs: "once-ui/components.mdx" navLabel: "Components" -navIcon: "learn" +navIcon: "lightbulb" --- Once UI components are prop-based, customizable, and built for real-world usage in modern apps. They aim to balance expressiveness with clarityโ€”avoiding over-abstraction while supporting flexibility and scalability. diff --git a/apps/docs/src/content/once-ui/basics/meta.json b/apps/docs/src/content/once-ui/basics/meta.json index b51003d..c137bdd 100644 --- a/apps/docs/src/content/once-ui/basics/meta.json +++ b/apps/docs/src/content/once-ui/basics/meta.json @@ -6,6 +6,7 @@ "color": 2, "spacing": 3, "typography": 4, - "border": 5 + "border": 5, + "components": 6 } } \ No newline at end of file diff --git a/apps/docs/src/content/once-ui/basics/spacing.mdx b/apps/docs/src/content/once-ui/basics/spacing.mdx index d1f29c2..2ea79d3 100644 --- a/apps/docs/src/content/once-ui/basics/spacing.mdx +++ b/apps/docs/src/content/once-ui/basics/spacing.mdx @@ -1,6 +1,6 @@ --- title: "Spacing" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "Once UI's spacing system is based on a custom 8px grid." updatedAt: "2025-05-04" docs: "once-ui/basics/spacing.mdx" navLabel: "Spacing" diff --git a/apps/docs/src/content/once-ui/basics/structure.mdx b/apps/docs/src/content/once-ui/basics/structure.mdx index 4ae85d8..c8b16bd 100644 --- a/apps/docs/src/content/once-ui/basics/structure.mdx +++ b/apps/docs/src/content/once-ui/basics/structure.mdx @@ -1,6 +1,6 @@ --- title: "Structure" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "Once UI's layout system is built using `Flex` and `Grid`, prop-based abstractions over CSS flexbox and grid." updatedAt: "2025-05-04" docs: "once-ui/basics/structure.mdx" navLabel: "Structure" @@ -639,8 +639,8 @@ The surface properties are designed for large layout container elements such as horizontal="between" vertical="center" > - - + + - - + + `, language: "tsx", diff --git a/apps/docs/src/content/once-ui/basics/typography.mdx b/apps/docs/src/content/once-ui/basics/typography.mdx index 73964d2..19ba237 100644 --- a/apps/docs/src/content/once-ui/basics/typography.mdx +++ b/apps/docs/src/content/once-ui/basics/typography.mdx @@ -1,6 +1,6 @@ --- title: "Typography" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "Once UI's typography system is built using CSS variables and utility classes." updatedAt: "2025-05-04" docs: "once-ui/basics/typography.mdx" navLabel: "Typography" diff --git a/apps/docs/src/content/once-ui/components/List.mdx b/apps/docs/src/content/once-ui/components/List.mdx index 266e03b..22784b6 100644 --- a/apps/docs/src/content/once-ui/components/List.mdx +++ b/apps/docs/src/content/once-ui/components/List.mdx @@ -6,8 +6,6 @@ docs: "once-ui/components/list.mdx" github: "components/List.tsx" navLabel: "List" navIcon: "components" -navTag: "New" -navTagVariant: "cyan" --- A component for creating an ordered or unordered list of items. The `List` component can be used to create nested lists and supports `Flex` props. The `ListItem` component can be used to create list items and supports `Text` props. diff --git a/apps/docs/src/content/once-ui/components/animation.mdx b/apps/docs/src/content/once-ui/components/animation.mdx new file mode 100644 index 0000000..0803041 --- /dev/null +++ b/apps/docs/src/content/once-ui/components/animation.mdx @@ -0,0 +1,490 @@ +--- +title: "Animation" +summary: "Animation is a versatile component that provides preset animation effects with configurable triggers, easing curves, and timing." +updatedAt: "2025-10-08" +docs: "once-ui/components/animation.mdx" +github: "components/Animation.tsx" +navLabel: "Animation" +navIcon: "components" +navTag: "New" +navTagVariant: "cyan" +--- + +The `Animation` component provides a simple way to add animations to any element with value-based animation props, configurable triggers, and fine-grained control over timing and easing. Each animation prop accepts a value representing the initial state. + + + + Trigger fade + + }> + + Fade + + + + Trigger scale + + }> + + Scale + + + + Trigger slide + + }> + + Slide + + + + } + codes={[ + { + language: "tsx", + label: "Animation", + code: +` + Trigger fade + + }> + + Fade + + + + + Trigger scale + + }> + + Scale + + + + + Trigger slide + + }> + + Slide + +` + } + ]} +/> + +## Animation types + +All animations are value-based - the value represents the initial state, and it animates to the natural end state (`opacity: 1`, `scale: 1`, `blur: 0`, `translate: 0`). + + + + Blur + + }> + + + + + + Zoom in + + }> + + + + + + Slide up + + }> + + + + + + } + codes={[ + { + language: "tsx", + label: "Types", + code: +` + Blur + + }> + + + + + + + Zoom in + + }> + + + +` + } + ]} +/> + +## Manual trigger + +Use the `trigger` prop with interactive elements like NavIcon or Button. For controlled state (like toggling NavIcon's active state), use `triggerType="manual"` with the `active` prop. + + + + + } + codes={[ + { + language: "tsx", + label: "Interactive", + code: +`"use client"; + +import { useState } from "react"; +import { Animation, NavIcon, Dropdown, Option } from "@once-ui-system/core"; + +function NavIconMenu() { + const [isActive, setIsActive] = useState(false); + + return ( + setIsActive(!isActive)}> + + + } + slideDown={1} + triggerType="manual" + active={isActive} + duration={300} + > + + + + ); +}` + } + ]} +/> + +## Easing curves + +Customize animation feel with different easing curves: `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`, `spring`, `bounce`. + + + + Spring + + }> + + + + + + Bounce + + }> + + + + + + Ease + + }> + + + + + + } + codes={[ + { + language: "tsx", + label: "Easing", + code: +` + Spring easing +` + } + ]} +/> + +## Self trigger + +When used without a trigger, animations apply directly to the element. + + + + + + + Fade in + + Fade in on hover + + + + + + + + + Zoom Card + + Scale up on hover + + + + + + + + + Blur + + Reveal on hover + + + + + + } + codes={[ + { + language: "tsx", + label: "Card", + code: +` + + + + Hover Card + + This card animates on hover. + + + +` + } + ]} +/> + +## Portal mode + +Enable portal rendering to display animated content in a positioned overlay using Floating UI. Perfect for tooltips, popovers, and hover cards. + + + + Hover for portal + + } + > + + + Portal Content + + This renders in a portal with Floating UI positioning! + + + + + + } + codes={[ + { + language: "tsx", + label: "Portal", + code: +` + Hover for portal + + } +> + + Portal Content + +` + } + ]} +/> + +## Combining animations + +Stack multiple animations by providing multiple props. Each value represents the initial state. + + + + Fade + Scale + + } + > + + + + + + Blur + Scale + Slide + + } + > + + + + + + } + codes={[ + { + language: "tsx", + label: "Custom", + code: +`Trigger} +> + Fade + Scale + + + + Blur + Scale + Slide +` + } + ]} +/> + +## API reference + + diff --git a/apps/docs/src/content/once-ui/components/autoScroll.mdx b/apps/docs/src/content/once-ui/components/autoScroll.mdx index ed2b8d6..c70ceee 100644 --- a/apps/docs/src/content/once-ui/components/autoScroll.mdx +++ b/apps/docs/src/content/once-ui/components/autoScroll.mdx @@ -16,24 +16,24 @@ The `AutoScroll` component provides an infinite scrollable container that automa previewPadding="0" preview={ - - - - - - + + + + + + } codes={[ { code: ` - - - - - - + + + + + + `, language: "tsx", label: "AutoScroll" @@ -51,24 +51,24 @@ The `speed` prop controls the speed of the scrolling. previewPadding="0" preview={ - - - - - - + + + + + + } codes={[ { code: ` - - - - - - + + + + + + `, language: "tsx", label: "Speed" @@ -88,12 +88,12 @@ Combine with the `` component to create a fade-in and fade-out effect. <> - - - - - - + + + + + + @@ -104,12 +104,12 @@ Combine with the `` component to create a fade-in and fade-out effect. `<> - - - - - - + + + + + + `, diff --git a/apps/docs/src/content/once-ui/components/blockquote.mdx b/apps/docs/src/content/once-ui/components/blockquote.mdx index 2b01680..fbd9065 100644 --- a/apps/docs/src/content/once-ui/components/blockquote.mdx +++ b/apps/docs/src/content/once-ui/components/blockquote.mdx @@ -6,8 +6,6 @@ docs: "once-ui/components/blockquote.mdx" github: "components/BlockQuote.tsx" navLabel: "BlockQuote" navIcon: "components" -navTag: "New" -navTagVariant: "cyan" --- Use `BlockQuote` to present quoted text with emphasis and proper semantics. It renders a semantic `
` element and forwards all layout and style props from `Flex`. diff --git a/apps/docs/src/content/once-ui/components/card.mdx b/apps/docs/src/content/once-ui/components/card.mdx index 092d3fe..73ad1d4 100644 --- a/apps/docs/src/content/once-ui/components/card.mdx +++ b/apps/docs/src/content/once-ui/components/card.mdx @@ -1,6 +1,6 @@ --- title: "Card" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "Once UI's card component is a versatile, fluid container for content with a simple hover effect." updatedAt: "2025-05-04" docs: "once-ui/components/card.mdx" github: "components/Card.tsx" diff --git a/apps/docs/src/content/once-ui/components/compareImage.mdx b/apps/docs/src/content/once-ui/components/compareImage.mdx index bc95190..1ed550b 100644 --- a/apps/docs/src/content/once-ui/components/compareImage.mdx +++ b/apps/docs/src/content/once-ui/components/compareImage.mdx @@ -1,6 +1,6 @@ --- title: "CompareImage" -summary: "Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications." +summary: "Compare two images side by side with a slider to switch between them." updatedAt: "2025-05-04" docs: "once-ui/components/compareImage.mdx" github: "components/CompareImage.tsx" diff --git a/apps/docs/src/content/once-ui/components/contextMenu.mdx b/apps/docs/src/content/once-ui/components/contextMenu.mdx index 3351b9b..97ba240 100644 --- a/apps/docs/src/content/once-ui/components/contextMenu.mdx +++ b/apps/docs/src/content/once-ui/components/contextMenu.mdx @@ -6,8 +6,6 @@ docs: "once-ui/components/contextMenu.mdx" github: "components/ContextMenu.tsx" navLabel: "ContextMenu" navIcon: "components" -navTag: "New" -navTagVariant: "cyan" --- A component for providing users with contextual options / information on right click. diff --git a/apps/docs/src/content/once-ui/components/dropdownWrapper.mdx b/apps/docs/src/content/once-ui/components/dropdownWrapper.mdx index e6f855e..1fbca31 100644 --- a/apps/docs/src/content/once-ui/components/dropdownWrapper.mdx +++ b/apps/docs/src/content/once-ui/components/dropdownWrapper.mdx @@ -6,6 +6,8 @@ docs: "once-ui/components/dropdownWrapper.mdx" github: "components/DropdownWrapper.tsx" navLabel: "DropdownWrapper" navIcon: "components" +navTag: "Update" +navTagVariant: "indigo" --- DropdownWrapper is a container component that handles the positioning and state management of dropdown menus. It provides a flexible way to create custom dropdown interfaces with various trigger elements and dropdown contents. It supports keyboard navigation when used with `Option` components. diff --git a/apps/docs/src/content/once-ui/components/emojiPicker.mdx b/apps/docs/src/content/once-ui/components/emojiPicker.mdx index 887a709..725a763 100644 --- a/apps/docs/src/content/once-ui/components/emojiPicker.mdx +++ b/apps/docs/src/content/once-ui/components/emojiPicker.mdx @@ -6,6 +6,8 @@ docs: "once-ui/components/emojiPicker.mdx" github: "components/EmojiPicker.tsx" navLabel: "EmojiPicker" navIcon: "components" +navTag: "Update" +navTagVariant: "indigo" --- The `EmojiPicker` component allows you to select and insert emojis from categories. diff --git a/apps/docs/src/content/once-ui/components/emojiPickerDropdown.mdx b/apps/docs/src/content/once-ui/components/emojiPickerDropdown.mdx new file mode 100644 index 0000000..224b15d --- /dev/null +++ b/apps/docs/src/content/once-ui/components/emojiPickerDropdown.mdx @@ -0,0 +1,242 @@ +--- +title: "EmojiPickerDropdown" +summary: "The EmojiPickerDropdown component provides a dropdown interface for selecting emojis." +updatedAt: "2025-10-13" +docs: "once-ui/components/emojiPickerDropdown.mdx" +github: "components/EmojiPickerDropdown.tsx" +navLabel: "EmojiPickerDropdown" +navIcon: "components" +--- + +The `EmojiPickerDropdown` component combines the `EmojiPicker` with a `DropdownWrapper` to provide a complete dropdown emoji selection experience. Simply pass a trigger element and handle emoji selection. + + + } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + /> + {selectedEmoji && ( + + Selected: {selectedEmoji} + + )} +`, + language: "tsx", + label: "EmojiPickerDropdown" + } + ]} +/> + +## With IconButton trigger + +You can use an `IconButton` as the trigger for a more compact UI. + + + } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} +`, + language: "tsx", + label: "With IconButton" + } + ]} +/> + +## Columns + +You can customize the number of columns in the emoji grid. + + + } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + columns="10" + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} +`, + language: "tsx", + label: "Custom columns" + } + ]} +/> + +## Placement + +Control where the dropdown appears relative to the trigger using the `placement` prop. + + + } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + placement="top" + /> + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + placement="bottom" + /> + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + placement="left" + /> + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + placement="right" + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} +`, + language: "tsx", + label: "Placement" + } + ]} +/> + +## Custom background + +Customize the dropdown background color. + + + } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + background="neutral-weak" + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} +`, + language: "tsx", + label: "Custom background" + } + ]} +/> + +## Controlled state + +Control the open/close state externally using `isOpen` and `onOpenChange`. + + + } + codes={[ + { + code: +`const [isOpen, setIsOpen] = useState(false); +const [selectedEmoji, setSelectedEmoji] = useState(""); + + + } + onSelect={(emoji) => setSelectedEmoji(emoji)} + isOpen={isOpen} + onOpenChange={setIsOpen} + /> + + + } + /> + } + codes={[ + { + language: "tsx", + label: "Hover", + code: +` + + + Hover over me + + Move your cursor over this card to see the overlay effect. + + + + } + overlay={ + + + + } +/>`, + } + ]} +/> + +## API reference + + diff --git a/apps/docs/src/content/once-ui/components/hoverCard.mdx b/apps/docs/src/content/once-ui/components/hoverCard.mdx new file mode 100644 index 0000000..bea2b44 --- /dev/null +++ b/apps/docs/src/content/once-ui/components/hoverCard.mdx @@ -0,0 +1,84 @@ +--- +title: "HoverCard" +summary: "HoverCard displays content in a portal positioned relative to a trigger element on hover, with customizable animations and placement." +updatedAt: "2025-10-09" +docs: "once-ui/components/hoverCard.mdx" +github: "components/HoverCard.tsx" +navLabel: "HoverCard" +navIcon: "components" +navTag: "New" +navTagVariant: "cyan" +--- + +The `HoverCard` component is a syntactic sugar for the `Animation` component with a handful of smart defaults to display additional information about an element when hovered or focused. + +} + > + + + + + Lorant One + + Design Engineer + + + + + Published 100k+ lines of open-source code. Author of The Dopler Method, The Design Dividend, and Learn anything. + + + Design + Frontend + Writing + + + + } + codes={[ + { + language: "tsx", + label: "HoverCard", + code: +`} +> + + + + + Lorant One + + Design Engineer + + + + + Published 100k+ lines of open-source code. Author of The Dopler Method, The Design Dividend, and Learn anything. + + + Design + Frontend + Writing + + +` + } + ]} +/> + + +## API reference + + diff --git a/apps/docs/src/content/once-ui/components/logo.mdx b/apps/docs/src/content/once-ui/components/logo.mdx index 97545b6..be86b4f 100644 --- a/apps/docs/src/content/once-ui/components/logo.mdx +++ b/apps/docs/src/content/once-ui/components/logo.mdx @@ -6,8 +6,6 @@ docs: "once-ui/components/logo.mdx" github: "components/Logo.tsx" navLabel: "Logo" navIcon: "components" -navTag: "Update" -navTagVariant: "indigo" --- The Logo component is used to display brand logos with consistent styling and sizing. It supports displaying both an icon and a wordmark, either separately or together. @@ -18,10 +16,10 @@ The Logo component is used to display brand logos with consistent styling and si preview={ - + - + @@ -30,10 +28,10 @@ The Logo component is used to display brand logos with consistent styling and si { code: ` - + - + `, language: "tsx", label: "Logo" @@ -51,29 +49,29 @@ The Logo component comes in different sizes to accommodate various use cases. preview={ <> - - - - - + + + + + - - - - - + + + + + } codes={[ { code: -` - - - -`, +` + + + +`, language: "tsx", label: "Sizes" } @@ -90,20 +88,20 @@ Display only the icon part of the logo. preview={ <> - - + + - - + + } codes={[ { code: -` -`, +` +`, language: "tsx", label: "Icon" } @@ -120,20 +118,20 @@ Display only the wordmark part of the logo. preview={ <> - - + + - - + + } codes={[ { code: -` -`, +` +`, language: "tsx", label: "Wordmark" } @@ -150,20 +148,20 @@ The Logo component can function as a link when provided with an `href` property. preview={ <> - - + + - - + + } codes={[ { code: -` -`, +` +`, language: "tsx", label: "Links" } @@ -179,15 +177,15 @@ The `brand` prop provides a `copy` option for allowing the icon and wordmark to marginBottom="24" preview={ <> - - + + } codes={[ { code: ` } @@ -30,7 +32,7 @@ The `Particle` component provides customizable decorative particles with gradien fill interactive speed={3} - interactionRadius={100} + intensity={100} height={24} />`, language: "tsx", @@ -160,7 +162,7 @@ The `speed` prop controls the speed of the particles. ## Interactive -The `interactive` prop controls whether the particles are interactive. Use the `interactionRadius` prop to control the radius of the interaction area. +The `interactive` prop controls whether the particles are interactive. Use the `intensity` prop to control the radius of the interaction area. } codes={[ @@ -188,6 +190,40 @@ The `interactive` prop controls whether the particles are interactive. Use the ` ]} /> +## Mode + +The `mode` prop controls how particles interact with the cursor. Use `repel` to push particles away or `attract` to pull them towards the cursor. + + + } + codes={[ + { + code: +``, + language: "tsx", + label: "Mode" + } + ]} +/> + ## Opacity The `opacity` prop controls the opacity of the particles. @@ -227,7 +263,8 @@ The `opacity` prop controls the opacity of the particles. ["size", "SpacingToken", "2"], ["speed", "number", "0.3"], ["interactive", "boolean", "false"], - ["interactionRadius", "number", "20"], + ["mode", ["repel","attract"], "repel"], + ["intensity", "number", "20"], ["opacity", "DisplayProps['opacity']", "100"], ["className"], ["style"], diff --git a/apps/docs/src/content/once-ui/components/progressBar.mdx b/apps/docs/src/content/once-ui/components/progressBar.mdx index 07cc2c3..14337b9 100644 --- a/apps/docs/src/content/once-ui/components/progressBar.mdx +++ b/apps/docs/src/content/once-ui/components/progressBar.mdx @@ -6,8 +6,6 @@ docs: "once-ui/components/progressBar.mdx" github: "components/ProgressBar.tsx" navLabel: "ProgressBar" navIcon: "components" -navTag: "New" -navTagVariant: "cyan" --- A component for showing the progress of an action or task with an animation as it progresses. diff --git a/apps/docs/src/content/once-ui/components/pulse.mdx b/apps/docs/src/content/once-ui/components/pulse.mdx index 155b122..335ec6b 100644 --- a/apps/docs/src/content/once-ui/components/pulse.mdx +++ b/apps/docs/src/content/once-ui/components/pulse.mdx @@ -6,8 +6,6 @@ docs: "once-ui/components/pulse.mdx" github: "components/Pulse.tsx" navLabel: "Pulse" navIcon: "components" -navTag: "New" -navTagVariant: "cyan" --- The `Pulse` component is used to display a colored dot with a pulsing animation effect. diff --git a/apps/docs/src/content/once-ui/components/swiper.mdx b/apps/docs/src/content/once-ui/components/swiper.mdx new file mode 100644 index 0000000..9ef0cb5 --- /dev/null +++ b/apps/docs/src/content/once-ui/components/swiper.mdx @@ -0,0 +1,270 @@ +--- +title: "Swiper" +summary: "A scroll-based carousel with native snap scrolling, similar to Instagram or Airbnb galleries." +updatedAt: "2025-10-18" +docs: "once-ui/components/scroll-carousel.mdx" +github: "components/Swiper.tsx" +navLabel: "Swiper" +navIcon: "components" +--- + +An interactive carousel that uses native CSS scroll-snap for smooth, performant scrolling. Features native touch/swipe gestures on mobile and drag-to-scroll on desktop for seamless navigation between slides. + + + } + codes={[ + { + code: +``, + language: "tsx", + label: "Swiper" + } + ]} +/> + +## Interactions + +The Swiper uses native CSS scroll-snap, providing smooth touch gestures on mobile, trackpad scrolling, and mouse drag-to-scroll on desktop. Simply click and drag to navigate between slides. + + + } + codes={[ + { + code: +``, + language: "tsx", + label: "Interactions" + } + ]} +/> + +## Indicators + +By default, the Swiper displays dot indicators below the carousel. The active dot is highlighted and slightly scaled for better visibility. + + + + + + } + codes={[ + { + code: +` + +`, + language: "tsx", + label: "Indicators" + } + ]} +/> + +## Controls + +The `controls` prop supports three options: `true` (appear on hover), `false` (hidden), or `"contained"` (always visible inside the carousel). Buttons are automatically hidden when at the first or last slide. + + + + + + + } + codes={[ + { + code: +` + + + +