148 cant access note without title from kanban board (#9817)

closes https://github.com/twentyhq/core-team-issues/issues/148

- fixes not openable kanban card when identifier empty
- update card behavior (onClick open recordPage)
- fixes right click actionDropdown position

## Before


https://github.com/user-attachments/assets/696194b8-d7fa-4fc1-a6f9-b46241a262e5

![image](https://github.com/user-attachments/assets/63a5f634-2688-41ba-9ac4-51292ef09b7a)

## After


https://github.com/user-attachments/assets/41e296e5-ae16-47f8-b174-7dd21d74188d

![image](https://github.com/user-attachments/assets/7f859764-946e-40d3-9b66-5460edb215f2)
This commit is contained in:
martmull
2025-01-23 18:05:35 +01:00
committed by GitHub
parent afa2282ea3
commit daa8ff1299
8 changed files with 394 additions and 241 deletions

View File

@ -2,48 +2,29 @@ import { useActionMenu } from '@/action-menu/hooks/useActionMenu';
import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
import {
FieldContext,
RecordUpdateHook,
RecordUpdateHookParams,
} from '@/object-record/record-field/contexts/FieldContext';
import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon';
import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
import { RecordInlineCellEditMode } from '@/object-record/record-inline-cell/components/RecordInlineCellEditMode';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { TextInput } from '@/ui/input/components/TextInput';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { RecordBoardScrollWrapperContext } from '@/ui/utilities/scroll/contexts/ScrollWrapperContexts';
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
import styled from '@emotion/styled';
import { ReactNode, useContext, useState } from 'react';
import { useContext, useState } from 'react';
import { InView, useInView } from 'react-intersection-observer';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import {
AnimatedEaseInOut,
AvatarChipVariant,
Checkbox,
CheckboxVariant,
IconEye,
IconEyeOff,
LightIconButton,
} from 'twenty-ui';
import { useSetRecoilState } from 'recoil';
import { AnimatedEaseInOut } from 'twenty-ui';
import { useDebouncedCallback } from 'use-debounce';
import { useAddNewCard } from '../../record-board-column/hooks/useAddNewCard';
import { RecordBoardCardBody } from '@/object-record/record-board/record-board-card/components/RecordBoardCardBody';
import { RecordBoardCardHeader } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeader';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { AppPath } from '@/types/AppPath';
const StyledBoardCard = styled.div<{ selected: boolean }>`
background-color: ${({ theme, selected }) =>
@ -81,76 +62,11 @@ const StyledBoardCard = styled.div<{ selected: boolean }>`
}
`;
const StyledTextInput = styled(TextInput)`
border-radius: ${({ theme }) => theme.border.radius.sm};
width: ${({ theme }) => theme.spacing(53)};
`;
const StyledBoardCardWrapper = styled.div`
padding-bottom: ${({ theme }) => theme.spacing(2)};
width: 100%;
`;
export const StyledBoardCardHeader = styled.div<{
showCompactView: boolean;
}>`
align-items: center;
display: flex;
flex-direction: row;
font-weight: ${({ theme }) => theme.font.weight.medium};
height: 24px;
padding-bottom: ${({ theme, showCompactView }) =>
theme.spacing(showCompactView ? 2 : 1)};
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
padding-top: ${({ theme }) => theme.spacing(2)};
transition: padding ease-in-out 160ms;
img {
height: ${({ theme }) => theme.icon.size.md}px;
object-fit: cover;
width: ${({ theme }) => theme.icon.size.md}px;
}
`;
export const StyledBoardCardBody = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(0.5)};
padding-bottom: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(2.5)};
padding-right: ${({ theme }) => theme.spacing(2)};
span {
align-items: center;
display: flex;
flex-direction: row;
svg {
color: ${({ theme }) => theme.font.color.tertiary};
margin-right: ${({ theme }) => theme.spacing(2)};
}
}
`;
const StyledCheckboxContainer = styled.div`
display: flex;
flex: 1;
justify-content: end;
`;
const StyledFieldContainer = styled.div`
display: flex;
flex-direction: row;
width: fit-content;
max-width: 100%;
`;
const StyledCompactIconContainer = styled.div`
align-items: center;
display: flex;
justify-content: center;
margin-left: ${({ theme }) => theme.spacing(1)};
`;
export const RecordBoardCard = ({
isCreating = false,
onCreateSuccess,
@ -160,15 +76,10 @@ export const RecordBoardCard = ({
onCreateSuccess?: () => void;
position?: 'first' | 'last';
}) => {
const navigate = useNavigateApp();
const { recordId } = useContext(RecordBoardCardContext);
const [newLabelValue, setNewLabelValue] = useState('');
const { handleBlur, handleInputEnter } = useAddNewCard();
const { updateOneRecord, objectMetadataItem } =
useContext(RecordBoardContext);
const visibleFieldDefinitions = useRecoilComponentValueV2(
recordBoardVisibleFieldDefinitionsComponentSelector,
);
@ -185,16 +96,12 @@ export const RecordBoardCard = ({
recordId,
);
const record = useRecoilValue(recordStoreFamilyState(recordId));
const { indexIdentifierUrl } = useRecordIndexContextOrThrow();
const { objectNameSingular } = useRecordIndexContextOrThrow();
const recordBoardId = useAvailableScopeIdOrThrow(
RecordBoardScopeInternalContext,
);
const { checkIfLastUnselectAndCloseDropdown } =
useRecordBoardSelection(recordBoardId);
const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId);
const actionMenuDropdownId =
@ -221,42 +128,19 @@ export const RecordBoardCard = ({
const handleCardClick = () => {
if (!isCreating) {
setIsCurrentCardSelected(!isCurrentCardSelected);
checkIfLastUnselectAndCloseDropdown();
navigate(AppPath.RecordShowPage, {
objectNameSingular,
objectRecordId: recordId,
});
}
};
const PreventSelectOnClickContainer = ({
children,
}: {
children: ReactNode;
}) => (
<StyledFieldContainer
onClick={(e) => {
e.stopPropagation();
}}
>
{children}
</StyledFieldContainer>
);
const onMouseLeaveBoard = useDebouncedCallback(() => {
if (isCompactModeActive && isCardExpanded) {
setIsCardExpanded(false);
}
}, 800);
const useUpdateOneRecordHook: RecordUpdateHook = () => {
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
updateOneRecord?.({
idToUpdate: variables.where.id as string,
updateOneRecordInput: variables.updateOneRecordInput,
});
};
return [updateEntity, { loading: false }];
};
const scrollWrapperRef = useContext(RecordBoardScrollWrapperContext);
const { ref: cardRef } = useInView({
@ -285,110 +169,23 @@ export const RecordBoardCard = ({
onMouseLeave={onMouseLeaveBoard}
onClick={handleCardClick}
>
<StyledBoardCardHeader showCompactView={isCompactModeActive}>
{isCreating && position !== undefined ? (
<RecordInlineCellEditMode>
<StyledTextInput
autoFocus
value={newLabelValue}
onInputEnter={() =>
handleInputEnter(
labelIdentifierField?.label ?? '',
newLabelValue,
position,
onCreateSuccess,
)
}
onBlur={() =>
handleBlur(
labelIdentifierField?.label ?? '',
newLabelValue,
position,
onCreateSuccess,
)
}
onChange={(text: string) => setNewLabelValue(text)}
placeholder={labelIdentifierField?.label}
/>
</RecordInlineCellEditMode>
) : (
<RecordIdentifierChip
objectNameSingular={objectMetadataItem.nameSingular}
record={record as ObjectRecord}
variant={AvatarChipVariant.Transparent}
maxWidth={150}
to={indexIdentifierUrl(recordId)}
/>
)}
{!isCreating && (
<>
{isCompactModeActive && (
<StyledCompactIconContainer className="compact-icon-container">
<LightIconButton
Icon={isCardExpanded ? IconEyeOff : IconEye}
accent="tertiary"
onClick={(e) => {
e.stopPropagation();
setIsCardExpanded((prev) => !prev);
}}
/>
</StyledCompactIconContainer>
)}
<StyledCheckboxContainer className="checkbox-container">
<Checkbox
hoverable
checked={isCurrentCardSelected}
onChange={() =>
setIsCurrentCardSelected(!isCurrentCardSelected)
}
variant={CheckboxVariant.Secondary}
/>
</StyledCheckboxContainer>
</>
)}
</StyledBoardCardHeader>
{labelIdentifierField && (
<RecordBoardCardHeader
identifierFieldDefinition={labelIdentifierField}
isCreating={isCreating}
onCreateSuccess={onCreateSuccess}
position={position}
isCardExpanded={isCardExpanded}
setIsCardExpanded={setIsCardExpanded}
/>
)}
<AnimatedEaseInOut
isOpen={isCardExpanded || !isCompactModeActive}
initial={false}
>
<StyledBoardCardBody>
{visibleFieldDefinitionsFiltered.map((fieldDefinition) => (
<PreventSelectOnClickContainer
key={fieldDefinition.fieldMetadataId}
>
<FieldContext.Provider
value={{
recordId: isCreating ? '' : recordId,
maxWidth: 156,
recoilScopeId:
(isCreating ? 'new' : recordId) +
fieldDefinition.fieldMetadataId,
isLabelIdentifier: false,
fieldDefinition: {
disableTooltip: false,
fieldMetadataId: fieldDefinition.fieldMetadataId,
label: fieldDefinition.label,
iconName: fieldDefinition.iconName,
type: fieldDefinition.type,
metadata: fieldDefinition.metadata,
defaultValue: fieldDefinition.defaultValue,
editButtonIcon: getFieldButtonIcon({
metadata: fieldDefinition.metadata,
type: fieldDefinition.type,
}),
},
useUpdateRecord: useUpdateOneRecordHook,
hotkeyScope: InlineCellHotkeyScope.InlineCell,
}}
>
<RecordInlineCell />
</FieldContext.Provider>
</PreventSelectOnClickContainer>
))}
</StyledBoardCardBody>
<RecordBoardCardBody
fieldDefinitions={visibleFieldDefinitionsFiltered}
/>
</AnimatedEaseInOut>
</StyledBoardCard>
</InView>

View File

@ -0,0 +1,71 @@
import { RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import {
FieldContext,
RecordUpdateHook,
RecordUpdateHookParams,
} from '@/object-record/record-field/contexts/FieldContext';
import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
import { StopPropagationContainer } from '@/object-record/record-board/record-board-card/components/StopPropagationContainer';
import { useContext } from 'react';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { RecordBoardCardBodyContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardBodyContainer';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
export const RecordBoardCardBody = ({
fieldDefinitions,
}: {
fieldDefinitions: RecordBoardFieldDefinition<FieldMetadata>[];
}) => {
const { recordId } = useContext(RecordBoardCardContext);
const { updateOneRecord } = useContext(RecordBoardContext);
const useUpdateOneRecordHook: RecordUpdateHook = () => {
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
updateOneRecord?.({
idToUpdate: variables.where.id as string,
updateOneRecordInput: variables.updateOneRecordInput,
});
};
return [updateEntity, { loading: false }];
};
return (
<RecordBoardCardBodyContainer>
{fieldDefinitions.map((fieldDefinition) => (
<StopPropagationContainer key={fieldDefinition.fieldMetadataId}>
<FieldContext.Provider
value={{
recordId,
maxWidth: 156,
recoilScopeId:
(recordId || 'new') + fieldDefinition.fieldMetadataId,
isLabelIdentifier: false,
fieldDefinition: {
disableTooltip: false,
fieldMetadataId: fieldDefinition.fieldMetadataId,
label: fieldDefinition.label,
iconName: fieldDefinition.iconName,
type: fieldDefinition.type,
metadata: fieldDefinition.metadata,
defaultValue: fieldDefinition.defaultValue,
editButtonIcon: getFieldButtonIcon({
metadata: fieldDefinition.metadata,
type: fieldDefinition.type,
}),
},
useUpdateRecord: useUpdateOneRecordHook,
hotkeyScope: InlineCellHotkeyScope.InlineCell,
}}
>
<RecordInlineCell />
</FieldContext.Provider>
</StopPropagationContainer>
))}
</RecordBoardCardBodyContainer>
);
};

View File

@ -0,0 +1,21 @@
import styled from '@emotion/styled';
const StyledBoardCardBody = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(0.5)};
padding-bottom: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(2.5)};
padding-right: ${({ theme }) => theme.spacing(2)};
span {
align-items: center;
display: flex;
flex-direction: row;
svg {
color: ${({ theme }) => theme.font.color.tertiary};
margin-right: ${({ theme }) => theme.spacing(2)};
}
}
`;
export { StyledBoardCardBody as RecordBoardCardBodyContainer };

View File

@ -0,0 +1,218 @@
import {
AvatarChipVariant,
Checkbox,
CheckboxVariant,
LightIconButton,
IconEye,
IconEyeOff,
} from 'twenty-ui';
import { RecordBoardCardHeaderContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeaderContainer';
import { RecordInlineCellEditMode } from '@/object-record/record-inline-cell/components/RecordInlineCellEditMode';
import styled from '@emotion/styled';
import { TextInput } from '@/ui/input/components/TextInput';
import { Dispatch, SetStateAction, useContext, useState } from 'react';
import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard';
import { RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import {
FieldContext,
RecordUpdateHook,
RecordUpdateHookParams,
} from '@/object-record/record-field/contexts/FieldContext';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
import { useRecoilValue } from 'recoil';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip';
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
import { StopPropagationContainer } from '@/object-record/record-board/record-board-card/components/StopPropagationContainer';
const StyledTextInput = styled(TextInput)`
border-radius: ${({ theme }) => theme.border.radius.sm};
width: ${({ theme }) => theme.spacing(53)};
`;
const StyledCompactIconContainer = styled.div`
align-items: center;
display: flex;
justify-content: center;
margin-left: ${({ theme }) => theme.spacing(1)};
`;
const StyledCheckboxContainer = styled.div`
margin-left: auto;
`;
type RecordBoardCardHeaderProps = {
isCreating?: boolean;
onCreateSuccess?: () => void;
position?: 'first' | 'last';
identifierFieldDefinition: RecordBoardFieldDefinition<FieldMetadata>;
isCardExpanded?: boolean;
setIsCardExpanded?: Dispatch<SetStateAction<boolean>>;
};
export const RecordBoardCardHeader = ({
isCreating = false,
onCreateSuccess,
position,
identifierFieldDefinition,
isCardExpanded,
setIsCardExpanded,
}: RecordBoardCardHeaderProps) => {
const [newLabelValue, setNewLabelValue] = useState('');
const { handleBlur, handleInputEnter } = useAddNewCard();
const { recordId } = useContext(RecordBoardCardContext);
const { indexIdentifierUrl } = useRecordIndexContextOrThrow();
const record = useRecoilValue(recordStoreFamilyState(recordId));
const { updateOneRecord, objectMetadataItem } =
useContext(RecordBoardContext);
const recordBoardId = useAvailableScopeIdOrThrow(
RecordBoardScopeInternalContext,
);
const showCompactView = useRecoilComponentValueV2(
isRecordBoardCompactModeActiveComponentState,
);
const isIdentifierEmpty =
(record?.[identifierFieldDefinition.metadata.fieldName] || '').trim() ===
'';
const { checkIfLastUnselectAndCloseDropdown } =
useRecordBoardSelection(recordBoardId);
const [isCurrentCardSelected, setIsCurrentCardSelected] =
useRecoilComponentFamilyStateV2(
isRecordBoardCardSelectedComponentFamilyState,
recordId,
);
const useUpdateOneRecordHook: RecordUpdateHook = () => {
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
updateOneRecord?.({
idToUpdate: variables.where.id as string,
updateOneRecordInput: variables.updateOneRecordInput,
});
};
return [updateEntity, { loading: false }];
};
return (
<RecordBoardCardHeaderContainer showCompactView={showCompactView}>
<StopPropagationContainer>
{isCreating && position !== undefined ? (
<RecordInlineCellEditMode>
<StyledTextInput
autoFocus
value={newLabelValue}
onInputEnter={() =>
handleInputEnter(
identifierFieldDefinition.label ?? '',
newLabelValue,
position,
onCreateSuccess,
)
}
onBlur={() =>
handleBlur(
identifierFieldDefinition.label ?? '',
newLabelValue,
position,
onCreateSuccess,
)
}
onChange={(text: string) => setNewLabelValue(text)}
placeholder={identifierFieldDefinition.label}
/>
</RecordInlineCellEditMode>
) : isIdentifierEmpty ? (
<FieldContext.Provider
value={{
recordId: (record as ObjectRecord).id,
maxWidth: 156,
recoilScopeId:
(isCreating ? 'new' : recordId) +
identifierFieldDefinition.fieldMetadataId,
isLabelIdentifier: true,
fieldDefinition: {
disableTooltip: false,
fieldMetadataId: identifierFieldDefinition.fieldMetadataId,
label: `Set ${identifierFieldDefinition.label}`,
iconName: identifierFieldDefinition.iconName,
type: identifierFieldDefinition.type,
metadata: identifierFieldDefinition.metadata,
defaultValue: identifierFieldDefinition.defaultValue,
editButtonIcon: getFieldButtonIcon({
metadata: identifierFieldDefinition.metadata,
type: identifierFieldDefinition.type,
}),
},
useUpdateRecord: useUpdateOneRecordHook,
hotkeyScope: InlineCellHotkeyScope.InlineCell,
}}
>
<RecordInlineCell />
</FieldContext.Provider>
) : (
<RecordIdentifierChip
objectNameSingular={objectMetadataItem.nameSingular}
record={record as ObjectRecord}
variant={AvatarChipVariant.Transparent}
maxWidth={150}
to={indexIdentifierUrl(recordId)}
/>
)}
</StopPropagationContainer>
{!isCreating && (
<>
{showCompactView && (
<StyledCompactIconContainer className="compact-icon-container">
<StopPropagationContainer>
<LightIconButton
Icon={isCardExpanded ? IconEyeOff : IconEye}
accent="tertiary"
onClick={() => {
setIsCardExpanded?.((prev) => !prev);
}}
/>
</StopPropagationContainer>
</StyledCompactIconContainer>
)}
<StyledCheckboxContainer className="checkbox-container">
<StopPropagationContainer>
<Checkbox
hoverable
checked={isCurrentCardSelected}
onChange={() => {
setIsCurrentCardSelected(!isCurrentCardSelected);
checkIfLastUnselectAndCloseDropdown();
}}
variant={CheckboxVariant.Secondary}
/>
</StopPropagationContainer>
</StyledCheckboxContainer>
</>
)}
</RecordBoardCardHeaderContainer>
);
};

View File

@ -0,0 +1,26 @@
import styled from '@emotion/styled';
const StyledBoardCardHeader = styled.div<{
showCompactView: boolean;
}>`
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
font-weight: ${({ theme }) => theme.font.weight.medium};
height: 24px;
padding-bottom: ${({ theme, showCompactView }) =>
theme.spacing(showCompactView ? 2 : 1)};
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
padding-top: ${({ theme }) => theme.spacing(2)};
transition: padding ease-in-out 160ms;
img {
height: ${({ theme }) => theme.icon.size.md}px;
object-fit: cover;
width: ${({ theme }) => theme.icon.size.md}px;
}
`;
export { StyledBoardCardHeader as RecordBoardCardHeaderContainer };

View File

@ -0,0 +1,23 @@
import { ReactNode } from 'react';
import styled from '@emotion/styled';
const StyledFieldContainer = styled.div`
display: flex;
flex-direction: row;
width: fit-content;
max-width: 100%;
`;
export const StopPropagationContainer = ({
children,
}: {
children: ReactNode;
}) => (
<StyledFieldContainer
onClick={(e) => {
e.stopPropagation();
}}
>
{children}
</StyledFieldContainer>
);

View File

@ -3,11 +3,8 @@ import styled from '@emotion/styled';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
import {
StyledBoardCardBody,
StyledBoardCardHeader,
} from '@/object-record/record-board/record-board-card/components/RecordBoardCard';
import { RecordBoardCardBodyContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardBodyContainer';
import { RecordBoardCardHeaderContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeaderContainer';
const StyledSkeletonIconAndText = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
@ -42,18 +39,18 @@ export const RecordBoardColumnCardContainerSkeletonLoader = ({
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
<StyledBoardCardHeader showCompactView={isCompactModeActive}>
<RecordBoardCardHeaderContainer showCompactView={isCompactModeActive}>
<StyledSkeletonTitle>
<Skeleton
width={titleSkeletonWidth}
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
/>
</StyledSkeletonTitle>
</StyledBoardCardHeader>
</RecordBoardCardHeaderContainer>
<StyledSeparator />
{!isCompactModeActive &&
skeletonItems.map(({ id }) => (
<StyledBoardCardBody key={id}>
<RecordBoardCardBodyContainer key={id}>
<StyledSkeletonIconAndText>
<Skeleton
width={16}
@ -64,7 +61,7 @@ export const RecordBoardColumnCardContainerSkeletonLoader = ({
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
/>
</StyledSkeletonIconAndText>
</StyledBoardCardBody>
</RecordBoardCardBodyContainer>
))}
</SkeletonTheme>
);

View File

@ -26,7 +26,7 @@ import { useDropdown } from '../hooks/useDropdown';
const StyledDropdownFallbackAnchor = styled.div`
left: 0;
position: absolute;
position: fixed;
top: 0;
`;