Skip to content

Commit

Permalink
feat: Slider Component (#1686)
Browse files Browse the repository at this point in the history
* feat(slider): initial structure

* chore(slider): readme improved

* fix: fixed border color of slider track

* docs: added range story

* feat: added rtl support to slider

* feat: improved value label formatting

* feat: refactor styling and add colors support to slider

* chore: improved thumb color

* docs: improved slider stories

* chore(slider): default color changed by foreground

* Update packages/core/theme/src/components/slider.ts

Co-authored-by: Jakob Guddas <[email protected]>

* feat: added fillOffset prop

* Update packages/components/slider/src/use-slider.ts

* fix(slider): animation

* Update packages/components/slider/src/use-slider.ts

* Update packages/core/theme/src/components/slider.ts

* feat: slider steps

* refactor: renamed variables

* feat: improved slider step styling

* fix: hide infinite steps

* fix: fixed step transparency issue

* fix: fixed thumb focus issue

* Update packages/components/slider/src/use-slider.ts

Co-authored-by: Junior Garcia <[email protected]>

* feat(slider): vertical orientation added, start & end content, bug fixes

* chore(slider): tests added

* fix(docs): scrollbar added to the sidebar (#1743)

* feat(slider): marks added

* chore(slider): example ts-doc changed

* feat(slider): vertical marks support

* feat(core): slider tooltip support added, popover modified (#1746)

* Feat/slider custom styles (#1751)

* feat(slider): custom styles story added

* fix(slider): custom styles on different sizes

* Fix/slider tooltip android position (#1753)

* feat(slider): custom styles story added

* fix(slider): tooltip update position dependecies added

* fix(popover): arrow placements improved

* feat(slider): docs started, custom thumb and custom output stories added

* feat(slider): render function added to custom render the slider parts

* feat(slider): docs in progress, new properties and examples added

* fix(slider): some issues fixed, output renamed to value, documentation improved

* feat(slider): docs done

* chore: changeset

---------

Co-authored-by: Jakob Guddas <[email protected]>
  • Loading branch information
jrgarciadev and jguddas authored Oct 16, 2023
1 parent 8de357c commit 3ddd5a9
Show file tree
Hide file tree
Showing 86 changed files with 6,741 additions and 2,872 deletions.
147 changes: 147 additions & 0 deletions .changeset/hip-years-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
"@nextui-org/shared-icons": patch
"@nextui-org/popover": patch
"@nextui-org/tooltip": patch
"@nextui-org/select": patch
"@nextui-org/slider": patch
"@nextui-org/badge": patch
"@nextui-org/theme": patch
---

Changes

- Slider tooltip support added

Breaking Changes

- Popover API changed to improve the arrow implementation, arrow is now a pseudo element, this allows the popover to also move the arrow all-together, this change impacts the Popover, Tooltip and Select implementations.

Popover changes:

```diff
<Popover
showArrow
backdrop="opaque"
placement="right"
classNames={{
- base: "py-3 px-4 border border-default-200 bg-gradient-to-br from-white to-default-300 dark:from-default-100 dark:to-default-50",
+ base: [
+ // the "before" pseudo element is now the popover' arrow
+ "before:bg-default-200"
+ ],
- arrow: "bg-default-200",
+ content: [ // now we need to use the "content" slot to actually modify the popover' content styles
+ "py-3 px-4 border border-default-200",
+ "bg-gradient-to-br from-white to-default-300",
+ "dark:from-default-100 dark:to-default-50",
],
}}
>
<PopoverTrigger>
<Button>Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
{(titleProps) => (
<div className="px-1 py-2">
<h3 className="text-small font-bold" {...titleProps}>
Popover Content
</h3>
<div className="text-tiny">This is the popover content</div>
</div>
)}
</PopoverContent>
</Popover>
```

Tooltip changes:

```diff
<Tooltip
showArrow
placement="right"
content="I am a tooltip"
classNames={{
- base: "py-2 px-4 shadow-xl text-black bg-gradient-to-br from-white to-neutral-400",
- arrow: "bg-neutral-400 dark:bg-white",
+ base: [
+ // the "before" pseudo element is now the popover' arrow
+ "before:bg-neutral-400 dark:before:bg-white",
+ ],
+ content: [ // now we need to use the "content" slot to actually modify the popover' content styles
+ "py-2 px-4 shadow-xl",
+ "text-black bg-gradient-to-br from-white to-neutral-400",
+ ],
}}
>
<Button variant="flat">Hover me</Button>
</Tooltip>
```

Select changes:

```diff
<Select
items={users}
label="Assigned to"
className="max-w-xs"
variant="bordered"
classNames={{
label: "group-data-[filled=true]:-translate-y-5",
trigger: "min-h-unit-16",
listboxWrapper: "max-h-[400px]",
}}
listboxProps={{
itemClasses: {
base: [
"rounded-md",
"text-default-500",
"transition-opacity",
"data-[hover=true]:text-foreground",
"data-[hover=true]:bg-default-100",
"dark:data-[hover=true]:bg-default-50",
"data-[selectable=true]:focus:bg-default-50",
"data-[pressed=true]:opacity-70",
"data-[focus-visible=true]:ring-default-500",
],
},
}}
popoverProps={{
classNames: {
- base: "p-0 border-small border-divider bg-background",
- arrow: "bg-default-200",
+ base: "before:bg-default-200", // the before pseudo element controls the popover's arrow
+ content: "p-0 border-small border-divider bg-background", // now instead of the "base" slot we use the "content" slot
},
}}
renderValue={(items) => {
return items.map((item) => (
<div key={item.key} className="flex items-center gap-2">
<Avatar
alt={item.data.name}
className="flex-shrink-0"
size="sm"
src={item.data.avatar}
/>
<div className="flex flex-col">
<span>{item.data.name}</span>
<span className="text-default-500 text-tiny">({item.data.email})</span>
</div>
</div>
));
}}
>
{(user) => (
<SelectItem key={user.id} textValue={user.name}>
<div className="flex gap-2 items-center">
<Avatar alt={user.name} className="flex-shrink-0" size="sm" src={user.avatar} />
<div className="flex flex-col">
<span className="text-small">{user.name}</span>
<span className="text-tiny text-default-400">{user.email}</span>
</div>
</div>
</SelectItem>
)}
</Select>
);
}`;
```
16 changes: 16 additions & 0 deletions .changeset/stupid-experts-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@nextui-org/react-rsc-utils": patch
"@nextui-org/shared-icons": patch
"@nextui-org/dropdown": patch
"@nextui-org/popover": patch
"@nextui-org/snippet": patch
"@nextui-org/tooltip": patch
"@nextui-org/select": patch
"@nextui-org/slider": patch
"@nextui-org/badge": patch
"@nextui-org/react": patch
"@nextui-org/theme": patch
---

- New component: Slider
- Arrow removed from the popover styles and code as well as from related components such as Tooltip, Snippet and Select
2 changes: 1 addition & 1 deletion apps/docs/app/docs/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function DocsLayout({children}: DocsLayoutProps) {
<>
<main className="relative container mx-auto max-w-7xl z-10 px-6 min-h-[calc(100vh_-_64px_-_108px)] mb-12 flex-grow">
<div className="grid grid-cols-12">
<div className="hidden relative z-10 lg:block lg:col-span-2 mt-8 pr-4">
<div className="hidden overflow-visible relative z-10 lg:block lg:col-span-2 mt-8 pr-4">
<DocsSidebar routes={manifest.routes} />
</div>
{children}
Expand Down
36 changes: 20 additions & 16 deletions apps/docs/components/docs/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ import Link from "next/link";
import {isEmpty} from "lodash";
import {usePathname, useRouter} from "next/navigation";

import {ScrollArea} from "../scroll-area";

import {getRoutePaths} from "./utils";

import {Route} from "@/libs/docs/page";
import {TreeKeyboardDelegate} from "@/utils/tree-keyboard-delegate";
import {useScrollPosition} from "@/hooks/use-scroll-position";
import {trackEvent} from "@/utils/va";

export interface Props<T> extends Omit<ItemProps<T>, "title">, Route {
Expand Down Expand Up @@ -69,6 +70,7 @@ function TreeItem<T>(props: TreeItemProps<T>) {
};

const isNew = item.props?.newPost;
const isUpdated = item.props?.updated;

const isExpanded = state.expandedKeys.has(key);
const isSelected =
Expand Down Expand Up @@ -108,7 +110,9 @@ function TreeItem<T>(props: TreeItemProps<T>) {
aria-expanded={dataAttr(hasChildNodes ? isExpanded : undefined)}
aria-selected={dataAttr(isSelected)}
className={clsx(
"flex flex-col gap-3 outline-none w-full tap-highlight-transparent",
"flex flex-col gap-3outline-none w-full tap-highlight-transparent",

hasChildNodes ? "mb-4" : "first:mt-4",
// focus ring
...dataFocusVisibleClasses,
)}
Expand Down Expand Up @@ -156,18 +160,25 @@ function TreeItem<T>(props: TreeItemProps<T>) {
>
{rendered}
</span>
{isUpdated && (
<Chip className="ml-1 py-1 text-tiny" color="default" size="sm" variant="flat">
Updated
</Chip>
)}
{isNew && (
<Chip className="ml-2" color="primary" size="sm" variant="flat">
<Chip className="ml-1 py-1 text-tiny" color="primary" size="sm" variant="flat">
New
</Chip>
)}
{item.props?.comingSoon && (
<Chip className="ml-2" color="default" size="sm" variant="flat">
<Chip className="ml-1 py-1 text-tiny" color="default" size="sm" variant="flat">
Coming soon
</Chip>
)}
</NextUILink>
)}
{/* Workaround to avoid scrollbar overlapping */}
<Spacer x={4} />
</div>
{isExpanded && hasChildNodes && (
<div className="flex flex-col gap-3 items-start" role="group">
Expand Down Expand Up @@ -196,9 +207,7 @@ function TreeHeading({item}: {item: any}) {
function Tree<T extends object>(props: CollectionBase<T> & Expandable & MultipleSelection) {
let state = useTreeState(props);

let ref = useRef<HTMLUListElement>(null);

const scrollPosition = useScrollPosition(ref);
let ref = useRef<HTMLDivElement>(null);

let keyboardDelegate = useMemo(
// @ts-expect-error
Expand All @@ -213,16 +222,11 @@ function Tree<T extends object>(props: CollectionBase<T> & Expandable & Multiple
});

return (
<ul
{...collectionProps}
<ScrollArea
ref={ref}
className="flex flex-col gap-4 scrollbar-hide lg:overflow-y-scroll lg:max-h-[calc(100vh_-_64px)] pb-28"
className="h-full lg:max-h-[calc(100vh_-_64px)]"
role="tree"
style={{
WebkitMaskImage: `linear-gradient(to top, transparent 0%, #000 100px, #000 ${
scrollPosition > 30 ? "90%" : "100%"
}, transparent 100%)`,
}}
{...collectionProps}
>
{[...state.collection].map((item) => {
if (item.type === "section") {
Expand All @@ -231,7 +235,7 @@ function Tree<T extends object>(props: CollectionBase<T> & Expandable & Multiple

return <TreeItem key={item.key} item={item} state={state} />;
})}
</ul>
</ScrollArea>
);
}

Expand Down
54 changes: 54 additions & 0 deletions apps/docs/components/scroll-area.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use client";

import * as React from "react";
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
import {cn} from "@nextui-org/react";

const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({className, children, ...props}, ref) => {
return (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit] pb-28">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
);
});

ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;

const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({className, orientation = "vertical", ...props}, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
className={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" && "h-2.5 border-t border-t-transparent p-[1px]",
className,
)}
orientation={orientation}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb
className={cn(
"relative rounded-full bg-default-400/50",
orientation === "vertical" && "flex-1",
)}
/>
</ScrollAreaPrimitive.ScrollAreaScrollbar>
));

ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;

export {ScrollArea, ScrollBar};
16 changes: 10 additions & 6 deletions apps/docs/config/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@
"key": "listbox",
"title": "Listbox",
"keywords": "listbox, selection, option list, multiple choice",
"path": "/docs/components/listbox.mdx",
"newPost": true
"path": "/docs/components/listbox.mdx"
},
{
"key": "modal",
Expand Down Expand Up @@ -261,8 +260,7 @@
"key": "select",
"title": "Select",
"keywords": "select, selection, option list, multiple choice",
"path": "/docs/components/select.mdx",
"newPost": true
"path": "/docs/components/select.mdx"
},
{
"key": "skeleton",
Expand All @@ -280,8 +278,7 @@
"key": "scroll-shadow",
"title": "Scroll Shadow",
"keywords": "scroll shadow, scroll indicator, scroll bar, scroll position",
"path": "/docs/components/scroll-shadow.mdx",
"newPost": true
"path": "/docs/components/scroll-shadow.mdx"
},
{
"key": "spacer",
Expand All @@ -301,6 +298,13 @@
"keywords": "switch, toggle, binary input, on/off control",
"path": "/docs/components/switch.mdx"
},
{
"key": "slider",
"title": "Slider",
"keywords": "slider, range input, value selector, sliding control",
"path": "/docs/components/slider.mdx",
"newPost": true
},
{
"key": "table",
"title": "Table",
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/content/components/badge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import placements from "./placements";
import shapes from "./shapes";
import visibility from "./visibility";
import contentExamples from "./content-examples";
import disableOutline from "./disable-outline";
import showOutline from "./show-outline";
import a11y from "./a11y";

export const badgeContent = {
Expand All @@ -18,6 +18,6 @@ export const badgeContent = {
shapes,
visibility,
contentExamples,
disableOutline,
showOutline,
a11y,
};
Loading

0 comments on commit 3ddd5a9

Please sign in to comment.