mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 21:15:18 +09:00
refactor: rewrite radix dialog and sheet templates with jsx (#4671)
- dropped radix sheet meta - added reusable button styles - added radix dialog and sheet templates
This commit is contained in:
1 parent
6c5711cf2a
commit
ef6e71ac6d
10 files changed
+489
-410
No files matched your search
@@ -0,0 +1,151 @@
|
||||
import { LargeXIcon } from "@webstudio-is/icons/svg";
|
||||
import {
|
||||
type TemplateMeta,
|
||||
$,
|
||||
css,
|
||||
PlaceholderValue,
|
||||
} from "@webstudio-is/template";
|
||||
import { radix } from "./shared/proxy";
|
||||
import {
|
||||
blur,
|
||||
borderRadius,
|
||||
borderWidth,
|
||||
boxShadow,
|
||||
colors,
|
||||
fontSize,
|
||||
fontSizeLineHeight,
|
||||
height,
|
||||
letterSpacing,
|
||||
lineHeight,
|
||||
maxWidth,
|
||||
opacity,
|
||||
spacing,
|
||||
width,
|
||||
zIndex,
|
||||
} from "./shared/theme";
|
||||
import { getButtonStyle } from "./shared/styles";
|
||||
|
||||
export const meta: TemplateMeta = {
|
||||
category: "radix",
|
||||
description:
|
||||
"Displays content with an overlay that covers the window, triggered by a button. Clicking the overlay will close the dialog.",
|
||||
order: 4,
|
||||
template: (
|
||||
<radix.Dialog>
|
||||
<radix.DialogTrigger>
|
||||
<$.Button ws:style={getButtonStyle("outline")}>
|
||||
{new PlaceholderValue("Button")}
|
||||
</$.Button>
|
||||
</radix.DialogTrigger>
|
||||
<radix.DialogOverlay
|
||||
/**
|
||||
* fixed inset-0 z-50 bg-background/80 backdrop-blur-sm
|
||||
* flex
|
||||
**/
|
||||
ws:style={css`
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: ${zIndex[50]};
|
||||
background-color: rgb(255 255 255 / 0.8);
|
||||
backdrop-filter: ${blur.sm};
|
||||
/* To allow positioning Content */
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
`}
|
||||
>
|
||||
<radix.DialogContent
|
||||
/**
|
||||
* fixed w-full z-50
|
||||
* grid gap-4 max-w-lg
|
||||
* m-auto
|
||||
* border bg-background p-6 shadow-lg
|
||||
**/
|
||||
ws:style={css`
|
||||
width: ${width.full};
|
||||
z-index: ${zIndex[50]};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${spacing[4]};
|
||||
margin: auto;
|
||||
max-width: ${maxWidth.lg};
|
||||
border: ${borderWidth.DEFAULT} solid ${colors.border};
|
||||
background-color: ${colors.background};
|
||||
padding: ${spacing[6]};
|
||||
box-shadow: ${boxShadow.lg};
|
||||
position: relative;
|
||||
`}
|
||||
>
|
||||
<$.Box
|
||||
ws:label="Dialog Header"
|
||||
ws:style={css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${spacing[2]};
|
||||
`}
|
||||
>
|
||||
<radix.DialogTitle
|
||||
/**
|
||||
* text-lg leading-none tracking-tight
|
||||
**/
|
||||
ws:style={css`
|
||||
font-size: ${fontSize.lg};
|
||||
line-height: ${lineHeight.none};
|
||||
letter-spacing: ${letterSpacing.tight};
|
||||
margin: 0;
|
||||
`}
|
||||
>
|
||||
{new PlaceholderValue("Dialog Title you can edit")}
|
||||
</radix.DialogTitle>
|
||||
<radix.DialogDescription
|
||||
/**
|
||||
* text-sm text-muted-foreground
|
||||
**/
|
||||
ws:style={css`
|
||||
font-size: ${fontSize.sm};
|
||||
line-height: ${fontSizeLineHeight.sm};
|
||||
color: ${colors.mutedForeground};
|
||||
margin: 0;
|
||||
`}
|
||||
>
|
||||
{new PlaceholderValue("Dialog description text you can edit")}
|
||||
</radix.DialogDescription>
|
||||
</$.Box>
|
||||
<$.Text>{new PlaceholderValue("The text you can edit")}</$.Text>
|
||||
<radix.DialogClose
|
||||
ws:label="Close Button"
|
||||
/**
|
||||
* absolute right-4 top-4
|
||||
* rounded-sm opacity-70
|
||||
* ring-offset-background
|
||||
* hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
|
||||
* flex items-center justify-center h-4 w-4
|
||||
**/
|
||||
ws:style={css`
|
||||
position: absolute;
|
||||
right: ${spacing[4]};
|
||||
top: ${spacing[4]};
|
||||
border-radius: ${borderRadius.sm};
|
||||
opacity: ${opacity[70]};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: ${height[4]};
|
||||
width: ${height[4]};
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
&:hover {
|
||||
opacity: ${opacity[100]};
|
||||
}
|
||||
&:focus-visible {
|
||||
box-shadow: ${boxShadow.ring};
|
||||
}
|
||||
`}
|
||||
>
|
||||
<$.HtmlEmbed ws:label="Close Icon" code={LargeXIcon} />
|
||||
</radix.DialogClose>
|
||||
</radix.DialogContent>
|
||||
</radix.DialogOverlay>
|
||||
</radix.Dialog>
|
||||
),
|
||||
};
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
HeadingIcon,
|
||||
TextIcon,
|
||||
ButtonElementIcon,
|
||||
LargeXIcon,
|
||||
} from "@webstudio-is/icons/svg";
|
||||
import {
|
||||
defaultStates,
|
||||
@@ -15,7 +14,6 @@ import {
|
||||
type WsComponentPropsMeta,
|
||||
} from "@webstudio-is/react-sdk";
|
||||
import { div, button, h2, p } from "@webstudio-is/sdk/normalize.css";
|
||||
import * as tc from "./theme/tailwind-classes";
|
||||
import {
|
||||
propsDialog,
|
||||
propsDialogContent,
|
||||
@@ -25,7 +23,7 @@ import {
|
||||
propsDialogTitle,
|
||||
propsDialogDescription,
|
||||
} from "./__generated__/dialog.props";
|
||||
import { buttonReset, getButtonStyles } from "./theme/styles";
|
||||
import { buttonReset } from "./theme/styles";
|
||||
|
||||
const presetStyle = {
|
||||
div,
|
||||
@@ -41,7 +39,6 @@ const descriptionPresetStyle = {
|
||||
|
||||
// @todo add [data-state] to button and link
|
||||
export const metaDialogTrigger: WsComponentMeta = {
|
||||
category: "hidden",
|
||||
type: "container",
|
||||
icon: TriggerIcon,
|
||||
stylable: false,
|
||||
@@ -52,7 +49,6 @@ export const metaDialogTrigger: WsComponentMeta = {
|
||||
};
|
||||
|
||||
export const metaDialogOverlay: WsComponentMeta = {
|
||||
category: "hidden",
|
||||
type: "container",
|
||||
presetStyle,
|
||||
icon: OverlayIcon,
|
||||
@@ -69,7 +65,6 @@ export const metaDialogOverlay: WsComponentMeta = {
|
||||
};
|
||||
|
||||
export const metaDialogContent: WsComponentMeta = {
|
||||
category: "hidden",
|
||||
type: "container",
|
||||
presetStyle,
|
||||
icon: ContentIcon,
|
||||
@@ -98,7 +93,6 @@ export const metaDialogContent: WsComponentMeta = {
|
||||
};
|
||||
|
||||
export const metaDialogTitle: WsComponentMeta = {
|
||||
category: "hidden",
|
||||
type: "container",
|
||||
presetStyle: titlePresetStyle,
|
||||
icon: HeadingIcon,
|
||||
@@ -109,7 +103,6 @@ export const metaDialogTitle: WsComponentMeta = {
|
||||
};
|
||||
|
||||
export const metaDialogDescription: WsComponentMeta = {
|
||||
category: "hidden",
|
||||
type: "container",
|
||||
presetStyle: descriptionPresetStyle,
|
||||
icon: TextIcon,
|
||||
@@ -120,7 +113,6 @@ export const metaDialogDescription: WsComponentMeta = {
|
||||
};
|
||||
|
||||
export const metaDialogClose: WsComponentMeta = {
|
||||
category: "hidden",
|
||||
type: "container",
|
||||
presetStyle: {
|
||||
button: [buttonReset, button].flat(),
|
||||
@@ -143,8 +135,6 @@ export const metaDialogClose: WsComponentMeta = {
|
||||
* Copyright (c) 2023 shadcn
|
||||
**/
|
||||
export const metaDialog: WsComponentMeta = {
|
||||
category: "radix",
|
||||
order: 4,
|
||||
type: "container",
|
||||
constraints: [
|
||||
{
|
||||
@@ -158,177 +148,6 @@ export const metaDialog: WsComponentMeta = {
|
||||
],
|
||||
icon: DialogIcon,
|
||||
stylable: false,
|
||||
description:
|
||||
"Displays content with an overlay that covers the window, triggered by a button. Clicking the overlay will close the dialog.",
|
||||
template: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "Dialog",
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogTrigger",
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "Button",
|
||||
styles: getButtonStyles("outline"),
|
||||
children: [{ type: "text", value: "Button", placeholder: true }],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogOverlay",
|
||||
/**
|
||||
* fixed inset-0 z-50 bg-background/80 backdrop-blur-sm
|
||||
* flex
|
||||
**/
|
||||
styles: [
|
||||
tc.fixed(),
|
||||
tc.inset(0),
|
||||
tc.z(50),
|
||||
tc.bg("background", 80),
|
||||
tc.backdropBlur("sm"),
|
||||
// To allow positioning Content
|
||||
tc.flex(),
|
||||
tc.overflow("auto"),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogContent",
|
||||
/**
|
||||
* fixed w-full z-50
|
||||
* grid gap-4 max-w-lg
|
||||
* m-auto
|
||||
* border bg-background p-6 shadow-lg
|
||||
**/
|
||||
styles: [
|
||||
tc.w("full"),
|
||||
tc.z(50),
|
||||
tc.flex(),
|
||||
tc.flex("col"),
|
||||
tc.gap(4),
|
||||
tc.m("auto"),
|
||||
tc.maxW("lg"),
|
||||
tc.border(),
|
||||
tc.bg("background"),
|
||||
tc.p(6),
|
||||
tc.shadow("lg"),
|
||||
tc.relative(),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "Box",
|
||||
label: "Dialog Header",
|
||||
styles: [tc.flex(), tc.flex("col"), tc.gap(1)].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogTitle",
|
||||
/**
|
||||
* text-lg leading-none tracking-tight
|
||||
**/
|
||||
styles: [
|
||||
tc.my(0),
|
||||
tc.leading("none"),
|
||||
tc.text("lg"),
|
||||
tc.tracking("tight"),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "text",
|
||||
value: "Dialog Title you can edit",
|
||||
placeholder: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogDescription",
|
||||
/**
|
||||
* text-sm text-muted-foreground
|
||||
**/
|
||||
styles: [
|
||||
tc.my(0),
|
||||
tc.text("sm"),
|
||||
tc.text("mutedForeground"),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "text",
|
||||
value: "Dialog description text you can edit",
|
||||
placeholder: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
type: "instance",
|
||||
component: "Text",
|
||||
children: [
|
||||
{
|
||||
type: "text",
|
||||
value: "The text you can edit",
|
||||
placeholder: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogClose",
|
||||
/**
|
||||
* absolute right-4 top-4
|
||||
* rounded-sm opacity-70
|
||||
* ring-offset-background
|
||||
* hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
|
||||
* flex items-center justify-center h-4 w-4
|
||||
**/
|
||||
styles: [
|
||||
tc.absolute(),
|
||||
tc.right(4),
|
||||
tc.top(4),
|
||||
tc.rounded("sm"),
|
||||
tc.opacity(70),
|
||||
tc.flex(),
|
||||
tc.items("center"),
|
||||
tc.justify("center"),
|
||||
tc.h(4),
|
||||
tc.w(4),
|
||||
tc.border(0),
|
||||
tc.bg("transparent"),
|
||||
tc.outline("none"),
|
||||
tc.hover(tc.opacity(100)),
|
||||
tc.focus(tc.ring("ring", 2, "background", 2)),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "HtmlEmbed",
|
||||
label: "Close Icon",
|
||||
props: [
|
||||
{
|
||||
type: "string",
|
||||
name: "code",
|
||||
value: LargeXIcon,
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const propsMetaDialog: WsComponentPropsMeta = {
|
||||
|
||||
@@ -6,6 +6,14 @@ import {
|
||||
import { radix } from "./shared/proxy";
|
||||
import { fontSize, lineHeight, weights } from "./shared/theme";
|
||||
|
||||
/**
|
||||
* Styles source without animations:
|
||||
* https://github.com/shadcn-ui/ui/blob/main/apps/www/registry/default/ui/label.tsx
|
||||
*
|
||||
* Attributions
|
||||
* MIT License
|
||||
* Copyright (c) 2023 shadcn
|
||||
**/
|
||||
export const meta: TemplateMeta = {
|
||||
category: "radix",
|
||||
description:
|
||||
|
||||
@@ -12,7 +12,6 @@ export {
|
||||
metaDialogTitle as DialogTitle,
|
||||
metaDialogDescription as DialogDescription,
|
||||
} from "./dialog.ws";
|
||||
export { meta as Sheet } from "./sheet.ws";
|
||||
export {
|
||||
metaPopover as Popover,
|
||||
metaPopoverTrigger as PopoverTrigger,
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { css, type TemplateStyleDecl } from "@webstudio-is/template";
|
||||
import {
|
||||
borderRadius,
|
||||
borderWidth,
|
||||
boxShadow,
|
||||
colors,
|
||||
fontSize,
|
||||
fontSizeLineHeight,
|
||||
height,
|
||||
opacity,
|
||||
spacing,
|
||||
weights,
|
||||
} from "./theme";
|
||||
|
||||
// ghost icon button
|
||||
// 'inline-flex items-center justify-center rounded-md text-sm font-medium
|
||||
// ring-offset-background transition-colors
|
||||
// focus-visible:outline-none focus-visible:ring-2
|
||||
// focus-visible:ring-ring focus-visible:ring-offset-2
|
||||
|
||||
// disabled:pointer-events-none disabled:opacity-50'
|
||||
const buttonStyle = css`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: transparent;
|
||||
border: 0 solid ${colors.border};
|
||||
border-radius: ${borderRadius.md};
|
||||
font-size: ${fontSize.sm};
|
||||
line-height: ${fontSizeLineHeight.sm};
|
||||
font-weight: ${weights.medium};
|
||||
&:focus-visible {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: ${boxShadow.ring};
|
||||
}
|
||||
&:disabled {
|
||||
pointer-events: none;
|
||||
opacity: ${opacity[50]};
|
||||
}
|
||||
`;
|
||||
|
||||
// hover:bg-accent hover:text-accent-foreground
|
||||
const ghostButtonStyle = css`
|
||||
&:hover {
|
||||
background-color: ${colors.accent};
|
||||
color: ${colors.accentForeground};
|
||||
}
|
||||
`;
|
||||
|
||||
// border border-input bg-background hover:bg-accent hover:text-accent-foreground
|
||||
const outlineButtonStyle = css`
|
||||
border: ${borderWidth.DEFAULT} solid ${colors.input};
|
||||
background-color: ${colors.background};
|
||||
&:hover {
|
||||
background-color: ${colors.accent};
|
||||
color: ${colors.accentForeground};
|
||||
}
|
||||
`;
|
||||
|
||||
// h-10 px-4 py-2
|
||||
const defaultButtonStyle = css`
|
||||
height: ${height[10]};
|
||||
padding: ${spacing[2]} ${spacing[4]};
|
||||
`;
|
||||
|
||||
// Set explicit paddings for IOS Safari to prevent the icon from collapsing
|
||||
// h-10 w-10
|
||||
const iconButtonStyle = css`
|
||||
height: ${spacing[10]};
|
||||
width: ${spacing[10]};
|
||||
padding: ${spacing[0]} ${spacing[1.5]};
|
||||
`;
|
||||
|
||||
export const getButtonStyle = (
|
||||
variant: "outline" | "ghost",
|
||||
size: "default" | /*"sm" |*/ "icon" = "default"
|
||||
) => {
|
||||
const style: TemplateStyleDecl[] = [...buttonStyle];
|
||||
if (variant === "ghost") {
|
||||
style.push(...ghostButtonStyle);
|
||||
}
|
||||
if (variant === "outline") {
|
||||
style.push(...outlineButtonStyle);
|
||||
}
|
||||
if (size === "default") {
|
||||
style.push(...defaultButtonStyle);
|
||||
}
|
||||
if (size === "icon") {
|
||||
style.push(...iconButtonStyle);
|
||||
}
|
||||
return style;
|
||||
};
|
||||
@@ -59,6 +59,15 @@ export const weights = {
|
||||
black: "900",
|
||||
} as const;
|
||||
|
||||
export const letterSpacing = {
|
||||
tighter: "-0.05em",
|
||||
tight: "-0.025em",
|
||||
normal: "0em",
|
||||
wide: "0.025em",
|
||||
wider: "0.05em",
|
||||
widest: "0.1em",
|
||||
} as const;
|
||||
|
||||
export const spacing = {
|
||||
"0": "0px",
|
||||
"1": "0.25rem",
|
||||
@@ -97,6 +106,11 @@ export const spacing = {
|
||||
"3.5": "0.875rem",
|
||||
} as const;
|
||||
|
||||
export const width = {
|
||||
...spacing,
|
||||
full: "100%",
|
||||
} as const;
|
||||
|
||||
export const height = {
|
||||
...spacing,
|
||||
auto: "auto",
|
||||
@@ -122,6 +136,34 @@ export const height = {
|
||||
fit: "fit-content",
|
||||
} as const;
|
||||
|
||||
export const maxWidth = {
|
||||
"0": "0rem",
|
||||
xs: "20rem",
|
||||
sm: "24rem",
|
||||
md: "28rem",
|
||||
lg: "32rem",
|
||||
xl: "36rem",
|
||||
"2xl": "42rem",
|
||||
"3xl": "48rem",
|
||||
"4xl": "56rem",
|
||||
"5xl": "64rem",
|
||||
"6xl": "72rem",
|
||||
"7xl": "80rem",
|
||||
full: "100%",
|
||||
min: "min-content",
|
||||
max: "max-content",
|
||||
fit: "fit-content",
|
||||
prose: "65ch",
|
||||
} as const;
|
||||
|
||||
export const borderWidth = {
|
||||
"0": "0px",
|
||||
"2": "2px",
|
||||
"4": "4px",
|
||||
"8": "8px",
|
||||
DEFAULT: "1px",
|
||||
};
|
||||
|
||||
export const borderRadius = {
|
||||
none: "0px",
|
||||
sm: "0.125rem",
|
||||
@@ -212,3 +254,24 @@ export const boxShadow = {
|
||||
`0 0 0 ${ringOffsetWidth[2]} ${colors.background}, ` +
|
||||
`0 0 0 calc(${ringWidth[2]} + ${ringOffsetWidth[2]}) ${colors.ring}`,
|
||||
} as const;
|
||||
|
||||
export const zIndex = {
|
||||
"0": "0",
|
||||
"10": "10",
|
||||
"20": "20",
|
||||
"30": "30",
|
||||
"40": "40",
|
||||
"50": "50",
|
||||
} as const;
|
||||
|
||||
export const blur = {
|
||||
sm: "blur(0 1px 2px 0 rgb(0 0 0 / 0.05))",
|
||||
DEFAULT:
|
||||
"blur(0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1))",
|
||||
md: "blur(0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))",
|
||||
lg: "blur(0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1))",
|
||||
xl: "blur(0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1))",
|
||||
"2xl": "blur(0 25px 50px -12px rgb(0 0 0 / 0.25))",
|
||||
inner: "blur(inset 0 2px 4px 0 rgb(0 0 0 / 0.05))",
|
||||
none: "blur(none)",
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
import { LargeXIcon, MenuIcon } from "@webstudio-is/icons/svg";
|
||||
import {
|
||||
type TemplateMeta,
|
||||
$,
|
||||
css,
|
||||
PlaceholderValue,
|
||||
} from "@webstudio-is/template";
|
||||
import { radix } from "./shared/proxy";
|
||||
import {
|
||||
blur,
|
||||
borderRadius,
|
||||
borderWidth,
|
||||
boxShadow,
|
||||
colors,
|
||||
fontSize,
|
||||
fontSizeLineHeight,
|
||||
height,
|
||||
letterSpacing,
|
||||
lineHeight,
|
||||
maxWidth,
|
||||
opacity,
|
||||
spacing,
|
||||
width,
|
||||
zIndex,
|
||||
} from "./shared/theme";
|
||||
import { getButtonStyle } from "./shared/styles";
|
||||
|
||||
/**
|
||||
* Styles source without animations:
|
||||
* https://github.com/shadcn-ui/ui/blob/main/apps/www/registry/default/ui/sheet.tsx
|
||||
*
|
||||
* Attributions
|
||||
* MIT License
|
||||
* Copyright (c) 2023 shadcn
|
||||
**/
|
||||
export const meta: TemplateMeta = {
|
||||
category: "radix",
|
||||
icon: MenuIcon,
|
||||
description:
|
||||
"Displays content in a menu that slides out from the side of the screen, triggered by a button. Use this component for a typical mobile hamburger menu.",
|
||||
order: 1,
|
||||
template: (
|
||||
<radix.Dialog ws:label="Sheet">
|
||||
<radix.DialogTrigger ws:label="Sheet Trigger">
|
||||
<$.Button ws:style={getButtonStyle("ghost", "icon")}>
|
||||
<$.HtmlEmbed ws:label="Hamburger Menu Svg" code={MenuIcon} />
|
||||
</$.Button>
|
||||
</radix.DialogTrigger>
|
||||
<radix.DialogOverlay
|
||||
ws:label="Sheet Overlay"
|
||||
/**
|
||||
* fixed inset-0 z-50 bg-background/80 backdrop-blur-sm
|
||||
* flex
|
||||
**/
|
||||
ws:style={css`
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: ${zIndex[50]};
|
||||
background-color: rgb(255 255 255 / 0.8);
|
||||
backdrop-filter: ${blur.sm};
|
||||
/* To allow positioning Content */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
`}
|
||||
>
|
||||
<radix.DialogContent
|
||||
ws:label="Sheet Content"
|
||||
/**
|
||||
* fixed w-full z-50
|
||||
* grid gap-4 max-w-lg
|
||||
* m-auto
|
||||
* border bg-background p-6 shadow-lg
|
||||
**/
|
||||
ws:style={css`
|
||||
width: ${width.full};
|
||||
z-index: ${zIndex[50]};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${spacing[4]};
|
||||
border: ${borderWidth.DEFAULT} solid ${colors.border};
|
||||
background-color: ${colors.background};
|
||||
padding: ${spacing[6]};
|
||||
box-shadow: ${boxShadow.lg};
|
||||
position: relative;
|
||||
/* side=left */
|
||||
margin-right: auto;
|
||||
max-width: ${maxWidth.sm};
|
||||
flex-grow: 1;
|
||||
`}
|
||||
>
|
||||
<$.Box ws:label="Navigation" tag="nav" role="navigation">
|
||||
<$.Box
|
||||
ws:label="Sheet Header"
|
||||
ws:style={css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${spacing[2]};
|
||||
`}
|
||||
>
|
||||
<radix.DialogTitle
|
||||
ws:label="Sheet Title"
|
||||
/**
|
||||
* text-lg leading-none tracking-tight
|
||||
**/
|
||||
ws:style={css`
|
||||
font-size: ${fontSize.lg};
|
||||
line-height: ${lineHeight.none};
|
||||
letter-spacing: ${letterSpacing.tight};
|
||||
margin: 0;
|
||||
`}
|
||||
>
|
||||
{new PlaceholderValue("Sheet Title")}
|
||||
</radix.DialogTitle>
|
||||
<radix.DialogDescription
|
||||
ws:label="Sheet Description"
|
||||
/**
|
||||
* text-sm text-muted-foreground
|
||||
**/
|
||||
ws:style={css`
|
||||
font-size: ${fontSize.sm};
|
||||
line-height: ${fontSizeLineHeight.sm};
|
||||
color: ${colors.mutedForeground};
|
||||
margin: 0;
|
||||
`}
|
||||
>
|
||||
{new PlaceholderValue("Sheet description text you can edit")}
|
||||
</radix.DialogDescription>
|
||||
</$.Box>
|
||||
<$.Text>{new PlaceholderValue("The text you can edit")}</$.Text>
|
||||
</$.Box>
|
||||
<radix.DialogClose
|
||||
ws:label="Close Button"
|
||||
/**
|
||||
* absolute right-4 top-4
|
||||
* rounded-sm opacity-70
|
||||
* ring-offset-background
|
||||
* hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
|
||||
* flex items-center justify-center h-4 w-4
|
||||
**/
|
||||
ws:style={css`
|
||||
position: absolute;
|
||||
right: ${spacing[4]};
|
||||
top: ${spacing[4]};
|
||||
border-radius: ${borderRadius.sm};
|
||||
opacity: ${opacity[70]};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: ${height[4]};
|
||||
width: ${height[4]};
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
&:hover {
|
||||
opacity: ${opacity[100]};
|
||||
}
|
||||
&:focus-visible {
|
||||
box-shadow: ${boxShadow.ring};
|
||||
}
|
||||
`}
|
||||
>
|
||||
<$.HtmlEmbed ws:label="Close Icon" code={LargeXIcon} />
|
||||
</radix.DialogClose>
|
||||
</radix.DialogContent>
|
||||
</radix.DialogOverlay>
|
||||
</radix.Dialog>
|
||||
),
|
||||
};
|
||||
@@ -1,226 +0,0 @@
|
||||
import { MenuIcon, LargeXIcon } from "@webstudio-is/icons/svg";
|
||||
import type { WsComponentMeta } from "@webstudio-is/react-sdk";
|
||||
import * as tc from "./theme/tailwind-classes";
|
||||
import { getButtonStyles } from "./theme/styles";
|
||||
|
||||
/**
|
||||
* Styles source without animations:
|
||||
* https://github.com/shadcn-ui/ui/blob/main/apps/www/registry/default/ui/sheet.tsx
|
||||
*
|
||||
* Attributions
|
||||
* MIT License
|
||||
* Copyright (c) 2023 shadcn
|
||||
**/
|
||||
export const meta: WsComponentMeta = {
|
||||
category: "radix",
|
||||
order: 1,
|
||||
type: "container",
|
||||
icon: MenuIcon,
|
||||
stylable: false,
|
||||
description:
|
||||
"Displays content in a menu that slides out from the side of the screen, triggered by a button. Use this component for a typical mobile hamburger menu.",
|
||||
template: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "Dialog",
|
||||
label: "Sheet",
|
||||
props: [],
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogTrigger",
|
||||
label: "Sheet Trigger",
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "Button",
|
||||
styles: getButtonStyles("ghost", "icon"),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "HtmlEmbed",
|
||||
label: "Hamburger Menu Svg",
|
||||
props: [
|
||||
{
|
||||
type: "string",
|
||||
name: "code",
|
||||
value: MenuIcon,
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogOverlay",
|
||||
label: "Sheet Overlay",
|
||||
/**
|
||||
* fixed inset-0 z-50 bg-background/80 backdrop-blur-sm
|
||||
* flex
|
||||
**/
|
||||
styles: [
|
||||
tc.fixed(),
|
||||
tc.inset(0),
|
||||
tc.z(50),
|
||||
tc.bg("background", 80),
|
||||
tc.backdropBlur("sm"),
|
||||
// To allow positioning Content
|
||||
tc.flex(),
|
||||
tc.flex("col"),
|
||||
tc.overflow("auto"),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogContent",
|
||||
label: "Sheet Content",
|
||||
/**
|
||||
* fixed w-full z-50
|
||||
* grid gap-4 max-w-lg
|
||||
* m-auto
|
||||
* border bg-background p-6 shadow-lg
|
||||
**/
|
||||
styles: [
|
||||
tc.w("full"),
|
||||
tc.z(50),
|
||||
tc.flex(),
|
||||
tc.flex("col"),
|
||||
tc.gap(4),
|
||||
tc.border(),
|
||||
tc.bg("background"),
|
||||
tc.p(6),
|
||||
tc.shadow("lg"),
|
||||
tc.relative(),
|
||||
// side=left
|
||||
tc.mr("auto"),
|
||||
tc.maxW("sm"),
|
||||
tc.grow(),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "Box",
|
||||
label: "Navigation",
|
||||
props: [
|
||||
{ name: "tag", type: "string", value: "nav" },
|
||||
{ name: "role", type: "string", value: "navigation" },
|
||||
],
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "Box",
|
||||
label: "Sheet Header",
|
||||
styles: [tc.flex(), tc.flex("col"), tc.gap(1)].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogTitle",
|
||||
label: "Sheet Title",
|
||||
/**
|
||||
* text-lg leading-none tracking-tight
|
||||
**/
|
||||
styles: [
|
||||
tc.my(0),
|
||||
tc.leading("none"),
|
||||
tc.text("lg"),
|
||||
tc.tracking("tight"),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "text",
|
||||
value: "Sheet Title",
|
||||
placeholder: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogDescription",
|
||||
label: "Sheet Description",
|
||||
/**
|
||||
* text-sm text-muted-foreground
|
||||
**/
|
||||
styles: [
|
||||
tc.my(0),
|
||||
tc.text("sm"),
|
||||
tc.text("mutedForeground"),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "text",
|
||||
value: "Sheet description text you can edit",
|
||||
placeholder: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
type: "instance",
|
||||
component: "Text",
|
||||
children: [
|
||||
{
|
||||
type: "text",
|
||||
value: "The text you can edit",
|
||||
placeholder: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "instance",
|
||||
component: "DialogClose",
|
||||
label: "Close Button",
|
||||
/**
|
||||
* absolute right-4 top-4
|
||||
* rounded-sm opacity-70
|
||||
* ring-offset-background
|
||||
* hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
|
||||
* flex items-center justify-center h-4 w-4
|
||||
**/
|
||||
styles: [
|
||||
tc.absolute(),
|
||||
tc.right(4),
|
||||
tc.top(4),
|
||||
tc.rounded("sm"),
|
||||
tc.opacity(70),
|
||||
tc.flex(),
|
||||
tc.items("center"),
|
||||
tc.justify("center"),
|
||||
tc.h(4),
|
||||
tc.w(4),
|
||||
tc.border(0),
|
||||
tc.bg("transparent"),
|
||||
tc.outline("none"),
|
||||
tc.hover(tc.opacity(100)),
|
||||
tc.focus(tc.ring("ring", 2, "background", 2)),
|
||||
].flat(),
|
||||
children: [
|
||||
{
|
||||
type: "instance",
|
||||
component: "HtmlEmbed",
|
||||
label: "Close Icon",
|
||||
props: [
|
||||
{
|
||||
type: "string",
|
||||
name: "code",
|
||||
value: LargeXIcon,
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -43,7 +43,8 @@ const tabsTriggerStyle = css`
|
||||
font-weight: ${weights.medium};
|
||||
transition: ${transition.all};
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: ${boxShadow.ring};
|
||||
}
|
||||
&:disabled {
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
export { meta as Label } from "./label.template";
|
||||
export { meta as Tabs } from "./tabs.template";
|
||||
export { meta as Sheet } from "./sheet.template";
|
||||
export { meta as Dialog } from "./dialog.template";
|
||||
Reference in new issue
Block a user