Skip to content
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

[feat] New Flexbox Controls #758

Merged
merged 22 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions apps/studio/common/helpers/twTranslator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,11 @@ const propertyMap: Map<string, Record<string, string> | ((val: string) => string
[
'align-items',
{
'flex-start': 'items-start',
'flex-end': 'items-end',
center: 'items-center',
verticalStart: 'items-start',
verticalEnd: 'items-end',
verticalCenter: 'items-center',
baseline: 'items-baseline',
stretch: 'items-stretch',
verticalStretch: 'items-stretch',
},
],
[
Expand Down Expand Up @@ -1433,10 +1433,10 @@ const propertyMap: Map<string, Record<string, string> | ((val: string) => string
[
'justify-content',
{
'flex-start': 'justify-start',
'flex-end': 'justify-end',
center: 'justify-center',
'space-between': 'justify-between',
horizontalStart: 'justify-start',
horizontalEnd: 'justify-end',
horizontalCenter: 'justify-center',
horizontalSpaceBetween: 'justify-between',
'space-around': 'justify-around',
'space-evenly': 'justify-evenly',
},
Expand Down
136 changes: 53 additions & 83 deletions apps/studio/src/lib/editor/styles/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,36 @@ export const PositionGroup = [
export const LayoutGroup = [
new CompoundStyleImpl(
CompoundStyleKey.Display,
new SingleStyleImpl('display', 'block', 'Type', StyleType.Select, {
options: ['block', 'flex', 'grid'],
new SingleStyleImpl('display', 'flex', 'Type', StyleType.Select, {
options: ['flex', 'grid'],
}),
[
// Flex direction control (row/column)
new SingleStyleImpl('flexDirection', 'row', 'Direction', StyleType.Select, {
options: ['row', 'column'],
}),
new SingleStyleImpl('justifyContent', 'flex-start', 'Justify', StyleType.Select, {
options: ['flex-start', 'center', 'flex-end', 'space-between'],
}),
new SingleStyleImpl('alignItems', 'flex-start', 'Align', StyleType.Select, {
options: ['flex-start', 'center', 'flex-end', 'space-between'],

// Horizontal alignment (Justify Content)
new SingleStyleImpl(
'justifyContent',
'horizontal-start',
'Horizontal',
StyleType.Select,
{
options: ['flex-start', 'center', 'flex-end', 'stretch'],
},
),

// Vertical alignment (Align Items)
new SingleStyleImpl('alignItems', 'vertical-start', 'Vertical', StyleType.Select, {
options: ['flex-start', 'center', 'flex-end', 'stretch'],
}),

// Grid settings (for CSS grid)
new SingleStyleImpl('gridTemplateColumns', '', 'Columns', StyleType.Text),
new SingleStyleImpl('gridTemplateRows', '', 'Rows', StyleType.Text),

// Gap control for spacing
new SingleStyleImpl('gap', '0px', 'Gap', StyleType.Number, {
units: ELEMENT_STYLE_UNITS,
max: 1000,
Expand Down Expand Up @@ -151,57 +166,29 @@ export const StyleGroup = [
max: STYLE_CONSTRAINTS.border.radius.max,
}),
[
new SingleStyleImpl(
'borderTopLeftRadius',
'',
'Top Left',
StyleType.Number,

{
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
},
),

new SingleStyleImpl(
'borderTopRightRadius',
'',
'Top Right',
StyleType.Number,

{
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
},
),

new SingleStyleImpl(
'borderBottomLeftRadius',
'',
'Bottom Left',
StyleType.Number,
new SingleStyleImpl('borderTopLeftRadius', '', 'Top Left', StyleType.Number, {
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
}),

{
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
},
),
new SingleStyleImpl('borderTopRightRadius', '', 'Top Right', StyleType.Number, {
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
}),

new SingleStyleImpl(
'borderBottomRightRadius',
'',
'Bottom Right',
StyleType.Number,
new SingleStyleImpl('borderBottomLeftRadius', '', 'Bottom Left', StyleType.Number, {
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
}),

{
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
},
),
new SingleStyleImpl('borderBottomRightRadius', '', 'Bottom Right', StyleType.Number, {
units: ELEMENT_STYLE_UNITS,
min: STYLE_CONSTRAINTS.border.radius.min,
max: STYLE_CONSTRAINTS.border.radius.max,
}),
],
),
new CompoundStyleImpl(
Expand All @@ -223,36 +210,19 @@ export const StyleGroup = [
export const TextGroup = [
new SingleStyleImpl('color', '#000000', 'Color', StyleType.Color),

new SingleStyleImpl('fontSize', '16px', 'Size', StyleType.Number, {
units: ELEMENT_STYLE_UNITS,
min: 1,
max: 1000,
new SingleStyleImpl('fontSize', '16', 'Size', StyleType.Number, {
units: ['px', 'rem', 'em', 'pt'],
min: 0,
max: 500,
}),
new SingleStyleImpl('fontWeight', 'normal', 'Weight', StyleType.Select, {
options: [
'lighter',
'normal',
'bold',
'100',
'200',
'300',
'400',
'500',
'600',
'700',
'800',
'900',
],

new SingleStyleImpl('fontFamily', '', 'Font', StyleType.Select, {
options: ['Arial', 'Helvetica', 'Times New Roman', 'Courier New'],
}),
new SingleStyleImpl('letterSpacing', '0px', 'Letter', StyleType.Number, {
units: ELEMENT_STYLE_UNITS,

new SingleStyleImpl('lineHeight', '1.5', 'Line Height', StyleType.Number, {
units: ['px', 'em'],
min: 0,
max: 100,
}),
new SingleStyleImpl('lineHeight', '100%', 'Line Height', StyleType.Number, {
units: ['%', 'px'],
max: 1000,
}),
new SingleStyleImpl('textAlign', 'start', 'Align', StyleType.Select, {
options: ['start', 'center', 'end'],
}),
];
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ enum DisplayType {

const DisplayTypeMap: Record<DisplayType, string[] | undefined> = {
[DisplayType.block]: [],
[DisplayType.flex]: ['flexDirection', 'justifyContent', 'alignItems', 'gap'],
[DisplayType.flex]: [
'flexDirection',
'horizontalDirection',
'verticalDirection',
'justifyContent',
'alignItems',
'gap',
],
[DisplayType.grid]: ['gridTemplateColumns', 'gridTemplateRows', 'gap'],
};

Expand Down Expand Up @@ -63,22 +70,6 @@ const DisplayInput = observer(({ compoundStyle }: { compoundStyle: CompoundStyle
return selectedStyle.styles['flexDirection'] ?? 'row';
}

function getLabelValue(elementStyle: SingleStyle) {
if (
elementStyle.key === 'justifyContent' ||
(elementStyle.key === 'alignItems' && displayType === DisplayType.flex)
) {
const flexDirection = getFlexDirection() as 'row' | 'column';
if (elementStyle.key === 'justifyContent') {
return flexDirection === 'row' ? 'X Align' : 'Y Align';
} else {
return flexDirection === 'row' ? 'Y Align' : 'X Align';
}
}

return elementStyle.displayName;
}

function renderBottomInputs() {
return compoundStyle.children.map(
(elementStyle) =>
Expand All @@ -92,7 +83,7 @@ const DisplayInput = observer(({ compoundStyle }: { compoundStyle: CompoundStyle
transition={{ duration: 0.2 }}
>
<div className="text-foreground-onlook">
<p className="text-xs text-left">{getLabelValue(elementStyle)}</p>
<p className="text-xs text-left">{elementStyle.displayName}</p>
</div>
<div className="w-32 ml-auto">
{RowColKeys.includes(elementStyle.key) ? (
Expand Down
46 changes: 39 additions & 7 deletions apps/studio/src/routes/editor/EditPanel/StylesTab/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React, { useState } from 'react';
import { useEditorEngine } from '@/components/Context';
import type { CompoundStyleImpl } from '@/lib/editor/styles';
import { LayoutGroup, PositionGroup, StyleGroup, TextGroup } from '@/lib/editor/styles/group';
Expand All @@ -20,6 +21,7 @@ import SelectInput from './single/SelectInput';
import TagDetails from './single/TagDetails';
import TailwindInput from './single/TailwindInput';
import TextInput from './single/TextInput';
import { MinusIcon, PlusIcon } from '@radix-ui/react-icons';

export const STYLE_GROUP_MAPPING: Record<StyleGroupKey, BaseStyle[]> = {
[StyleGroupKey.Position]: PositionGroup,
Expand All @@ -31,6 +33,18 @@ export const STYLE_GROUP_MAPPING: Record<StyleGroupKey, BaseStyle[]> = {
const ManualTab = observer(() => {
const editorEngine = useEditorEngine();
const TAILWIND_KEY = 'tw';
const [isAdd, setIsAdd] = useState(true);
const [openSections, setOpenSections] = useState<Record<string, boolean>>({
[StyleGroupKey.Layout]: false,
});

const handleButtonClick = (groupKey: string) => {
setOpenSections((prev) => ({
...prev,
[groupKey]: !prev[groupKey],
}));
setIsAdd(!openSections[groupKey]);
};

function renderSingle(style: SingleStyle) {
return (
Expand Down Expand Up @@ -98,13 +112,31 @@ const ManualTab = observer(() => {
function renderStyleSections() {
return Object.entries(STYLE_GROUP_MAPPING).map(([groupKey, baseElementStyles]) => (
<AccordionItem key={groupKey} value={groupKey}>
<AccordionTrigger>
<h2 className="text-xs font-semibold">{groupKey}</h2>
</AccordionTrigger>
<AccordionContent>
{groupKey === StyleGroupKey.Text && <TagDetails />}
{renderGroupValues(baseElementStyles)}
</AccordionContent>
{groupKey === StyleGroupKey.Layout ? (
<div style={{ position: 'relative' }}>
<h2 className="text-xs font-semibold">{groupKey}</h2>
<button
onClick={() => handleButtonClick(groupKey)}
className="absolute top-1/2 right-0 transform -translate-y-1/2 bg-none border-none text-muted-foreground transition-transform duration-200"
>
{openSections[groupKey] ? (
<MinusIcon className="h-4 w-4" />
) : (
<PlusIcon className="h-4 w-4" />
)}
</button>
</div>
) : (
<AccordionTrigger>
<h2 className="text-xs font-semibold">{groupKey}</h2>
</AccordionTrigger>
)}
{(groupKey !== StyleGroupKey.Layout || openSections[groupKey]) && (
<AccordionContent>
{groupKey === StyleGroupKey.Text && <TagDetails />}
{renderGroupValues(baseElementStyles)}
</AccordionContent>
)}
</AccordionItem>
));
}
Expand Down
Loading