Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
4701d99
chore(deps): add deps for command pallete
Dinil-Thilakarathne Nov 30, 2025
6912db9
feat: update mdx content
Dinil-Thilakarathne Nov 30, 2025
a3efc0e
feat: update site styles
Dinil-Thilakarathne Nov 30, 2025
6f0e601
feat: implement global documentation search with command palette func…
Dinil-Thilakarathne Nov 30, 2025
48a0c60
Merge pull request #40 from Dinil-Thilakarathne/feat/comp-searching
Dinil-Thilakarathne Nov 30, 2025
c99249b
fix: improve sidebar layout (#46)
Dinil-Thilakarathne Dec 3, 2025
88c6c2b
Fix/component search component (#48)
Dinil-Thilakarathne Dec 3, 2025
654ac1c
fix: add theme provider (#50)
Dinil-Thilakarathne Dec 3, 2025
d1fe0b0
fix: update site header ui (#52)
Dinil-Thilakarathne Dec 3, 2025
7bdbe64
fix/sidebar layout (#53)
Dinil-Thilakarathne Dec 3, 2025
36a59b5
Fix/sidebar layout (#54)
Dinil-Thilakarathne Dec 3, 2025
a15250d
fix: update sidebar ui
Dinil-Thilakarathne Dec 3, 2025
0657509
Merge branch 'master' into dev
Dinil-Thilakarathne Dec 3, 2025
5a11917
fix: update core dependencies (fix CVE-2025-55182 issues).
Dinil-Thilakarathne Dec 6, 2025
69da0eb
chore: update packages
Dinil-Thilakarathne Jan 12, 2026
f656e6e
chore: add fumadocs-ui
Dinil-Thilakarathne Jan 12, 2026
557a459
style: update site custom theme variables
Dinil-Thilakarathne Jan 12, 2026
684a81a
refactor: use kebab-case for the component file naming
Dinil-Thilakarathne Jan 12, 2026
8491ccc
chore: update deps
Dinil-Thilakarathne Jan 13, 2026
9ce8385
chore: add new deps for icons
Dinil-Thilakarathne Jan 13, 2026
b89c17f
feat: migare camel case file names to the kebab case file naming
Dinil-Thilakarathne Jan 13, 2026
9e642ee
feat: update registry prebuild command
Dinil-Thilakarathne Jan 13, 2026
89ad86a
style: update the layout of the code preview comp
Dinil-Thilakarathne Jan 16, 2026
293f295
chore: add cva deps for manage variants classes
Dinil-Thilakarathne Jan 19, 2026
8e7779a
feat: update library registry
Dinil-Thilakarathne Jan 19, 2026
8c55932
feat: update site core ui components
Dinil-Thilakarathne Jan 19, 2026
e0f33a3
feat: update accordion comp
Dinil-Thilakarathne Jan 19, 2026
11fb8fd
feat: refactor code block styling.
Dinil-Thilakarathne Jan 19, 2026
5238733
refactor: update the filename that follows the kebbab style
Dinil-Thilakarathne Feb 1, 2026
0cd1fec
style: update component style that follows the site theme
Dinil-Thilakarathne Feb 1, 2026
137f443
refactor: remove flaoting copy icon from the codeblock
Dinil-Thilakarathne Feb 1, 2026
08dd3e4
refactor: update files name to follow kebbab format
Dinil-Thilakarathne Feb 1, 2026
04335d8
refactor: remove component wrapper component component example files
Dinil-Thilakarathne Feb 1, 2026
6cf2bd6
refactor: rename component names for better ux
Dinil-Thilakarathne Feb 1, 2026
c7bdab1
refactor: update all the component pages to follow the new layout and…
Dinil-Thilakarathne Feb 1, 2026
94cbe1b
refactor: rename the folder names
Dinil-Thilakarathne Feb 1, 2026
616cd89
refactor: internal folder names
Dinil-Thilakarathne Feb 1, 2026
1b7ceb9
refactor: rename registry exmaple folder
Dinil-Thilakarathne Feb 1, 2026
32f7365
refactor: update component style
Dinil-Thilakarathne Feb 1, 2026
a2e31a1
feat: update internal layout and style
Dinil-Thilakarathne Feb 1, 2026
8497d54
refactor: Remove auto-generated `example_registry.ts` and update moti…
Dinil-Thilakarathne Feb 1, 2026
49ca883
refctor: update system lock files
Dinil-Thilakarathne Feb 2, 2026
b39038c
feat: update system config
Dinil-Thilakarathne Feb 2, 2026
6b84ae8
feat: add site get started pages
Dinil-Thilakarathne Feb 2, 2026
b18f5b5
feat: impllment internal code block component
Dinil-Thilakarathne Feb 2, 2026
6320a1a
fix: file naming issue
Dinil-Thilakarathne Feb 2, 2026
fb56b6b
fix: file naming issues
Dinil-Thilakarathne Feb 2, 2026
54af9a5
feat: add component registry json files
Dinil-Thilakarathne Feb 2, 2026
d0432a8
chore: add shdcn cli dep and update build command
Dinil-Thilakarathne Feb 2, 2026
e8c4ed5
style: update internal component style
Dinil-Thilakarathne Feb 2, 2026
a0b8c2b
refactor: update file for better dx
Dinil-Thilakarathne Feb 2, 2026
02788b0
feat: Add shadcn/ui registry integration with a new build script
Dinil-Thilakarathne Feb 2, 2026
8212db0
docs: Update installation guide to use shadcn-ui CLI with Sona UI reg…
Dinil-Thilakarathne Feb 2, 2026
8c59432
fix: duplicate files property
Dinil-Thilakarathne Feb 2, 2026
227989e
feat: Enhance theming with centralized CSS variables, update componen…
Dinil-Thilakarathne Feb 2, 2026
aa36057
refacfor: update files names
Dinil-Thilakarathne Feb 4, 2026
2b5d4c9
refactor: standardize component file paths and imports to kebab-case.
Dinil-Thilakarathne Feb 4, 2026
e06018f
Merge pull request #58 from Dinil-Thilakarathne/v3.0
Dinil-Thilakarathne Feb 4, 2026
52606b0
Merge branch 'master' of https://github.com/Dinil-Thilakarathne/sona-…
Dinil-Thilakarathne Feb 4, 2026
9bd21f8
feat: add variants to `ScrollUpButton`, introduce a "Get started" but…
Dinil-Thilakarathne Feb 4, 2026
65c92c2
refactor: Update component registry entries with standardized titles,…
Dinil-Thilakarathne Feb 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"tailwindCSS.classFunctions": ["cva", "cx"]
}
42 changes: 42 additions & 0 deletions FEATURE_REQUEST_SHADCN_REGISTRY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: Feature request
about: Suggest an idea for this project
title: "Integrate Sona UI as a Shadcn Registry"
labels: enhancement
assignees: ""
---

**Is your feature request related to a problem? Please describe.**
Currently, Sona UI operates as a standalone component library. While it offers high-quality components, consuming them requires manual copying or specific installation steps that may not align with the increasingly popular `shadcn` ecosystem workflow. Users accustomed to the `shadcn` CLI for adding components may find the current process less streamlined.

**Describe the solution you'd like**
I would like to integrate Sona UI as a fully compatible **shadcn registry**. This involves:

1. Creating the necessary `registry.json` (or split registry files) that define the components, their dependencies, and file paths.
2. Ensuring the structure matches the shadcn registry specification so that it works seamlessly with major UI libraries and tools in the industry.
3. Allowing users to potentially use commands like `npx shadcn@latest add <url>/<component>` (or equivalent) to install Sona UI components.

**Describe alternatives you've considered**

- **Standard NPM Package:** Distributing as a compiled npm package (which loses the "copy-paste" flexibility and customization of shadcn-like libraries).
- **Manual Copy-Paste:** Continuing with the current manual documentation approach, which is functional but has higher friction for users.

**Additional context**
This is a **major goal** for the project. By becoming a shadcn-compatible registry, Sona UI can leverage the existing ecosystem of tools and provide a top-tier developer experience, making it a viable competitor or complement to major UI libraries in the industry.


# page strucute

# header
## title
## description
## links


# preview

# installation

# usage

# example
1,410 changes: 596 additions & 814 deletions bun.lock

Large diffs are not rendered by default.

67 changes: 24 additions & 43 deletions components.json
Original file line number Diff line number Diff line change
@@ -1,46 +1,27 @@
{
"Accordion": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/accordion/Accordion.tsx",
"dependencies": ["AnimatedPlusMinusButton"]
},
"AnimatedPlusMinusButton": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/accordion/AnimatedPlusMinusButton.tsx",
"dependencies": []
},
"ExpandableTabs": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/expandableTabs/ExpandableTabs.tsx",
"dependencies": []
},
"LinkPreview": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/linkPreview/LinkPreview.tsx",
"dependencies": []
},
"MagneticButton": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/magnetic/MagneticButton.tsx",
"dependencies": []
},
"RippleButton": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/rippleButton/RippleButton.tsx",
"dependencies": []
},
"SpinningText": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/spinningText/SpinningText.tsx",
"dependencies": []
},
"StaggerText": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/staggerText/StaggerText.tsx",
"dependencies": []
},
"VerticalTab": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/verticalTab/VerticalTab.tsx",
"dependencies": []
},
"Marquee": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/marquee/Marquee.tsx",
"dependencies": []
},
"BubbleUpButton": {
"url": "https://raw.githubusercontent.com/Dinil-Thilakarathne/sona-ui/refs/heads/master/src/registry/sonaui/bubbleUpButton/BubbleUpButton.tsx",
"dependencies": []
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide",
"registries": {
"@sona-ui": {
"url": "https://sona-ui.vercel.app/r/{name}.json",
"description": "Sona UI - Modern React components"
}
}
}
56 changes: 34 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,67 +8,79 @@
"homepage": "https://sona-ui.vercel.app",
"type": "module",
"scripts": {
"predev": "node copy-sources.js",
"predev": "bun run sync:releases",
"dev": "next dev --turbopack",
"prebuild": "node copy-sources.js",
"prebuild": "bun run build:registry && bun run sync:releases",
"build:registry": "bun run scripts/build-registry.ts && bun run scripts/build-registry-json.ts",
"sync:releases": "bun run scripts/sync-releases.ts",
"build": "next build --turbopack",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@base-ui/react": "^1.1.0",
"@gsap/react": "^2.1.2",
"@hugeicons/core-free-icons": "^3.1.1",
"@hugeicons/react": "^1.1.4",
"@icons-pack/react-simple-icons": "^13.8.0",
"@mdx-js/loader": "^3.1.1",
"@mdx-js/react": "^3.1.1",
"@next/mdx": "16.0.0",
"@number-flow/react": "^0.5.10",
"@number-flow/react": "^0.5.11",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/themes": "^3.2.1",
"@radix-ui/themes": "^3.3.0",
"@types/mdx": "^2.0.13",
"@types/react-syntax-highlighter": "^15.5.13",
"arktype": "^2.1.26",
"arktype": "^2.1.29",
"caniuse-lite": "^1.0.30001767",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"fumadocs-ui": "^16.5.0",
"fuse.js": "^7.1.0",
"gsap": "^3.13.0",
"lenis": "^1.3.15",
"lucide-react": "^0.509.0",
"motion": "^12.23.24",
"gsap": "^3.14.2",
"lenis": "^1.3.17",
"lucide-react": "^0.563.0",
"motion": "^12.29.2",
"next": "16.0.7",
"next-mdx-remote": "^5.0.0",
"next-themes": "^0.4.6",
"next-view-transitions": "^0.3.4",
"posthog-js": "^1.293.0",
"react": "19.2.0",
"react-dom": "19.2.0",
"next-view-transitions": "^0.3.5",
"posthog-js": "^1.336.4",
"radix-ui": "^1.4.3",
"react": "19.2.1",
"react-dom": "19.2.1",
"react-icons": "^5.5.0",
"react-syntax-highlighter": "^15.6.6",
"react-use-measure": "^2.1.7",
"shiki": "^3.22.0",
"tailwind-merge": "^3.4.0",
"usehooks-ts": "^3.1.1"
},
"devDependencies": {
"@content-collections/core": "^0.8.2",
"@content-collections/mdx": "^0.2.2",
"@content-collections/next": "^0.2.9",
"@eslint/eslintrc": "^3.3.1",
"@content-collections/next": "^0.2.10",
"@eslint/eslintrc": "^3.3.3",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^11.0.6",
"@tailwindcss/postcss": "^4.1.17",
"@types/node": "^20.19.25",
"@tailwindcss/postcss": "^4.1.18",
"@types/node": "^20.19.30",
"@types/react": "19.2.2",
"@types/react-dom": "19.2.2",
"eslint": "^9.39.1",
"baseline-browser-mapping": "^2.9.19",
"eslint": "^9.39.2",
"eslint-config-next": "16.0.0",
"prettier": "^3.6.2",
"prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.6.14",
"semantic-release": "^24.2.9",
"tailwindcss": "^4.1.17",
"tailwindcss": "^4.1.18",
"tw-animate-css": "^1.4.0",
"typescript": "^5.9.3"
},
"overrides": {
"@types/react": "19.2.2",
"@types/react-dom": "19.2.2"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
}
21 changes: 21 additions & 0 deletions public/r/accordion.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "accordion",
"type": "registry:ui",
"title": "Accordion",
"description": "The `Accordion` component allows you to toggle the visibility of content sections. It is useful for FAQs, menus, and more.",
"files": [
{
"path": "registry/sonaui/accordion/accordion.tsx",
"type": "registry:ui"
},
{
"path": "registry/sonaui/accordion/animated-plus-minus-button.tsx",
"type": "registry:ui"
}
],
"dependencies": [
"class-variance-authority",
"motion"
],
"registryDependencies": []
}
14 changes: 14 additions & 0 deletions public/r/bubble-up-button.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "bubble-up-button",
"type": "registry:ui",
"title": "BubbleUpButton",
"description": "The `BubbleUpButton` component provides an interactive button with a fluid \"bubble-up\" animation effect when hovered. It creates an engaging user experience with minimal effort.",
"files": [
{
"path": "registry/sonaui/bubble-up-button/bubble-up-button.tsx",
"type": "registry:ui"
}
],
"dependencies": [],
"registryDependencies": []
}
16 changes: 16 additions & 0 deletions public/r/expandable-tabs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "expandable-tabs",
"type": "registry:ui",
"title": "ExpandableTabs",
"description": "The `ExpandableTabs` component is a dynamic and interactive UI element designed for creating horizontal tabbed navigation.",
"files": [
{
"path": "registry/sonaui/expandable-tabs/expandable-tabs.tsx",
"type": "registry:ui"
}
],
"dependencies": [
"react-icons"
],
"registryDependencies": []
}
16 changes: 16 additions & 0 deletions public/r/link-preview.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "link-preview",
"type": "registry:ui",
"title": "LinkPreview",
"description": "The `LinkPreview` component is an interactive UI element that displays a preview of a link when hovered over. It enhances user experience by providing additional context about the link.",
"files": [
{
"path": "registry/sonaui/link-preview/link-preview.tsx",
"type": "registry:ui"
}
],
"dependencies": [
"react-use-measure"
],
"registryDependencies": []
}
16 changes: 16 additions & 0 deletions public/r/magnetic-button.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "magnetic-button",
"type": "registry:ui",
"title": "Magnetic Button",
"description": "Component for magnetic-button",
"files": [
{
"path": "registry/sonaui/magnetic-button/magnetic-button.tsx",
"content": "\"use client\";\n\nimport { useState, useEffect, useRef, type ReactNode } from \"react\";\nimport {\n motion,\n useMotionValue,\n useSpring,\n type SpringOptions,\n} from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nconst SPRING_CONFIG = { stiffness: 30, damping: 6, mass: 0.6 };\n\ninterface MagneticProps {\n children: ReactNode;\n magneticIntensity?: number;\n magneticRange?: number;\n interactionArea?: \"self\" | \"parent\";\n springConfig?: SpringOptions;\n customClassName?: string;\n}\n\nexport default function Magnetic({\n children,\n magneticIntensity = 0.6,\n magneticRange = 100,\n interactionArea = \"self\",\n springConfig,\n customClassName,\n}: MagneticProps) {\n const [isMouseHovered, setMouseHovered] = useState(false);\n const magneticRef = useRef<HTMLDivElement>(null);\n\n springConfig = springConfig || SPRING_CONFIG;\n\n const motionX = useMotionValue(0);\n const motionY = useMotionValue(0);\n\n const springMotionX = useSpring(motionX, springConfig);\n const springMotionY = useSpring(motionY, springConfig);\n\n useEffect(() => {\n const calculateMouseDistance = (event: MouseEvent) => {\n if (magneticRef.current) {\n const rect = magneticRef.current.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const distanceX = event.clientX - centerX;\n const distanceY = event.clientY - centerY;\n\n const absoluteDistance = Math.sqrt(distanceX ** 2 + distanceY ** 2);\n\n if (isMouseHovered && absoluteDistance <= magneticRange) {\n const scale = 1 - absoluteDistance / magneticRange;\n\n motionX.set(distanceX * magneticIntensity * scale);\n motionY.set(distanceY * magneticIntensity * scale);\n } else {\n motionX.set(0);\n motionY.set(0);\n }\n }\n };\n\n document.addEventListener(\"mousemove\", calculateMouseDistance);\n\n return () => {\n document.removeEventListener(\"mousemove\", calculateMouseDistance);\n };\n }, [\n magneticRef,\n isMouseHovered,\n magneticIntensity,\n magneticRange,\n motionX,\n motionY,\n interactionArea,\n ]);\n\n useEffect(() => {\n if (interactionArea === \"parent\" && magneticRef.current?.parentElement) {\n const parentElement = magneticRef.current.parentElement;\n\n const handleParentMouseEnter = () => setMouseHovered(true);\n const handleParentMouseLeave = () => setMouseHovered(false);\n\n parentElement.addEventListener(\"mouseenter\", handleParentMouseEnter);\n parentElement.addEventListener(\"mouseleave\", handleParentMouseLeave);\n\n return () => {\n parentElement.removeEventListener(\"mouseenter\", handleParentMouseEnter);\n parentElement.removeEventListener(\"mouseleave\", handleParentMouseLeave);\n };\n }\n }, [interactionArea]);\n\n const handleMouseEnter = () => {\n if (interactionArea === \"self\") {\n setMouseHovered(true);\n }\n };\n\n const handleMouseLeave = () => {\n if (interactionArea === \"self\") {\n setMouseHovered(false);\n motionX.set(0);\n motionY.set(0);\n }\n };\n\n return (\n <motion.div\n ref={magneticRef}\n onMouseEnter={interactionArea === \"self\" ? handleMouseEnter : undefined}\n onMouseLeave={interactionArea === \"self\" ? handleMouseLeave : undefined}\n style={{\n x: springMotionX,\n y: springMotionY,\n }}\n role=\"presentation\"\n className={cn(\"\", customClassName)}\n >\n {children}\n </motion.div>\n );\n}\n",
"type": "registry:ui",
"target": "components/sona-ui/magnetic-button/magnetic-button.tsx"
}
],
"dependencies": [],
"registryDependencies": []
}
16 changes: 16 additions & 0 deletions public/r/marquee.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "marquee",
"type": "registry:ui",
"title": "Marquee",
"description": "The `Marquee` component is a versatile UI element that creates a scrolling marquee effect. It is highly customizable and can adapt to various use cases, such as displaying text or other content in a continuous loop.",
"files": [
{
"path": "registry/sonaui/marquee/marquee.tsx",
"type": "registry:ui"
}
],
"dependencies": [
"react-use-measure"
],
"registryDependencies": []
}
Loading