wip: api playground fixes (#11345)

# ISSUE 
- closes #10926 

- [x] fix paddings
- [x] fix page change to playground animation
- [x] fixes multiple skeletons issues

---

- Also was showing multiple skeletons on reloading, **before**: 


https://github.com/user-attachments/assets/0cdef639-c121-4cbb-b056-b89e60862c54

---------

Co-authored-by: ehconitin <nitinkoche03@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Nabhag Motivaras
2025-04-10 20:32:55 +05:30
committed by GitHub
parent a86317eb71
commit bc8f71fab5
5 changed files with 62 additions and 42 deletions

View File

@ -1,5 +1,6 @@
import { playgroundApiKeyState } from '@/settings/playground/states/playgroundApiKeyState'; import { playgroundApiKeyState } from '@/settings/playground/states/playgroundApiKeyState';
import { PlaygroundSchemas } from '@/settings/playground/types/PlaygroundSchemas'; import { PlaygroundSchemas } from '@/settings/playground/types/PlaygroundSchemas';
import styled from '@emotion/styled';
import { explorerPlugin } from '@graphiql/plugin-explorer'; import { explorerPlugin } from '@graphiql/plugin-explorer';
import '@graphiql/plugin-explorer/dist/style.css'; import '@graphiql/plugin-explorer/dist/style.css';
import { createGraphiQLFetcher } from '@graphiql/toolkit'; import { createGraphiQLFetcher } from '@graphiql/toolkit';
@ -7,8 +8,8 @@ import { GraphiQL } from 'graphiql';
import 'graphiql/graphiql.css'; import 'graphiql/graphiql.css';
import { useContext } from 'react'; import { useContext } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { ThemeContext } from 'twenty-ui/theme'; import { ThemeContext } from 'twenty-ui/theme';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
type GraphQLPlaygroundProps = { type GraphQLPlaygroundProps = {
onError(): void; onError(): void;
@ -20,6 +21,16 @@ export const schemaToPath = {
[PlaygroundSchemas.METADATA]: 'metadata', [PlaygroundSchemas.METADATA]: 'metadata',
}; };
const StyledGraphiQLContainer = styled.div`
height: 100%;
width: 100%;
.graphiql-container {
background: ${({ theme }) => theme.background.primary};
border-radius: ${({ theme }) => theme.border.radius.md};
}
`;
export const GraphQLPlayground = ({ export const GraphQLPlayground = ({
onError, onError,
schema, schema,
@ -43,13 +54,15 @@ export const GraphQLPlayground = ({
}); });
return ( return (
<GraphiQL <StyledGraphiQLContainer>
forcedTheme={theme.name as 'light' | 'dark'} <GraphiQL
plugins={[explorer]} forcedTheme={theme.name as 'light' | 'dark'}
fetcher={fetcher} plugins={[explorer]}
defaultHeaders={JSON.stringify({ fetcher={fetcher}
Authorization: `Bearer ${playgroundApiKey}`, defaultHeaders={JSON.stringify({
})} Authorization: `Bearer ${playgroundApiKey}`,
/> })}
/>
</StyledGraphiQLContainer>
); );
}; };

View File

@ -10,9 +10,23 @@ import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledContainer = styled.div` const StyledContainer = styled.div`
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};
height: 100%; height: 100%;
overflow-y: scroll; overflow-y: scroll;
width: 100%; width: 100%;
.scalar-api-reference {
--scalar-background-1: ${({ theme }) => theme.background.primary};
--scalar-background-2: ${({ theme }) => theme.background.secondary};
--scalar-background-3: ${({ theme }) => theme.background.tertiary};
--scalar-background-accent: ${({ theme }) =>
theme.background.transparent.lighter};
--scalar-border-color: ${({ theme }) => theme.border.color.medium};
--scalar-color-1: ${({ theme }) => theme.font.color.primary};
--scalar-color-2: ${({ theme }) => theme.font.color.secondary};
--scalar-color-3: ${({ theme }) => theme.font.color.tertiary};
}
`; `;
const ApiReferenceReact = lazy(() => const ApiReferenceReact = lazy(() =>

View File

@ -7,9 +7,6 @@ import {
BreadcrumbProps, BreadcrumbProps,
} from '@/ui/navigation/bread-crumb/components/Breadcrumb'; } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { IconButton } from 'twenty-ui/input';
import { IconX } from 'twenty-ui/display';
import { useIsMobile } from 'twenty-ui/utilities'; import { useIsMobile } from 'twenty-ui/utilities';
type FullScreenContainerProps = { type FullScreenContainerProps = {
@ -19,19 +16,22 @@ type FullScreenContainerProps = {
}; };
const StyledFullScreen = styled.div` const StyledFullScreen = styled.div`
background: ${({ theme }) => theme.background.noisy};
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100dvw; width: 100%;
height: 100dvh;
background: ${({ theme }) => theme.background.noisy};
`; `;
const StyledMainContainer = styled.div` const StyledMainContainer = styled.div`
border-top: 1px solid ${({ theme }) => theme.border.color.medium};
height: calc( height: calc(
100% - ${PAGE_BAR_MIN_HEIGHT}px - ${({ theme }) => theme.spacing(2 * 2)} 100% - ${PAGE_BAR_MIN_HEIGHT}px - ${({ theme }) => theme.spacing(2 * 2 + 3)}
); );
width: 100%; padding: ${({ theme }) =>
`0 ${theme.spacing(3)} ${theme.spacing(3)} ${theme.spacing(3)}`};
`;
const StyledPageHeader = styled(PageHeader)`
padding-left: ${({ theme }) => theme.spacing(3)};
`; `;
export const FullScreenContainer = ({ export const FullScreenContainer = ({
@ -40,25 +40,14 @@ export const FullScreenContainer = ({
exitFullScreen, exitFullScreen,
}: FullScreenContainerProps) => { }: FullScreenContainerProps) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { t } = useLingui();
const handleExitFullScreen = () => {
exitFullScreen();
};
return ( return (
<StyledFullScreen> <StyledFullScreen>
<PageHeader title={<Breadcrumb links={links} />}> <StyledPageHeader
<IconButton title={<Breadcrumb links={links} />}
Icon={IconX} hasClosePageButton={!isMobile}
dataTestId="close-button" onClosePage={exitFullScreen}
size={isMobile ? 'medium' : 'small'} />
variant="secondary"
accent="default"
onClick={handleExitFullScreen}
ariaLabel={t`Exit Full Screen`}
/>
</PageHeader>
<StyledMainContainer>{children}</StyledMainContainer> <StyledMainContainer>{children}</StyledMainContainer>
</StyledFullScreen> </StyledFullScreen>
); );

View File

@ -80,14 +80,16 @@ export const DefaultLayout = () => {
<AppErrorBoundary FallbackComponent={AppFullScreenErrorFallback}> <AppErrorBoundary FallbackComponent={AppFullScreenErrorFallback}>
<StyledPageContainer <StyledPageContainer
animate={{ animate={{
marginLeft: transform:
isSettingsPage && !isMobile && !useShowFullScreen isSettingsPage && !isMobile && !useShowFullScreen
? (windowsWidth - ? `translateX(${
(OBJECT_SETTINGS_WIDTH + (windowsWidth -
NAV_DRAWER_WIDTHS.menu.desktop.expanded + (OBJECT_SETTINGS_WIDTH +
76)) / NAV_DRAWER_WIDTHS.menu.desktop.expanded +
2 76)) /
: 0, 2
}px)`
: 'translateX(0)',
}} }}
transition={{ transition={{
duration: theme.animation.duration.normal, duration: theme.animation.duration.normal,

View File

@ -92,6 +92,7 @@ type PageHeaderProps = {
onClosePage?: () => void; onClosePage?: () => void;
Icon?: IconComponent; Icon?: IconComponent;
children?: ReactNode; children?: ReactNode;
className?: string;
}; };
export const PageHeader = ({ export const PageHeader = ({
@ -100,6 +101,7 @@ export const PageHeader = ({
onClosePage, onClosePage,
Icon, Icon,
children, children,
className,
}: PageHeaderProps) => { }: PageHeaderProps) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const theme = useTheme(); const theme = useTheme();
@ -108,7 +110,7 @@ export const PageHeader = ({
); );
return ( return (
<StyledTopBarContainer> <StyledTopBarContainer className={className}>
<StyledLeftContainer> <StyledLeftContainer>
{!isMobile && !isNavigationDrawerExpanded && ( {!isMobile && !isNavigationDrawerExpanded && (
<StyledTopBarButtonContainer> <StyledTopBarButtonContainer>