hook into application state, add icons from figma

This commit is contained in:
Sultan committed 2022-10-07 19:27:31 +03:00
1 parent f94432465a
commit 015fa13f21
21 files changed
+667 -74

No files matched your search

@@ -1,24 +1,30 @@
import { ToggleGroup } from "@webstudio-is/design-system";
import {
TextAlignLeftIcon,
TextAlignCenterIcon,
TextAlignRightIcon,
} from "@webstudio-is/icons";
import { ToggleGroup, Tooltip } from "@webstudio-is/design-system";
export const ToggleGroupControl = () => (
export type ToggleGroupControlProps = {
value: string;
items: { child: JSX.Element; label: string; value: string }[];
onValueChange?: (value: string) => void;
};
export const ToggleGroupControl = ({
value = "",
items = [],
onValueChange,
}: ToggleGroupControlProps) => (
<ToggleGroup.Root
type="single"
defaultValue="center"
aria-label="Text alignment"
value={value}
onValueChange={onValueChange}
css={{ width: "fit-content" }}
>
<ToggleGroup.Item value="left" aria-label="Left aligned">
<TextAlignLeftIcon />
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned">
<TextAlignCenterIcon />
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned">
<TextAlignRightIcon />
</ToggleGroup.Item>
{items.map(({ child, label, value }, index) => {
return (
<ToggleGroup.Item key={index} value={value}>
<Tooltip content={label} delayDuration={0}>
{child}
</Tooltip>
</ToggleGroup.Item>
);
})}
</ToggleGroup.Root>
);
@@ -0,0 +1,193 @@
import { Flex, Grid } from "@webstudio-is/design-system";
import type { RenderCategoryProps } from "../../style-sections";
import { ToggleGroupControl } from "../../controls";
import { PropertyName } from "../../shared/property-name";
import {
CrossSmallIcon,
AlignSelfStartIcon,
AlignSelfEndIcon,
AlignSelfCenterIcon,
AlignSelfBaselineIcon,
AlignSelfStretchIcon,
FlexSizingShrinkIcon,
FlexSizingGrowIcon,
OrderFirstIcon,
OrderLastIcon,
EllipsesIcon,
} from "@webstudio-is/icons";
export const FlexChildSection = ({
setProperty,
createBatchUpdate,
currentStyle,
sectionStyle,
}: RenderCategoryProps) => {
const setAlignSelf = setProperty("alignSelf");
const setOrder = setProperty("order");
const setSizing = createBatchUpdate();
return (
<Flex css={{ flexDirection: "column", gap: "$2" }}>
<Grid css={{ gridTemplateColumns: "4fr auto" }}>
<PropertyName
property={sectionStyle.alignSelf?.styleConfig.property}
label="Align"
/>
<ToggleGroupControl
onValueChange={(value) => setAlignSelf(value)}
value={String(currentStyle.alignSelf?.value)}
items={[
{
child: <CrossSmallIcon />,
label: "Do not align items",
value: "auto",
},
{
child: <AlignSelfStartIcon />,
label: "align-items: flex-start",
value: "start",
},
{
child: <AlignSelfEndIcon />,
label: "align-items: flex-end",
value: "end",
},
{
child: <AlignSelfCenterIcon />,
label: "align-items: center",
value: "center",
},
{
child: <AlignSelfStretchIcon />,
label: "align-items: stretch",
value: "stretch",
},
{
child: <AlignSelfBaselineIcon />,
label: "align-items: baseline",
value: "baseline",
},
]}
/>
</Grid>
<Grid css={{ gridTemplateColumns: "4fr auto" }}>
<PropertyName
property={sectionStyle.flexGrow?.styleConfig.property}
label="Sizing"
/>
<ToggleGroupControl
onValueChange={(value) => {
switch (value) {
case "none": {
setSizing.setProperty("flexGrow")("0");
setSizing.setProperty("flexShrink")("0");
setSizing.publish();
break;
}
case "grow": {
setSizing.setProperty("flexGrow")("1");
setSizing.setProperty("flexShrink")("0");
setSizing.publish();
break;
}
case "shrink": {
setSizing.setProperty("flexGrow")("0");
setSizing.setProperty("flexShrink")("1");
setSizing.publish();
break;
}
default: {
alert("@todo render sizing popup");
}
}
}}
value={(() => {
switch (
String(currentStyle.flexGrow?.value) +
String(currentStyle.flexShrink?.value)
) {
case "00": {
return "none";
}
case "10": {
return "grow";
}
case "01": {
return "shrink";
}
default: {
return "";
}
}
})()}
items={[
{
child: <CrossSmallIcon />,
label: "Don't grow or shrink",
value: "none",
},
{
child: <FlexSizingGrowIcon />,
label: "Grow if possible",
value: "grow",
},
{
child: <FlexSizingShrinkIcon />,
label: "Shrink if needed",
value: "shrink",
},
{
child: <EllipsesIcon />,
label: "More sizing options",
value: "",
},
]}
/>
</Grid>
<Grid css={{ gridTemplateColumns: "4fr auto" }}>
<PropertyName
property={sectionStyle.order?.styleConfig.property}
label="Order"
/>
<ToggleGroupControl
onValueChange={(value) => {
switch (value) {
case "0":
case "1":
case "-1": {
setOrder(value);
break;
}
default: {
alert("@todo render order popup");
}
}
}}
value={String(currentStyle.order?.value)}
items={[
{
child: <CrossSmallIcon />,
label: "Dont't change",
value: "0",
},
{
child: <OrderFirstIcon />,
label: "Make first",
value: "1",
},
{
child: <OrderLastIcon />,
label: "Make last",
value: "-1",
},
{
child: <EllipsesIcon />,
label: "Customize order",
value: "",
},
]}
/>
</Grid>
</Flex>
);
};
@@ -1,21 +0,0 @@
import type { RenderCategoryProps } from "../../style-sections";
import { ShowMore } from "../../shared/show-more";
import { renderProperty } from "../../style-sections";
import { ToggleGroupControl } from "../../controls";
export const FlexChildSection = ({
styleConfigsByCategory,
moreStyleConfigsByCategory,
}: RenderCategoryProps) => {
return (
<>
<ToggleGroupControl />
{styleConfigsByCategory.map((entry) => renderProperty(entry))}
<ShowMore
styleConfigs={moreStyleConfigsByCategory.map((entry) =>
renderProperty(entry)
)}
/>
</>
);
};
@@ -1,6 +1,6 @@
export * from "./layout/layout";
export * from "./flexChild/flexChild";
export * from "./gridChild/gridChild";
export * from "./flex-child/flex-child";
export * from "./grid-child/grid-child";
export * from "./spacing/spacing";
export * from "./size/size";
export * from "./position/position";
@@ -2,12 +2,7 @@ import { Box, Flex, Grid } from "@webstudio-is/design-system";
import type { RenderCategoryProps } from "../../style-sections";
import { FlexGrid } from "./shared/flex-grid";
import { Lock } from "./shared/lock";
import {
MenuControl,
SelectControl,
TextControl,
ToggleGroupControl,
} from "../../controls";
import { MenuControl, SelectControl, TextControl } from "../../controls";
import { PropertyName } from "../../shared/property-name";
const LayoutSectionFlex = ({
@@ -15,7 +15,6 @@ import {
MenuControl,
FontFamilyControl,
} from "./controls";
import { ShowMore } from "./shared/show-more";
import {
LayoutSection,
FlexChildSection,
@@ -3,38 +3,36 @@ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
export const Root = styled(ToggleGroupPrimitive.Root, {
display: "inline-flex",
backgroundColor: "$slate5",
borderRadius: 4,
boxShadow: `0 2px 10px $blackA7`,
borderRadius: "$1",
boxShadow: `0 0 0 1px $colors$slate7`,
padding: 2,
});
export const Item = styled(ToggleGroupPrimitive.Item, {
all: "unset",
backgroundColor: "$panel",
backgroundColor: "$loContrast",
color: "$hiContrast",
display: "flex",
whiteSpace: "nowrap",
fontSize: 15,
lineHeight: 1,
width: "$5",
height: "$5",
borderRadius: 2,
alignItems: "center",
justifyContent: "center",
marginLeft: 1,
"&": {
px: "$2",
py: "$1",
},
"&:first-child": {
marginLeft: 0,
borderTopLeftRadius: 4,
borderBottomLeftRadius: 4,
},
"&:last-child": { borderTopRightRadius: 4, borderBottomRightRadius: 4 },
"&:hover": { backgroundColor: "$slateA3" },
"&[data-state=on]": {
backgroundColor: "$slateA5",
},
"&:focus": {
position: "relative",
boxShadow: `0 0 0 2px black`,
},
"&:hover": { backgroundColor: "$slate5" },
"&:focus": { boxShadow: "0 0 0 2px $colors$blue10", zIndex: 1 },
"&[data-state=on]": { backgroundColor: "$slate5" },
// whiteSpace: "nowrap",
// fontSize: 15,
// lineHeight: 1,
// marginLeft: 1,
// "&": {
// px: "$2",
// py: "$1",
// },
// "&:first-child": {
// marginLeft: 0,
// borderTopLeftRadius: 4,
// borderBottomLeftRadius: 4,
// },
// "&:last-child": { borderTopRightRadius: 4, borderBottomRightRadius: 4 },
});
@@ -0,0 +1,47 @@
import * as React from "react";
import { IconProps } from "./types";
export const AlignSelfBaselineIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<mask id="a" fill="#fff">
<rect width="3" height="10" x="6.5" y="3" rx=".8" />
</mask>
<rect
width="3"
height="10"
x="6.5"
y="3"
stroke={color}
strokeWidth="2"
mask="url(#a)"
rx=".8"
/>
<rect
width="3"
height="5.73926"
x="6.5"
y="7.25977"
fill={color}
rx=".8"
/>
<path
fill={color}
fillRule="evenodd"
d="M1.5 7.95c0-.3866.34393-.7.76818-.7H13.7318c.4243 0 .7682.3134.7682.7 0 .3866-.3439.7-.7682.7H2.26818c-.42425 0-.76818-.3134-.76818-.7Z"
clipRule="evenodd"
/>
</svg>
);
}
);
AlignSelfBaselineIcon.displayName = "AlignSelfBaselineIcon";
+27
View File
@@ -0,0 +1,27 @@
import * as React from "react";
import { IconProps } from "./types";
export const AlignSelfCenterIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<rect width="3" height="10" x="6.5" y="3" fill={color} rx=".8" />
<path
fill={color}
fillRule="evenodd"
d="M1.5 7.95c0-.3866.34393-.7.76818-.7H13.7318c.4243 0 .7682.3134.7682.7 0 .3866-.3439.7-.7682.7H2.26818c-.42425 0-.76818-.3134-.76818-.7Z"
clipRule="evenodd"
/>
</svg>
);
}
);
AlignSelfCenterIcon.displayName = "AlignSelfCenterIcon";
+35
View File
@@ -0,0 +1,35 @@
import * as React from "react";
import { IconProps } from "./types";
export const AlignSelfEndIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<path
fill={color}
fillRule="evenodd"
d="M14.5 14.2004c0 .3866-.3439.7-.7682.7H2.26818c-.42425 0-.76818-.3134-.76818-.7 0-.3866.34393-.7.76818-.7H13.7318c.4243 0 .7682.3134.7682.7Z"
clipRule="evenodd"
/>
<rect
width="3"
height="9"
x="9.5"
y="12.4004"
fill={color}
rx=".8"
transform="rotate(-180 9.5 12.4004)"
/>
</svg>
);
}
);
AlignSelfEndIcon.displayName = "AlignSelfEndIcon";
+27
View File
@@ -0,0 +1,27 @@
import * as React from "react";
import { IconProps } from "./types";
export const AlignSelfStartIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<path
fill={color}
fillRule="evenodd"
d="M1.5 1.79961c0-.3866.34393-.7.76818-.7H13.7318c.4243 0 .7682.3134.7682.7 0 .3866-.3439.7-.7682.7H2.26818c-.42425 0-.76818-.3134-.76818-.7Z"
clipRule="evenodd"
/>
<rect width="3" height="9" x="6.5" y="3.59961" fill={color} rx=".8" />
</svg>
);
}
);
AlignSelfStartIcon.displayName = "AlignSelfStartIcon";
+41
View File
@@ -0,0 +1,41 @@
import * as React from "react";
import { IconProps } from "./types";
export const AlignSelfStretchIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<path
fill={color}
fillRule="evenodd"
d="M14.5 14.2004c0 .3866-.3439.7-.7682.7H2.26818c-.42425 0-.76818-.3134-.76818-.7 0-.3866.34393-.7.76818-.7H13.7318c.4243 0 .7682.3134.7682.7Z"
clipRule="evenodd"
/>
<rect
width="3"
height="9"
x="9.5"
y="12.5"
fill={color}
rx=".8"
transform="rotate(-180 9.5 12.5)"
/>
<path
fill={color}
fillRule="evenodd"
d="M14.5 1.8c0 .3866-.3439.7-.7682.7H2.26818C1.84393 2.5 1.5 2.1866 1.5 1.8c0-.3866.34393-.7.76818-.7H13.7318c.4243 0 .7682.3134.7682.7Z"
clipRule="evenodd"
/>
</svg>
);
}
);
AlignSelfStretchIcon.displayName = "AlignSelfStretchIcon";
+26
View File
@@ -0,0 +1,26 @@
import * as React from "react";
import { IconProps } from "./types";
export const CrossLargeIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<path
stroke={color}
strokeLinecap="round"
strokeWidth="1.6"
d="M13 3 7.99998 8.00002m0 0L3 13m4.99998-4.99998L3 3.00008m4.99998 4.99994L13 13"
/>
</svg>
);
}
);
CrossLargeIcon.displayName = "CrossLargeIcon";
+26
View File
@@ -0,0 +1,26 @@
import * as React from "react";
import { IconProps } from "./types";
export const CrossSmallIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<path
stroke={color}
strokeLinecap="round"
strokeWidth="1.4"
d="M11 5 7.99999 8.00001m0 0L5 11m2.99999-2.99999L5 5.00005m2.99999 2.99996L11 11"
/>
</svg>
);
}
);
CrossSmallIcon.displayName = "CrossSmallIcon";
+23
View File
@@ -0,0 +1,23 @@
import * as React from "react";
import { IconProps } from "./types";
export const EllipsesIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<circle cx="2.5" cy="8" r="1.5" fill={color} />
<circle cx="8" cy="8" r="1.5" fill={color} />
<circle cx="13.5" cy="8" r="1.5" fill={color} />
</svg>
);
}
);
EllipsesIcon.displayName = "EllipsesIcon";
+34
View File
@@ -0,0 +1,34 @@
import * as React from "react";
import { IconProps } from "./types";
export const FlexSizingGrowIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<path
fill={color}
d="M10.7641 5.54038c-.2539-.25384-.6654-.25384-.91928 0-.25384.25384-.25384.6654 0 .91924l.91928-.91924ZM12.3044 8l.4597.45962c.2538-.25384.2538-.6654 0-.91924L12.3044 8ZM9.84482 9.54038c-.25384.25384-.25384.66542 0 .91922.25388.2539.66538.2539.91928 0l-.91928-.91922ZM7.80469 7.35c-.35899 0-.65.29101-.65.65 0 .35899.29101.65.65.65v-1.3Zm2.04013-.89038 1.99998 2 .9193-.91924-2-2-.91928.91924Zm1.99998 1.08076-1.99998 2 .91928.91922 2-1.99998-.9193-.91924ZM7.80469 8.65h4.49971v-1.3H7.80469v1.3Z"
/>
<path
fill={color}
d="m3.69531 8-.45962-.45962c-.25384.25384-.25384.6654 0 .91924L3.69531 8Zm2.45962-1.54038c.25384-.25384.25384-.6654 0-.91924-.25384-.25384-.6654-.25384-.91924 0l.91924.91924Zm-.91924 3.99998c.25384.2539.6654.2539.91924 0 .25384-.2538.25384-.66538 0-.91922l-.91924.91922ZM8.19556 8.65c.35898 0 .65-.29101.65-.65 0-.35899-.29102-.65-.65-.65v1.3Zm-4.04063-.19038 2-2-.91924-.91924-2 2 .91924.91924Zm-.91924 0 2 1.99998.91924-.91922-2-2-.91924.91924Zm.45962.19038h4.50025v-1.3H3.69531v1.3Z"
/>
<path
stroke={color}
strokeLinecap="round"
strokeWidth="1.4"
d="M1.5 2.5v11m13-11v11"
/>
</svg>
);
}
);
FlexSizingGrowIcon.displayName = "FlexSizingGrowIcon";
+30
View File
@@ -0,0 +1,30 @@
import * as React from "react";
import { IconProps } from "./types";
export const FlexSizingShrinkIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<path
stroke={color}
strokeLinecap="round"
strokeWidth="1.4"
d="M7.95312 2.5v11"
/>
<path
fill={color}
d="m5.42188 8 .51745.47143c.2434-.26716.2434-.6757 0-.94286L5.42188 8ZM3.0823 9.52857c-.26036.28578-.23976.72853.04602.98883.28578.2604.72852.2398.98888-.046l-1.0349-.94283Zm1.0349-4c-.26036-.28578-.7031-.30638-.98888-.04602-.28578.26036-.30638.7031-.04602.98888l1.0349-.94286ZM1.32188 7.3c-.386604 0-.700005.3134-.700005.7 0 .3866.313401.7.700005.7V7.3Zm3.58255.22857-1.82213 2 1.0349.94283 1.82213-1.99997-1.0349-.94286Zm1.0349 0-1.82213-2-1.0349.94286 1.82212 2 1.03491-.94286ZM5.42188 7.3h-4.1v1.4h4.1V7.3Zm6.41672 3.1776c.2638.2827.7068.2979.9894.0341.2826-.2638.2979-.70672.0341-.98934l-1.0235.95524ZM10.4836 8l-.51173-.47764c-.25103.26895-.25103.68633 0 .95528L10.4836 8Zm2.3785-1.52236c.2638-.28262.2485-.72557-.0341-.98937-.2826-.26379-.7256-.24853-.9894.03409l1.0235.95528ZM14.6836 8.7c.3866 0 .7-.3134.7-.7 0-.3866-.3134-.7-.7-.7v1.4Zm-1.8215.82236-1.8668-2-1.02343.95528 1.86673 1.99996 1.0235-.95524Zm-1.8668-1.04472 1.8668-2-1.0235-.95528-1.86673 2 1.02343.95528ZM14.6836 7.3h-4.2v1.4h4.2V7.3Z"
/>
</svg>
);
}
);
FlexSizingShrinkIcon.displayName = "FlexSizingGrowIcon";
+12
View File
@@ -48,3 +48,15 @@ export { TrashIcon } from "./trash";
export { SizeIcon } from "./size";
export { UploadIcon } from "./upload";
export { GearIcon, gearIconCssVars } from "./gear";
export * from "./align-self-start";
export * from "./align-self-end";
export * from "./align-self-center";
export * from "./align-self-stretch";
export * from "./align-self-baseline";
export * from "./flex-sizing-grow";
export * from "./flex-sizing-shrink";
export * from "./order-first";
export * from "./order-last";
export * from "./cross-small";
export * from "./cross-large";
export * from "./ellipses";
+47
View File
@@ -0,0 +1,47 @@
import * as React from "react";
import { IconProps } from "./types";
export const OrderFirstIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
>
<mask id="a" fill="#fff">
<rect width="4" height="8" x="10.9" y="4" rx="1" />
</mask>
<rect
width="4"
height="8"
x="10.9"
y="4"
stroke={color}
strokeWidth="2.2"
mask="url(#a)"
rx="1"
/>
<mask id="b" fill="#fff">
<rect width="4" height="8" x="6.10022" y="4" rx="1" />
</mask>
<rect
width="4"
height="8"
x="6.10022"
y="4"
stroke={color}
strokeWidth="2.2"
mask="url(#b)"
rx="1"
/>
<rect width="3.8" height="11" x="1.10022" y="2.5" fill={color} rx="1" />
</svg>
);
}
);
OrderFirstIcon.displayName = "OrderFirstIcon";
+48
View File
@@ -0,0 +1,48 @@
import * as React from "react";
import { IconProps } from "./types";
export const OrderLastIcon = React.forwardRef<SVGSVGElement, IconProps>(
({ color = "currentColor", ...props }, forwardedRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 16 16"
width="16"
height="16"
{...props}
ref={forwardedRef}
style={{ transform: "scale(-1)" }}
>
<mask id="a" fill="#fff">
<rect width="4" height="8" x="10.9" y="4" rx="1" />
</mask>
<rect
width="4"
height="8"
x="10.9"
y="4"
stroke={color}
strokeWidth="2.2"
mask="url(#a)"
rx="1"
/>
<mask id="b" fill="#fff">
<rect width="4" height="8" x="6.10022" y="4" rx="1" />
</mask>
<rect
width="4"
height="8"
x="6.10022"
y="4"
stroke={color}
strokeWidth="2.2"
mask="url(#b)"
rx="1"
/>
<rect width="3.8" height="11" x="1.10022" y="2.5" fill={color} rx="1" />
</svg>
);
}
);
OrderLastIcon.displayName = "OrderFirstIcon";