Skip to content

Commit

Permalink
feat: resizeable component (#385)
Browse files Browse the repository at this point in the history
  • Loading branch information
sadeghbarati authored Mar 6, 2024
1 parent 0e84af7 commit 126e187
Show file tree
Hide file tree
Showing 20 changed files with 697 additions and 82 deletions.
6 changes: 6 additions & 0 deletions apps/www/.vitepress/theme/config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ export const docsConfig: DocsConfig = {
href: '/docs/components/radio-group',
items: [],
},
{
title: 'Resizable',
href: '/docs/components/resizable',
label: 'New',
items: [],
},
{
title: 'Scroll Area',
href: '/docs/components/scroll-area',
Expand Down
42 changes: 42 additions & 0 deletions apps/www/__registry__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,27 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/RangePickerWithSlot.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/RangePickerWithSlot.vue"],
},
"ResizableDemo": {
name: "ResizableDemo",
type: "components:example",
registryDependencies: ["resizable"],
component: () => import("../src/lib/registry/default/example/ResizableDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/ResizableDemo.vue"],
},
"ResizableHandleDemo": {
name: "ResizableHandleDemo",
type: "components:example",
registryDependencies: ["resizable"],
component: () => import("../src/lib/registry/default/example/ResizableHandleDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/ResizableHandleDemo.vue"],
},
"ResizableVerticalDemo": {
name: "ResizableVerticalDemo",
type: "components:example",
registryDependencies: ["resizable"],
component: () => import("../src/lib/registry/default/example/ResizableVerticalDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/ResizableVerticalDemo.vue"],
},
"ScrollAreaDemo": {
name: "ScrollAreaDemo",
type: "components:example",
Expand Down Expand Up @@ -1600,6 +1621,27 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/RangePickerWithSlot.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/RangePickerWithSlot.vue"],
},
"ResizableDemo": {
name: "ResizableDemo",
type: "components:example",
registryDependencies: ["resizable"],
component: () => import("../src/lib/registry/new-york/example/ResizableDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/ResizableDemo.vue"],
},
"ResizableHandleDemo": {
name: "ResizableHandleDemo",
type: "components:example",
registryDependencies: ["resizable"],
component: () => import("../src/lib/registry/new-york/example/ResizableHandleDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/ResizableHandleDemo.vue"],
},
"ResizableVerticalDemo": {
name: "ResizableVerticalDemo",
type: "components:example",
registryDependencies: ["resizable"],
component: () => import("../src/lib/registry/new-york/example/ResizableVerticalDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/ResizableVerticalDemo.vue"],
},
"ScrollAreaDemo": {
name: "ScrollAreaDemo",
type: "components:example",
Expand Down
14 changes: 7 additions & 7 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"embla-carousel-autoplay": "^8.0.0",
"embla-carousel-vue": "^8.0.0",
"lucide-vue-next": "^0.276.0",
"radix-vue": "^1.4.9",
"radix-vue": "^1.5.0",
"tailwindcss-animate": "^1.0.7",
"v-calendar": "^3.1.2",
"vaul-vue": "^0.1.0",
Expand All @@ -42,9 +42,9 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@iconify-json/radix-icons": "^1.1.11",
"@iconify-json/tabler": "^1.1.89",
"@iconify/json": "^2.2.108",
"@iconify-json/radix-icons": "^1.1.14",
"@iconify-json/tabler": "^1.1.106",
"@iconify/json": "^2.2.189",
"@iconify/vue": "^4.1.1",
"@shikijs/transformers": "^1.1.7",
"@types/lodash.template": "^4.5.3",
Expand All @@ -56,7 +56,7 @@
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.18",
"lodash.template": "^4.5.0",
"oxc-parser": "^0.7.0",
"oxc-parser": "^0.8.0",
"pathe": "^1.1.2",
"rimraf": "^5.0.5",
"shiki": "^1.1.7",
Expand All @@ -65,8 +65,8 @@
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"unplugin-icons": "^0.18.5",
"vite": "^5.1.4",
"vite": "^5.1.5",
"vitepress": "^1.0.0-rc.44",
"vue-tsc": "^2.0.3"
"vue-tsc": "^2.0.5"
}
}
117 changes: 117 additions & 0 deletions apps/www/src/content/docs/components/resizable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
title: Resizable
description: Accessible resizable panel groups and layouts with keyboard support.
source: apps/www/src/lib/registry/default/ui/resizable
primitive: https://www.radix-vue.com/components/splitter.html
---

<ComponentPreview name="ResizableDemo" />

## Installation

<TabPreview name="CLI">
<template #CLI>

```bash
npx shadcn-vue@latest add resizable
```
</template>

<template #Manual>

<Steps>

### Install the following dependency:

```bash
npm install radix-vue
```

### Copy and paste the following code into your project:

`index.ts`

<<< @/lib/registry/default/ui/resizable/index.ts

`ResizablePanelGroup.vue`

<<< @/lib/registry/default/ui/resizable/ResizablePanelGroup.vue

