Skip to content

Commit

Permalink
Make style section hideable and suppressable. (#5719)
Browse files Browse the repository at this point in the history
* group inspector sections

* cleanup

* update tests

* move the component section and the target selector to the right place
  • Loading branch information
bkrmendy authored May 22, 2024
1 parent 7fce599 commit 8099d72
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,11 @@ describe('inspector tests with real metadata', () => {
`"detected-fromcss"`,
)

await act(async () => {
await screen.findByTestId('section-header-Advanced')
fireEvent.click(screen.getByTestId('section-header-Advanced'))
})

await act(async () => {
await screen.findByTestId('target-selector-style')
fireEvent.click(screen.getByTestId('target-selector'))
Expand Down Expand Up @@ -1559,6 +1564,11 @@ describe('inspector tests with real metadata', () => {
await dispatchDone
})

await act(async () => {
await screen.findByTestId('section-header-Advanced')
fireEvent.click(screen.getByTestId('section-header-Advanced'))
})

await act(async () => {
await screen.findByTestId('target-selector-style')
fireEvent.click(screen.getByTestId('target-selector'))
Expand Down
216 changes: 146 additions & 70 deletions editor/src/components/inspector/inspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,16 @@ import {
useKeepReferenceEqualityIfPossible,
useKeepShallowReferenceEquality,
} from '../../utils/react-performance'
import { Icn, useColorTheme, UtopiaTheme, FlexRow, Button } from '../../uuiui'
import {
Icn,
useColorTheme,
UtopiaTheme,
FlexRow,
Button,
H1,
SectionActionSheet,
SquareButton,
} from '../../uuiui'
import { getElementsToTarget } from './common/inspector-utils'
import type { ElementPath, PropertyPath } from '../../core/shared/project-file-types'
import { unless, when } from '../../utils/react-conditionals'
Expand Down Expand Up @@ -84,6 +93,7 @@ import { usePermissions } from '../editor/store/permissions'
import { DisableControlsInSubtree } from '../../uuiui/utilities/disable-subtree'
import { getInspectorPreferencesForTargets } from '../../core/property-controls/property-controls-utils'
import { ListSection } from './sections/layout-section/list-section'
import { ExpandableIndicator } from '../navigator/navigator-item/expandable-indicator'

export interface ElementPathElement {
name?: string
Expand Down Expand Up @@ -245,7 +255,7 @@ export const InspectorSectionsContainerTestID = 'inspector-sections-container'
export const Inspector = React.memo<InspectorProps>((props: InspectorProps) => {
const { selectedViews, setSelectedTarget, targets } = props

const hideAllSections = useEditorState(
const isCodeElement = useEditorState(
Substores.metadata,
(store) =>
store.editor.selectedViews.length > 0 &&
Expand All @@ -269,7 +279,7 @@ export const Inspector = React.memo<InspectorProps>((props: InspectorProps) => {
}, [selectedViews, targets, setSelectedTarget])

const dispatch = useDispatch()
const { focusedPanel, anyComponents, hasNonDefaultPositionAttributes } = useEditorState(
const { focusedPanel, anyComponents } = useEditorState(
Substores.fullStore,
(store) => {
const rootMetadata = store.editor.jsxMetadata
Expand Down Expand Up @@ -352,7 +362,10 @@ export const Inspector = React.memo<InspectorProps>((props: InspectorProps) => {
'Inspector inspectorPreferences',
)

const shouldShowAlignmentButtons = !hideAllSections && inspectorPreferences.includes('layout')
const { value: styleSectionOpen, toggle: toggleStyleSection } = useBoolean(true)
const { value: advancedSectionOpen, toggle: toggleAdvancedSection } = useBoolean(false)

const shouldShowAlignmentButtons = !isCodeElement && inspectorPreferences.includes('layout')
const shouldShowClassNameSubsection = isTwindEnabled() && inspectorPreferences.includes('visual')
const shouldShowTargetSelectorSection = canEdit && inspectorPreferences.includes('visual')
const shouldShowFlexSection =
Expand All @@ -378,72 +391,88 @@ export const Inspector = React.memo<InspectorProps>((props: InspectorProps) => {
data-testid={InspectorSectionsContainerTestID}
>
<DisableControlsInSubtree disable={!canEdit}>
<FlexCol
css={{
overflowY: 'scroll',
width: '100%',
height: '100%',
position: 'relative',
paddingBottom: 50,
}}
>
{rootElementIsSelected ? (
<RootElementIndicator />
) : (
when(
shouldShowAlignmentButtons,
<AlignmentButtons numberOfTargets={selectedViews.length} />,
)
)}
{unless(
hideAllSections,
<>
{when(shouldShowClassNameSubsection, <ClassNameSubsection />)}
{anyComponents || multiselectedContract === 'fragment' ? (
<ComponentSection isScene={false} />
) : null}
</>,
)}
<CodeElementSection paths={selectedViews} />
<ConditionalSection paths={selectedViews} />
<ListSection paths={selectedViews} />
{unless(
hideAllSections,
<>
{when(
shouldShowTargetSelectorSection,
<TargetSelectorSection
targets={props.targets}
selectedTargetPath={props.selectedTargetPath}
onSelectTarget={props.onSelectTarget}
onStyleSelectorRename={props.onStyleSelectorRename}
onStyleSelectorDelete={props.onStyleSelectorDelete}
onStyleSelectorInsert={props.onStyleSelectorInsert}
/>,
)}
{when(multiselectedContract === 'fragment', <FragmentSection />)}
{when(
multiselectedContract !== 'fragment' && shouldShowSimplifiedLayoutSection,
// Position and Sizing sections are shown if Frame or Group is selected
<>
<SimplifiedLayoutSubsection />
<ConstraintsSection />
</>,
)}
{when(shouldShowFlexSection, <FlexSection />)}
{when(
multiselectedContract === 'frame' || multiselectedContract === 'wrapper-div',
// All the regular inspector sections are only visible if frames are selected
<>
<StyleSection />
<WarningSubsection />
<ImgSection />
<EventHandlersSection />
</>,
)}
</>,
)}
</FlexCol>
{isCodeElement ? (
<>
<CodeElementSection paths={selectedViews} />
<ConditionalSection paths={selectedViews} />
<ListSection paths={selectedViews} />
</>
) : (
<FlexCol
css={{
overflowY: 'scroll',
width: '100%',
height: '100%',
position: 'relative',
paddingBottom: 50,
}}
>
{anyComponents || multiselectedContract === 'fragment' ? (
<ComponentSection isScene={false} />
) : null}
<InspectorSectionHeader
title='Styles'
toggle={toggleStyleSection}
open={styleSectionOpen}
/>
{when(
styleSectionOpen,
<>
{rootElementIsSelected ? (
<RootElementIndicator />
) : (
when(
shouldShowAlignmentButtons,
<AlignmentButtons numberOfTargets={selectedViews.length} />,
)
)}
{when(multiselectedContract === 'fragment', <FragmentSection />)}
{when(
multiselectedContract !== 'fragment' && shouldShowSimplifiedLayoutSection,
// Position and Sizing sections are shown if Frame or Group is selected
<>
<SimplifiedLayoutSubsection />
<ConstraintsSection />
</>,
)}
{when(shouldShowFlexSection, <FlexSection />)}
{when(
multiselectedContract === 'frame' || multiselectedContract === 'wrapper-div',
// All the regular inspector sections are only visible if frames are selected
<>
<StyleSection />
<WarningSubsection />
<ImgSection />
<EventHandlersSection />
</>,
)}
</>,
)}

<InspectorSectionHeader
title='Advanced'
toggle={toggleAdvancedSection}
open={advancedSectionOpen}
/>
{when(
advancedSectionOpen,
<>
{when(shouldShowClassNameSubsection, <ClassNameSubsection />)}
{when(
shouldShowTargetSelectorSection,
<TargetSelectorSection
targets={props.targets}
selectedTargetPath={props.selectedTargetPath}
onSelectTarget={props.onSelectTarget}
onStyleSelectorRename={props.onStyleSelectorRename}
onStyleSelectorDelete={props.onStyleSelectorDelete}
onStyleSelectorInsert={props.onStyleSelectorInsert}
/>,
)}
</>,
)}
</FlexCol>
)}
</DisableControlsInSubtree>
</div>
</React.Fragment>
Expand Down Expand Up @@ -828,3 +857,50 @@ export const InspectorContextProvider = React.memo<{
</InspectorCallbackContext.Provider>
)
})

function InspectorSectionHeader({
title,
open,
toggle,
}: {
title: string
open: boolean
toggle: () => void
}) {
return (
<FlexRow
style={{
padding: 8,
cursor: 'pointer',
}}
onClick={toggle}
data-testid={`section-header-${title}`}
>
<H1
style={{
flexGrow: 1,
display: 'inline',
overflow: 'hidden',
fontSize: '12px',
}}
>
{title}
</H1>
<SectionActionSheet className='actionsheet' style={{ gap: 4 }}>
<SquareButton highlight style={{ width: 12 }}>
<ExpandableIndicator visible collapsed={!open} selected={false} />
</SquareButton>
</SectionActionSheet>
</FlexRow>
)
}

function useBoolean(starting: boolean): {
value: boolean
set: (_: boolean) => void
toggle: () => void
} {
const [value, set] = React.useState(starting)
const toggle = React.useCallback(() => set((v) => !v), [])
return { value, set, toggle }
}
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ const TargetListHeader = React.memo((props: TargetListHeaderProps) => {
overflow: 'hidden',
}}
>
{selectedTargetPath}
Target
</H1>
<SectionActionSheet className='actionsheet' style={{ gap: 4 }}>
<SquareButton highlight disabled={isAdding} onClick={startAdding} style={{ width: 12 }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ const ClassNameControl = React.memo(() => {
}}
>
<span style={{ flexGrow: 1, cursor: 'pointer' }} onClick={toggleIsExpanded}>
Class Names
CSS
</span>
<SquareButton highlight onClick={toggleIsExpanded}>
<ExpandableIndicator visible collapsed={!isExpanded} selected={false} />
Expand Down
Loading

0 comments on commit 8099d72

Please sign in to comment.