shadcn-ui / ui Goto Github PK
View Code? Open in Web Editor NEWBeautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
Home Page: https://ui.shadcn.com
License: MIT License
Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
Home Page: https://ui.shadcn.com
License: MIT License
Right now there's no such wrapper code available in the docs for close functionality in Dialog component. I have tried to implement the same and it's working all fine.
const DialogClose = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Close>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Close
ref={ref}
{...props}
/>
))
DialogClose.displayName = DialogPrimitive.Title.displayName
This can be used like the snippet shown below
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</DialogDescription>
</DialogHeader>
<DialogFooter>
{/* this is how it can be used */}
<DialogClose />
</DialogFooter>
</DialogContent>
</Dialog>
Hope this helps! Happy to have a chat around this issue/feature-request.
My proposition is to develop semantic colors for light and dark theme, write them into CSS variables and set them in TailwindCSS config https://tailwindcss.com/docs/customizing-colors#using-css-variables. This will almost completely automate the creation of a dark theme, since the colors will automatically change from the given variables for the dark and light theme, and another advantage is that it will be possible to add new different themes.
// tailwind.config.js
module.exports = {
darkMode: ['class'],
theme: {
colors: {
current: 'currentColor',
transparent: 'transparent',
black: '#000',
white: '#fff',
background: 'hsl(var(--background) / 1)',
base: {
50: 'hsl(var(--base) / 0.05)',
100: 'hsl(var(--base) / 0.1)',
200: 'hsl(var(--base) / 0.2)',
300: 'hsl(var(--base) / 0.3)',
400: 'hsl(var(--base) / 0.4)',
500: 'hsl(var(--base) / 0.5)',
600: 'hsl(var(--base) / 0.6)',
700: 'hsl(var(--base) / 0.7)',
800: 'hsl(var(--base) / 0.8)',
900: 'hsl(var(--base) / 1)',
},
primary: {
50: 'hsl(var(--primary-50))',
100: 'hsl(var(--primary-100))',
200: 'hsl(var(--primary-200))',
300: 'hsl(var(--primary-300))',
400: 'hsl(var(--primary-400))',
500: 'hsl(var(--primary-500))',
600: 'hsl(var(--primary-600))',
700: 'hsl(var(--primary-700))',
800: 'hsl(var(--primary-800))',
900: 'hsl(var(--primary-900))',
},
secondary: {
50: 'hsl(var(--secondary-50))',
100: 'hsl(var(--secondary-100))',
200: 'hsl(var(--secondary-200))',
300: 'hsl(var(--secondary-300))',
400: 'hsl(var(--secondary-400))',
500: 'hsl(var(--secondary-500))',
600: 'hsl(var(--secondary-600))',
700: 'hsl(var(--secondary-700))',
800: 'hsl(var(--secondary-800))',
900: 'hsl(var(--secondary-900))',
},
tertiary: {
50: 'hsl(var(--tertiary-50))',
100: 'hsl(var(--tertiary-100))',
200: 'hsl(var(--tertiary-200))',
300: 'hsl(var(--tertiary-300))',
400: 'hsl(var(--tertiary-400))',
500: 'hsl(var(--tertiary-500))',
600: 'hsl(var(--tertiary-600))',
700: 'hsl(var(--tertiary-700))',
800: 'hsl(var(--tertiary-800))',
900: 'hsl(var(--tertiary-900))',
},
success: {
50: 'hsl(var(--success-50))',
100: 'hsl(var(--success-100))',
200: 'hsl(var(--success-200))',
300: 'hsl(var(--success-300))',
400: 'hsl(var(--success-400))',
500: 'hsl(var(--success-500))',
600: 'hsl(var(--success-600))',
700: 'hsl(var(--success-700))',
800: 'hsl(var(--success-800))',
900: 'hsl(var(--success-900))',
},
highlight: {
50: 'hsl(var(--highlight-50))',
100: 'hsl(var(--highlight-100))',
200: 'hsl(var(--highlight-200))',
300: 'hsl(var(--highlight-300))',
400: 'hsl(var(--highlight-400))',
500: 'hsl(var(--highlight-500))',
600: 'hsl(var(--highlight-600))',
700: 'hsl(var(--highlight-700))',
800: 'hsl(var(--highlight-800))',
900: 'hsl(var(--highlight-900))',
},
warning: {
50: 'hsl(var(--warning-50))',
100: 'hsl(var(--warning-100))',
200: 'hsl(var(--warning-200))',
300: 'hsl(var(--warning-300))',
400: 'hsl(var(--warning-400))',
500: 'hsl(var(--warning-500))',
600: 'hsl(var(--warning-600))',
700: 'hsl(var(--warning-700))',
800: 'hsl(var(--warning-800))',
900: 'hsl(var(--warning-900))',
},
},
},
};
/* globals.css */
@layer base {
:root {
--background: 0 0% 100%;
--base: 0 0% 10%;
--primary-50: 216 100% 97%;
--primary-100: 214 94% 93%;
--primary-200: 213 97% 87%;
--primary-300: 212 96% 78%;
--primary-400: 213 94% 68%;
--primary-500: 217 80% 56%;
--primary-600: 221 83% 53%;
--primary-700: 224 76% 48%;
--primary-800: 226 71% 40%;
--primary-900: 224 64% 33%;
--secondary-50: 270 100% 98%;
--secondary-100: 270 100% 95%;
--secondary-200: 269 100% 92%;
--secondary-300: 269 97% 85%;
--secondary-400: 270 95% 75%;
--secondary-500: 271 91% 65%;
--secondary-600: 271 81% 56%;
--secondary-700: 272 72% 47%;
--secondary-800: 273 67% 39%;
--secondary-900: 274 66% 32%;
--tertiary-50: 0 0% 99%;
--tertiary-100: 240 5% 96%;
--tertiary-200: 240 6% 90%;
--tertiary-300: 240 5% 84%;
--tertiary-400: 240 5% 65%;
--tertiary-500: 240 4% 46%;
--tertiary-600: 240 5% 34%;
--tertiary-700: 240 5% 26%;
--tertiary-800: 240 4% 16%;
--tertiary-900: 240 6% 10%;
--success-50: 136 73% 97%;
--success-100: 142 83% 93%;
--success-200: 141 79% 85%;
--success-300: 142 77% 73%;
--success-400: 142 69% 58%;
--success-500: 142 76% 43%;
--success-600: 142 76% 36%;
--success-700: 142 72% 29%;
--success-800: 143 61% 27%;
--success-900: 144 63% 18%;
--highlight-50: 55 92% 95%;
--highlight-100: 55 97% 88%;
--highlight-200: 53 98% 77%;
--highlight-300: 50 98% 64%;
--highlight-400: 48 96% 53%;
--highlight-500: 45 93% 47%;
--highlight-600: 41 96% 40%;
--highlight-700: 35 92% 33%;
--highlight-800: 32 81% 29%;
--highlight-900: 28 73% 26%;
--warning-50: 0 87% 97%;
--warning-100: 0 94% 94%;
--warning-200: 0 96% 89%;
--warning-300: 0 93% 82%;
--warning-400: 0 97% 71%;
--warning-500: 0 84% 60%;
--warning-600: 0 72% 51%;
--warning-700: 0 74% 42%;
--warning-800: 0 70% 35%;
--warning-900: 0 63% 31%;
}
.dark {
--background: 0 0% 8%;
--base: 0 0% 100%;
--primary-50: 230 37% 18%;
--primary-100: 222 87% 29%;
--primary-200: 223 83% 44%;
--primary-300: 221 87% 49%;
--primary-400: 217 81% 56%;
--primary-500: 213 92% 57%;
--primary-600: 212 100% 66%;
--primary-700: 212 100% 74%;
--primary-800: 214 94% 93%;
--primary-900: 216 100% 97%;
--secondary-50: 274 50% 19%;
--secondary-100: 274 59% 28%;
--secondary-200: 272 72% 47%;
--secondary-300: 272 82% 59%;
--secondary-400: 270 100% 67%;
--secondary-500: 278 100% 75%;
--secondary-600: 286 100% 81%;
--secondary-700: 300 100% 87%;
--secondary-800: 300 100% 92%;
--secondary-900: 300 100% 97%;
--tertiary-50: 0 0% 15%;
--tertiary-100: 0 0% 20%;
--tertiary-200: 0 0% 26%;
--tertiary-300: 0 0% 37%;
--tertiary-400: 0 0% 45%;
--tertiary-500: 0 0% 53%;
--tertiary-600: 0 0% 61%;
--tertiary-700: 0 0% 73%;
--tertiary-800: 0 0% 84%;
--tertiary-900: 0 0% 94%;
--success-50: 136 59% 13%;
--success-100: 144 61% 20%;
--success-200: 143 64% 24%;
--success-300: 142 80% 32%;
--success-400: 142 71% 45%;
--success-500: 142 69% 58%;
--success-600: 142 77% 73%;
--success-700: 141 79% 85%;
--success-800: 142 83% 93%;
--success-900: 136 73% 97%;
--highlight-50: 55 47% 17%;
--highlight-100: 32 81% 29%;
--highlight-200: 35 92% 33%;
--highlight-300: 41 96% 40%;
--highlight-400: 45 93% 47%;
--highlight-500: 48 96% 53%;
--highlight-600: 50 98% 64%;
--highlight-700: 53 98% 77%;
--highlight-800: 55 96% 90%;
--highlight-900: 55 92% 95%;
--warning-50: 0 45% 25%;
--warning-100: 0 59% 30%;
--warning-200: 0 46% 47%;
--warning-300: 0 69% 55%;
--warning-400: 0 91% 63%;
--warning-500: 0 100% 69%;
--warning-600: 0 100% 79%;
--warning-700: 0 100% 83%;
--warning-800: 0 100% 87%;
--warning-900: 0 96% 91%;
}
body {
@apply bg-background text-base-900;
}
}
export const Demo = () => (
<div className="bg-tertiary-100 p-4 text-tertiary-900">Hello World!</div>
);
☀️ Light theme:
🌙 Dark theme:
Any plans on adding a 'position' prop that could be passed when using the useToast hook?
Something similar to react-hot-toast ⬇️
toast('Hello World', { position: 'top-center', });
Getting typescript errors when adding components:
const TooltipProvider: FC<TooltipPrimitive.TooltipProviderProps>
Unsafe assignment of an `any` value.eslint[@typescript-eslint/no-unsafe-assignment](https://typescript-eslint.io/rules/no-unsafe-assignment)
Using tailwind, there are a lot of mentions of different colors (i.e. bg-slate-900, bg-red-500 etc.).
With 'slate' being the 'primary' color.
Let's say my primary colors is a blue, how would I go about changing that?
From my current understanding, I would have to go through every single file and change every single occurrence of slate,
which is difficult, as slate may in some cases refer to a 'border' and not a primary color.
What would be the suggested way to deal with this issue?
When using the dialog with content larger than the screen height, the dialog gets cut off on top and bottom without the ability to scroll.
Steps to reproduce: Put component with height > screen height inside of Dialog.
Intended behavior: Scroll
First ever Issue, sorry if its unclear. Happy to elaborate.
Thanks a lot for making this open source. It is invaluable!
After adding the library to 2 different projects I stumbled upon the problem in both on how I add the font variable to my application for the default tw config to work.
I always had to check out the template in order to copy the next config and the _app.tsx from there.
The following content should be added to the install instructions.
To add a font to your project you have to install @nextjs/font and add the following to your next.config.js
:
const config = {
reactStrictMode: true,
experimental: {
fontLoaders: [
{
loader: "@next/font/google",
options: { subsets: ["latin"] },
},
],
},
}
Then declare the CSS variable in your \_app.tsx
import { Inter as FontSans } from "@next/font/google"
const fontSans = FontSans({
subsets: ["latin"],
variable: "--font-sans",
display: "swap",
})
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<style jsx global>{`
:root {
--font-sans: ${fontSans.style.fontFamily};
}
}`}</style>
<Component {...pageProps} />
</>
)
}
The dialog box does not seem to be aligned to 'flex-start' on the small screens and nor are the corners rounded
It works better, in my opinion, on making the following changes:
After the changes suggested above, this is the result:
I would like to congratulate you on this library, especially because I have started actively using this in my projects.
Reach out to me on twitter: @KshitijMohan14
When transitioning from light to dark mode the associated icon stays fixed as sun, instead of switching to moon icon (to reflect the current theme setting).
having the possibility to work with expo or react native
When using the select component, opening the select content completely breaks the entire page, and I don't know if the problem is actually the component itself or if I forgot something when implementing it.
the code for it is the following:
<Select>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select" />
</SelectTrigger>
<SelectContent>
<SelectItem value="DEPRIVED">Deprived</SelectItem>
<SelectItem value="KNIGHT">Knight</SelectItem>
<SelectItem value="MAGE">Mage</SelectItem>
<SelectItem value="CLERIC">Cleric</SelectItem>
<SelectItem value="ARCHER">Archer</SelectItem>
</SelectContent>
</Select>
And this is the behavior that I get when clicking the trigger.
Im trying to extends the props of the accordion component and I'm having some truble getting it done.
For example I would like to have a prop where I can pass a boolean to define where the accordion has borders or not. Something like this
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={classNames(
props.hasBorder ? "border-b border-b-slate-200" : "",
className
)}
{...props}
/>
));
But I've been trying to extend the props but I having trubble finding a way to do that. Any help?
In Firefox Developer edition, on my vertical monitor with a resolution of 1080x1920, previewing the component requires a long horizontal scroll. This problem is not visible at higher resolutions. The issue is occurs in the md
and lg
breakpoints for much of the range in my testing. The cause appears to be the addition of the aside
element messing up the width: 100%
calculations used elsewhere.
This project is really great, I love it! Thank you for your efforts!!
To be frankly, it lacks some useful components, like datepicker, breadcrumb, form...so on
May be BaseWeb from Uber can give you some ideas :)
Hopefully, I can see more features in the future!
I've been using this component library for a couple of days now, LOVING IT!
The only part that's missing is the exit animations, especially for the dialogs and menu components. They animate-in
nicely but they disappear instantly on unmount. I'm somewhat new to radixUI, but I read this from radix which basically uses the data-[state=open/close]
attributes to animate the state transitions (and this is what accordions seem to use on this library with animations declared on tw config)
So, is not having exit animations on certain components an intentional design choice?
I don't see a components page anywhere. Great project by the way, I'm definitely using it in my next project.
Hi! in the <DropdownMenu />
component, CSS classes aren't load in the final <div>
element.
As you can see I am using <DropdownMenuSeparator />
withour classes and the final div is empty, but if I add classes by my own, its loads only my custom classes.
I added in lib folder the utils.ts file, but I dont undertand the why it is not working. This is happeding with all childs of <DropdownMenu />
Thank you.
This may not be a big deal or even worth adjusting, as devices may not fall into this specific pixel range. However, I saw this while working on another issue and thought I'd file it in case.
At the md
breakpoint, the content in the <MainNav>
component overflows the screen at the lower end of the breakpoint range.
Hello, superb library!
Because the tooltip utilizes divs, but divs aren't valid descendants of paragraphs (view this stackoverflow discussion), if someone where to use tooltip in a paragraph tag, they would get the error
Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
Thanks to the radix discord, I suggest wrapping the content in the tooltip portal like so:
const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md border border-slate-100 bg-white px-3 py-1.5 text-sm text-slate-700 shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
className
)}
{...props}
/>
</TooltipPrimitive.Portal>
))
TooltipContent.displayName = TooltipPrimitive.Content.displayName
This allows the content to be rendered in a different scope, avoiding the invalid descendants issue and retaining the styling and semantics as far as I can tell.
I am using the Popover.tsx
component, and while the behavior and Tailwind styling are functioning correctly, I am experiencing difficulties applying local fonts to the component. Despite adding the font-sans
class to all classNames within the Popover component and its child components, the utility class does not seem to affect any content inside PopoverContent
. PopoverTrigger
applies the custom font-family without any issues.
Please find the relevant code snippets below.
Popover.tsx
'use client'
import * as React from 'react'
import * as PopoverPrimitive from '@radix-ui/react-popover'
import { cn } from '@/lib/utils'
const Popover = PopoverPrimitive.Root
const PopoverTrigger = PopoverPrimitive.Trigger
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
'animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=right]:slide-in-from-left-2 data-[side=left]:slide-in-from-right-2 border-gray-3 z-50 rounded border bg-white p-4 font-sans text-gray-900 shadow-md outline-none',
className,
)}
{...props}
/>
</PopoverPrimitive.Portal>
))
PopoverContent.displayName = PopoverPrimitive.Content.displayName
export { Popover, PopoverTrigger, PopoverContent }
Component usage (redacted for clarity):
<Popover>
{/* FILTER TRIGGER */}
<PopoverTrigger>
<Button variant="ghost">
<SlidersHorizontal size={20} strokeWidth={1} className="mr-2" />
Filters
</Button>
</PopoverTrigger>
{/* FILTER CONTENT */}
<PopoverContent>
<div className="font-sans">
{/* INACTIVE SDGs */}
<h4 className="font-sans text-base">SDGs</h4>
</div>
</PopoverContent>
</Popover>
Here is my _app.js
where the local fonts are loaded (redacted for clarity):
import localFont from 'next/font/local'
import PlausibleProvider from 'next-plausible'
import '@/styles/globals.css'
const CMUSerif = localFont({
variable: '--font-cmu-serif',
src: [
{
path: '../assets/fonts/cmu-serif-roman.woff',
weight: '400',
style: 'normal',
},
…
],
})
const HKGrotesk = localFont({
variable: '--font-hk-grotesk',
src: [
{
path: '../assets/fonts/HKGrotesk-Light.woff2',
weight: '300',
style: 'normal',
},
…
],
})
function MyApp({ Component, pageProps }) {
return (
<PlausibleProvider
>
<main className={`${CMUSerif.variable} ${HKGrotesk.variable} font-sans`}>
<Component {...pageProps} />
</main>
</PlausibleProvider>
)
}
export default MyApp
Any help or tips are appreciated 🙌
I ran pnpm install
and duplicated the .env.example
as .env.local
, then got error at pnpm build
.
Looks like same issue vercel/next.js#45080
www:build: Generated 30 documents in .contentlayer
www:build: info - Creating an optimized production build...
next-template:build: Failed to compile.
next-template:build:
next-template:build: pages/_app.tsx
next-template:build: `@next/font` error:
next-template:build: Failed to fetch `Inter` from Google Fonts.
next-template:build:
next-template:build:
next-template:build: > Build failed because of webpack errors
next-template:build: ELIFECYCLE Command failed with exit code 1.
next-template:build: ERROR: command finished with error: command (/home/linux/Github/ui/templates/next-template) pnpm run build exited (1)
command (/home/linux/Github/ui/templates/next-template) pnpm run build exited (1)
Tasks: 0 successful, 1 total
Cached: 0 cached, 1 total
Time: 2m16.794s
ERROR run failed: command exited (1)
ELIFECYCLE Command failed with exit code 1.
Attaching a video to better explain this, but sometimes, input fields don’t display what’s being entered, on mobile.
When we need a more extensive Navigation Menu, Viewport with Content does not follow the position of the Trigger. Instead, all menus are in the center of the screen.
You can see behavior on this test page:
https://chakras-edtsr25u2-miljenko-storydeckio.vercel.app/
The same issues are mentioned here:
radix-ui/primitives#1462
Is there any parameter to position Viewport under the Trigger point?
When using the register
method of react hook form, the component does not change the state of the provided form.
export default function Survey() {
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm<{isDesktop: boolean}>();
// ....
return (<form>
<Label htmlFor="isDesktop">Are you using a desktop version of our app?</Label>
<Checkbox {...register("isDesktop")} />
<button>Submit</button>
</form>)
}
Hi there ✋🏼
thanks for this amazing components !
Is there a way to select multiple data with the Select component ?
Thanks !
Hi there!
Have you consider adding date related inputs (single date, range, calendars)?
react-aria has a great set of hooks to build accesible date fields:
Date pickers are notoriously difficult to implement, leave alone make them fully accessible and so I think it will take a while for radix-ui to catch up in this aspect. What do you think?
Some important notes:
react-stately
, @internationalized/date
)I have experience using react-aria (I've built some calendar inputs at work) and I could contribute maybe starting with simpler cases like DateField
and TimeField
. For the others, a good set of defaults should be discussed.
Just a little feedback, navigating between components in the docs seems surprisingly sluggish. Not sure how easy a fix this is but it would great if it checking out the components was a snappier experience!
When Toasts are used with a Dialog component, the toast shows behind the dialog.
Here is a reproduction
Codesanbox
Hi, awesome Job ! I see you used 'next-themes' for the support for the dark-mode. I have the following question, do you came across this problem in development. I use tailwindCSS
With related to "Hydration failed because of the initial UI"
app/layout.tsx
// Styles
import '@styles/global.css';
// Lib
import Providers from '@lib/Providers';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
<html lang="en" suppressHydrationWarning>
<head />
<Providers>
<body>{children}</body>
</Providers>
</html>
</>
);
}
lib/Providers
'use client';
import { ReactNode } from 'react';
import { ThemeProvider } from 'next-themes';
// Context
import { SettingsProvider } from './SettingsContext';
export default function Providers({ children }: { children: ReactNode }) {
return (
<SettingsProvider>
<ThemeProvider
disableTransitionOnChange
attribute="class"
defaultTheme="system"
>
{children}
</ThemeProvider>
</SettingsProvider>
);
}
NOTE: In production these message not show
In readme it says Licensed under the MIT license
. But there is no license in place. Is this project even open source?
Just curious.
In the navigation-menu component, the 'origin-top-center' class is used in `NavigationMenuPrimitive.Viewport'. I have installed everything required in the installation instructions but my editor is still claiming it's not a valid class. I am not sure if this could have to do with the navbar dropdown not being centered or not, but it seems to be an error regardless. (if this is not responsible, how do I make the dropdown go underneath the button instead of stuck to the left?)
const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<div className={cn("absolute left-0 top-full flex justify-center")}>
<NavigationMenuPrimitive.Viewport
className={cn(
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border border-slate-200 bg-white shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:zoom-in-90 data-[state=closed]:zoom-out-95 dark:border-slate-700 dark:bg-slate-800 md:w-[var(--radix-navigation-menu-viewport-width)]",
className
)}
ref={ref}
{...props}
/>
</div>
));
Hi!
Just wondering if anyone tried using the components with Preact. If not, I'd be happy to try it out and report back 🙂
I would like to ask how does tooltip work on mobile devices? Because when i tried to use it there it does not work. Is there some solution for this to trigger tooltip when user clicks on trigger?
Cmd-k to open "Search Documentation" selects URL bar in Firefox.
Instead of focusing on the newly opened search document page it focuses on the URL bar.
is there some way to easy pull new updates / new components that are added to the library?
since it's not released as a package
It's a very important component for portfolio/photo/social websites but existing solutions are way too heavy with complex gallery/navigation functionality. Right now I'm using a hacky solution on top of modified Dialog
component and while it works, it's not very elegant.
The NavigationMenu does stay open on a first click and closes again. It works after a second click.
Can be reproduced by clickinng on a example on the docs page: https://ui.shadcn.com/docs/primitives/navigation-menu.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.