`ResizableHandle.vue`

<<< @/lib/registry/default/ui/resizable/ResizableHandle.vue

</Steps>

</template>
</TabPreview>

## Usage

```vue
<script setup lang="ts">
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/components/ui/resizable'
</script>
<template>
<ResizablePanelGroup direction="horizontal">
<ResizablePanel>One</ResizablePanel>
<ResizableHandle />
<ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>
</template>
```

## Examples

### Vertical

Use the direction prop to set the direction of the resizable panels.

<ComponentPreview name="ResizableVerticalDemo" />

```vue:line-numbers {10}
<script setup lang="ts">
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/components/ui/resizable'
</script>
<template>
<ResizablePanelGroup direction="horizontal">
<ResizablePanel>One</ResizablePanel>
<ResizableHandle />
<ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>
</template>
```

### Handle

You can set or hide the handle by using the withHandle prop on the ResizableHandle component.

<ComponentPreview name="ResizableHandleDemo" />

```vue:line-numbers {12}
<script setup lang="ts">
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/components/ui/resizable'
</script>
<template>
<ResizablePanelGroup direction="horizontal">
<ResizablePanel>One</ResizablePanel>
<ResizableHandle with-handle />
<ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>
</template>
```
36 changes: 36 additions & 0 deletions apps/www/src/lib/registry/default/example/ResizableDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script setup lang="ts">
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/lib/registry/default/ui/resizable'
</script>

<template>
<ResizablePanelGroup
direction="horizontal"
class="max-w-md rounded-lg border"
>
<ResizablePanel :default-size="50">
<div class="flex h-[200px] items-center justify-center p-6">
<span class="font-semibold">One</span>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel :default-size="50">
<ResizablePanelGroup direction="vertical">
<ResizablePanel :default-size="25">
<div class="flex h-full items-center justify-center p-6">
<span class="font-semibold">Two</span>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel :default-size="75">
<div class="flex h-full items-center justify-center p-6">
<span class="font-semibold">Three</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
</template>
26 changes: 26 additions & 0 deletions apps/www/src/lib/registry/default/example/ResizableHandleDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts">
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/lib/registry/default/ui/resizable'
</script>

<template>
<ResizablePanelGroup
direction="horizontal"
class="min-h-[200px] max-w-md rounded-lg border"
>
<ResizablePanel :default-size="25">
<div class="flex h-full items-center justify-center p-6">
<span class="font-semibold">Sidebar</span>
</div>
</ResizablePanel>
<ResizableHandle with-handle />
<ResizablePanel :default-size="75">
<div class="flex h-full items-center justify-center p-6">
<span class="font-semibold">Content</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts">
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/lib/registry/default/ui/resizable'
</script>

<template>
<ResizablePanelGroup
direction="vertical"
class="min-h-[200px] max-w-md rounded-lg border"
>
<ResizablePanel :default-size="25">
<div class="flex h-full items-center justify-center p-6">
<span class="font-semibold">Header</span>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel :default-size="75">
<div class="flex h-full items-center justify-center p-6">
<span class="font-semibold">Content</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</template>
26 changes: 26 additions & 0 deletions apps/www/src/lib/registry/default/ui/resizable/ResizableHandle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { SplitterResizeHandle, type SplitterResizeHandleEmits, type SplitterResizeHandleProps, useForwardPropsEmits } from 'radix-vue'
import { GripVertical } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
const props = defineProps<SplitterResizeHandleProps & { class?: HTMLAttributes['class'], withHandle?: boolean }>()
const emits = defineEmits<SplitterResizeHandleEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
<SplitterResizeHandle v-bind="forwarded" :class="cn('relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 [&[data-orientation=vertical]]:h-px [&[data-orientation=vertical]]:w-full [&[data-orientation=vertical]]:after:left-0 [&[data-orientation=vertical]]:after:h-1 [&[data-orientation=vertical]]:after:w-full [&[data-orientation=vertical]]:after:-translate-y-1/2 [&[data-orientation=vertical]]:after:translate-x-0 [&[data-orientation=vertical]>div]:rotate-90', props.class)">
<template v-if="props.withHandle">
<div class="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
<GripVertical class="h-2.5 w-2.5" />
</div>
</template>
</SplitterResizeHandle>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { SplitterGroup, type SplitterGroupEmits, type SplitterGroupProps, useForwardPropsEmits } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<SplitterGroupProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<SplitterGroupEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
<SplitterGroup v-bind="forwarded" :class="cn('flex h-full w-full data-[panel-group-direction=vertical]:flex-col', props.class)">
<slot />
</SplitterGroup>
</template>
3 changes: 3 additions & 0 deletions apps/www/src/lib/registry/default/ui/resizable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as ResizablePanelGroup } from './ResizablePanelGroup.vue'
export { default as ResizableHandle } from './ResizableHandle.vue'
export { SplitterPanel as ResizablePanel } from 'radix-vue'
Loading

0 comments on commit 126e187

Please sign in to comment.