-
Notifications
You must be signed in to change notification settings - Fork 1
refactor(ui): migrate devtools panel to shadcn-vue #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d622760
db89a02
4fa8502
72e3b8f
1d9d435
9533426
95859ec
55d61b5
cea7766
3caa162
0cfc15d
f24f8b6
6452ec5
cbaf181
25e538d
fe5fa71
141b696
fc6f291
bb45612
6cf942e
f95235f
dbbf92b
7e7ce32
f32c914
4ee4ea4
4cd1a71
ac959ad
4f787d0
b0222ac
ccd898a
0a47bf4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,100 @@ | ||
| @import "tailwindcss"; | ||
|
|
||
| body { | ||
| padding: 16px; | ||
| overflow-x: hidden; | ||
| overflow-y: scroll; | ||
| @source "../entrypoints"; | ||
| @source "../components"; | ||
| @source "../lib"; | ||
|
|
||
| @custom-variant dark (&:where(.dark, .dark *)); | ||
|
|
||
| @theme inline { | ||
| --color-background: hsl(var(--background)); | ||
| --color-foreground: hsl(var(--foreground)); | ||
| --color-popover: hsl(var(--popover)); | ||
| --color-popover-foreground: hsl(var(--popover-foreground)); | ||
| --color-primary: hsl(var(--primary)); | ||
| --color-primary-foreground: hsl(var(--primary-foreground)); | ||
| --color-secondary: hsl(var(--secondary)); | ||
| --color-secondary-foreground: hsl(var(--secondary-foreground)); | ||
| --color-muted: hsl(var(--muted)); | ||
| --color-muted-foreground: hsl(var(--muted-foreground)); | ||
| --color-accent: hsl(var(--accent)); | ||
| --color-accent-foreground: hsl(var(--accent-foreground)); | ||
| --color-destructive: hsl(var(--destructive)); | ||
| --color-destructive-foreground: hsl(var(--destructive-foreground)); | ||
| --color-border: hsl(var(--border)); | ||
| --color-input: hsl(var(--input)); | ||
| --color-ring: hsl(var(--ring)); | ||
| --radius-lg: var(--radius); | ||
| --radius-md: calc(var(--radius) - 2px); | ||
| --radius-sm: calc(var(--radius) - 4px); | ||
| } | ||
|
|
||
| @layer base { | ||
| :root { | ||
| --background: 0 0% 100%; | ||
| --foreground: 0 0% 3.9%; | ||
| --popover: 0 0% 100%; | ||
| --popover-foreground: 0 0% 3.9%; | ||
| --primary: 0 0% 9%; | ||
| --primary-foreground: 0 0% 98%; | ||
| --secondary: 0 0% 96.1%; | ||
| --secondary-foreground: 0 0% 9%; | ||
| --muted: 0 0% 96.1%; | ||
| --muted-foreground: 0 0% 45.1%; | ||
| --accent: 0 0% 96.1%; | ||
| --accent-foreground: 0 0% 9%; | ||
| --destructive: 0 0% 9%; | ||
| --destructive-foreground: 0 0% 98%; | ||
| --border: 0 0% 89.8%; | ||
| --input: 0 0% 89.8%; | ||
| --ring: 0 0% 3.9%; | ||
| --radius: 0.5rem; | ||
| } | ||
|
|
||
| .dark { | ||
| --background: 0 0% 3.9%; | ||
| --foreground: 0 0% 98%; | ||
| --popover: 0 0% 3.9%; | ||
| --popover-foreground: 0 0% 98%; | ||
| --primary: 0 0% 98%; | ||
| --primary-foreground: 0 0% 9%; | ||
| --secondary: 0 0% 14.9%; | ||
| --secondary-foreground: 0 0% 98%; | ||
| --muted: 0 0% 14.9%; | ||
| --muted-foreground: 0 0% 63.9%; | ||
| --accent: 0 0% 14.9%; | ||
| --accent-foreground: 0 0% 98%; | ||
| --destructive: 0 0% 98%; | ||
| --destructive-foreground: 0 0% 9%; | ||
| --border: 0 0% 14.9%; | ||
| --input: 0 0% 14.9%; | ||
| --ring: 0 0% 83.1%; | ||
| } | ||
|
|
||
| * { | ||
| @apply border-border; | ||
| } | ||
|
|
||
| html { | ||
| color-scheme: light; | ||
| } | ||
|
|
||
| html.dark { | ||
| color-scheme: dark; | ||
| } | ||
|
|
||
| body { | ||
| @apply bg-background text-foreground antialiased; | ||
| min-width: 0; | ||
| margin: 0; | ||
| padding: 16px; | ||
| overflow-y: hidden; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the DevTools pane is docked/resized short enough that the header plus selection/filter cards exceed the available height, the panel content overflows the fixed-height Useful? React with 👍 / 👎. |
||
| } | ||
| } | ||
|
|
||
| .el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell{ | ||
| background-color: inherit !important; | ||
| @layer utilities { | ||
| .css-diff-scrollbar { | ||
| scrollbar-color: hsl(var(--muted-foreground) / 0.35) transparent; | ||
| scrollbar-width: thin; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "$schema": "https://shadcn-vue.com/schema.json", | ||
| "style": "new-york", | ||
| "typescript": true, | ||
| "tailwind": { | ||
| "config": "", | ||
| "css": "assets/main.css", | ||
| "baseColor": "neutral", | ||
| "cssVariables": true, | ||
| "prefix": "" | ||
| }, | ||
| "aliases": { | ||
| "components": "@/components", | ||
| "composables": "@/composables", | ||
| "utils": "@/lib/utils", | ||
| "ui": "@/components/ui", | ||
| "lib": "@/lib" | ||
| }, | ||
| "iconLibrary": "lucide" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| <script setup lang="ts"> | ||
| import type { HTMLAttributes } from 'vue' | ||
| import { Primitive, type PrimitiveProps } from 'reka-ui' | ||
| import { cn } from '@/lib/utils' | ||
| import { buttonVariants, type ButtonVariants } from '.' | ||
|
|
||
| interface Props extends PrimitiveProps { | ||
| variant?: ButtonVariants['variant'] | ||
| size?: ButtonVariants['size'] | ||
| class?: HTMLAttributes['class'] | ||
| } | ||
|
|
||
| const props = withDefaults(defineProps<Props>(), { | ||
| as: 'button', | ||
| }) | ||
| </script> | ||
|
|
||
| <template> | ||
| <Primitive | ||
| :as="props.as" | ||
| :as-child="props.asChild" | ||
| :class="cn(buttonVariants({ variant: props.variant, size: props.size }), props.class)" | ||
| > | ||
| <slot /> | ||
| </Primitive> | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { cva, type VariantProps } from 'class-variance-authority' | ||
|
|
||
| export { default as Button } from './Button.vue' | ||
|
|
||
| export const buttonVariants = cva( | ||
| 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | ||
| { | ||
| variants: { | ||
| variant: { | ||
| default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90', | ||
| destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', | ||
| outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', | ||
| secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', | ||
| ghost: 'hover:bg-accent hover:text-accent-foreground', | ||
| }, | ||
| size: { | ||
| default: 'h-9 px-4 py-2', | ||
| sm: 'h-8 rounded-md px-3 text-xs', | ||
| icon: 'h-8 w-8', | ||
| }, | ||
| }, | ||
| defaultVariants: { | ||
| variant: 'default', | ||
| size: 'default', | ||
| }, | ||
| }, | ||
| ) | ||
|
|
||
| export type ButtonVariants = VariantProps<typeof buttonVariants> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <script setup lang="ts"> | ||
| import type { HTMLAttributes } from 'vue' | ||
| import { Check } from 'lucide-vue-next' | ||
| import { CheckboxIndicator, CheckboxRoot } from 'reka-ui' | ||
| import { cn } from '@/lib/utils' | ||
|
|
||
| const props = defineProps<{ | ||
| class?: HTMLAttributes['class'] | ||
| }>() | ||
|
|
||
| const checked = defineModel<boolean | 'indeterminate'>('checked') | ||
| </script> | ||
|
|
||
| <template> | ||
| <CheckboxRoot | ||
| v-model:checked="checked" | ||
| :class="cn('peer h-4 w-4 shrink-0 rounded border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground', props.class)" | ||
| > | ||
| <CheckboxIndicator class="flex items-center justify-center text-current"> | ||
| <Check class="h-3.5 w-3.5" /> | ||
| </CheckboxIndicator> | ||
| </CheckboxRoot> | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { default as Checkbox } from './Checkbox.vue' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| <script setup lang="ts"> | ||
| import type { HTMLAttributes } from 'vue' | ||
| import { cn } from '@/lib/utils' | ||
|
|
||
| const props = defineProps<{ | ||
| class?: HTMLAttributes['class'] | ||
| }>() | ||
|
|
||
| const modelValue = defineModel<string | number>() | ||
| </script> | ||
|
|
||
| <template> | ||
| <input | ||
| v-model="modelValue" | ||
| :class="cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)" | ||
| > | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { default as Input } from './Input.vue' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| <script setup lang="ts"> | ||
| import type { HTMLAttributes } from 'vue' | ||
| import { PopoverContent, PopoverPortal } from 'reka-ui' | ||
| import { cn } from '@/lib/utils' | ||
|
|
||
| const props = withDefaults(defineProps<{ | ||
| align?: 'center' | 'end' | 'start' | ||
| class?: HTMLAttributes['class'] | ||
| side?: 'bottom' | 'left' | 'right' | 'top' | ||
| sideOffset?: number | ||
| }>(), { | ||
| align: 'center', | ||
| side: 'bottom', | ||
| sideOffset: 4, | ||
| }) | ||
| </script> | ||
|
|
||
| <template> | ||
| <PopoverPortal> | ||
| <PopoverContent | ||
| :align="props.align" | ||
| :side="props.side" | ||
| :side-offset="props.sideOffset" | ||
| :class="cn('z-50 w-64 rounded-md border bg-popover p-3 text-xs leading-5 text-popover-foreground shadow-md outline-none', props.class)" | ||
| > | ||
| <slot /> | ||
| </PopoverContent> | ||
| </PopoverPortal> | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { default as PopoverContent } from './PopoverContent.vue' | ||
| export { PopoverRoot as Popover, PopoverTrigger } from 'reka-ui' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| <script setup lang="ts"> | ||
| import type { HTMLAttributes } from 'vue' | ||
| import { SelectContent, SelectPortal, SelectViewport } from 'reka-ui' | ||
| import { cn } from '@/lib/utils' | ||
|
|
||
| const props = defineProps<{ | ||
| class?: HTMLAttributes['class'] | ||
| }>() | ||
| </script> | ||
|
|
||
| <template> | ||
| <SelectPortal> | ||
| <SelectContent | ||
| position="popper" | ||
| :class="cn('relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', props.class)" | ||
| > | ||
| <SelectViewport class="p-1"> | ||
| <slot /> | ||
| </SelectViewport> | ||
| </SelectContent> | ||
| </SelectPortal> | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <script setup lang="ts"> | ||
| import type { HTMLAttributes } from 'vue' | ||
| import { Check } from 'lucide-vue-next' | ||
| import { SelectItem, SelectItemIndicator, SelectItemText } from 'reka-ui' | ||
| import { cn } from '@/lib/utils' | ||
|
|
||
| const props = defineProps<{ | ||
| value: string | ||
| class?: HTMLAttributes['class'] | ||
| }>() | ||
| </script> | ||
|
|
||
| <template> | ||
| <SelectItem | ||
| :value="props.value" | ||
| :class="cn('relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-xs outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', props.class)" | ||
| > | ||
| <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> | ||
| <SelectItemIndicator> | ||
| <Check class="h-3.5 w-3.5" /> | ||
| </SelectItemIndicator> | ||
| </span> | ||
| <SelectItemText> | ||
| <slot /> | ||
| </SelectItemText> | ||
| </SelectItem> | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| <script setup lang="ts"> | ||
| import type { HTMLAttributes } from 'vue' | ||
| import { ChevronDown } from 'lucide-vue-next' | ||
| import { SelectIcon, SelectTrigger } from 'reka-ui' | ||
| import { cn } from '@/lib/utils' | ||
|
|
||
| const props = defineProps<{ | ||
| class?: HTMLAttributes['class'] | ||
| }>() | ||
| </script> | ||
|
|
||
| <template> | ||
| <SelectTrigger | ||
| :class="cn('flex h-8 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-xs shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1', props.class)" | ||
| > | ||
| <slot /> | ||
| <SelectIcon as-child> | ||
| <ChevronDown class="h-3.5 w-3.5 opacity-50" /> | ||
| </SelectIcon> | ||
| </SelectTrigger> | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <script setup lang="ts"> | ||
| import { SelectValue } from 'reka-ui' | ||
| </script> | ||
|
|
||
| <template> | ||
| <SelectValue> | ||
| <slot /> | ||
| </SelectValue> | ||
| </template> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export { default as SelectContent } from './SelectContent.vue' | ||
| export { default as SelectItem } from './SelectItem.vue' | ||
| export { default as SelectTrigger } from './SelectTrigger.vue' | ||
| export { default as SelectValue } from './SelectValue.vue' | ||
| export { SelectRoot as Select } from 'reka-ui' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because browsers give
bodyan 8px default margin, the new fixed-height panel (100vh - 32px) plus 16px top/bottom padding still occupies more than the DevTools pane onceoverflow-yis hidden here. In normal browser styling this clips the bottom of the sidebar/table instead of allowing it to scroll; reset the body margin or account for it before disabling overflow.Useful? React with 👍 / 👎.