diff --git a/apps/builder/app/builder/features/props-panel/controls/url.tsx b/apps/builder/app/builder/features/props-panel/controls/url.tsx
index ecf9625ab6..f2cf538137 100644
--- a/apps/builder/app/builder/features/props-panel/controls/url.tsx
+++ b/apps/builder/app/builder/features/props-panel/controls/url.tsx
@@ -7,7 +7,7 @@ import {
InputField,
Flex,
ToggleGroup,
- ToggleGroupItem,
+ ToggleGroupButton,
Select,
Tooltip,
Label,
@@ -385,9 +385,9 @@ export const UrlControl = ({
}}
>
{Object.entries(modes).map(([key, { icon, label }]) => (
-
- {icon}
-
+
+ {icon}
+
))}
diff --git a/apps/builder/app/builder/features/style-panel/controls/toggle/toggle-control.tsx b/apps/builder/app/builder/features/style-panel/controls/toggle/toggle-control.tsx
index 01e8577514..487854454a 100644
--- a/apps/builder/app/builder/features/style-panel/controls/toggle/toggle-control.tsx
+++ b/apps/builder/app/builder/features/style-panel/controls/toggle/toggle-control.tsx
@@ -1,15 +1,13 @@
import {
- styled,
Flex,
ToggleGroup,
- ToggleGroupItem,
+ ToggleGroupButton,
EnhancedTooltip,
} from "@webstudio-is/design-system";
import type { StyleSource } from "../../shared/style-info";
-import { theme } from "@webstudio-is/design-system";
export type ToggleGroupControlProps = {
- styleSource: StyleSource;
+ styleSource?: StyleSource;
value: string;
items: { child: JSX.Element; label: string; value: string }[];
onValueChange?: (value: string) => void;
@@ -24,6 +22,7 @@ export const ToggleGroupControl = ({
}: ToggleGroupControlProps) => {
return (
{items.map(({ child, label, value }, index) => {
return (
-
-
+
+
{child}
-
-
+
+
);
})}
);
};
-
-const ToggleGroupControlItem = styled(ToggleGroupItem, {
- variants: {
- source: {
- default: {},
- preset: {},
- local: {
- "&[data-state=on]": {
- color: theme.colors.foregroundLocalMain,
- backgroundColor: theme.colors.backgroundLocalMain,
- },
- },
- overwritten: {
- "&[data-state=on]": {
- color: theme.colors.foregroundOverwrittenMain,
- backgroundColor: theme.colors.backgroundOverwrittenMain,
- },
- },
- remote: {
- "&[data-state=on]": {
- color: theme.colors.foregroundRemoteMain,
- backgroundColor: theme.colors.backgroundRemoteMain,
- },
- },
- },
- },
-});
diff --git a/apps/builder/app/builder/features/style-panel/sections/backgrounds/background-content.tsx b/apps/builder/app/builder/features/style-panel/sections/backgrounds/background-content.tsx
index f384d6be44..c22ef8c633 100644
--- a/apps/builder/app/builder/features/style-panel/sections/backgrounds/background-content.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/backgrounds/background-content.tsx
@@ -9,7 +9,7 @@ import {
Flex,
Grid,
ToggleGroup,
- ToggleGroupItem,
+ ToggleGroupButton,
Separator,
styled,
} from "@webstudio-is/design-system";
@@ -131,12 +131,12 @@ export const BackgroundContent = (props: BackgroundContentProps) => {
}
}}
>
-
+
Image
-
-
+
+
Gradient
-
+
@@ -311,12 +311,12 @@ export const BackgroundContent = (props: BackgroundContentProps) => {
});
}}
>
-
+
Scroll
-
-
+
+
Fixed
-
+
diff --git a/apps/builder/app/builder/features/style-panel/sections/borders/border-style.tsx b/apps/builder/app/builder/features/style-panel/sections/borders/border-style.tsx
index ecf4711831..d72b89e8ee 100644
--- a/apps/builder/app/builder/features/style-panel/sections/borders/border-style.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/borders/border-style.tsx
@@ -4,7 +4,7 @@ import {
Grid,
theme,
ToggleGroup,
- ToggleGroupItem,
+ ToggleGroupButton,
Tooltip,
} from "@webstudio-is/design-system";
import {
@@ -92,11 +92,11 @@ export const BorderStyle = (
}}
>
{borderStyleValues.map(({ value, Icon }) => (
-
-
+
+
-
-
+
+
))}
diff --git a/apps/builder/app/builder/features/style-panel/sections/flex-child/flex-child.tsx b/apps/builder/app/builder/features/style-panel/sections/flex-child/flex-child.tsx
index 8f092d2f03..7137d728bd 100644
--- a/apps/builder/app/builder/features/style-panel/sections/flex-child/flex-child.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/flex-child/flex-child.tsx
@@ -19,7 +19,6 @@ import {
MenuEllipsesIcon,
} from "@webstudio-is/icons";
import { FloatingPanel } from "~/builder/shared/floating-panel";
-import { getStyleSource } from "../../shared/style-info";
import { CollapsibleSection } from "../../shared/collapsible-section";
const properties: StyleProperty[] = [
@@ -59,7 +58,6 @@ const FlexChildSectionAlign = (props: RenderCategoryProps) => {
onReset={() => deleteProperty("alignSelf")}
/>
setAlignSelf({ type: "keyword", value })}
value={toValue(currentStyle.alignSelf?.value)}
items={[
@@ -117,10 +115,6 @@ const FlexChildSectionSizing = (props: RenderCategoryProps) => {
}}
/>
{
switch (value) {
case "none": {
@@ -279,7 +273,6 @@ const FlexChildSectionOrder = (props: RenderCategoryProps) => {
onReset={() => deleteProperty("order")}
/>
{
switch (value) {
case "0":
diff --git a/apps/builder/app/builder/features/style-panel/sections/outline/outline-style.tsx b/apps/builder/app/builder/features/style-panel/sections/outline/outline-style.tsx
index 85f9992153..e2b1516cfd 100644
--- a/apps/builder/app/builder/features/style-panel/sections/outline/outline-style.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/outline/outline-style.tsx
@@ -3,7 +3,7 @@ import {
Grid,
theme,
ToggleGroup,
- ToggleGroupItem,
+ ToggleGroupButton,
Tooltip,
} from "@webstudio-is/design-system";
import {
@@ -65,11 +65,11 @@ export const OutlineStyle = (
}
>
{outlineStyleValues.map(({ value, Icon }) => (
-
-
+
+
-
-
+
+
))}
diff --git a/apps/builder/app/builder/features/style-panel/sections/size/size.tsx b/apps/builder/app/builder/features/style-panel/sections/size/size.tsx
index fcf465c66c..5b69127858 100644
--- a/apps/builder/app/builder/features/style-panel/sections/size/size.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/size/size.tsx
@@ -15,7 +15,6 @@ import {
ScrollIcon,
AutoScrollIcon,
} from "@webstudio-is/icons";
-import { getStyleSource } from "../../shared/style-info";
import { CollapsibleSection } from "../../shared/collapsible-section";
import { theme } from "@webstudio-is/design-system";
import { ToggleGroupControl } from "../../controls/toggle/toggle-control";
@@ -133,7 +132,6 @@ export const SizeSection = ({
onReset={() => deleteProperty("overflow")}
/>
,
diff --git a/apps/builder/app/builder/features/style-panel/sections/typography/typography.tsx b/apps/builder/app/builder/features/style-panel/sections/typography/typography.tsx
index cbd8f57837..27debfe137 100644
--- a/apps/builder/app/builder/features/style-panel/sections/typography/typography.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/typography/typography.tsx
@@ -347,7 +347,6 @@ export const TypographySectionAdvancedPopover = (
onReset={() => deleteProperty("direction")}
/>
setDirection({ type: "keyword", value })
}
@@ -374,7 +373,6 @@ export const TypographySectionAdvancedPopover = (
onReset={() => deleteProperty("hyphens")}
/>
setHyphens({ type: "keyword", value })}
value={toValue(currentStyle.hyphens?.value)}
items={[
@@ -399,7 +397,6 @@ export const TypographySectionAdvancedPopover = (
onReset={() => deleteProperty("textOverflow")}
/>
setTextOverflow({ type: "keyword", value })
}
diff --git a/packages/design-system/src/components/toggle-group.stories.tsx b/packages/design-system/src/components/toggle-group.stories.tsx
new file mode 100644
index 0000000000..c7710a6fc8
--- /dev/null
+++ b/packages/design-system/src/components/toggle-group.stories.tsx
@@ -0,0 +1,152 @@
+import type { ComponentProps } from "react";
+import { BorderRadiusIndividualIcon } from "@webstudio-is/icons";
+import { ToggleGroup, ToggleGroupButton } from "./toggle-group";
+import { StorySection, StoryGrid } from "./storybook";
+import { EnhancedTooltip, EnhancedTooltipProvider } from "./enhanced-tooltip";
+
+const toggleGroupColors = [
+ "default",
+ "preset",
+ "local",
+ "overwritten",
+ "remote",
+] as const;
+
+const ToggleGroupButtons = () => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export const Demo = ({
+ type = "single",
+ color = "default",
+ disabled = false,
+}: ComponentProps) => (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {toggleGroupColors.map((color) => (
+
+
+
+ ))}
+
+
+
+
+
+ {toggleGroupColors.map((color) => (
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+ One
+
+
+ Two
+
+
+ Three
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+
+Demo.argTypes = {
+ type: {
+ control: { type: "inline-radio", options: ["single", "multiple"] },
+ },
+ color: {
+ control: { type: "inline-radio", options: toggleGroupColors },
+ },
+ disabled: {
+ control: { type: "boolean" },
+ },
+};
+
+Demo.storyName = "Toggle Group";
+
+export default {
+ title: "Library/Toggle Group",
+ parameters: {
+ // to make the variant=contrast visible
+ backgrounds: { default: "Panel" },
+ },
+};
diff --git a/packages/design-system/src/components/toggle-group.tsx b/packages/design-system/src/components/toggle-group.tsx
index de0bcfd606..f4a6f1cf18 100644
--- a/packages/design-system/src/components/toggle-group.tsx
+++ b/packages/design-system/src/components/toggle-group.tsx
@@ -1,48 +1,111 @@
-import { styled } from "../stitches.config";
+/**
+ * Implementation of the "Toggle Group" component from:
+ * https://www.figma.com/file/sfCE7iLS0k25qCxiifQNLE/%F0%9F%93%9A-Webstudio-Library?type=design&node-id=4-2831&t=9qVuJbUcZqhAI06U-0
+ */
+
+import {
+ type ComponentProps,
+ type ElementRef,
+ createContext,
+ useContext,
+ forwardRef,
+} from "react";
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
-import { theme } from "../stitches.config";
+import { styled, theme } from "../stitches.config";
+import { IconButton } from "./icon-button";
+import { textVariants } from "./text";
-export const ToggleGroup = styled(ToggleGroupPrimitive.Root, {
- display: "inline-flex",
- borderRadius: theme.spacing[3],
- boxShadow: `0 0 0 ${theme.spacing[1]} ${theme.colors.slate7}`,
- padding: 2,
- backgroundColor: theme.colors.backgroundControls,
-});
+type Color = "default" | "preset" | "local" | "remote" | "overwritten";
-export const ToggleGroupItem = styled(ToggleGroupPrimitive.Item, {
- // all: "unset", // @note weird bug, this somehow gets into weird specifity issues with how styles are inserted
- border: "none",
- backgroundColor: theme.colors.backgroundControls,
- color: theme.colors.hiContrast,
+const ToggleGroupContext = createContext<{
+ color?: Color;
+}>({});
+
+type ToggleGroupProps = ComponentProps<
+ typeof ToggleGroupPrimitive.ToggleGroup
+> & {
+ color?: Color;
+};
+
+const BaseToggleGroup = forwardRef, ToggleGroupProps>(
+ ({ color = "default", children, onValueChange, ...props }, ref) => {
+ return (
+
+ {
+ // prevent unselecting buttons when only single can be selected
+ if (newValue !== "") {
+ onValueChange?.(newValue as string & string[]);
+ }
+ }}
+ >
+ {children}
+
+
+ );
+ }
+);
+
+BaseToggleGroup.displayName = "BaseToggleGroup";
+
+export const ToggleGroup = styled(BaseToggleGroup, {
+ boxSizing: "border-box",
display: "flex",
- whiteSpace: "nowrap",
- fontSize: theme.deprecatedFontSize[4],
- lineHeight: 1,
+ flexDirection: "row",
alignItems: "center",
- justifyContent: "center",
- height: theme.spacing[11],
- outline: "none",
- "&": {
- px: theme.spacing[3],
- },
- "&:first-child": {
- marginLeft: 0,
- borderTopLeftRadius: theme.spacing[3],
- borderBottomLeftRadius: theme.spacing[3],
- },
- "&:last-child": {
- borderTopRightRadius: theme.spacing[3],
- borderBottomRightRadius: theme.spacing[3],
- },
- "&:hover": { backgroundColor: theme.colors.slateA3 },
- // @note because the outline is outside of the element others can end up covering it
- "&:focus-visible": {
- outline: `2px solid ${theme.colors.borderFocus}`,
- outlineOffset: "-2px",
- borderRadius: theme.spacing[3],
-
- zIndex: 1,
- },
- "&[data-state=on]": { backgroundColor: theme.colors.slate5 },
+ padding: 1,
+ background: theme.colors.backgroundControls,
+ border: `1px solid ${theme.colors.borderMain}`,
+ borderRadius: theme.borderRadius[4],
});
+
+const BaseToggleGroupButton = forwardRef<
+ ElementRef<"button">,
+ ComponentProps
+>((props, ref) => {
+ const { color } = useContext(ToggleGroupContext);
+ return (
+
+ );
+});
+
+BaseToggleGroupButton.displayName = "BaseToggleGroupButton";
+
+type ToggleGroupButtonProps = ComponentProps;
+
+export const ToggleGroupButton = forwardRef<
+ ElementRef<"button">,
+ ToggleGroupButtonProps
+>(({ children, ...props }, ref) => {
+ return (
+
+ {children}
+
+ );
+});
+
+ToggleGroupButton.displayName = "ToggleGroupButton";
diff --git a/packages/design-system/src/components/toggle.tsx b/packages/design-system/src/components/toggle.tsx
deleted file mode 100644
index 214f747a3f..0000000000
--- a/packages/design-system/src/components/toggle.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { styled } from "../stitches.config";
-import * as TogglePrimitive from "@radix-ui/react-toggle";
-import { theme } from "../stitches.config";
-
-export const Toggle = styled(TogglePrimitive.Root, {
- // Reset
- alignItems: "center",
- appearance: "none",
- borderWidth: "0",
- boxSizing: "border-box",
- display: "inline-flex",
- flexShrink: 0,
- fontFamily: "inherit",
- fontSize: theme.deprecatedFontSize[4],
- WebkitFontSmoothing: "antialiased",
- justifyContent: "center",
- lineHeight: "1",
- outline: "none",
- padding: "0",
- textDecoration: "none",
- userSelect: "none",
- WebkitTapHighlightColor: "transparent",
- color: theme.colors.hiContrast,
- "&::before": {
- boxSizing: "border-box",
- },
- "&::after": {
- boxSizing: "border-box",
- },
- height: theme.spacing[11],
- width: theme.spacing[11],
- backgroundColor: "transparent",
- "@hover": {
- "&:hover": {
- backgroundColor: theme.colors.slateA3,
- },
- },
- "&:active": {
- backgroundColor: theme.colors.slateA4,
- },
- "&:focus": {
- boxShadow: `inset 0 0 0 1px ${theme.colors.slateA8}, 0 0 0 1px ${theme.colors.slateA8}`,
- zIndex: 1,
- },
-
- '&[data-state="on"]': {
- backgroundColor: theme.colors.slateA5,
- "@hover": {
- "&:hover": {
- backgroundColor: theme.colors.slateA5,
- },
- },
- "&:active": {
- backgroundColor: theme.colors.slateA7,
- },
- },
-
- variants: {
- shape: {
- circle: {
- borderRadius: theme.borderRadius.round,
- },
- square: {
- borderRadius: theme.borderRadius[4],
- },
- },
- },
-});
diff --git a/packages/design-system/src/index.ts b/packages/design-system/src/index.ts
index 5c519c2030..26334dd0b2 100644
--- a/packages/design-system/src/index.ts
+++ b/packages/design-system/src/index.ts
@@ -55,7 +55,6 @@ export {
SidebarTabsTrigger,
} from "./components/sidebar-tabs";
export { Card } from "./components/card";
-export { Toggle } from "./components/toggle";
export { Tooltip, InputErrorsTooltip } from "./components/tooltip";
export {
EnhancedTooltip,