diff --git a/apps/designer/app/designer/features/style-panel/sections/typography/typography.tsx b/apps/designer/app/designer/features/style-panel/sections/typography/typography.tsx index a71078d2ec..285b5ded8b 100644 --- a/apps/designer/app/designer/features/style-panel/sections/typography/typography.tsx +++ b/apps/designer/app/designer/features/style-panel/sections/typography/typography.tsx @@ -1,19 +1,318 @@ import type { RenderCategoryProps } from "../../style-sections"; -import { ShowMore } from "../../shared/show-more"; -import { renderProperty } from "../../style-sections"; +import { Flex, Grid, IconButton, Tooltip } from "@webstudio-is/design-system"; +import { PropertyName } from "../../shared/property-name"; +import { + ColorControl, + FontFamilyControl, + FontWeightControl, + SelectControl, + TextControl, +} from "../../controls"; +import { + CrossSmallIcon, + EllipsesIcon, + TextDirectionLTRIcon, + TextDirectionRTLIcon, + TextAlignCenterIcon, + TextAlignJustifyIcon, + TextAlignLeftIcon, + TextAlignRightIcon, + TextCapitalizeIcon, + TextHyphenIcon, + TextItalicIcon, + TextLowercaseIcon, + TextStrikethroughIcon, + TextTruncateIcon, + TextUnderlineIcon, + TextUppercaseIcon, +} from "@webstudio-is/icons"; +import { ToggleGroupControl } from "../../controls/toggle/toggle-control"; +import { ValuePickerPopover } from "../../shared/value-picker-popover"; -export const TypographySection = ({ - styleConfigsByCategory, - moreStyleConfigsByCategory, -}: RenderCategoryProps) => { +export const TypographySection = (props: RenderCategoryProps) => { return ( - <> - {styleConfigsByCategory.map((entry) => renderProperty(entry))} - - renderProperty(entry) - )} - /> - + + + + + ); }; + +export const TypographySectionFont = (props: RenderCategoryProps) => { + const { sectionStyle } = props; + + return ( + + + + + + + + + + + + + + + ); +}; + +export const TypographySectionSizing = (props: RenderCategoryProps) => { + const { sectionStyle } = props; + + return ( + + + + + + + + + + + + + + + ); +}; + +export const TypographySectionAdvanced = (props: RenderCategoryProps) => { + const { setProperty, currentStyle } = props; + const setTextAlign = setProperty("textAlign"); + const setTextDecorationLine = setProperty("textDecorationLine"); + const setTextTransform = setProperty("textTransform"); + const setFontStyle = setProperty("fontStyle"); + + return ( + + + setTextAlign(value)} + value={String(getTextAlign(String(currentStyle.textAlign?.value)))} + items={[ + { + child: , + label: "align: left", + value: "start", + }, + { + child: , + label: "align: center", + value: "center", + }, + { + child: , + label: "align: right", + value: "end", + }, + { + child: , + label: "align: justify", + value: "justify", + }, + ]} + /> + setTextDecorationLine(value)} + value={String(currentStyle.textDecorationLine?.value)} + items={[ + { + child: , + label: "None", + value: "none", + }, + { + child: , + label: "Underline", + value: "underline", + }, + { + child: , + label: "Line through", + value: "line-through", + }, + ]} + /> + + + setTextTransform(value)} + value={String(currentStyle.textTransform?.value)} + items={[ + { + child: , + label: "None", + value: "none", + }, + { + child: , + label: "Uppercase", + value: "uppercase", + }, + { + child: , + label: "Capitalize", + value: "capitalize", + }, + { + child: , + label: "Lowercase", + value: "lowercase", + }, + ]} + /> + setFontStyle(value)} + value={String(currentStyle.fontStyle?.value)} + items={[ + { + child: , + label: "None", + value: "normal", + }, + { + child: , + label: "Italic", + value: "italic", + }, + ]} + /> + + + + ); +}; + +export const TypographySectionAdvancedPopover = ( + props: RenderCategoryProps +) => { + const { setProperty, currentStyle, sectionStyle } = props; + const setDirection = setProperty("direction"); + const setTextOverflow = setProperty("textOverflow"); + const setHyphens = setProperty("hyphens"); + return ( + + + + + + + + setDirection(value)} + value={String(currentStyle.direction?.value)} + items={[ + { + child: , + label: "Left to Right", + value: "ltr", + }, + { + child: , + label: "Right to Left", + value: "rtl", + }, + ]} + /> + + + + setHyphens(value)} + value={String(currentStyle.hyphens?.value)} + items={[ + { + child: , + label: "None", + value: "manual", + }, + { + child: , + label: "Auto", + value: "auto", + }, + ]} + /> + + + + setTextOverflow(value)} + value={String(currentStyle.textOverflow?.value)} + items={[ + { + child: , + label: "None", + value: "clip", + }, + { + child: , + label: "Ellipsis", + value: "ellipsis", + }, + ]} + /> + + + } + > + + + + + + + + + ); +}; + +const getTextAlign = (value: string) => { + switch (value) { + case "left": + return "start"; + case "right": + return "end"; + default: + return value; + } +}; diff --git a/packages/design-system/src/components/toggle-group.tsx b/packages/design-system/src/components/toggle-group.tsx index 8cb67c13c7..674aec8c7c 100644 --- a/packages/design-system/src/components/toggle-group.tsx +++ b/packages/design-system/src/components/toggle-group.tsx @@ -9,7 +9,8 @@ export const ToggleGroupRoot = styled(ToggleGroupPrimitive.Root, { }); export const ToggleGroupItem = styled(ToggleGroupPrimitive.Item, { - all: "unset", + // all: "unset", // @note weird bug, this somehow gets into weird specifity issues with how styles are inserted + border: "none", backgroundColor: "$loContrast", color: "$hiContrast", display: "flex", diff --git a/packages/icons/src/external-link.tsx b/packages/icons/src/external-link.tsx new file mode 100644 index 0000000000..19eb805c01 --- /dev/null +++ b/packages/icons/src/external-link.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const ExternalLinkIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); + +ExternalLinkIcon.displayName = "ExternalLinkIcon"; diff --git a/packages/icons/src/index.ts b/packages/icons/src/index.ts index 71cfed5e37..94842ae9ef 100644 --- a/packages/icons/src/index.ts +++ b/packages/icons/src/index.ts @@ -77,3 +77,17 @@ export * from "./order-last"; export * from "./cross-small"; export * from "./cross-large"; export * from "./ellipses"; +export * from "./text-align-center"; +export * from "./text-align-justify"; +export * from "./text-align-left"; +export * from "./text-align-right"; +export * from "./text-capitalize"; +export * from "./text-hyphen"; +export * from "./text-italic"; +export * from "./text-lowercase"; +export * from "./text-strikethrough"; +export * from "./text-truncate"; +export * from "./text-underline"; +export * from "./text-uppercase"; +export * from "./text-direction-ltr"; +export * from "./text-direction-rtl"; diff --git a/packages/icons/src/legacy.ts b/packages/icons/src/legacy.ts index b885b1d51a..1cae8ef769 100644 --- a/packages/icons/src/legacy.ts +++ b/packages/icons/src/legacy.ts @@ -21,7 +21,6 @@ export { CommitIcon, InputIcon, ButtonIcon, - TextAlignLeftIcon, HeadingIcon, TextIcon, SquareIcon, diff --git a/packages/icons/src/text-align-center.tsx b/packages/icons/src/text-align-center.tsx new file mode 100644 index 0000000000..f76f304647 --- /dev/null +++ b/packages/icons/src/text-align-center.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextAlignCenterIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + + + ); + } +); +TextAlignCenterIcon.displayName = "TextAlignCenterIcon"; diff --git a/packages/icons/src/text-align-justify.tsx b/packages/icons/src/text-align-justify.tsx new file mode 100644 index 0000000000..bc26e8b8e0 --- /dev/null +++ b/packages/icons/src/text-align-justify.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextAlignJustifyIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + + + ); + } +); +TextAlignJustifyIcon.displayName = "TextAlignJustifyIcon"; diff --git a/packages/icons/src/text-align-left.tsx b/packages/icons/src/text-align-left.tsx new file mode 100644 index 0000000000..32f740dddf --- /dev/null +++ b/packages/icons/src/text-align-left.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextAlignLeftIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + + + ); + } +); +TextAlignLeftIcon.displayName = "TextAlignLeftIcon"; diff --git a/packages/icons/src/text-align-right.tsx b/packages/icons/src/text-align-right.tsx new file mode 100644 index 0000000000..9a9484701a --- /dev/null +++ b/packages/icons/src/text-align-right.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextAlignRightIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + + + ); + } +); +TextAlignRightIcon.displayName = "TextAlignRightIcon"; diff --git a/packages/icons/src/text-capitalize.tsx b/packages/icons/src/text-capitalize.tsx new file mode 100644 index 0000000000..604d0d6b76 --- /dev/null +++ b/packages/icons/src/text-capitalize.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextCapitalizeIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextCapitalizeIcon.displayName = "TextCapitalizeIcon"; diff --git a/packages/icons/src/text-direction-ltr.tsx b/packages/icons/src/text-direction-ltr.tsx new file mode 100644 index 0000000000..1b05b79a72 --- /dev/null +++ b/packages/icons/src/text-direction-ltr.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextDirectionLTRIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextDirectionLTRIcon.displayName = "TextDirectionLTRIcon"; diff --git a/packages/icons/src/text-direction-rtl.tsx b/packages/icons/src/text-direction-rtl.tsx new file mode 100644 index 0000000000..771f7de58f --- /dev/null +++ b/packages/icons/src/text-direction-rtl.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextDirectionRTLIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextDirectionRTLIcon.displayName = "TextDirectionRTLIcon"; diff --git a/packages/icons/src/text-hyphen.tsx b/packages/icons/src/text-hyphen.tsx new file mode 100644 index 0000000000..408a7c91bd --- /dev/null +++ b/packages/icons/src/text-hyphen.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextHyphenIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextHyphenIcon.displayName = "TextHyphenIcon"; diff --git a/packages/icons/src/text-italic.tsx b/packages/icons/src/text-italic.tsx new file mode 100644 index 0000000000..e7d7427b41 --- /dev/null +++ b/packages/icons/src/text-italic.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextItalicIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextItalicIcon.displayName = "TextItalicIcon"; diff --git a/packages/icons/src/text-lowercase.tsx b/packages/icons/src/text-lowercase.tsx new file mode 100644 index 0000000000..ce08efd7db --- /dev/null +++ b/packages/icons/src/text-lowercase.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextLowercaseIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextLowercaseIcon.displayName = "TextLowercaseIcon"; diff --git a/packages/icons/src/text-strikethrough.tsx b/packages/icons/src/text-strikethrough.tsx new file mode 100644 index 0000000000..f78957bfed --- /dev/null +++ b/packages/icons/src/text-strikethrough.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextStrikethroughIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + + + ); + } +); +TextStrikethroughIcon.displayName = "TextStrikethroughIcon"; diff --git a/packages/icons/src/text-truncate.tsx b/packages/icons/src/text-truncate.tsx new file mode 100644 index 0000000000..fa120abcc9 --- /dev/null +++ b/packages/icons/src/text-truncate.tsx @@ -0,0 +1,36 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextTruncateIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + + + + ); + } +); +TextTruncateIcon.displayName = "TextTruncateIcon"; diff --git a/packages/icons/src/text-underline.tsx b/packages/icons/src/text-underline.tsx new file mode 100644 index 0000000000..a0e36e6dc0 --- /dev/null +++ b/packages/icons/src/text-underline.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextUnderlineIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextUnderlineIcon.displayName = "TextUnderlineIcon"; diff --git a/packages/icons/src/text-uppercase.tsx b/packages/icons/src/text-uppercase.tsx new file mode 100644 index 0000000000..b96c00181f --- /dev/null +++ b/packages/icons/src/text-uppercase.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { IconProps } from "./types"; + +export const TextUppercaseIcon = React.forwardRef( + ({ color = "currentColor", ...props }, forwardedRef) => { + return ( + + + + ); + } +); +TextUppercaseIcon.displayName = "TextUppercaseIcon";