Storybook Examples need sourcode #844
ivanjeremic
started this conversation in
General
Replies: 3 comments 1 reply
-
Any updates on this @clauderic 👀? |
Beta Was this translation helpful? Give feedback.
0 replies
-
I do agree that having simpler stories on Storybook would benefit the community. However, I believe it will require some additional effort. Meanwhile, here's a simple sample code for sortable vertical and grid layouts, in case anyone needs it. Vertical sample import { useState } from "react";
import {
DndContext,
type DragEndEvent,
KeyboardSensor,
PointerSensor,
type UniqueIdentifier,
closestCenter,
useSensor,
useSensors,
} from "@dnd-kit/core";
import {
SortableContext,
arrayMove,
sortableKeyboardCoordinates,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Meta, StoryObj } from "@storybook/react";
interface SortableItemProps {
id: UniqueIdentifier
}
const SortableItem = (props: SortableItemProps) => {
const { id } = props;
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
} = useSortable({
id,
transition: {
duration: 150, // milliseconds
easing: "cubic-bezier(0.25, 1, 0.5, 1)",
},
});
return (
<div
className="flex h-12 w-64 items-center justify-center rounded-md border-2 border-black bg-white"
ref={setNodeRef}
style={{
transform: CSS.Transform.toString(transform),
transition,
}}
{...attributes}
{...listeners}
>
{id}
</div>
);
};
const Container = () => {
const [items, setItems] = useState<UniqueIdentifier[]>(["1", "2", "3", "4", "5"]);
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(
KeyboardSensor,
{
coordinateGetter: sortableKeyboardCoordinates,
},
),
);
function handleDragEnd(event: DragEndEvent) {
const { active, over } = event;
if ((over !== null) && (active.id !== over.id)) {
setItems((items) => {
const oldIndex = items.indexOf(active.id);
const newIndex = items.indexOf(over.id);
return arrayMove(items, oldIndex, newIndex);
});
}
}
return (
<>
<div className="my-6">
Values:
{" "}
{items}
</div>
<DndContext
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
sensors={sensors}
>
<SortableContext
items={items}
strategy={verticalListSortingStrategy}
>
<div className="flex flex-col gap-2">
{items.map((id) => <SortableItem id={id} key={id} />)}
</div>
</SortableContext>
</DndContext>
</>
);
};
const meta: Meta<typeof Container> = {
title: "library/dnd-kit/Sortable",
component: Container,
decorators: [
(Story) => (
<div className="container max-w-md">
<Story />
</div>
),
],
parameters: {
layout: "centered",
},
};
export default meta;
type Story = StoryObj<typeof Container>;
export const Default: Story = {}; Grid sample import { useState } from "react";
import {
DndContext,
type DragEndEvent,
KeyboardSensor,
PointerSensor,
type UniqueIdentifier,
closestCenter,
useSensor,
useSensors,
} from "@dnd-kit/core";
import {
SortableContext,
arrayMove,
rectSortingStrategy,
sortableKeyboardCoordinates,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Meta, StoryObj } from "@storybook/react";
interface SortableItemProps {
id: UniqueIdentifier
}
const SortableItem = (props: SortableItemProps) => {
const { id } = props;
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
} = useSortable({
id,
});
return (
<div
className="flex size-32 items-center justify-center rounded-md border-2 border-black bg-white"
ref={setNodeRef}
style={{
transform: CSS.Transform.toString(transform),
transition,
}}
{...attributes}
{...listeners}
>
{id}
</div>
);
};
const Container = () => {
const [items, setItems] = useState<UniqueIdentifier[]>(["1", "2", "3", "4", "5", "a", "b", "c", "d", "e"]);
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(
KeyboardSensor,
{
coordinateGetter: sortableKeyboardCoordinates,
},
),
);
function handleDragEnd(event: DragEndEvent) {
const { active, over } = event;
if ((over !== null) && (active.id !== over.id)) {
setItems((items) => {
const oldIndex = items.indexOf(active.id);
const newIndex = items.indexOf(over.id);
return arrayMove(items, oldIndex, newIndex);
});
}
}
return (
<>
<div className="my-6">
Values:
{" "}
{items}
</div>
<DndContext
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
sensors={sensors}
>
<SortableContext
items={items}
strategy={rectSortingStrategy}
>
<div className="grid grid-cols-3 gap-2">
{items.map((id) => <SortableItem id={id} key={id} />)}
</div>
</SortableContext>
</DndContext>
</>
);
};
const meta: Meta<typeof Container> = {
title: "library/dnd-kit/Grid",
component: Container,
decorators: [
(Story) => (
<div className="container max-w-2xl">
<Story />
</div>
),
],
parameters: {
layout: "centered",
},
};
export default meta;
type Story = StoryObj<typeof Container>;
export const Base: Story = {}; Grid with Large First Tile sample import { type ForwardedRef, type HTMLAttributes, forwardRef, useCallback, useState } from "react";
import {
DndContext,
type DragEndEvent,
DragOverEvent,
DragOverlay,
type DragStartEvent,
KeyboardSensor,
PointerSensor,
type UniqueIdentifier,
closestCorners,
useSensor,
useSensors,
} from "@dnd-kit/core";
import {
SortableContext,
arrayMove,
rectSortingStrategy,
sortableKeyboardCoordinates,
} from "@dnd-kit/sortable";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Meta, StoryObj } from "@storybook/react";
import { createPortal } from "react-dom";
import { cn } from "@/lib/utils";
interface ItemProps extends Omit<HTMLAttributes<HTMLDivElement>, "id"> {
id: UniqueIdentifier
}
const Item = forwardRef((props: ItemProps, ref: ForwardedRef<HTMLDivElement>) => {
const { id, className, ...divProps } = props;
return (
<div
ref={ref}
{...divProps}
className={cn(
"flex aspect-square items-center justify-center rounded-md border-2 border-red-500 bg-slate-200 shadow-md",
className,
)}
>
{id}
</div>
);
});
Item.displayName = "Item";
interface SortableItemProps {
id: UniqueIdentifier
index: number
}
const SortableItem = (props: SortableItemProps) => {
const { id, index } = props;
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
} = useSortable({
id,
});
return (
<Item
className={cn(
index === 0 && "col-span-2 row-span-2 ",
"border-blue-400 bg-white",
)}
id={id}
ref={setNodeRef}
style={{
transform: CSS.Transform.toString(transform),
transformOrigin: "0 0", // ** Important **
transition,
}}
{...attributes}
{...listeners}
>
{id}
</Item>
);
};
let count = 0;
const Container = () => {
count += 1;
const [activeId, setActiveId] = useState<UniqueIdentifier>();
const [items, setItems] = useState<UniqueIdentifier[]>(["1", "2", "3", "4", "5", "a", "b", "c", "d", "e"]);
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(
KeyboardSensor,
{
coordinateGetter: sortableKeyboardCoordinates,
},
),
);
function handleDragStart(event: DragStartEvent) {
const { active } = event;
setActiveId(active.id);
}
function handleDragEnd(event: DragEndEvent) {
const { active, over } = event;
if ((over !== null) && (active.id !== over.id)) {
setItems((items) => {
const oldIndex = items.indexOf(active.id);
const newIndex = items.indexOf(over.id);
return arrayMove(items, oldIndex, newIndex);
});
}
}
return (
<>
<div>
Render count:
{" "}
{count}
</div>
<div className="mb-6 mt-1">
Values:
{" "}
{items}
</div>
<DndContext
collisionDetection={closestCorners}
onDragEnd={handleDragEnd}
onDragStart={handleDragStart}
sensors={sensors}
>
<SortableContext
items={items}
strategy={rectSortingStrategy}
>
<div className="grid w-96 grid-cols-4 gap-2">
{items.map((id, index) => <SortableItem id={id} index={index} key={id} />)}
</div>
</SortableContext>
{createPortal(
<DragOverlay adjustScale={true}>
{activeId ? <Item id={activeId} /> : null}
</DragOverlay>,
document.body,
)}
</DndContext>
</>
);
};
const meta: Meta<typeof Container> = {
title: "library/dnd-kit/Grid",
component: Container,
decorators: [
(Story) => (
<div className="container max-w-2xl">
<Story />
</div>
),
],
parameters: {
layout: "centered",
},
};
export default meta;
type Story = StoryObj<typeof Container>;
export const BigFirstWithOverlay: Story = {}; |
Beta Was this translation helpful? Give feedback.
1 reply
-
Ok Let me start working on this |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Storybook Example without sourcode directly inside to copy is really hard to rebuild, it is pretty hard to go trough GitHub source code and collect all the pieces together which we saw in Storybook, for Example the Grid Example inside Storybook, we need now to go trough all the Storybook files on GitHub to see how the Grid example works? I think adding the Example source code directly on the docs site as single Component to copy paste would be better.
Beta Was this translation helpful? Give feedback.
All reactions