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
+
-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.
+
` 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(""); + + +
`, + language: "tsx", + label: "EmojiPickerDropdown" + } + ]} +/> + +## With IconButton trigger + +You can use an `IconButton` as the trigger for a more compact UI. + +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + /> + {selectedEmoji && ( + + Selected: {selectedEmoji} + + )} ++ } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + +
`, + language: "tsx", + label: "With IconButton" + } + ]} +/> + +## Columns + +You can customize the number of columns in the emoji grid. + +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} ++ } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + +
`, + language: "tsx", + label: "Custom columns" + } + ]} +/> + +## Placement + +Control where the dropdown appears relative to the trigger using the `placement` prop. + +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + columns="10" + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} ++ } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + +
`, + language: "tsx", + label: "Placement" + } + ]} +/> + +## Custom background + +Customize the dropdown background color. + +} + 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} + + )} ++ } + codes={[ + { + code: +`const [selectedEmoji, setSelectedEmoji] = useState(""); + + +
`, + language: "tsx", + label: "Custom background" + } + ]} +/> + +## Controlled state + +Control the open/close state externally using `isOpen` and `onOpenChange`. + +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + background="neutral-weak" + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} ++ } + codes={[ + { + code: +`const [isOpen, setIsOpen] = useState(false); +const [selectedEmoji, setSelectedEmoji] = useState(""); + + +
`, + language: "tsx", + label: "Controlled state" + } + ]} +/> + +## API reference + +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + isOpen={isOpen} + onOpenChange={setIsOpen} + /> + void", "Callback when an emoji is selected (required)"], + ["columns", "gridSize", "Number of columns in the emoji grid", "8"], + ["background", "StyleProps['background']", "Background color of the dropdown", "surface"], + ["closeAfterClick", "boolean", "Whether to close dropdown after selecting emoji", "true"], + ["placement", "Placement", "Position of dropdown relative to trigger", "bottom"], + ["isOpen", "boolean", "Controlled open state"], + ["onOpenChange", "(open: boolean) => void", "Callback when open state changes"], + ["fillWidth", "boolean", "Whether dropdown matches trigger width"], + ["minDropdownWidth", "number", "Minimum width of dropdown in pixels"] + ]} +/> diff --git a/apps/docs/src/content/once-ui/components/flex.mdx b/apps/docs/src/content/once-ui/components/flex.mdx index 0242347..907bc8b 100644 --- a/apps/docs/src/content/once-ui/components/flex.mdx +++ b/apps/docs/src/content/once-ui/components/flex.mdx @@ -6,6 +6,8 @@ docs: "once-ui/components/flex.mdx" github: "components/Flex.tsx" navLabel: "Flex" navIcon: "components" +navTag: "Update" +navTagVariant: "indigo" --- Learn more about the `Flex` component usage in the [Structure](/once-ui/basics/structure) section. \ No newline at end of file diff --git a/apps/docs/src/content/once-ui/components/grid.mdx b/apps/docs/src/content/once-ui/components/grid.mdx index d976540..809950e 100644 --- a/apps/docs/src/content/once-ui/components/grid.mdx +++ b/apps/docs/src/content/once-ui/components/grid.mdx @@ -6,6 +6,8 @@ docs: "once-ui/components/grid.mdx" github: "components/Grid.tsx" navLabel: "Grid" navIcon: "components" +navTag: "Update" +navTagVariant: "indigo" --- Learn more about the `Grid` component usage in the [Structure](/once-ui/basics/structure) section. \ No newline at end of file diff --git a/apps/docs/src/content/once-ui/components/hover.mdx b/apps/docs/src/content/once-ui/components/hover.mdx new file mode 100644 index 0000000..2959ce8 --- /dev/null +++ b/apps/docs/src/content/once-ui/components/hover.mdx @@ -0,0 +1,308 @@ +--- +title: "Hover" +summary: "Hover is a wrapper component that displays an overlay on top of its trigger element when hovered or focused." +updatedAt: "2025-10-08" +docs: "once-ui/components/hover.mdx" +github: "components/Hover.tsx" +navLabel: "Hover" +navIcon: "components" +navTag: "New" +navTagVariant: "cyan" +--- + +The `Hover` component wraps any element and displays an overlay on top when the user hovers over it or focuses on it. It's perfect for creating interactive cards with hover effects, image overlays, or any content that needs to reveal additional information on interaction. + + + + + + + } + overlay={ +Hover over me ++ Move your cursor over this card to see the overlay effect. + ++ New! + + } + /> + } + codes={[ + { + language: "tsx", + label: "Hover", + code: +`+ + + + + } + overlay={ +Hover over me ++ Move your cursor over this card to see the overlay effect. + ++ New! + + } +/>`, + } + ]} +/> + +## Delay + +Add a delay before the overlay appears or disappears with the `delay` and `hideDelay` props. + ++ + + + + } + overlay={ +Hover over me ++ Move your cursor over this card to see the overlay effect. + ++
+ } + /> + } + codes={[ + { + language: "tsx", + label: "Delay", + code: +`+ Read article
++ + + + + } + overlay={ +Hover over me ++ Move your cursor over this card to see the overlay effect. + ++
+ } +/>`, + } + ]} +/> + +## Accessibility + +The component supports keyboard navigation. For non-focusable triggers, add `tabIndex={0}` to make the wrapper keyboard-accessible. If your trigger is already focusable (like a Card with `href`), use `tabIndex={-1}` to prevent duplicate focus stops. + ++ Read article
++ Keyboard accessible ++ Tab to this card to see the overlay + + + } + overlay={ ++ + } + /> + } + codes={[ + { + language: "tsx", + label: "Accessibility", + code: +`+ Focused! + ++ Showing an overlay + ++ Keyboard accessible ++ Tab to this card to see the overlay + + + } + overlay={ ++ + } +/>`, + } + ]} +/> + +By default, the hover effect is disabled on touch devices. You can set `touch="enable"` to allow hover interactions, or `touch="display"` to always show the overlay on touch devices. + +## Interactive + +By default, the overlay is not interactive and click events are passed through to the trigger. You can set `interactive` to make the overlay interactive. + ++ Focused! + ++ Showing an overlay + +Be careful when using interactive overlays, since they prevent click events from reaching the trigger. + ++ + + + + } + overlay={ +Hover over me ++ Move your cursor over this card to see the overlay effect. + ++ +
+ } + /> + } + codes={[ + { + language: "tsx", + label: "Hover", + code: +`+ + + + + } + overlay={ +Hover over me ++ Move your cursor over this card to see the overlay effect. + ++ +
+ } +/>`, + } + ]} +/> + +## 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. + + } + > + + + + } + 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 + ++
++ + +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 +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: +` + + + + `, + language: "tsx", + label: "Controls" + } + ]} +/> + +## Aspect ratio + +Customize the aspect ratio of the carousel to fit your design needs. Supports standard aspect ratio values. + + + + + + + } + codes={[ + { + code: +` + + + + `, + language: "tsx", + label: "Aspect ratio" + } + ]} +/> + +## Custom content + +You can place custom content inside the slides as `ReactNode`, not just images. + + Slide 1 }, + { slide:}, + { slide:
Slide 2 }, + ]} + /> + } + codes={[ + { + code: +`
Slide 3 Slide 1 }, + { slide:}, + { slide:
Slide 2 }, + ]} +/>`, + language: "tsx", + label: "Custom content" + } + ]} +/> + +## API Reference + +
Slide 3 ", "[]"], + ["aspectRatio", "string", "16 / 9"], + ["controls", ["true", "false", "contained"], "true"], + ["indicator", "boolean", "true"], + ["priority", "boolean", "false"], + ["fill", "boolean", "false"], + ["sizes", "string", "undefined"], + ["...flex"] + ]} +/> diff --git a/apps/docs/src/content/once-ui/components/timeline.mdx b/apps/docs/src/content/once-ui/components/timeline.mdx new file mode 100644 index 0000000..115751e --- /dev/null +++ b/apps/docs/src/content/once-ui/components/timeline.mdx @@ -0,0 +1,489 @@ +--- +title: "Timeline" +summary: "Display events or steps in chronological order with flexible layouts and states." +updatedAt: "2025-10-14" +docs: "once-ui/components/timeline.mdx" +github: "components/Timeline.tsx" +navLabel: "Timeline" +navIcon: "components" +navTag: "New" +navTagVariant: "cyan" +--- + +Timeline helps visualize sequences of events, process steps, or historical data. Configure items via an object array with simple props or custom React nodes. + +## Basic usage + +Use `label` and `description` props for quick setup. + + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Basic" + } + ]} +/> + +## Alignment + +Control timeline alignment with the `alignment` prop. Use `left` or `right` for different layouts. + + + + +Left aligned ++ + + + } + codes={[ + { + code: +`// Left aligned (default) +Right aligned ++ + +// Alternate sides + `, + language: "tsx", + label: "Alignment" + } + ]} +/> + +## Sizes + +Control size with the `size` prop: `xs`, `s`, `m`, `l` or `xl`. + + + + + + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Sizes" + } + ]} +/> + +## Marker + +Customize the marker with the `marker` prop. + + + + , + label: "Payment received", + state: "completed" + }, + { + marker: , + label: "Order shipped", + state: "active" + }, + { + marker: , + label: "Out for delivery", + description: "Couldn't reach customer", + state: "danger" + } + ]} + /> + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Marker" + } + ]} +/> + +## States + +Visual feedback with different marker states: `default`, `active`, `success`, and `danger`. + + + + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "States" + } + ]} +/> + +## Extra content + +Extend the label and description with custom React nodes. Use the `children` prop with additional content to extend the layout. + + Dispatched Done , + description: "Order #123456789", + children: ( ++ 3 days ago +
+ ) + }, + { + state: "active", + label:Shipped to distribution
, + description: "Order #123456789", + children: ( +In Progress + Now +
+ ) + }, + { + state: "default", + label:Shipped to customer
, + description: "Waiting for carrier", + children: ( +Planned + Delivery in: ~2 days +
+ ) + } + ]} + /> + } + codes={[ + { + code: +`+ +
+Version 1.0 +Shipped ++ Initial product launch + +3 months ago + + ) + } + ]} +/>`, + language: "tsx", + label: "Extra content" + } + ]} +/> + +## Row + +Use the `marker` prop to render custom marker elements. + ++ } + codes={[ + { + code: +` , + label: "Payment received", + state: "completed" + }, + { + marker: , + label: "Order shipped", + state: "active" + } + ]} +/>`, + language: "tsx", + label: "Custom markers" + } + ]} +/> + +## API reference + +### Timeline + + +### TimelineItem + diff --git a/apps/docs/src/content/once-ui/config.mdx b/apps/docs/src/content/once-ui/config.mdx index 9ab51a4..3af5c8e 100644 --- a/apps/docs/src/content/once-ui/config.mdx +++ b/apps/docs/src/content/once-ui/config.mdx @@ -1,6 +1,6 @@ --- title: "Config" -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: "Configure Once UI with app-level design settings." updatedAt: "2025-05-04" docs: "once-ui/config.mdx" navLabel: "Config" diff --git a/apps/docs/src/content/once-ui/contexts/iconProvider.mdx b/apps/docs/src/content/once-ui/contexts/iconProvider.mdx index fdd8bb6..834c9df 100644 --- a/apps/docs/src/content/once-ui/contexts/iconProvider.mdx +++ b/apps/docs/src/content/once-ui/contexts/iconProvider.mdx @@ -1,6 +1,6 @@ --- title: "IconProvider" -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 icon provider component allows you to pass an object of icon instances to your application." updatedAt: "2025-06-08" docs: "once-ui/contexts/iconProvider.mdx" github: "contexts/IconProvider.tsx" diff --git a/apps/docs/src/content/once-ui/contexts/layoutProvider.mdx b/apps/docs/src/content/once-ui/contexts/layoutProvider.mdx index 4d9ab2a..9feaa4e 100644 --- a/apps/docs/src/content/once-ui/contexts/layoutProvider.mdx +++ b/apps/docs/src/content/once-ui/contexts/layoutProvider.mdx @@ -6,8 +6,6 @@ docs: "once-ui/contexts/layoutProvider.mdx" github: "contexts/LayoutProvider.tsx" navLabel: "LayoutProvider" navIcon: "chip" -navTag: "New" -navTagVariant: "cyan" --- The `LayoutProvider` component is a context provider that creates a listener for the Flex and Grid components to track window size. @@ -35,7 +33,7 @@ Wrap your app with `LayoutProvider`. ## Advanced setup -You can pass a breakpoint object to the `LayoutProvider`. These breakpoints will only be used by the Flex and Grid components to handle runtime logic, such as `hide` and `style`. Utility classes will be applied at the standard breakpoints. +You can pass a breakpoint object to the `LayoutProvider`. + } + codes={[ + { + code: +` `, + language: "tsx", + label: "MatrixFx" + } + ]} +/> + +## Speed + +Control the reveal animation speed with the `speed` prop. Higher values make the reveal faster. + + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Speed" + } + ]} +/> + +## Colors + +Use multiple colors for variety. Supports CSS variables and any valid color format. + + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Colors" + } + ]} +/> + +## Size & Spacing + +Customize the size of dots and spacing between them. + + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Size & Spacing" + } + ]} +/> + +## Direction + +Control where the reveal animation starts from. + + + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Direction" + } + ]} +/> + +## Content + +Place content inside the reveal effect. + + + + + + } + codes={[ + { + code: +`+ Canvas Reveal + ++ Animated dot matrix effect with native Canvas 2D + ++ `, + language: "tsx", + label: "Content" + } + ]} +/> + +## Flicker + +Add a subtle animated flicker to create a dynamic, alive feeling. + ++ ++ Canvas Reveal + ++ Animated dot matrix effect + ++ } + codes={[ + { + code: +` `, + language: "tsx", + label: "Flicker" + } + ]} +/> + +## Hover + +Use `trigger="hover"` for native hover support. Dots progressively appear on hover and smoothly reverse when you move away. + + + +
++ + + ++ + +
+ + } + codes={[ + { + code: +` ++ + + ++ + +
++ + + ++ + +
`, + language: "tsx", + label: "Hover" + } + ]} +/> + +## API reference + ++ + + ++ + diff --git a/apps/docs/src/content/once-ui/effects/meta.json b/apps/docs/src/content/once-ui/effects/meta.json index 3014460..e2c4691 100644 --- a/apps/docs/src/content/once-ui/effects/meta.json +++ b/apps/docs/src/content/once-ui/effects/meta.json @@ -1,5 +1,10 @@ { "title": "Effects", "order": 7, - "pages": {} + "pages": { + "matrixFx": 1, + "shineFx": 2, + "typeFx": 3, + "tiltFx": 4 + } } \ No newline at end of file diff --git a/apps/docs/src/content/once-ui/effects/shineFx.mdx b/apps/docs/src/content/once-ui/effects/shineFx.mdx new file mode 100644 index 0000000..2a031a1 --- /dev/null +++ b/apps/docs/src/content/once-ui/effects/shineFx.mdx @@ -0,0 +1,205 @@ +--- +title: "ShineFx" +summary: "Adds a smooth animated shine effect to text. Perfect for highlighting key features or creating eye-catching headings." +updatedAt: "2025-10-14" +docs: "once-ui/effects/shineFx.mdx" +github: "components/ShineFx.tsx" +navLabel: "ShineFx" +navIcon: "sparkle" +navTag: "New" +navTagVariant: "cyan" +--- + +ShineFx creates a smooth, animated shine effect that sweeps across text. The effect uses a gradient that moves horizontally, creating a shimmering appearance ideal for drawing attention to important text. + + + Thinking... + + } + codes={[ + { + code: +` + Shine bright like a diamond + `, + language: "tsx", + label: "Basic" + } + ]} +/> + +## Speed + +Adjust the animation speed with the `speed` prop. Higher values create slower animations, while lower values make the shine effect faster. + ++ + Fast shine (2s) + ++ Default shine (5s) + ++ Slow shine (10s) + + + } + codes={[ + { + code: +`+ Fast shine (2s) + + ++ Default shine (5s) + + ++ Slow shine (10s) + `, + language: "tsx", + label: "Speed" + } + ]} +/> + +## Base opacity + +Control the base text visibility with the `baseOpacity` prop (0-1). Higher values improve readability and accessibility, while lower values create a more subtle effect. + ++ + Subtle (0.1) + ++ Default (0.3) + ++ More visible (0.6) + ++ High visibility (0.9) + + + } + codes={[ + { + code: +`+ Subtle (0.1) + + ++ Default (0.3) + + ++ More visible (0.6) + + ++ High visibility (0.9) + `, + language: "tsx", + label: "Opacity" + } + ]} +/> + +## Disabled + +Disable the animation with the `disabled` prop to show static text without the shine effect. + ++ + Animated + ++ Disabled + + + } + codes={[ + { + code: +`+ Animated + + ++ Disabled + `, + language: "tsx", + label: "Disabled" + } + ]} +/> + +## Variants + +ShineFx works with all Text component variants and styling props. + ++ + Display variant + ++ Heading with color + ++ Body with color + + + } + codes={[ + { + code: +`+ Display variant + + ++ Heading with color + + ++ Body with color + `, + language: "tsx", + label: "Variants" + } + ]} +/> + +## API reference + +diff --git a/apps/docs/src/content/once-ui/effects/tiltFx.mdx b/apps/docs/src/content/once-ui/effects/tiltFx.mdx index 1aa77dd..08ac342 100644 --- a/apps/docs/src/content/once-ui/effects/tiltFx.mdx +++ b/apps/docs/src/content/once-ui/effects/tiltFx.mdx @@ -1,14 +1,16 @@ --- title: "TiltFx" summary: "Applies a subtle 3D tilt effect based on mouse movement. Ideal for interactive cards or media blocks." -updatedAt: "2025-05-11" +updatedAt: "2025-10-14" docs: "once-ui/effects/tiltFx.mdx" github: "components/TiltFx.tsx" navLabel: "TiltFx" navIcon: "sparkle" +navTag: "Update" +navTagVariant: "indigo" --- -TiltFx creates a depth-based tilt animation that follows the userโs mouse cursor. The effect is driven by `rotateX`/`rotateY` transforms and resets on mouse leave. Itโs designed for hoverable visual elements like images or feature blocks. +TiltFx creates a depth-based tilt animation that follows the user's mouse cursor. The effect is driven by `rotateX`/`rotateY` transforms and resets on mouse leave. It's designed for hoverable visual elements like images or feature blocks. Purple Worm `, language: "tsx", - label: "TiltFx" + label: "Basic" + } + ]} +/> + +## Intensity + +Control the strength of the tilt effect with the `intensity` prop. Lower values create a subtle effect, while higher values make it more dramatic. + + + + ++ + Default (1) + ++ + + } + codes={[ + { + code: +`+ + Strong (4) + ++ + ++ Default (1) ++ `, + language: "tsx", + label: "Intensity" } ]} /> @@ -47,6 +108,7 @@ TiltFx creates a depth-based tilt animation that follows the userโs mouse curs+ Strong (4) ++ Build{" "} + + } + codes={[ + { + code: +`+
`, + language: "tsx", + label: "TypeFx" + } + ]} +/> + +## Single word + +TypeFx can also display a single word that types out once without looping. + ++ Build + ++ + } + codes={[ + { + code: +` `, + language: "tsx", + label: "Single word" + } + ]} +/> + +## Custom trigger + +Use the `custom` trigger to programmatically control when the typing animation starts. + + + + + } + codes={[ + { + code: +`function TypeFxCustomExample() { + const triggerFnRef = useRef<(() => void) | null>(null); + + return ( + <> + { + triggerFnRef.current = fn; + }} + /> + + > + ); +}`, + language: "tsx", + label: "Custom trigger" + } + ]} +/> + +## API reference + + void) => void"], + ["...text", "TextProps"], + ]} +/> diff --git a/apps/docs/src/content/once-ui/form-controls/datePicker.mdx b/apps/docs/src/content/once-ui/form-controls/datePicker.mdx index 58e39ca..561f529 100644 --- a/apps/docs/src/content/once-ui/form-controls/datePicker.mdx +++ b/apps/docs/src/content/once-ui/form-controls/datePicker.mdx @@ -66,7 +66,7 @@ The DatePicker component provides an interactive calendar interface for selectin ["timePicker", "boolean", "false"], ["defaultDate", "Date"], ["defaultTime", "{ hours: number; minutes: number }"], - ["size", "'s' | 'm' | 'l'", "'m'"], + ["size", ["s", "m", "l"], "m"], ["currentMonth", "number", "Current month"], ["currentYear", "number", "Current year"], ["onMonthChange", "(increment: number) => void"], diff --git a/apps/docs/src/content/once-ui/form-controls/input.mdx b/apps/docs/src/content/once-ui/form-controls/input.mdx index 3ee7e30..6fb55e5 100644 --- a/apps/docs/src/content/once-ui/form-controls/input.mdx +++ b/apps/docs/src/content/once-ui/form-controls/input.mdx @@ -8,7 +8,7 @@ navLabel: "Input" navIcon: "switch" --- -import { ValidationInputExample } from "../../product/InputExample" +import { ValidationInputExample, CharacterCountExample } from "../../product/InputExample" The `Input` component provides a text entry field with floating labels, validation support, and customizable styling. Use it for collecting user input in forms. @@ -221,6 +221,37 @@ Use the `description` prop to add a description below the input. ]} /> +## Character count + +Display a character counter with color-coded feedback based on remaining characters. The counter changes color when approaching the limit. + + } + codes={[ + { + code: +`const [bio, setBio] = useState (""); + +const handleChange = (e: React.ChangeEvent ) => { + setBio(e.target.value); +}; + +`, + language: "tsx", + label: "Character count" + } + ]} +/> + ## NumberInput The `NumberInput` component provides a specialized input for numeric values with increment and decrement buttons. It supports min, max, and step values to control the range and increments. @@ -401,6 +432,7 @@ You can use the `radius` prop to apply custom radius to sides or corners. It wor ["radius", ["none", "top", "right", "bottom", "left", "top-left", "top-right", "bottom-right", "bottom-left"]], ["hasPrefix", "ReactNode"], ["hasSuffix", "ReactNode"], + ["characterCount", "boolean", "false"], ["cursor", ["interactive"]], ["validate", "(value: ReactNode) => ReactNode | null"], ["className"], diff --git a/apps/docs/src/content/once-ui/form-controls/textarea.mdx b/apps/docs/src/content/once-ui/form-controls/textarea.mdx index 9160688..1359a28 100644 --- a/apps/docs/src/content/once-ui/form-controls/textarea.mdx +++ b/apps/docs/src/content/once-ui/form-controls/textarea.mdx @@ -8,6 +8,8 @@ navLabel: "Textarea" navIcon: "switch" --- +import { ValidationTextareaExample, TextareaCharacterCountExample } from "../../product/TextareaExamples" + The `Textarea` component provides a multi-line text input field for collecting longer form text content from users. It supports various features like auto-resizing, validation, and custom styling. +## Character count + +Display a character counter with color-coded feedback based on remaining characters. The counter changes color when approaching the limit. + + } + codes={[ + { + code: +`const [bio, setBio] = useState (""); + +const handleChange = (e: React.ChangeEvent ) => { + setBio(e.target.value); +}; + +`, + language: "tsx", + label: "Character count" + } + ]} +/> + ## API reference ReactNode | null"], ["className"], diff --git a/apps/docs/src/content/once-ui/modules/codeBlock.mdx b/apps/docs/src/content/once-ui/modules/codeBlock.mdx index 317568f..f56c62d 100644 --- a/apps/docs/src/content/once-ui/modules/codeBlock.mdx +++ b/apps/docs/src/content/once-ui/modules/codeBlock.mdx @@ -6,8 +6,6 @@ github: "modules/code/CodeBlock.tsx" docs: "once-ui/modules/codeBlock.mdx" navLabel: "CodeBlock" navIcon: "modules" -navTag: "Update" -navTagVariant: "indigo" --- The `CodeBlock` component provides a way to display code snippets with syntax highlighting, interactive tabs for multiple code examples, and optional live previews. It supports various customization options including copy buttons, fullscreen mode, and line numbers. diff --git a/apps/docs/src/content/once-ui/modules/headingNav.mdx b/apps/docs/src/content/once-ui/modules/headingNav.mdx index 3a45909..bf6b570 100644 --- a/apps/docs/src/content/once-ui/modules/headingNav.mdx +++ b/apps/docs/src/content/once-ui/modules/headingNav.mdx @@ -6,6 +6,8 @@ docs: "once-ui/modules/headingNav.mdx" github: "modules/navigation/HeadingNav.tsx" navLabel: "HeadingNav" navIcon: "modules" +navTag: "Update" +navTagVariant: "indigo" --- The `HeadingNav` component provides an automatic table of contents navigation that diff --git a/apps/docs/src/content/once-ui/modules/kbar.mdx b/apps/docs/src/content/once-ui/modules/kbar.mdx index 6038fce..b641f9f 100644 --- a/apps/docs/src/content/once-ui/modules/kbar.mdx +++ b/apps/docs/src/content/once-ui/modules/kbar.mdx @@ -6,6 +6,8 @@ docs: "once-ui/modules/kbar.mdx" github: "modules/navigation/Kbar.tsx" navLabel: "Kbar" navIcon: "modules" +navTag: "Update" +navTagVariant: "indigo" --- The `Kbar` component provides a powerful command palette for your application, allowing users to quickly navigate and perform actions using keyboard shortcuts. It enhances productivity by providing a searchable interface for commands and navigation. diff --git a/apps/docs/src/content/once-ui/modules/megaMenu.mdx b/apps/docs/src/content/once-ui/modules/megaMenu.mdx index 59eabe8..1ebbdcc 100644 --- a/apps/docs/src/content/once-ui/modules/megaMenu.mdx +++ b/apps/docs/src/content/once-ui/modules/megaMenu.mdx @@ -1,11 +1,13 @@ --- title: "MegaMenu" summary: "MegaMenu displays a top-level navigation bar with expandable dropdowns for organized access to grouped links. It supports dynamic sizing and contextual visibility." -updatedAt: "2025-05-09" +updatedAt: "2025-10-06" docs: "once-ui/modules/megaMenu.mdx" github: "modules/navigation/MegaMenu.tsx" navLabel: "MegaMenu" navIcon: "modules" +navTag: "Update" +navTagVariant: "indigo" --- Use `MegaMenu` for complex navigational layouts where primary sections include sub-links, descriptions, and icons. Ideal for app headers and multi-level SaaS interfaces. @@ -55,6 +57,12 @@ Use `MegaMenu` for complex navigational layouts where primary sections include s icon: "settings", description: "Configure your preferences", }, + { + label: "Monitor", + href: "#", + icon: "screen", + description: "Monitor your metrics", + }, ], }, ], @@ -122,23 +130,6 @@ Use `MegaMenu` for complex navigational layouts where primary sections include s }, ], }, - { - title: "Support", - links: [ - { - label: "Help center", - href: "#", - icon: "help", - description: "Get your questions answered", - }, - { - label: "Community", - href: "#", - icon: "person", - description: "Connect with other users", - }, - ], - }, ], }, { @@ -358,14 +349,124 @@ Use `MegaMenu` for complex navigational layouts where primary sections include s ]} />`, language: "tsx", - label: "Megamenu" + label: "MegaMenu" + } + ]} +/> + +## Custom content + +You can use the `content` prop to render custom JSX instead of the default sections layout: + + + + + New Release + ++
+ + ), + }, + { + id: "products", + label: "Products", + href: "/products", + }, + ]} + /> + + } + codes={[ + { + code: +`+ ++ ++ AI Features ++ Agents and Chatbots + ++ ++ ++ Performance ++ 10x faster than before + ++ + New Release + ++
+ + ), + }, + ]} +/>`, + language: "tsx", + label: "Custom content" } ]} /> ## Usage -The `MegaMenu` component is designed for desktop screens. You can hide it at the medium breakpoint by adding the `hide="m"` prop directly to the component. +The `MegaMenu` component is designed for desktop screens. You can hide it at the medium breakpoint by adding the `m={{hide: true}}` prop directly to the component. ## API reference @@ -380,7 +481,7 @@ The `MegaMenu` component is designed for desktop screens. You can hide it at the ### Types -```ts +```tsx interface MenuGroup { id: string; label: ReactNode; @@ -388,6 +489,7 @@ interface MenuGroup { href?: string; selected?: boolean; sections?: MenuSection[]; + content?: ReactNode; // Custom content slot for dropdown } interface MenuSection { diff --git a/apps/docs/src/content/once-ui/modules/meta.json b/apps/docs/src/content/once-ui/modules/meta.json index ad8f99c..101022b 100644 --- a/apps/docs/src/content/once-ui/modules/meta.json +++ b/apps/docs/src/content/once-ui/modules/meta.json @@ -1,5 +1,8 @@ { "title": "Modules", "order": 3, - "pages": {} + "pages": { + "kbar": 1, + "megaMenu": 2 + } } \ No newline at end of file diff --git a/apps/docs/src/content/once-ui/modules/mobileMegaMenu.mdx b/apps/docs/src/content/once-ui/modules/mobileMegaMenu.mdx index 79c1c1a..43973cd 100644 --- a/apps/docs/src/content/once-ui/modules/mobileMegaMenu.mdx +++ b/apps/docs/src/content/once-ui/modules/mobileMegaMenu.mdx @@ -365,7 +365,7 @@ Use `MobileMegaMenu` as the mobile counterpart to `MegaMenu`. It supports dynami ## Usage -The `MobileMegaMenu` component is designed for mobile screens. You can hide it at the large breakpoint by adding the `hide="l"` prop directly to the component. Make sure you design a desktop navigation that works well with your app. +The `MobileMegaMenu` component is designed for mobile screens. You can hide it at the large breakpoint by adding the `hide` boolean prop directly to the component, and overwriting it at a breakpoint using the `hide={{l: false}}` prop. Make sure you design a desktop navigation that works well with your app. ## API reference @@ -380,7 +380,7 @@ The `MobileMegaMenu` component is designed for mobile screens. You can hide it a ### Types -```ts +```tsx interface MenuGroup { id: string; label: ReactNode; diff --git a/apps/docs/src/content/once-ui/quick-start.mdx b/apps/docs/src/content/once-ui/quick-start.mdx index d740ce0..796443f 100644 --- a/apps/docs/src/content/once-ui/quick-start.mdx +++ b/apps/docs/src/content/once-ui/quick-start.mdx @@ -9,7 +9,7 @@ navIcon: "learn" ## About -Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the [next generation](https://lorant.one/work/once-ui) of web applications. +Once UI is an open-source design system built for indie creators, small teams, and startups to fuel the next generation of web applications. Developed and maintained by [Lorant](https://lorant.one) and the [Design Engineers Club](https://designengineers.club). ## License diff --git a/apps/docs/src/content/magic-agent/meta.json b/apps/docs/src/content/products/magic-agent/meta.json similarity index 100% rename from apps/docs/src/content/magic-agent/meta.json rename to apps/docs/src/content/products/magic-agent/meta.json diff --git a/apps/docs/src/content/magic-agent/quick-start.mdx b/apps/docs/src/content/products/magic-agent/quick-start.mdx similarity index 100% rename from apps/docs/src/content/magic-agent/quick-start.mdx rename to apps/docs/src/content/products/magic-agent/quick-start.mdx diff --git a/apps/docs/src/content/magic-bio/meta.json b/apps/docs/src/content/products/magic-bio/meta.json similarity index 100% rename from apps/docs/src/content/magic-bio/meta.json rename to apps/docs/src/content/products/magic-bio/meta.json diff --git a/apps/docs/src/content/magic-bio/quick-start.mdx b/apps/docs/src/content/products/magic-bio/quick-start.mdx similarity index 100% rename from apps/docs/src/content/magic-bio/quick-start.mdx rename to apps/docs/src/content/products/magic-bio/quick-start.mdx diff --git a/apps/docs/src/content/magic-convert/meta.json b/apps/docs/src/content/products/magic-convert/meta.json similarity index 100% rename from apps/docs/src/content/magic-convert/meta.json rename to apps/docs/src/content/products/magic-convert/meta.json diff --git a/apps/docs/src/content/magic-convert/quick-start.mdx b/apps/docs/src/content/products/magic-convert/quick-start.mdx similarity index 100% rename from apps/docs/src/content/magic-convert/quick-start.mdx rename to apps/docs/src/content/products/magic-convert/quick-start.mdx diff --git a/apps/docs/src/content/magic-docs/changelog.mdx b/apps/docs/src/content/products/magic-docs/changelog.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/changelog.mdx rename to apps/docs/src/content/products/magic-docs/changelog.mdx diff --git a/apps/docs/src/content/magic-docs/components.mdx b/apps/docs/src/content/products/magic-docs/components.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/components.mdx rename to apps/docs/src/content/products/magic-docs/components.mdx diff --git a/apps/docs/src/content/magic-docs/meta.json b/apps/docs/src/content/products/magic-docs/meta.json similarity index 100% rename from apps/docs/src/content/magic-docs/meta.json rename to apps/docs/src/content/products/magic-docs/meta.json diff --git a/apps/docs/src/content/magic-docs/pages.mdx b/apps/docs/src/content/products/magic-docs/pages.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/pages.mdx rename to apps/docs/src/content/products/magic-docs/pages.mdx diff --git a/apps/docs/src/content/magic-docs/quick-start.mdx b/apps/docs/src/content/products/magic-docs/quick-start.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/quick-start.mdx rename to apps/docs/src/content/products/magic-docs/quick-start.mdx diff --git a/apps/docs/src/content/magic-docs/roadmap.mdx b/apps/docs/src/content/products/magic-docs/roadmap.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/roadmap.mdx rename to apps/docs/src/content/products/magic-docs/roadmap.mdx diff --git a/apps/docs/src/content/magic-docs/search.mdx b/apps/docs/src/content/products/magic-docs/search.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/search.mdx rename to apps/docs/src/content/products/magic-docs/search.mdx diff --git a/apps/docs/src/content/magic-docs/seo.mdx b/apps/docs/src/content/products/magic-docs/seo.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/seo.mdx rename to apps/docs/src/content/products/magic-docs/seo.mdx diff --git a/apps/docs/src/content/magic-docs/sidebar.mdx b/apps/docs/src/content/products/magic-docs/sidebar.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/sidebar.mdx rename to apps/docs/src/content/products/magic-docs/sidebar.mdx diff --git a/apps/docs/src/content/magic-docs/styling.mdx b/apps/docs/src/content/products/magic-docs/styling.mdx similarity index 100% rename from apps/docs/src/content/magic-docs/styling.mdx rename to apps/docs/src/content/products/magic-docs/styling.mdx diff --git a/apps/docs/src/content/magic-portfolio/blog.mdx b/apps/docs/src/content/products/magic-portfolio/blog.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/blog.mdx rename to apps/docs/src/content/products/magic-portfolio/blog.mdx diff --git a/apps/docs/src/content/magic-portfolio/content.mdx b/apps/docs/src/content/products/magic-portfolio/content.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/content.mdx rename to apps/docs/src/content/products/magic-portfolio/content.mdx diff --git a/apps/docs/src/content/magic-portfolio/localization.mdx b/apps/docs/src/content/products/magic-portfolio/localization.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/localization.mdx rename to apps/docs/src/content/products/magic-portfolio/localization.mdx diff --git a/apps/docs/src/content/magic-portfolio/mailchimp.mdx b/apps/docs/src/content/products/magic-portfolio/mailchimp.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/mailchimp.mdx rename to apps/docs/src/content/products/magic-portfolio/mailchimp.mdx diff --git a/apps/docs/src/content/magic-portfolio/meta.json b/apps/docs/src/content/products/magic-portfolio/meta.json similarity index 100% rename from apps/docs/src/content/magic-portfolio/meta.json rename to apps/docs/src/content/products/magic-portfolio/meta.json diff --git a/apps/docs/src/content/magic-portfolio/pages.mdx b/apps/docs/src/content/products/magic-portfolio/pages.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/pages.mdx rename to apps/docs/src/content/products/magic-portfolio/pages.mdx diff --git a/apps/docs/src/content/magic-portfolio/password.mdx b/apps/docs/src/content/products/magic-portfolio/password.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/password.mdx rename to apps/docs/src/content/products/magic-portfolio/password.mdx diff --git a/apps/docs/src/content/magic-portfolio/quick-start.mdx b/apps/docs/src/content/products/magic-portfolio/quick-start.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/quick-start.mdx rename to apps/docs/src/content/products/magic-portfolio/quick-start.mdx diff --git a/apps/docs/src/content/magic-portfolio/seo.mdx b/apps/docs/src/content/products/magic-portfolio/seo.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/seo.mdx rename to apps/docs/src/content/products/magic-portfolio/seo.mdx diff --git a/apps/docs/src/content/magic-portfolio/styling.mdx b/apps/docs/src/content/products/magic-portfolio/styling.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/styling.mdx rename to apps/docs/src/content/products/magic-portfolio/styling.mdx diff --git a/apps/docs/src/content/magic-portfolio/work.mdx b/apps/docs/src/content/products/magic-portfolio/work.mdx similarity index 100% rename from apps/docs/src/content/magic-portfolio/work.mdx rename to apps/docs/src/content/products/magic-portfolio/work.mdx diff --git a/apps/docs/src/content/magic-store/collections.mdx b/apps/docs/src/content/products/magic-store/collections.mdx similarity index 100% rename from apps/docs/src/content/magic-store/collections.mdx rename to apps/docs/src/content/products/magic-store/collections.mdx diff --git a/apps/docs/src/content/magic-store/compliance.mdx b/apps/docs/src/content/products/magic-store/compliance.mdx similarity index 100% rename from apps/docs/src/content/magic-store/compliance.mdx rename to apps/docs/src/content/products/magic-store/compliance.mdx diff --git a/apps/docs/src/content/magic-store/mailchimp.mdx b/apps/docs/src/content/products/magic-store/mailchimp.mdx similarity index 100% rename from apps/docs/src/content/magic-store/mailchimp.mdx rename to apps/docs/src/content/products/magic-store/mailchimp.mdx diff --git a/apps/docs/src/content/magic-store/meta.json b/apps/docs/src/content/products/magic-store/meta.json similarity index 100% rename from apps/docs/src/content/magic-store/meta.json rename to apps/docs/src/content/products/magic-store/meta.json diff --git a/apps/docs/src/content/magic-store/products.mdx b/apps/docs/src/content/products/magic-store/products.mdx similarity index 100% rename from apps/docs/src/content/magic-store/products.mdx rename to apps/docs/src/content/products/magic-store/products.mdx diff --git a/apps/docs/src/content/magic-store/promotions.mdx b/apps/docs/src/content/products/magic-store/promotions.mdx similarity index 100% rename from apps/docs/src/content/magic-store/promotions.mdx rename to apps/docs/src/content/products/magic-store/promotions.mdx diff --git a/apps/docs/src/content/magic-store/quick-start.mdx b/apps/docs/src/content/products/magic-store/quick-start.mdx similarity index 100% rename from apps/docs/src/content/magic-store/quick-start.mdx rename to apps/docs/src/content/products/magic-store/quick-start.mdx diff --git a/apps/docs/src/content/magic-store/seo.mdx b/apps/docs/src/content/products/magic-store/seo.mdx similarity index 100% rename from apps/docs/src/content/magic-store/seo.mdx rename to apps/docs/src/content/products/magic-store/seo.mdx diff --git a/apps/docs/src/content/magic-store/size-guide.mdx b/apps/docs/src/content/products/magic-store/size-guide.mdx similarity index 100% rename from apps/docs/src/content/magic-store/size-guide.mdx rename to apps/docs/src/content/products/magic-store/size-guide.mdx diff --git a/apps/docs/src/content/magic-store/styling.mdx b/apps/docs/src/content/products/magic-store/styling.mdx similarity index 100% rename from apps/docs/src/content/magic-store/styling.mdx rename to apps/docs/src/content/products/magic-store/styling.mdx diff --git a/apps/docs/src/content/products/meta.json b/apps/docs/src/content/products/meta.json new file mode 100644 index 0000000..61be0d0 --- /dev/null +++ b/apps/docs/src/content/products/meta.json @@ -0,0 +1,14 @@ +{ + "title": "Products", + "order": 2, + "pages": { + "magic-portfolio": 1, + "magic-docs": 2, + "magic-store": 3, + "magic-agent": 4, + "magic-bio": 5, + "magic-convert": 6, + "supabase-starter": 7, + "magic-spotlight": 8 + } +} \ No newline at end of file diff --git a/apps/docs/src/content/supabase-starter/meta.json b/apps/docs/src/content/products/supabase-starter/meta.json similarity index 100% rename from apps/docs/src/content/supabase-starter/meta.json rename to apps/docs/src/content/products/supabase-starter/meta.json diff --git a/apps/docs/src/content/supabase-starter/quick-start.mdx b/apps/docs/src/content/products/supabase-starter/quick-start.mdx similarity index 90% rename from apps/docs/src/content/supabase-starter/quick-start.mdx rename to apps/docs/src/content/products/supabase-starter/quick-start.mdx index 32e4dd3..f1235f5 100644 --- a/apps/docs/src/content/supabase-starter/quick-start.mdx +++ b/apps/docs/src/content/products/supabase-starter/quick-start.mdx @@ -1,7 +1,7 @@ --- title: "Quick start" -summary: "Magic Agent is a deployment-ready chatbot template built with the Vercel AI SDK." -image: "/images/docs/magic-agent.jpg" +summary: "Supabase Starter is a deployment-ready web-app template built with Supabase auth, Upstash Redis and Once UI." +image: "/images/docs/supabase-starter.jpg" updatedAt: "2025-08-04" navLabel: "Quick start" navIcon: "learn" diff --git a/apps/docs/src/product/AnimationExample.tsx b/apps/docs/src/product/AnimationExample.tsx new file mode 100644 index 0000000..dfdd743 --- /dev/null +++ b/apps/docs/src/product/AnimationExample.tsx @@ -0,0 +1,57 @@ +"use client"; + +import { useState } from "react"; +import { Animation, NavIcon, Dropdown, Option, ArrowNavigation } from "@once-ui-system/core"; + +export function AnimationNavIconExample() { + const [isActive, setIsActive] = useState(false); + + const handleToggle = () => { + setIsActive(!isActive); + }; + + const handleOptionClick = () => { + setIsActive(false); + }; + + return ( ++ ++ ++ AI Features ++ Explore our new AI-powered tools + ++ ++ ++ Performance ++ 10x faster than before + ++ } + slideDown={1} + triggerType="manual" + duration={300} + active={isActive} + > + + + + ); +} diff --git a/apps/docs/src/product/Cta.tsx b/apps/docs/src/product/Cta.tsx index adbfba9..3b67e8c 100644 --- a/apps/docs/src/product/Cta.tsx +++ b/apps/docs/src/product/Cta.tsx @@ -1,35 +1,78 @@ -import { Row, Button, Mask, Particle, Text, Column } from "@once-ui-system/core"; +import { Row, Button, Mask, Particle, Column, TypeFx, Background } from "@once-ui-system/core"; export const Cta = () => { return ( -+ + + + +- +-
--
-
--
-
- Ship your product -. --
-
-
-
-+ + fill + lines={{ + display: true, + color: "neutral-alpha-weak", + angle: -45, + size: "4" + }}/> ++
+ - - +
++ + +
+
+
- -+ + + + ++ + + ); }; \ No newline at end of file diff --git a/apps/docs/src/product/EmojiPickerDropdownExample.tsx b/apps/docs/src/product/EmojiPickerDropdownExample.tsx new file mode 100644 index 0000000..4aa3e83 --- /dev/null +++ b/apps/docs/src/product/EmojiPickerDropdownExample.tsx @@ -0,0 +1,144 @@ +"use client"; + +import React, { useState } from "react"; +import { + Button, + EmojiPickerDropdown, + IconButton, + Row, + Text, +} from "@once-ui-system/core"; + +export function BasicEmojiPickerDropdown() { + const [selectedEmoji, setSelectedEmoji] = useState(""); + + return ( +
+
+ ); +} + +export function IconButtonEmojiPickerDropdown() { + const [selectedEmoji, setSelectedEmoji] = useState(""); + + return ( +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + /> + {selectedEmoji && ( + + Selected: {selectedEmoji} + + )} ++
+ ); +} + +export function CustomColumnsEmojiPickerDropdown() { + const [selectedEmoji, setSelectedEmoji] = useState(""); + + return ( +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} ++
+ ); +} + +export function PlacementEmojiPickerDropdown() { + const [selectedEmoji, setSelectedEmoji] = useState(""); + + return ( +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + columns="10" + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} ++
+ ); +} + +export function CustomBackgroundEmojiPickerDropdown() { + const [selectedEmoji, setSelectedEmoji] = useState(""); + + return ( +} + 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} + + )} ++
+ ); +} + +export function ControlledEmojiPickerDropdown() { + const [isOpen, setIsOpen] = useState(false); + const [selectedEmoji, setSelectedEmoji] = useState(""); + + return ( +} + onSelect={(emoji) => setSelectedEmoji(emoji)} + background="neutral-weak" + /> + {selectedEmoji && ( + + {selectedEmoji} + + )} ++
+ ); +} diff --git a/apps/docs/src/product/Footer.tsx b/apps/docs/src/product/Footer.tsx index a6c4aa9..1862b88 100644 --- a/apps/docs/src/product/Footer.tsx +++ b/apps/docs/src/product/Footer.tsx @@ -1,50 +1,59 @@ -import { social } from "@/resources"; -import { Column, IconButton, Logo, Row, SmartLink, Tag, Text } from "@once-ui-system/core"; +import { layout, social } from "@/resources"; +import { Avatar, Background, Column, IconButton, Logo, Row, SmartLink, Tag, Text } from "@once-ui-system/core"; import { Cta } from "./Cta"; const navigation = [ { title: "Products", - items: [ + free: [ { label: "All Products", href: "https://once-ui.com/products" }, { label: "Once UI Core", href: "https://once-ui.com/products/once-ui-core" }, - { label: "Magic Agent", href: "https://once-ui.com/products/magic-agent", tag: "New" }, { label: "Magic Portfolio", href: "https://once-ui.com/products/magic-portfolio" }, - { label: "Magic Convert", href: "https://once-ui.com/products/magic-convert" }, - { label: "Magic Store", href: "https://once-ui.com/products/magic-store" }, { label: "Magic Docs", href: "https://once-ui.com/products/magic-docs" }, { label: "Magic Bio", href: "https://once-ui.com/products/magic-bio" }, - { label: "Once UI Blocks", href: "https://once-ui.com/blocks/quickStart" }, { label: "Once UI Figma", href: "https://once-ui.com/figma" }, ], + pro: [ + { label: "Magic Spotlight", href: "https://once-ui.com/products/magic-spotlight", tag: "New" }, + { label: "Supabase Starter", href: "https://once-ui.com/products/supabase-starter", tag: "New" }, + { label: "Magic Agent", href: "https://once-ui.com/products/magic-agent" }, + { label: "Magic Convert", href: "https://once-ui.com/products/magic-convert" }, + { label: "Magic Store", href: "https://once-ui.com/products/magic-store" }, + { label: "Once UI Blocks", href: "https://once-ui.com/blocks/quickStart" }, + ] }, { title: "Learn", - items: [ + free: [ { label: "Customize", href: "https://once-ui.com/customize" }, { label: "Once UI Core docs", href: "/once-ui/quick-start" }, - { label: "Magic Agent docs", href: "/magic-agent/quick-start" }, - { label: "Magic Portfolio docs", href: "/once-ui/quick-start" }, - { label: "Magic Convert docs", href: "/magic-convert/quick-start" }, - { label: "Magic Store docs", href: "/once-ui/quick-start" }, - { label: "Magic Docs docs", href: "/once-ui/quick-start" }, - { label: "Magic Bio docs", href: "/once-ui/quick-start" }, + { label: "Magic Portfolio docs", href: "/magic-portfolio/quick-start" }, + { label: "Magic Docs docs", href: "/magic-docs/quick-start" }, + { label: "Magic Bio docs", href: "/magic-bio/quick-start" }, { label: "Roadmap", href: "/roadmap" }, { label: "Changelog", href: "/changelog" }, ], + pro: [ + { label: "Supabase Starter docs", href: "/supabase-starter/quick-start" }, + { label: "Magic Agent docs", href: "/magic-agent/quick-start" }, + { label: "Magic Convert docs", href: "/magic-convert/quick-start" }, + { label: "Magic Store docs", href: "/magic-store/quick-start" }, + ] }, { title: "Resources", - items: [ + resources: [ { label: "Pricing", href: "https://once-ui.com/pricing" }, { label: "Blog", href: "https://once-ui.com/blog" }, { label: "About us", href: "https://once-ui.com/about" }, { label: "Merch store", href: "https://store.dopler.app" }, { label: "Brand assets", href: "https://once-ui.com/brand" }, + ], + legal: [ { label: "Terms of Use", href: "https://dopler.app/terms" }, { label: "Privacy Policy", href: "https://dopler.app/privacy" }, { label: "License Agreement", href: "https://dopler.app/license" }, - ], + ] }, { title: "Hub", @@ -57,72 +66,257 @@ const navigation = [ const Footer = () => { return ( -} + onSelect={(emoji) => setSelectedEmoji(emoji)} + isOpen={isOpen} + onOpenChange={setIsOpen} + /> + - ); diff --git a/apps/docs/src/product/Header.tsx b/apps/docs/src/product/Header.tsx index c95bf5a..fcab5b1 100644 --- a/apps/docs/src/product/Header.tsx +++ b/apps/docs/src/product/Header.tsx @@ -2,7 +2,7 @@ import { usePathname } from "next/navigation"; import { useState, useEffect } from "react"; -import { Button, Fade, Flex, Logo, NavIcon, Row, Kbar, useTheme } from "@once-ui-system/core"; +import { Button, Flex, Logo, NavIcon, Row, Kbar, useTheme, Animation } from "@once-ui-system/core"; import { layout, routes } from "@/resources/once-ui.config"; import { Sidebar, NavigationItem } from "./Sidebar"; @@ -152,22 +152,35 @@ export function Header() { return ( <> -- -
- +-
- - - {social.map((item, index) => ( -
+ + +
+ ++ + + +
+
++ + ++
++ + + + ++
++ + + {social.map((item, index) => ( +
++ ))} + + {navigation.map((section) => ( +
++ ))}+ {section.title} + + {[ + { key: "free", label: "Free" }, + { key: "pro", label: "Pro" }, + { key: "resources", label: "Resources" }, + { key: "legal", label: "Legal" }, + { key: "items", label: undefined }, + ].map(({ key, label }) => { + const arr = (section as any)[key] as Array| undefined; + if (!arr || arr.length === 0) return null; + return ( + + {label && ( + + ); + })} ++ {label} + + )} + {arr.map((item: any) => ( ++ + ))} ++ {item.label} + + {item.tag && ( ++ {item.tag} + + )} ++
-+ - {navigation.map((section) => ( -
+ +- - ))} +- {section.title} - - {section.items.map((item) => ( -- - ))} -- {item.label} - - {item.tag && ( -- {item.tag} - - )} -+
+
-+ |
- Once UI is an open-source project by{" "} +
+ Built with curiosity by{" "}
-- - - Dopler + + Lorant One +
+
++ + + - + - - {sidebarVisible && ( - |
-
- - + + }> + ++
++ + - )} > ); }; diff --git a/apps/docs/src/product/InputExamples.tsx b/apps/docs/src/product/InputExamples.tsx index 45ac9bb..155de97 100644 --- a/apps/docs/src/product/InputExamples.tsx +++ b/apps/docs/src/product/InputExamples.tsx @@ -79,6 +79,25 @@ export function ValidationInputExample() { ); } +export function CharacterCountExample() { + const [bio, setBio] = useState (""); + + const handleChange = (e: React.ChangeEvent ) => { + setBio(e.target.value); + }; + + return ( + + ); +} + // Color input example with managed state export function ColorInputExample() { const [colorValue, setColorValue] = useState("#4287f5"); diff --git a/apps/docs/src/product/NavIconExample.tsx b/apps/docs/src/product/NavIconExample.tsx index 0a729b1..298b18d 100644 --- a/apps/docs/src/product/NavIconExample.tsx +++ b/apps/docs/src/product/NavIconExample.tsx @@ -22,8 +22,8 @@ export function NavIconToggle() { vertical="center" fillWidth > - - + + + {[ { title: "Once UI Core", @@ -30,6 +30,12 @@ export function Products() { image: "/images/docs/magic-store.jpg", href: "/magic-store/quick-start" }, + { + title: "Supabase Starter", + description: "Set up a database and authentication in minutes", + image: "/images/docs/supabase-starter.jpg", + href: "/supabase-starter/quick-start" + }, { title: "Magic Convert", description: "Launch your conversion-optimized landing page", @@ -59,8 +65,8 @@ export function Products() { paddingX="4" > -
- + + Once UI = ({ children }) => { if (loading) { return ( - + ); diff --git a/apps/docs/src/product/Sidebar.tsx b/apps/docs/src/product/Sidebar.tsx index d9de4ac..1ec7eef 100644 --- a/apps/docs/src/product/Sidebar.tsx +++ b/apps/docs/src/product/Sidebar.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useEffect, useState, useMemo } from "react"; -import { Schemes, Accordion, Column, Flex, Icon, Row, Tag, ToggleButton } from "@once-ui-system/core"; +import { Schemes, Accordion, Column, Flex, Icon, Row, Tag, ToggleButton, Text, Mask, MatrixFx, Card, Hover, Background, Animation, Button, Spinner, Skeleton } from "@once-ui-system/core"; import { usePathname } from 'next/navigation'; import { routes, layout } from "@/resources"; @@ -334,26 +334,48 @@ const Sidebar: React.FC = ({ initialNavigation, ...rest }) => { } }, [initialNavigation, hasLoaded]); - // Create a stable container that doesn't change - const containerStyle = useMemo(() => ({ - maxHeight: "calc(100vh - var(--static-space-80))" - }), []); - return ( - - {hasLoaded && ); }; diff --git a/apps/docs/src/product/TextareaExamples.tsx b/apps/docs/src/product/TextareaExamples.tsx index 996a946..f4a10d2 100644 --- a/apps/docs/src/product/TextareaExamples.tsx +++ b/apps/docs/src/product/TextareaExamples.tsx @@ -29,3 +29,23 @@ export function ValidationTextareaExample() { /> ); } + +export function TextareaCharacterCountExample() { + const [bio, setBio] = useState} + minWidth={layout.sidebar.width} + paddingY="4" + {...rest}> + + {hasLoaded ? ( + + ) : ( + + {Array.from({ length: 7 }).map((_, i) => ( + + )} ++
+ ))} ++
++ +
++ ++ + + +Get Once UI Pro +Build a digital presence with deployment-ready apps + +(""); + + const handleChange = (e: React.ChangeEvent ) => { + setBio(e.target.value); + }; + + return ( + + ); +} diff --git a/apps/docs/src/product/TypeFxCustomExample.tsx b/apps/docs/src/product/TypeFxCustomExample.tsx new file mode 100644 index 0000000..19e780e --- /dev/null +++ b/apps/docs/src/product/TypeFxCustomExample.tsx @@ -0,0 +1,25 @@ +'use client'; + +import { useRef } from 'react'; +import { TypeFx, Button, Column } from "@once-ui-system/core"; + +export const TypeFxCustomExample = () => { + const triggerFnRef = useRef<(() => void) | null>(null); + + return ( + + + ); +}; diff --git a/apps/docs/src/product/index.ts b/apps/docs/src/product/index.ts index 6633ae0..7239613 100644 --- a/apps/docs/src/product/index.ts +++ b/apps/docs/src/product/index.ts @@ -3,6 +3,7 @@ export * from "./Footer"; export * from "./Sidebar"; export * from "./RouteGuard"; export * from "./Providers"; +export * from "./AnimationExample"; export * from "./CheckboxExample"; export * from "./ChipExamples"; export * from "./ClientOption"; @@ -12,6 +13,7 @@ export * from "./DateRangeInputExamples"; export * from "./DialogExample"; export * from "./DropdownExample"; export * from "./DropdownWrapperExample"; +export * from "./EmojiPickerDropdownExample"; export * from "./InfiniteScrollExample"; export * from "./InputExamples"; export * from "./InteractiveDetailsExamples"; @@ -23,4 +25,5 @@ export * from "./RadioButtonExample"; export * from "./SwitchExample"; export * from "./TextareaExamples"; export * from "./ToastExample"; +export * from "./TypeFxCustomExample"; export * from "./Products"; \ No newline at end of file diff --git a/apps/docs/src/product/mdx.tsx b/apps/docs/src/product/mdx.tsx index c2415c3..24598b9 100644 --- a/apps/docs/src/product/mdx.tsx +++ b/apps/docs/src/product/mdx.tsx @@ -17,26 +17,10 @@ const onceUIComponents = allComponents; function CustomLink({ href, children, ...props }: CustomLinkProps) { - if (href.startsWith("/")) { - return ( -{ + triggerFnRef.current = fn; + }} + /> + + - {children} - - ); - } - - if (href.startsWith("#")) { - return ( - - {children} - - ); - } - return ( - +{children} - + ); } diff --git a/apps/docs/src/resources/changelog.js b/apps/docs/src/resources/changelog.js index 9a983f1..0b06225 100644 --- a/apps/docs/src/resources/changelog.js +++ b/apps/docs/src/resources/changelog.js @@ -1,8 +1,53 @@ +import { SmartLink, InlineCode } from "@once-ui-system/core"; + const changelog = [ + { + date: "2025-10-19", + title: "Once UI 1.5: Curiosity in code", + image: "/images/changelog/once-ui-1-5.jpg", + sections: [ + { + title: "New components", + bullets: [ + <>Hover : Minimal component for overlaying elements>, + <>Animation : Robust component for complex interactions>, + <>HoverCard : Portal-based element with Animation>, + <>Timeline : Static timeline with various data elements>, + <>Swiper : Multi-image with gestures and dragging>, + <>TypeFx : Typewriter-style animation>, + <>MatrixFx : Canvas-based dot pattern animation>, + <>ShineFx : Shining text effect>, + ], + }, + { + title: "Component improvements", + bullets: [ + <>Flex : Custom breakpoint support, scrollbar customization, radius 'full' for individual corners>, + <>Button : rounded prop for a fully rounded style (shorthand for data-border)>, + <>Background : Better visual rendering for background lines>, + <>Card : Improved border radius, removed hover effect on tap>, + <>Input ,Textarea : Native char count support for maxLength>, + <>MegaMenu : Better animations, custom content support, less re-rendering>, + <>Icon ,IconButton ,HeadingLink : Refactored with Animation component>, + <>HeadingNav : Default heading for element>, + <>Tooltip : Fadein animation support>, + <>Heading ,Text : Display size line-height adjustments and support forxs andxl label sizes>, + <>TiltFx : Distortion amount support>, + ] + }, + { + title: "Accessibility improvements", + bullets: [ + <>DropdownWrapper : Scroll lock and better hover + arrow key handling>, + <>EmojiPicker : Refactored scroll behavior and performance>, + ], + } + ] + }, { date: "2025-07-30", - title: "Once UI v1.4", - image: "/api/og/generate?title=Once UI v1.4&description=Next level devX", + title: "Once UI 1.4: Next level devX", + image: "/api/og/generate?title=Once UI 1.4&description=Next level devX", description: "Once UI v1.4 is here with new components and enhanced developer experience.", sections: [ { diff --git a/apps/docs/src/resources/custom.scss b/apps/docs/src/resources/custom.scss new file mode 100644 index 0000000..2393bab --- /dev/null +++ b/apps/docs/src/resources/custom.scss @@ -0,0 +1,11 @@ +:root { + --font-size-display-multiplier: 1; + --font-size-heading-multiplier: 1; + --font-size-body-multiplier: 1; + --font-size-label-multiplier: 1; + + --line-height-display-multiplier: 1; + --line-height-heading-multiplier: 1; + --line-height-body-multiplier: 1; + --line-height-label-multiplier: 1; +} \ No newline at end of file diff --git a/apps/docs/src/resources/icons.ts b/apps/docs/src/resources/icons.ts index 513af40..baced61 100644 --- a/apps/docs/src/resources/icons.ts +++ b/apps/docs/src/resources/icons.ts @@ -60,6 +60,8 @@ import { HiOutlineChartPie, HiOutlineArrowTrendingUp, HiOutlineCpuChip, + HiOutlineTruck, + HiOutlineArchiveBox, } from "react-icons/hi2"; import { LiaCubesSolid } from "react-icons/lia"; @@ -104,7 +106,6 @@ export const iconLibrary: Record= { visa: RiVisaLine, security: HiOutlineShieldCheck, sparkle: HiOutlineSparkles, - document: HiOutlineBars3BottomLeft, linkedin: FaLinkedin, analytics: HiOutlineDocumentChartBar, threads: FaThreads, @@ -144,7 +145,9 @@ export const iconLibrary: Record = { lineChart: HiOutlineArrowTrendingUp, pieChart: HiOutlineChartPie, lineBarChart: HiOutlinePresentationChartLine, - chip: HiOutlineCpuChip + chip: HiOutlineCpuChip, + truck: HiOutlineTruck, + package: HiOutlineArchiveBox, }; export type IconLibrary = typeof iconLibrary; diff --git a/apps/docs/src/resources/once-ui.config.js b/apps/docs/src/resources/once-ui.config.js index 0ab9176..66b6a4b 100644 --- a/apps/docs/src/resources/once-ui.config.js +++ b/apps/docs/src/resources/once-ui.config.js @@ -8,12 +8,12 @@ const routes = { const style = { theme: "system", // dark | light neutral: "gray", // sand | gray | slate - brand: "indigo", // blue | indigo | violet | magenta | pink | red | orange | yellow | moss | green | emerald | aqua | cyan + brand: "blue", // blue | indigo | violet | magenta | pink | red | orange | yellow | moss | green | emerald | aqua | cyan accent: "indigo", // blue | indigo | violet | magenta | pink | red | orange | yellow | moss | green | emerald | aqua | cyan solid: "contrast", // color | contrast solidStyle: "flat", // flat | plastic border: "playful", // rounded | playful | conservative - surface: "translucent", // filled | translucent + surface: "filled", // filled | translucent transition: "all", // all | micro | macro scaling: "100" }; diff --git a/apps/docs/src/resources/roadmap.js b/apps/docs/src/resources/roadmap.js index e754364..74ceb95 100644 --- a/apps/docs/src/resources/roadmap.js +++ b/apps/docs/src/resources/roadmap.js @@ -1,31 +1,16 @@ const roadmap = [ { - product: "Once UI OSS", + product: "Once UI Core", brand: "blue", columns: [ { title: "Planned", tasks: [ - { - title: "Smartlink preview", - description: "Optional prop to preview OG data on hover.", - type: "improvement" - }, - { - title: "Text highlights", - description: "Add highlight effects (svg) to text.", - type: "feature" - }, { title: "StylePanel refactoring", description: "Make stylepanel composable and add additional edit options like custom colors.", type: "feature" }, - { - title: "OgCard", - description: "Update OgCard docs with display prop. (Related: OgCard improvements)", - type: "documentation" - }, { title: "Chart states", description: "Add state examples to chart docs. (Related: Chart error state)", @@ -47,85 +32,10 @@ const roadmap = [ title: "Done", tasks: [ { - title: "Codeblock higlhight", - description: "Fix highlight issue when switching between Codeblock tabs.", - type: "bug" - }, - { - title: "Flex & Grid breakpoint objects", - description: "Override props based on breakpoint.", - type: "improvement" - }, - { - title: "Logo copy svg + visit brand page", - description: "Add svg copy to logo and optional link to visit brand page.", - type: "improvement" - }, - { - title: "ContextMenu", - description: "New component: Context menu on right click.", + title: "Once UI 1.5", + description: "New Once UI 1.5 components and documentation.", type: "feature" }, - { - title: "Accordion auto-collapse", - description: "Optional prop to collapse other accordions when opening a new one.", - type: "improvement" - }, - { - title: "Chart error state", - description: "Add error state to chart components.", - type: "improvement" - }, - { - title: "Media caption", - description: "Add optional caption to the Media component.", - type: "improvement" - }, - { - title: "OgCard improvements", - description: "Add size prop and data overrides separately.", - type: "improvement" - }, - { - title: "ProgressBar", - description: "New component: Progress bar.", - type: "feature" - }, - { - title: "Custom cursor", - description: "Allow Flex and Grid to support custom cursor elements as ReactNode.", - type: "feature" - }, - { - title: "List and ListItem", - description: "New List and ListItem components.", - type: "feature" - }, - { - title: "Select multiple options", - description: "Add option for Select to handle multiple options.", - type: "feature" - }, - { - title: "Number animations", - description: "Create component to handle number animations.", - type: "feature" - }, - { - title: "Carousel effects", - description: "Rework timing functions in RevealFx and Carousel.", - type: "improvement" - }, - { - title: "BlockQuote", - description: "New component: Block quote and remove default styles from global.scss.", - type: "feature" - }, - { - title: "Datepicker accessibility", - description: "Add arrow navigation and use Options instead of Buttons.", - type: "bug" - }, ] } ] @@ -137,60 +47,24 @@ const roadmap = [ { title: "Planned", tasks: [ - ] - }, - { - title: "In Progress", - tasks: [ - { - title: "Magic Connect", - description: "New social media app product template.", - type: "feature" - }, - ] - }, - { - title: "Done", - tasks: [ - { - title: "Blocks page", - description: "Rework the page layout and UI.", - type: "feature" - }, { - title: "Comments", - description: "Add comment system UI to Blocks.", + title: "Once UI 1.5 blocks", + description: "New Once UI 1.5 blocks.", type: "feature" }, - { - title: "Improve block designs", - description: "Rework block UI and improve aesthetics.", - type: "improvement" - }, { title: "Magic Agent", - description: "New chat agent product template.", - type: "feature" + description: "Upgrade to latest AI SDK.", + type: "improvement" }, ] }, - ] - }, - { - product: "Magic Convert", - brand: "green", - columns: [ - { - title: "Planned", - tasks: [ - ] - }, { title: "In Progress", tasks: [ { - title: "Product page designs", - description: "Create designs for product pages.", + title: "Supa Hub", + description: "Monorepo with multiple social media frontends and a single backend.", type: "feature" }, ] @@ -198,13 +72,8 @@ const roadmap = [ { title: "Done", tasks: [ - { - title: "Brand guidelines page", - description: "Create brand guidelines page. (Related: Logo copy svg + visit brand page)", - type: "feature" - }, ] - } + }, ] }, { @@ -264,109 +133,6 @@ const roadmap = [ } ] }, - { - product: "Magic Bio", - brand: "emerald", - columns: [ - { - title: "Planned", - tasks: [ - ] - }, - { - title: "In Progress", - tasks: [ - { - title: "Add OG data overrides", - description: "Add OG data overrides to links. (Related: OgCard improvements)", - type: "improvement" - }, - ] - }, - { - title: "Done", - tasks: [ - ] - } - ] - }, - { - product: "Once UI Hub", - brand: "cyan", - columns: [ - { - title: "Planned", - tasks: [ - { - title: "Notifications", - description: "Notification center for project updates and comments.", - type: "feature" - }, - { - title: "Post formats", - description: "Support for different post formats.", - type: "feature" - }, - { - title: "Achievements", - description: "Add achievements to profile page.", - type: "feature" - }, - { - title: "Testimonials", - description: "Submit testimonials and display on Once UI landing pages.", - type: "feature" - }, - ] - }, - { - title: "In Progress", - tasks: [ - ] - }, - { - title: "Done", - tasks: [ - { - title: "Drafts", - description: "Add new draft status that hides posts from feed and search.", - type: "feature" - }, - ] - } - ] - }, - { - product: "Design Engineers Club", - brand: "aqua", - columns: [ - { - title: "Planned", - tasks: [ - { - title: "New landing page", - description: "Create a new home for our community.", - type: "feature" - }, - ] - }, - { - title: "In Progress", - tasks: [ - ] - }, - { - title: "Done", - tasks: [ - { - title: "Merch drop", - description: "New mascot design for Once UI and merch line", - type: "feature" - }, - ] - } - ] - } ]; const task = { diff --git a/packages/core/README.md b/packages/core/README.md deleted file mode 100644 index 63ea590..0000000 --- a/packages/core/README.md +++ /dev/null @@ -1,159 +0,0 @@ -# Once UI - -A design system for indie builders who move fast and break limits without neglecting quality. Once UI combines the simplicity of low-code with the power of code: write 70% less compared to shadcn + tailwind. - -* **Customization**: Manage design config with the ThemeProvider context. -* **Components**: Access advanced components with simple APIs. -* **Data-viz**: Add responsive charts with a few lines of code. -* **SEO**: Use SEO components to simplify meta and schema setup. - -## Installation - -```bash -npm install @once-ui-system/core -# or -yarn add @once-ui-system/core -# or -pnpm add @once-ui-system/core -``` - -## Documentation - -Learn how to build with Once UI at [docs.once-ui.com](https://docs.once-ui.com/once-ui/quick-start). - -## Setup - -Import styles and tokens in your root layout file: - -```js -// Import the pre-compiled CSS files -import '@once-ui-system/core/css/styles.css'; -import '@once-ui-system/core/css/tokens.css'; -``` - -Create a `Providers.tsx` component: - -```js -"use client"; - -import { DataThemeProvider, IconProvider, ThemeProvider, ToastProvider } from "@once-ui-system/core"; - -export function Providers({ children }: { children: React.ReactNode }) { - return ( - - - ); -} -``` - -Wrap your app with the `Providers` component in your root layout: - -```js -import { Providers } from "./providers"; - -export default function RootLayout({ children }: { - children: React.ReactNode -}) { - return ( -- -- -- {children} - -- {children} - - ); -} -``` - -Prevent flash of unstyled content (FOUC) by adding the following script to the `` of your root layout: - -```js - -