Migrate to twenty-ui - input/button (#7994)
This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-7529](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7529). --- ### Description - Migrated all button components to `twenty-ui` \ \ `Button`\ `ButtonGroup`\ `ColorPickerButton`\ `FloatingButton`\ `FloatingButtonGroup`\ `FloatingIconButton`\ `FloatingIconButtonGroup`\ `IconButton`\ `IconButtonGroup`\ `LightButton`\ `LightIconButton`\ `LightIconButtonGroup`\ `MainButton`\ \ Fixes twentyhq/private-issues#89 Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
committed by
GitHub
parent
60e44ccf73
commit
0a28c15747
@ -3,8 +3,8 @@ import styled from '@emotion/styled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { ChangeEvent, useRef } from 'react';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { AppThemeProvider } from '@/ui/theme/components/AppThemeProvider';
|
||||
import { Button } from 'twenty-ui';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconArrowBackUp, IconUserCircle } from 'twenty-ui';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { Button, IconArrowBackUp, IconUserCircle } from 'twenty-ui';
|
||||
|
||||
const StyledThreadBottomBar = styled.div`
|
||||
align-items: center;
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useState } from 'react';
|
||||
import { IconArrowsVertical } from 'twenty-ui';
|
||||
import { Button, IconArrowsVertical } from 'twenty-ui';
|
||||
|
||||
import { EmailThreadMessage } from '@/activities/emails/components/EmailThreadMessage';
|
||||
import { EmailThreadMessageWithSender } from '@/activities/emails/types/EmailThreadMessageWithSender';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
|
||||
@ -9,12 +9,11 @@ import { EmailThreadMessage } from '@/activities/emails/components/EmailThreadMe
|
||||
import { IntermediaryMessages } from '@/activities/emails/right-drawer/components/IntermediaryMessages';
|
||||
import { useRightDrawerEmailThread } from '@/activities/emails/right-drawer/hooks/useRightDrawerEmailThread';
|
||||
import { emailThreadIdWhenEmailThreadWasClosedState } from '@/activities/emails/states/lastViewableEmailThreadIdState';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID } from '@/ui/layout/right-drawer/constants/RightDrawerClickOutsideListener';
|
||||
import { messageThreadState } from '@/ui/layout/right-drawer/states/messageThreadState';
|
||||
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { IconArrowBackUp } from 'twenty-ui';
|
||||
import { Button, IconArrowBackUp } from 'twenty-ui';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
|
||||
@ -3,9 +3,9 @@ import {
|
||||
IconDownload,
|
||||
IconPencil,
|
||||
IconTrash,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
AnimatedPlaceholderEmptySubTitle,
|
||||
AnimatedPlaceholderEmptyTextContainer,
|
||||
AnimatedPlaceholderEmptyTitle,
|
||||
Button,
|
||||
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
|
||||
IconPlus,
|
||||
} from 'twenty-ui';
|
||||
@ -16,7 +17,6 @@ import { DropZone } from '@/activities/files/components/DropZone';
|
||||
import { useAttachments } from '@/activities/files/hooks/useAttachments';
|
||||
import { useUploadAttachmentFile } from '@/activities/files/hooks/useUploadAttachmentFile';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
const StyledAttachmentsContainer = styled.div`
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
import { NoteList } from '@/activities/notes/components/NoteList';
|
||||
import { useNotes } from '@/activities/notes/hooks/useNotes';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
AnimatedPlaceholder,
|
||||
@ -5,18 +11,11 @@ import {
|
||||
AnimatedPlaceholderEmptySubTitle,
|
||||
AnimatedPlaceholderEmptyTextContainer,
|
||||
AnimatedPlaceholderEmptyTitle,
|
||||
Button,
|
||||
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
|
||||
IconPlus,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
import { NoteList } from '@/activities/notes/components/NoteList';
|
||||
import { useNotes } from '@/activities/notes/hooks/useNotes';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
|
||||
const StyledNotesContainer = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
import { IconPlus } from 'twenty-ui';
|
||||
import { Button, IconPlus } from 'twenty-ui';
|
||||
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
|
||||
export const AddTaskButton = ({
|
||||
activityTargetableObjects,
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
AnimatedPlaceholderEmptySubTitle,
|
||||
AnimatedPlaceholderEmptyTextContainer,
|
||||
AnimatedPlaceholderEmptyTitle,
|
||||
Button,
|
||||
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
|
||||
IconPlus,
|
||||
} from 'twenty-ui';
|
||||
@ -15,11 +16,9 @@ import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateAct
|
||||
import { TASKS_TAB_LIST_COMPONENT_ID } from '@/activities/tasks/constants/TasksTabListComponentId';
|
||||
import { useTasks } from '@/activities/tasks/hooks/useTasks';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
|
||||
|
||||
import { Task } from '@/activities/types/Task';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
|
||||
import groupBy from 'lodash.groupby';
|
||||
import { AddTaskButton } from './AddTaskButton';
|
||||
import { TaskList } from './TaskList';
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { IconCheckbox, IconNotes, IconPaperclip } from 'twenty-ui';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { ButtonGroup } from '@/ui/input/button/components/ButtonGroup';
|
||||
import { TAB_LIST_COMPONENT_ID } from '@/ui/layout/show-page/components/ShowPageSubContainer';
|
||||
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
IconCheckbox,
|
||||
IconNotes,
|
||||
IconPaperclip,
|
||||
} from 'twenty-ui';
|
||||
|
||||
export const TimelineCreateButtonGroup = ({
|
||||
isInRightDrawer = false,
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconChevronDown, IconChevronUp } from 'twenty-ui';
|
||||
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { IconButton, IconChevronDown, IconChevronUp } from 'twenty-ui';
|
||||
|
||||
type EventCardToggleButtonProps = {
|
||||
isOpen: boolean;
|
||||
|
||||
@ -1,12 +1,3 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Controller } from 'react-hook-form';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { ActionLink, IconGoogle, IconKey, IconMicrosoft } from 'twenty-ui';
|
||||
|
||||
import { FooterNote } from '@/auth/sign-in-up/components/FooterNote';
|
||||
import { HorizontalSeparator } from '@/auth/sign-in-up/components/HorizontalSeparator';
|
||||
import { useHandleResetPassword } from '@/auth/sign-in-up/hooks/useHandleResetPassword';
|
||||
@ -19,8 +10,21 @@ import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCapt
|
||||
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
||||
import { captchaProviderState } from '@/client-config/states/captchaProviderState';
|
||||
import { Loader } from '@/ui/feedback/loader/components/Loader';
|
||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Controller } from 'react-hook-form';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import {
|
||||
ActionLink,
|
||||
IconGoogle,
|
||||
IconKey,
|
||||
IconMicrosoft,
|
||||
MainButton,
|
||||
} from 'twenty-ui';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
const StyledContentContainer = styled.div`
|
||||
|
||||
@ -16,7 +16,6 @@ import { getCompanyDomainName } from '@/object-metadata/utils/getCompanyDomainNa
|
||||
import { useSearchRecords } from '@/object-record/hooks/useSearchRecords';
|
||||
import { Opportunity } from '@/opportunities/types/Opportunity';
|
||||
import { Person } from '@/people/types/Person';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
|
||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
@ -30,7 +29,14 @@ import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useMemo, useRef } from 'react';
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { Avatar, IconNotes, IconSparkles, IconX, isDefined } from 'twenty-ui';
|
||||
import {
|
||||
Avatar,
|
||||
IconNotes,
|
||||
IconSparkles,
|
||||
IconX,
|
||||
LightIconButton,
|
||||
isDefined,
|
||||
} from 'twenty-ui';
|
||||
import { useDebounce } from 'use-debounce';
|
||||
import { getLogoUrlFromDomainName } from '~/utils';
|
||||
|
||||
|
||||
@ -9,11 +9,10 @@ import {
|
||||
AnimatedPlaceholderEmptySubTitle,
|
||||
AnimatedPlaceholderEmptyTextContainer,
|
||||
AnimatedPlaceholderEmptyTitle,
|
||||
Button,
|
||||
IconRefresh,
|
||||
THEME_LIGHT,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
type GenericErrorFallbackProps = FallbackProps;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import styled from '@emotion/styled';
|
||||
import { Banner, BannerVariant, IconComponent } from 'twenty-ui';
|
||||
import { Banner, BannerVariant, Button, IconComponent } from 'twenty-ui';
|
||||
|
||||
const StyledBanner = styled(Banner)`
|
||||
position: absolute;
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { IconX } from 'twenty-ui';
|
||||
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { IconButton, IconX } from 'twenty-ui';
|
||||
|
||||
import {
|
||||
StyledContainer,
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { IconPlus } from 'twenty-ui';
|
||||
import { IconPlus, LightButton } from 'twenty-ui';
|
||||
|
||||
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
import { LightButton } from '@/ui/input/button/components/LightButton';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
type AddObjectFilterFromDetailsButtonProps = {
|
||||
|
||||
@ -17,7 +17,6 @@ import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/
|
||||
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 { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Checkbox, CheckboxVariant } from '@/ui/input/components/Checkbox';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
@ -33,6 +32,7 @@ import {
|
||||
ChipSize,
|
||||
IconEye,
|
||||
IconEyeOff,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { useAddNewCard } from '../../record-board-column/hooks/useAddNewCard';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext, useState } from 'react';
|
||||
import { IconDotsVertical, IconPlus, Tag } from 'twenty-ui';
|
||||
import { IconDotsVertical, IconPlus, LightIconButton, Tag } from 'twenty-ui';
|
||||
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
|
||||
@ -12,7 +12,6 @@ import { useIsOpportunitiesCompanyFieldDisabled } from '@/object-record/record-b
|
||||
import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope';
|
||||
import { RecordBoardColumnDefinitionType } from '@/object-record/record-board/types/RecordBoardColumnDefinition';
|
||||
import { SingleEntitySelect } from '@/object-record/relation-picker/components/SingleEntitySelect';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
|
||||
const StyledHeader = styled.div`
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconCopy } from 'twenty-ui';
|
||||
import { IconCopy, LightIconButton } from 'twenty-ui';
|
||||
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
padding: 0 ${({ theme }) => theme.spacing(1)};
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { IconCheck, IconPlus } from 'twenty-ui';
|
||||
import { IconCheck, IconPlus, LightIconButton } from 'twenty-ui';
|
||||
|
||||
import { PhoneRecord } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import {
|
||||
DropdownMenuInput,
|
||||
|
||||
@ -7,7 +7,6 @@ import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/
|
||||
import { RecordIndexPageKanbanAddMenuItem } from '@/object-record/record-index/components/RecordIndexPageKanbanAddMenuItem';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
@ -15,7 +14,7 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import styled from '@emotion/styled';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconPlus } from 'twenty-ui';
|
||||
import { IconButton, IconPlus } from 'twenty-ui';
|
||||
|
||||
const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
||||
width: 100%;
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { AnimatedContainer, IconComponent } from 'twenty-ui';
|
||||
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
import {
|
||||
AnimatedContainer,
|
||||
FloatingIconButton,
|
||||
IconComponent,
|
||||
} from 'twenty-ui';
|
||||
|
||||
const StyledInlineCellButtonContainer = styled.div`
|
||||
align-items: center;
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
IconDotsVertical,
|
||||
IconTrash,
|
||||
IconUnlink,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
@ -33,7 +34,6 @@ import { RecordDetailRecordsListItem } from '@/object-record/record-show/record-
|
||||
import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isFieldCellSupported } from '@/object-record/utils/isFieldCellSupported';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
@ -2,7 +2,7 @@ import styled from '@emotion/styled';
|
||||
import qs from 'qs';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconForbid, IconPencil, IconPlus } from 'twenty-ui';
|
||||
import { IconForbid, IconPencil, IconPlus, LightIconButton } from 'twenty-ui';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
@ -26,7 +26,6 @@ import { EntityForSelect } from '@/object-record/relation-picker/types/EntityFor
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { isObjectMetadataReadOnly } from '@/object-metadata/utils/isObjectMetadataReadOnly';
|
||||
import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { useContext } from 'react';
|
||||
import {
|
||||
AnimatedPlaceholder,
|
||||
@ -9,6 +8,7 @@ import {
|
||||
AnimatedPlaceholderEmptyTextContainer,
|
||||
AnimatedPlaceholderEmptyTitle,
|
||||
AnimatedPlaceholderType,
|
||||
Button,
|
||||
IconComponent,
|
||||
} from 'twenty-ui';
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { AnimatedContainer, IconComponent } from 'twenty-ui';
|
||||
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
import {
|
||||
AnimatedContainer,
|
||||
FloatingIconButton,
|
||||
IconComponent,
|
||||
} from 'twenty-ui';
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
margin: ${({ theme }) => theme.spacing(1)};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { IconPlus } from 'twenty-ui';
|
||||
import { IconPlus, LightIconButton } from 'twenty-ui';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { isObjectMetadataReadOnly } from '@/object-metadata/utils/isObjectMetadataReadOnly';
|
||||
@ -12,7 +12,6 @@ import { useTableColumns } from '@/object-record/record-table/hooks/useTableColu
|
||||
import { RecordTableColumnHeadWithDropdown } from '@/object-record/record-table/record-table-header/components/RecordTableColumnHeadWithDropdown';
|
||||
import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import styled from '@emotion/styled';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Button } from 'twenty-ui';
|
||||
import { isDomain } from '~/utils/is-domain';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import { IconX, OverflowingTextWithTooltip } from 'twenty-ui';
|
||||
|
||||
import { BlocklistItem } from '@/accounts/types/BlocklistItem';
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { IconButton, IconX, OverflowingTextWithTooltip } from 'twenty-ui';
|
||||
import { formatToHumanReadableDate } from '~/utils/date-utils';
|
||||
|
||||
type SettingsAccountsBlocklistTableRowProps = {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconGoogle } from 'twenty-ui';
|
||||
import { Button, IconGoogle } from 'twenty-ui';
|
||||
|
||||
import { useTriggerGoogleApisOAuth } from '@/settings/accounts/hooks/useTriggerGoogleApisOAuth';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { CardHeader } from '@/ui/layout/card/components/CardHeader';
|
||||
|
||||
@ -5,13 +5,13 @@ import {
|
||||
IconMail,
|
||||
IconRefresh,
|
||||
IconTrash,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useDestroyOneRecord } from '@/object-record/hooks/useDestroyOneRecord';
|
||||
import { useTriggerGoogleApisOAuth } from '@/settings/accounts/hooks/useTriggerGoogleApisOAuth';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { LightButton } from '@/ui/input/button/components/LightButton';
|
||||
import { LightButton } from 'twenty-ui';
|
||||
|
||||
type CancelButtonProps = {
|
||||
onCancel?: () => void;
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { IconDeviceFloppy } from 'twenty-ui';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { Button, IconDeviceFloppy } from 'twenty-ui';
|
||||
|
||||
type SaveButtonProps = {
|
||||
onSave?: () => void;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
@ -13,7 +12,7 @@ import {
|
||||
useParams,
|
||||
useSearchParams,
|
||||
} from 'react-router-dom';
|
||||
import { IconChevronDown, isDefined } from 'twenty-ui';
|
||||
import { Button, IconChevronDown, isDefined } from 'twenty-ui';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
align-items: center;
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { IconInfoCircle, IconMinus, IconPlus } from 'twenty-ui';
|
||||
import { Button, IconInfoCircle, IconMinus, IconPlus } from 'twenty-ui';
|
||||
import { castAsNumberOrNull } from '~/utils/cast-as-number-or-null';
|
||||
|
||||
type SettingsDataModelFieldNumberDecimalsInputProps = {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { DropResult } from '@hello-pangea/dnd';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { IconPlus, IconTool, MAIN_COLORS } from 'twenty-ui';
|
||||
import { IconPlus, IconTool, LightButton, MAIN_COLORS } from 'twenty-ui';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
@ -14,7 +14,6 @@ import { selectFieldDefaultValueSchema } from '@/object-record/record-field/vali
|
||||
import { useSelectSettingsFormInitialValues } from '@/settings/data-model/fields/forms/select/hooks/useSelectSettingsFormInitialValues';
|
||||
import { generateNewSelectOption } from '@/settings/data-model/fields/forms/select/utils/generateNewSelectOption';
|
||||
import { isSelectOptionDefaultValue } from '@/settings/data-model/utils/isSelectOptionDefaultValue';
|
||||
import { LightButton } from '@/ui/input/button/components/LightButton';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { CardFooter } from '@/ui/layout/card/components/CardFooter';
|
||||
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
IconGripVertical,
|
||||
IconTrash,
|
||||
IconX,
|
||||
LightIconButton,
|
||||
MAIN_COLOR_NAMES,
|
||||
} from 'twenty-ui';
|
||||
import { v4 } from 'uuid';
|
||||
@ -16,7 +17,6 @@ import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataIt
|
||||
import { EXPANDED_WIDTH_ANIMATION_VARIANTS } from '@/settings/constants/ExpandedWidthAnimationVariants';
|
||||
import { OPTION_VALUE_MAXIMUM_LENGTH } from '@/settings/data-model/constants/OptionValueMaximumLength';
|
||||
import { getOptionValueFromLabel } from '@/settings/data-model/fields/forms/select/utils/getOptionValueFromLabel';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
import { SettingsDataModelOverviewEffect } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect';
|
||||
import { SettingsDataModelOverviewObject } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewObject';
|
||||
import { SettingsDataModelOverviewRelationMarkers } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewRelationMarkers';
|
||||
import { calculateHandlePosition } from '@/settings/data-model/graph-overview/utils/calculateHandlePosition';
|
||||
import styled from '@emotion/styled';
|
||||
import { useCallback, useState } from 'react';
|
||||
import ReactFlow, {
|
||||
@ -13,6 +17,8 @@ import ReactFlow, {
|
||||
useReactFlow,
|
||||
} from 'reactflow';
|
||||
import {
|
||||
Button,
|
||||
IconButtonGroup,
|
||||
IconLock,
|
||||
IconLockOpen,
|
||||
IconMaximize,
|
||||
@ -20,17 +26,8 @@ import {
|
||||
IconPlus,
|
||||
IconX,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { SettingsDataModelOverviewEffect } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect';
|
||||
import { SettingsDataModelOverviewObject } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewObject';
|
||||
import { SettingsDataModelOverviewRelationMarkers } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverviewRelationMarkers';
|
||||
import { calculateHandlePosition } from '@/settings/data-model/graph-overview/utils/calculateHandlePosition';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { IconButtonGroup } from '@/ui/input/button/components/IconButtonGroup';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import 'reactflow/dist/style.css';
|
||||
|
||||
const NodeTypes = {
|
||||
object: SettingsDataModelOverviewObject,
|
||||
};
|
||||
|
||||
@ -4,9 +4,9 @@ import {
|
||||
IconEye,
|
||||
IconPencil,
|
||||
IconTextSize,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
@ -4,9 +4,9 @@ import {
|
||||
IconEye,
|
||||
IconPencil,
|
||||
IconTrash,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
@ -1,22 +1,11 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useMemo } from 'react';
|
||||
import { IconMinus, IconPlus, isDefined, useIcons } from 'twenty-ui';
|
||||
|
||||
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
|
||||
import { isFieldTypeSupportedInSettings } from '@/settings/data-model/utils/isFieldTypeSupportedInSettings';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
|
||||
import { RELATION_TYPES } from '../../constants/RelationTypes';
|
||||
|
||||
import { LABEL_IDENTIFIER_FIELD_METADATA_TYPES } from '@/object-metadata/constants/LabelIdentifierFieldMetadataTypes';
|
||||
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
|
||||
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
|
||||
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getFieldSlug } from '@/object-metadata/utils/getFieldSlug';
|
||||
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
|
||||
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
|
||||
import { useDeleteRecordFromCache } from '@/object-record/cache/hooks/useDeleteRecordFromCache';
|
||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||
@ -24,13 +13,26 @@ import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { SettingsObjectFieldActiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldActiveActionDropdown';
|
||||
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
|
||||
import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { isFieldTypeSupportedInSettings } from '@/settings/data-model/utils/isFieldTypeSupportedInSettings';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import {
|
||||
IconMinus,
|
||||
IconPlus,
|
||||
LightIconButton,
|
||||
isDefined,
|
||||
useIcons,
|
||||
} from 'twenty-ui';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import { SettingsObjectDetailTableItem } from '~/pages/settings/data-model/types/SettingsObjectDetailTableItem';
|
||||
import { RELATION_TYPES } from '../../constants/RelationTypes';
|
||||
import { SettingsObjectFieldDataType } from './SettingsObjectFieldDataType';
|
||||
|
||||
type SettingsObjectFieldItemTableRowProps = {
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconArchive, IconDotsVertical, IconPencil, useIcons } from 'twenty-ui';
|
||||
import {
|
||||
IconArchive,
|
||||
IconDotsVertical,
|
||||
IconPencil,
|
||||
LightIconButton,
|
||||
useIcons,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem';
|
||||
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
|
||||
@ -8,7 +14,6 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard';
|
||||
import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/components/SettingsDataModelObjectTypeTag';
|
||||
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconEye } from 'twenty-ui';
|
||||
import { FloatingButton, IconEye } from 'twenty-ui';
|
||||
|
||||
import { FloatingButton } from '@/ui/input/button/components/FloatingButton';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
import { IconArchiveOff, IconDotsVertical, IconTrash } from 'twenty-ui';
|
||||
import {
|
||||
IconArchiveOff,
|
||||
IconDotsVertical,
|
||||
IconTrash,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconCopy } from 'twenty-ui';
|
||||
import { Button, IconCopy } from 'twenty-ui';
|
||||
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { IconBook2 } from 'twenty-ui';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { Button, IconBook2 } from 'twenty-ui';
|
||||
|
||||
export const SettingsReadDocumentationButton = () => {
|
||||
return (
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconArrowUpRight, IconBolt, IconPlus, Pill } from 'twenty-ui';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button, IconArrowUpRight, IconBolt, IconPlus, Pill } from 'twenty-ui';
|
||||
|
||||
import { SettingsIntegration } from '@/settings/integrations/types/SettingsIntegration';
|
||||
import { Status } from '@/ui/display/status/components/Status';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
interface SettingsIntegrationComponentProps {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { FetchResult } from '@apollo/client';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconReload } from 'twenty-ui';
|
||||
import { Button, IconReload } from 'twenty-ui';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { SyncRemoteTableSchemaChangesMutation } from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledText = styled.h3`
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard';
|
||||
import { SettingsIntegrationDatabaseConnectionSyncStatus } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionSyncStatus';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
IconDotsVertical,
|
||||
IconPencil,
|
||||
IconTrash,
|
||||
LightIconButton,
|
||||
UndecoratedLink,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard';
|
||||
import { SettingsIntegrationDatabaseConnectionSyncStatus } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionSyncStatus';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
|
||||
type SettingsIntegrationDatabaseConnectionSummaryCardProps = {
|
||||
databaseLogoUrl: string;
|
||||
connectionId: string;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconChevronRight } from 'twenty-ui';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { IconChevronRight, LightIconButton } from 'twenty-ui';
|
||||
|
||||
import { SettingsListCard } from '@/settings/components/SettingsListCard';
|
||||
import { SettingsIntegrationDatabaseConnectionSyncStatus } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionSyncStatus';
|
||||
import { SettingsIntegration } from '@/settings/integrations/types/SettingsIntegration';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { RemoteServer } from '~/generated-metadata/graphql';
|
||||
|
||||
type SettingsIntegrationDatabaseConnectionsListCardProps = {
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { H2Title } from 'twenty-ui';
|
||||
import { Button, H2Title } from 'twenty-ui';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { useEmailPasswordResetLinkMutation } from '~/generated/graphql';
|
||||
|
||||
export const ChangePassword = () => {
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { H2Title } from 'twenty-ui';
|
||||
import { Button, H2Title } from 'twenty-ui';
|
||||
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useDeleteUserAccountMutation } from '~/generated/graphql';
|
||||
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import { useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { H2Title, IconTrash } from 'twenty-ui';
|
||||
import { Button, H2Title, IconTrash } from 'twenty-ui';
|
||||
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useDeleteCurrentWorkspaceMutation } from '~/generated/graphql';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
export const DeleteWorkspace = () => {
|
||||
const [isDeleteWorkSpaceModalOpen, setIsDeleteWorkSpaceModalOpen] =
|
||||
useState(false);
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { CardHeader } from '@/ui/layout/card/components/CardHeader';
|
||||
import { IconKey } from 'twenty-ui';
|
||||
import styled from '@emotion/styled';
|
||||
import { Button, IconKey } from 'twenty-ui';
|
||||
|
||||
const StyledHeader = styled(CardHeader)`
|
||||
align-items: center;
|
||||
|
||||
@ -2,13 +2,12 @@
|
||||
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { H2Title, IconCopy } from 'twenty-ui';
|
||||
import { Button, H2Title, IconCopy } from 'twenty-ui';
|
||||
|
||||
const StyledInputsContainer = styled.div`
|
||||
display: flex;
|
||||
|
||||
@ -4,7 +4,6 @@ import { HorizontalSeparator } from '@/auth/sign-in-up/components/HorizontalSepa
|
||||
import { parseSAMLMetadataFromXMLFile } from '@/settings/security/utils/parseSAMLMetadataFromXMLFile';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { useTheme } from '@emotion/react';
|
||||
@ -12,6 +11,7 @@ import styled from '@emotion/styled';
|
||||
import { ChangeEvent, useRef } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import {
|
||||
Button,
|
||||
H2Title,
|
||||
IconCheck,
|
||||
IconCopy,
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
/* @license Enterprise */
|
||||
|
||||
import { IconArchive, IconDotsVertical, IconTrash } from 'twenty-ui';
|
||||
import {
|
||||
IconArchive,
|
||||
IconDotsVertical,
|
||||
IconTrash,
|
||||
LightIconButton,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { useDeleteSSOIdentityProvider } from '@/settings/security/hooks/useDeleteSSOIdentityProvider';
|
||||
import { useUpdateSSOIdentityProvider } from '@/settings/security/hooks/useUpdateSSOIdentityProvider';
|
||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
AnimatedPlaceholder,
|
||||
@ -8,6 +7,7 @@ import {
|
||||
AnimatedPlaceholderEmptySubTitle,
|
||||
AnimatedPlaceholderEmptyTextContainer,
|
||||
AnimatedPlaceholderEmptyTitle,
|
||||
Button,
|
||||
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
|
||||
IconPlus,
|
||||
} from 'twenty-ui';
|
||||
|
||||
@ -6,7 +6,6 @@ import { SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/settings/s
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { CoreEditorHeader } from '@/ui/input/code-editor/components/CodeEditorHeader';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { TabList } from '@/ui/layout/tab/components/TabList';
|
||||
@ -16,7 +15,13 @@ import styled from '@emotion/styled';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { H2Title, IconGitCommit, IconPlayerPlay, IconRestore } from 'twenty-ui';
|
||||
import {
|
||||
Button,
|
||||
H2Title,
|
||||
IconGitCommit,
|
||||
IconPlayerPlay,
|
||||
IconRestore,
|
||||
} from 'twenty-ui';
|
||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
||||
|
||||
const StyledTabList = styled(TabList)`
|
||||
|
||||
@ -4,14 +4,13 @@ import { ServerlessFunctionFormValues } from '@/settings/serverless-functions/ho
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { H2Title } from 'twenty-ui';
|
||||
import { Button, H2Title } from 'twenty-ui';
|
||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
||||
import { SettingsServerlessFunctionTabEnvironmentVariablesSection } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariablesSection';
|
||||
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { EnvironmentVariable } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariablesSection';
|
||||
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import styled from '@emotion/styled';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
IconCheck,
|
||||
IconDotsVertical,
|
||||
IconPencil,
|
||||
IconTrash,
|
||||
IconX,
|
||||
LightIconButton,
|
||||
OverflowingTextWithTooltip,
|
||||
} from 'twenty-ui';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import React, { useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { EnvironmentVariable } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariablesSection';
|
||||
|
||||
const StyledEditModeTableRow = styled(TableRow)`
|
||||
grid-template-columns: 180px auto 56px;
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
import dotenv from 'dotenv';
|
||||
import { H2Title, IconPlus, IconSearch, MOBILE_VIEWPORT } from 'twenty-ui';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import styled from '@emotion/styled';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { ServerlessFunctionFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { SettingsServerlessFunctionTabEnvironmentVariableTableRow } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariableTableRow';
|
||||
import { ServerlessFunctionFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import styled from '@emotion/styled';
|
||||
import dotenv from 'dotenv';
|
||||
import { useMemo, useState } from 'react';
|
||||
import {
|
||||
Button,
|
||||
H2Title,
|
||||
IconPlus,
|
||||
IconSearch,
|
||||
MOBILE_VIEWPORT,
|
||||
} from 'twenty-ui';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
const StyledSearchInput = styled(TextInput)`
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { H2Title, IconPlayerPlay } from 'twenty-ui';
|
||||
import { Button, H2Title, IconPlayerPlay } from 'twenty-ui';
|
||||
|
||||
import { LightCopyIconButton } from '@/object-record/record-field/components/LightCopyIconButton';
|
||||
import { SettingsServerlessFunctionCodeEditorContainer } from '@/settings/serverless-functions/components/SettingsServerlessFunctionCodeEditorContainer';
|
||||
@ -10,7 +10,6 @@ import { settingsServerlessFunctionOutputState } from '@/settings/serverless-fun
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { CodeEditor } from '@/ui/input/code-editor/components/CodeEditor';
|
||||
import { CoreEditorHeader } from '@/ui/input/code-editor/components/CodeEditorHeader';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconX } from 'twenty-ui';
|
||||
import { IconButton, IconX } from 'twenty-ui';
|
||||
|
||||
import { useSpreadsheetImportInitialStep } from '@/spreadsheet-import/hooks/useSpreadsheetImportInitialStep';
|
||||
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
|
||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import { useStepBar } from '@/ui/navigation/step-bar/hooks/useStepBar';
|
||||
|
||||
const StyledCloseButtonContainer = styled.div`
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { CircularProgressBar } from '@/ui/feedback/progress-bar/components/CircularProgressBar';
|
||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||
import { MainButton } from 'twenty-ui';
|
||||
|
||||
import { Modal } from '@/ui/layout/modal/components/Modal';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
@ -7,7 +7,7 @@ import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpre
|
||||
import { readFileAsync } from '@/spreadsheet-import/utils/readFilesAsync';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||
import { MainButton } from 'twenty-ui';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
align-items: center;
|
||||
|
||||
@ -1,3 +1,20 @@
|
||||
import { Heading } from '@/spreadsheet-import/components/Heading';
|
||||
import { SpreadsheetImportTable } from '@/spreadsheet-import/components/SpreadsheetImportTable';
|
||||
import { StepNavigationButton } from '@/spreadsheet-import/components/StepNavigationButton';
|
||||
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
|
||||
import {
|
||||
ColumnType,
|
||||
Columns,
|
||||
} from '@/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep';
|
||||
import { SpreadsheetImportStep } from '@/spreadsheet-import/steps/types/SpreadsheetImportStep';
|
||||
import { SpreadsheetImportStepType } from '@/spreadsheet-import/steps/types/SpreadsheetImportStepType';
|
||||
import {
|
||||
ImportValidationResult,
|
||||
ImportedStructuredRow,
|
||||
} from '@/spreadsheet-import/types';
|
||||
import { addErrorsAndRunHooks } from '@/spreadsheet-import/utils/dataMutations';
|
||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||
import { Modal } from '@/ui/layout/modal/components/Modal';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
Dispatch,
|
||||
@ -8,28 +25,8 @@ import {
|
||||
} from 'react';
|
||||
// @ts-expect-error Todo: remove usage of react-data-grid`
|
||||
import { RowsChangeData } from 'react-data-grid';
|
||||
import { IconTrash, Toggle } from 'twenty-ui';
|
||||
|
||||
import { Heading } from '@/spreadsheet-import/components/Heading';
|
||||
import { SpreadsheetImportTable } from '@/spreadsheet-import/components/SpreadsheetImportTable';
|
||||
import { StepNavigationButton } from '@/spreadsheet-import/components/StepNavigationButton';
|
||||
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
|
||||
import {
|
||||
Columns,
|
||||
ColumnType,
|
||||
} from '@/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep';
|
||||
import {
|
||||
ImportedStructuredRow,
|
||||
ImportValidationResult,
|
||||
} from '@/spreadsheet-import/types';
|
||||
import { addErrorsAndRunHooks } from '@/spreadsheet-import/utils/dataMutations';
|
||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { Button, IconTrash, Toggle } from 'twenty-ui';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { SpreadsheetImportStep } from '@/spreadsheet-import/steps/types/SpreadsheetImportStep';
|
||||
import { SpreadsheetImportStepType } from '@/spreadsheet-import/steps/types/SpreadsheetImportStepType';
|
||||
import { Modal } from '@/ui/layout/modal/components/Modal';
|
||||
import { generateColumns } from './components/columns';
|
||||
import { ImportedStructuredRowMetadata } from './types';
|
||||
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconHelpCircle } from 'twenty-ui';
|
||||
import { Button, IconHelpCircle } from 'twenty-ui';
|
||||
|
||||
import { SupportButtonSkeletonLoader } from '@/support/components/SupportButtonSkeletonLoader';
|
||||
import { useSupportChat } from '@/support/hooks/useSupportChat';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
display: flex;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconInfoCircle } from 'twenty-ui';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button, IconInfoCircle } from 'twenty-ui';
|
||||
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
|
||||
export type InfoAccent = 'blue' | 'danger';
|
||||
export type InfoProps = {
|
||||
|
||||
@ -3,8 +3,8 @@ import { motion } from 'framer-motion';
|
||||
import { useCallback } from 'react';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { Button } from 'twenty-ui';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { DialogHotkeyScope } from '../types/DialogHotkeyScope';
|
||||
|
||||
@ -7,13 +7,13 @@ import {
|
||||
IconInfoCircle,
|
||||
IconSquareRoundedCheck,
|
||||
IconX,
|
||||
LightButton,
|
||||
LightIconButton,
|
||||
MOBILE_VIEWPORT,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { ProgressBar } from '@/ui/feedback/progress-bar/components/ProgressBar';
|
||||
import { useProgressAnimation } from '@/ui/feedback/progress-bar/hooks/useProgressAnimation';
|
||||
import { LightButton } from '@/ui/input/button/components/LightButton';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export enum SnackBarVariant {
|
||||
|
||||
@ -1,406 +0,0 @@
|
||||
import isPropValid from '@emotion/is-prop-valid';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { IconComponent, Pill } from 'twenty-ui';
|
||||
|
||||
export type ButtonSize = 'medium' | 'small';
|
||||
export type ButtonPosition = 'standalone' | 'left' | 'middle' | 'right';
|
||||
export type ButtonVariant = 'primary' | 'secondary' | 'tertiary';
|
||||
export type ButtonAccent = 'default' | 'blue' | 'danger';
|
||||
|
||||
export type ButtonProps = {
|
||||
className?: string;
|
||||
Icon?: IconComponent;
|
||||
title?: string;
|
||||
fullWidth?: boolean;
|
||||
variant?: ButtonVariant;
|
||||
inverted?: boolean;
|
||||
size?: ButtonSize;
|
||||
position?: ButtonPosition;
|
||||
accent?: ButtonAccent;
|
||||
soon?: boolean;
|
||||
justify?: 'center' | 'flex-start' | 'flex-end';
|
||||
disabled?: boolean;
|
||||
focus?: boolean;
|
||||
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
to?: string;
|
||||
target?: string;
|
||||
dataTestId?: string;
|
||||
} & React.ComponentProps<'button'>;
|
||||
|
||||
const StyledButton = styled('button', {
|
||||
shouldForwardProp: (prop) =>
|
||||
!['fullWidth'].includes(prop) && isPropValid(prop),
|
||||
})<
|
||||
Pick<
|
||||
ButtonProps,
|
||||
| 'fullWidth'
|
||||
| 'variant'
|
||||
| 'inverted'
|
||||
| 'size'
|
||||
| 'position'
|
||||
| 'accent'
|
||||
| 'focus'
|
||||
| 'justify'
|
||||
| 'to'
|
||||
| 'target'
|
||||
>
|
||||
>`
|
||||
align-items: center;
|
||||
${({ theme, variant, inverted, accent, disabled, focus }) => {
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
switch (accent) {
|
||||
case 'default':
|
||||
return css`
|
||||
background: ${!inverted
|
||||
? theme.background.secondary
|
||||
: theme.background.primary};
|
||||
border-color: ${!inverted
|
||||
? focus
|
||||
? theme.color.blue
|
||||
: theme.background.transparent.light
|
||||
: theme.background.transparent.light};
|
||||
border-width: 1px 1px 1px 1px !important;
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${
|
||||
!inverted
|
||||
? theme.accent.tertiary
|
||||
: theme.background.transparent.medium
|
||||
}`
|
||||
: 'none'};
|
||||
color: ${!inverted
|
||||
? !disabled
|
||||
? theme.font.color.secondary
|
||||
: theme.font.color.extraLight
|
||||
: theme.font.color.secondary};
|
||||
&:hover {
|
||||
background: ${!inverted
|
||||
? theme.background.tertiary
|
||||
: theme.background.secondary};
|
||||
}
|
||||
&:active {
|
||||
background: ${!inverted
|
||||
? theme.background.quaternary
|
||||
: theme.background.tertiary};
|
||||
}
|
||||
`;
|
||||
case 'blue':
|
||||
return css`
|
||||
background: ${!inverted
|
||||
? theme.color.blue
|
||||
: theme.background.primary};
|
||||
border-color: ${!inverted
|
||||
? focus
|
||||
? theme.color.blue
|
||||
: theme.background.transparent.light
|
||||
: theme.background.transparent.light};
|
||||
border-width: 1px 1px 1px 1px !important;
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${
|
||||
!inverted
|
||||
? theme.accent.tertiary
|
||||
: theme.background.transparent.medium
|
||||
}`
|
||||
: 'none'};
|
||||
color: ${!inverted ? theme.grayScale.gray0 : theme.color.blue};
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
${disabled
|
||||
? ''
|
||||
: css`
|
||||
&:hover {
|
||||
background: ${!inverted
|
||||
? theme.color.blue50
|
||||
: theme.background.secondary};
|
||||
}
|
||||
&:active {
|
||||
background: ${!inverted
|
||||
? theme.color.blue60
|
||||
: theme.background.tertiary};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
case 'danger':
|
||||
return css`
|
||||
background: ${!inverted
|
||||
? theme.color.red
|
||||
: theme.background.primary};
|
||||
border-color: ${!inverted
|
||||
? focus
|
||||
? theme.color.red
|
||||
: theme.background.transparent.light
|
||||
: theme.background.transparent.light};
|
||||
border-width: 1px 1px !important;
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${
|
||||
!inverted
|
||||
? theme.color.red10
|
||||
: theme.background.transparent.medium
|
||||
}`
|
||||
: 'none'};
|
||||
color: ${!inverted ? theme.background.primary : theme.color.red};
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
${disabled
|
||||
? ''
|
||||
: css`
|
||||
&:hover {
|
||||
background: ${!inverted
|
||||
? theme.color.red40
|
||||
: theme.background.secondary};
|
||||
}
|
||||
&:active {
|
||||
background: ${!inverted
|
||||
? theme.color.red50
|
||||
: theme.background.tertiary};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
}
|
||||
break;
|
||||
case 'secondary':
|
||||
case 'tertiary':
|
||||
switch (accent) {
|
||||
case 'default':
|
||||
return css`
|
||||
background: transparent;
|
||||
border-color: ${!inverted
|
||||
? variant === 'secondary'
|
||||
? !disabled && focus
|
||||
? theme.color.blue
|
||||
: theme.background.transparent.medium
|
||||
: focus
|
||||
? theme.color.blue
|
||||
: 'transparent'
|
||||
: variant === 'secondary'
|
||||
? focus || disabled
|
||||
? theme.grayScale.gray0
|
||||
: theme.background.transparent.primary
|
||||
: focus
|
||||
? theme.grayScale.gray0
|
||||
: 'transparent'};
|
||||
border-width: 1px 1px 1px 1px !important;
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${
|
||||
!inverted
|
||||
? theme.accent.tertiary
|
||||
: theme.background.transparent.medium
|
||||
}`
|
||||
: 'none'};
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
color: ${!inverted
|
||||
? !disabled
|
||||
? theme.font.color.secondary
|
||||
: theme.font.color.extraLight
|
||||
: theme.font.color.inverted};
|
||||
&:hover {
|
||||
background: ${!inverted
|
||||
? !disabled
|
||||
? theme.background.transparent.light
|
||||
: 'transparent'
|
||||
: theme.background.transparent.light};
|
||||
}
|
||||
&:active {
|
||||
background: ${!inverted
|
||||
? !disabled
|
||||
? theme.background.transparent.light
|
||||
: 'transparent'
|
||||
: theme.background.transparent.medium};
|
||||
}
|
||||
`;
|
||||
case 'blue':
|
||||
return css`
|
||||
background: transparent;
|
||||
border-color: ${!inverted
|
||||
? variant === 'secondary'
|
||||
? focus
|
||||
? theme.color.blue
|
||||
: theme.accent.primary
|
||||
: focus
|
||||
? theme.color.blue
|
||||
: 'transparent'
|
||||
: variant === 'secondary'
|
||||
? focus || disabled
|
||||
? theme.grayScale.gray0
|
||||
: theme.background.transparent.primary
|
||||
: focus
|
||||
? theme.grayScale.gray0
|
||||
: 'transparent'};
|
||||
border-width: 1px 1px 1px 1px !important;
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${
|
||||
!inverted
|
||||
? theme.accent.tertiary
|
||||
: theme.background.transparent.medium
|
||||
}`
|
||||
: 'none'};
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
color: ${!inverted
|
||||
? !disabled
|
||||
? theme.color.blue
|
||||
: theme.accent.accent4060
|
||||
: theme.font.color.inverted};
|
||||
&:hover {
|
||||
background: ${!inverted
|
||||
? !disabled
|
||||
? theme.accent.tertiary
|
||||
: 'transparent'
|
||||
: theme.background.transparent.light};
|
||||
}
|
||||
&:active {
|
||||
background: ${!inverted
|
||||
? !disabled
|
||||
? theme.accent.secondary
|
||||
: 'transparent'
|
||||
: theme.background.transparent.medium};
|
||||
}
|
||||
`;
|
||||
case 'danger':
|
||||
return css`
|
||||
background: transparent;
|
||||
border-color: ${!inverted
|
||||
? variant === 'secondary'
|
||||
? focus
|
||||
? theme.color.red
|
||||
: theme.border.color.danger
|
||||
: focus
|
||||
? theme.color.red
|
||||
: 'transparent'
|
||||
: variant === 'secondary'
|
||||
? focus || disabled
|
||||
? theme.grayScale.gray0
|
||||
: theme.background.transparent.primary
|
||||
: focus
|
||||
? theme.grayScale.gray0
|
||||
: 'transparent'};
|
||||
border-width: 1px 1px 1px 1px !important;
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${
|
||||
!inverted
|
||||
? theme.color.red10
|
||||
: theme.background.transparent.medium
|
||||
}`
|
||||
: 'none'};
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
color: ${!inverted
|
||||
? !disabled
|
||||
? theme.font.color.danger
|
||||
: theme.color.red20
|
||||
: theme.font.color.inverted};
|
||||
&:hover {
|
||||
background: ${!inverted
|
||||
? !disabled
|
||||
? theme.background.danger
|
||||
: 'transparent'
|
||||
: theme.background.transparent.light};
|
||||
}
|
||||
&:active {
|
||||
background: ${!inverted
|
||||
? !disabled
|
||||
? theme.background.danger
|
||||
: 'transparent'
|
||||
: theme.background.transparent.medium};
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
text-decoration: none;
|
||||
border-radius: ${({ position, theme }) => {
|
||||
switch (position) {
|
||||
case 'left':
|
||||
return `${theme.border.radius.sm} 0px 0px ${theme.border.radius.sm}`;
|
||||
case 'right':
|
||||
return `0px ${theme.border.radius.sm} ${theme.border.radius.sm} 0px`;
|
||||
case 'middle':
|
||||
return '0px';
|
||||
case 'standalone':
|
||||
return theme.border.radius.sm;
|
||||
}
|
||||
}};
|
||||
border-style: solid;
|
||||
border-width: ${({ variant, position }) => {
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
case 'secondary':
|
||||
return position === 'middle' ? '1px 0px' : '1px';
|
||||
case 'tertiary':
|
||||
return '0';
|
||||
}
|
||||
}};
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
font-weight: 500;
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
height: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
justify-content: ${({ justify }) => justify};
|
||||
padding: ${({ theme }) => {
|
||||
return `0 ${theme.spacing(2)}`;
|
||||
}};
|
||||
|
||||
transition: background 0.1s ease;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
width: ${({ fullWidth }) => (fullWidth ? '100%' : 'auto')};
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledSoonPill = styled(Pill)`
|
||||
margin-left: auto;
|
||||
`;
|
||||
|
||||
export const Button = ({
|
||||
className,
|
||||
Icon,
|
||||
title,
|
||||
fullWidth = false,
|
||||
variant = 'primary',
|
||||
inverted = false,
|
||||
size = 'medium',
|
||||
accent = 'default',
|
||||
position = 'standalone',
|
||||
soon = false,
|
||||
disabled = false,
|
||||
justify = 'flex-start',
|
||||
focus = false,
|
||||
onClick,
|
||||
to,
|
||||
target,
|
||||
dataTestId,
|
||||
}: ButtonProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<StyledButton
|
||||
fullWidth={fullWidth}
|
||||
variant={variant}
|
||||
inverted={inverted}
|
||||
size={size}
|
||||
position={position}
|
||||
disabled={soon || disabled}
|
||||
focus={focus}
|
||||
justify={justify}
|
||||
accent={accent}
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
to={to}
|
||||
as={to ? Link : 'button'}
|
||||
target={target}
|
||||
data-testid={dataTestId}
|
||||
>
|
||||
{Icon && <Icon size={theme.icon.size.sm} />}
|
||||
{title}
|
||||
{soon && <StyledSoonPill label="Soon" />}
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
||||
@ -1,59 +0,0 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { ButtonPosition, ButtonProps } from './Button';
|
||||
|
||||
const StyledButtonGroupContainer = styled.div`
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export type ButtonGroupProps = Pick<
|
||||
ButtonProps,
|
||||
'variant' | 'size' | 'accent'
|
||||
> & {
|
||||
className?: string;
|
||||
children: ReactNode[];
|
||||
};
|
||||
|
||||
export const ButtonGroup = ({
|
||||
className,
|
||||
children,
|
||||
variant,
|
||||
size,
|
||||
accent,
|
||||
}: ButtonGroupProps) => (
|
||||
<StyledButtonGroupContainer className={className}>
|
||||
{React.Children.map(children, (child, index) => {
|
||||
if (!React.isValidElement(child)) return null;
|
||||
|
||||
let position: ButtonPosition;
|
||||
|
||||
if (index === 0) {
|
||||
position = 'left';
|
||||
} else if (index === children.length - 1) {
|
||||
position = 'right';
|
||||
} else {
|
||||
position = 'middle';
|
||||
}
|
||||
|
||||
const additionalProps: any = { position, variant, accent, size };
|
||||
|
||||
if (isDefined(variant)) {
|
||||
additionalProps.variant = variant;
|
||||
}
|
||||
|
||||
if (isDefined(accent)) {
|
||||
additionalProps.variant = variant;
|
||||
}
|
||||
|
||||
if (isDefined(size)) {
|
||||
additionalProps.size = size;
|
||||
}
|
||||
|
||||
return React.cloneElement(child, additionalProps);
|
||||
})}
|
||||
</StyledButtonGroupContainer>
|
||||
);
|
||||
@ -1,41 +0,0 @@
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { ColorSample, ColorSampleProps } from 'twenty-ui';
|
||||
|
||||
import {
|
||||
LightIconButton,
|
||||
LightIconButtonProps,
|
||||
} from '@/ui/input/button/components/LightIconButton';
|
||||
|
||||
type ColorPickerButtonProps = Pick<ColorSampleProps, 'colorName'> &
|
||||
Pick<LightIconButtonProps, 'onClick'> & {
|
||||
isSelected?: boolean;
|
||||
};
|
||||
|
||||
const StyledButton = styled(LightIconButton)<{
|
||||
isSelected?: boolean;
|
||||
}>`
|
||||
${({ isSelected, theme }) =>
|
||||
isSelected
|
||||
? css`
|
||||
background-color: ${theme.background.transparent.medium};
|
||||
|
||||
&:hover {
|
||||
background-color: ${theme.background.transparent.medium};
|
||||
}
|
||||
`
|
||||
: ''}
|
||||
`;
|
||||
|
||||
export const ColorPickerButton = ({
|
||||
colorName,
|
||||
isSelected,
|
||||
onClick,
|
||||
}: ColorPickerButtonProps) => (
|
||||
<StyledButton
|
||||
size="medium"
|
||||
isSelected={isSelected}
|
||||
Icon={() => <ColorSample colorName={colorName} />}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
@ -1,134 +0,0 @@
|
||||
import isPropValid from '@emotion/is-prop-valid';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
export type FloatingButtonSize = 'small' | 'medium';
|
||||
export type FloatingButtonPosition = 'standalone' | 'left' | 'middle' | 'right';
|
||||
|
||||
export type FloatingButtonProps = {
|
||||
className?: string;
|
||||
Icon?: IconComponent;
|
||||
title?: string;
|
||||
size?: FloatingButtonSize;
|
||||
position?: FloatingButtonPosition;
|
||||
applyShadow?: boolean;
|
||||
applyBlur?: boolean;
|
||||
disabled?: boolean;
|
||||
focus?: boolean;
|
||||
to?: string;
|
||||
};
|
||||
|
||||
const StyledButton = styled('button', {
|
||||
shouldForwardProp: (prop) =>
|
||||
!['applyBlur', 'applyShadow', 'focus', 'position', 'size'].includes(prop) &&
|
||||
isPropValid(prop),
|
||||
})<
|
||||
Pick<
|
||||
FloatingButtonProps,
|
||||
| 'size'
|
||||
| 'focus'
|
||||
| 'position'
|
||||
| 'applyBlur'
|
||||
| 'applyShadow'
|
||||
| 'position'
|
||||
| 'to'
|
||||
>
|
||||
>`
|
||||
align-items: center;
|
||||
backdrop-filter: ${({ applyBlur }) => (applyBlur ? 'blur(20px)' : 'none')};
|
||||
background: ${({ theme }) => theme.background.primary};
|
||||
|
||||
border: ${({ focus, theme }) =>
|
||||
focus ? `1px solid ${theme.color.blue}` : 'none'};
|
||||
border-radius: ${({ position, theme }) => {
|
||||
switch (position) {
|
||||
case 'left':
|
||||
return `${theme.border.radius.sm} 0px 0px ${theme.border.radius.sm}`;
|
||||
case 'right':
|
||||
return `0px ${theme.border.radius.sm} ${theme.border.radius.sm} 0px`;
|
||||
case 'middle':
|
||||
return '0px';
|
||||
case 'standalone':
|
||||
return theme.border.radius.sm;
|
||||
}
|
||||
}};
|
||||
box-shadow: ${({ theme, applyShadow, focus }) =>
|
||||
applyShadow
|
||||
? `0px 2px 4px 0px ${
|
||||
theme.background.transparent.light
|
||||
}, 0px 0px 4px 0px ${theme.background.transparent.medium}${
|
||||
focus ? `,0 0 0 3px ${theme.color.blue10}` : ''
|
||||
}`
|
||||
: focus
|
||||
? `0 0 0 3px ${theme.color.blue10}`
|
||||
: 'none'};
|
||||
color: ${({ theme, disabled, focus }) => {
|
||||
return !disabled
|
||||
? focus
|
||||
? theme.color.blue
|
||||
: theme.font.color.secondary
|
||||
: theme.font.color.extraLight;
|
||||
}};
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
display: flex;
|
||||
|
||||
flex-direction: row;
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
height: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
padding: ${({ theme }) => {
|
||||
return `0 ${theme.spacing(2)}`;
|
||||
}};
|
||||
transition: background 0.1s ease;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme, disabled }) =>
|
||||
!disabled ? theme.background.transparent.lighter : 'transparent'};
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: ${({ theme, disabled }) =>
|
||||
!disabled ? theme.background.transparent.medium : 'transparent'};
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
text-decoration: none;
|
||||
`;
|
||||
|
||||
export const FloatingButton = ({
|
||||
className,
|
||||
Icon,
|
||||
title,
|
||||
size = 'small',
|
||||
position = 'standalone',
|
||||
applyBlur = true,
|
||||
applyShadow = true,
|
||||
disabled = false,
|
||||
focus = false,
|
||||
to,
|
||||
}: FloatingButtonProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledButton
|
||||
disabled={disabled}
|
||||
focus={focus && !disabled}
|
||||
size={size}
|
||||
applyBlur={applyBlur}
|
||||
applyShadow={applyShadow}
|
||||
position={position}
|
||||
className={className}
|
||||
to={to}
|
||||
as={to ? Link : 'button'}
|
||||
>
|
||||
{Icon && <Icon size={theme.icon.size.sm} />}
|
||||
{title}
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
||||
@ -1,52 +0,0 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { FloatingButtonPosition, FloatingButtonProps } from './FloatingButton';
|
||||
|
||||
const StyledFloatingButtonGroupContainer = styled.div`
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
box-shadow: ${({ theme }) =>
|
||||
`0px 2px 4px 0px ${theme.background.transparent.light}, 0px 0px 4px 0px ${theme.background.transparent.medium}`};
|
||||
display: inline-flex;
|
||||
`;
|
||||
|
||||
export type FloatingButtonGroupProps = Pick<FloatingButtonProps, 'size'> & {
|
||||
children: React.ReactElement[];
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const FloatingButtonGroup = ({
|
||||
children,
|
||||
size,
|
||||
className,
|
||||
}: FloatingButtonGroupProps) => (
|
||||
<StyledFloatingButtonGroupContainer className={className}>
|
||||
{React.Children.map(children, (child, index) => {
|
||||
let position: FloatingButtonPosition;
|
||||
|
||||
if (index === 0) {
|
||||
position = 'left';
|
||||
} else if (index === children.length - 1) {
|
||||
position = 'right';
|
||||
} else {
|
||||
position = 'middle';
|
||||
}
|
||||
|
||||
const additionalProps: any = {
|
||||
position,
|
||||
size,
|
||||
applyShadow: false,
|
||||
applyBlur: false,
|
||||
};
|
||||
|
||||
if (isDefined(size)) {
|
||||
additionalProps.size = size;
|
||||
}
|
||||
|
||||
return React.cloneElement(child, additionalProps);
|
||||
})}
|
||||
</StyledFloatingButtonGroupContainer>
|
||||
);
|
||||
@ -1,146 +0,0 @@
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import React from 'react';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
export type FloatingIconButtonSize = 'small' | 'medium';
|
||||
export type FloatingIconButtonPosition =
|
||||
| 'standalone'
|
||||
| 'left'
|
||||
| 'middle'
|
||||
| 'right';
|
||||
|
||||
export type FloatingIconButtonProps = {
|
||||
className?: string;
|
||||
Icon?: IconComponent;
|
||||
size?: FloatingIconButtonSize;
|
||||
position?: FloatingIconButtonPosition;
|
||||
applyShadow?: boolean;
|
||||
applyBlur?: boolean;
|
||||
disabled?: boolean;
|
||||
focus?: boolean;
|
||||
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
isActive?: boolean;
|
||||
};
|
||||
const shouldForwardProp = (prop: string) =>
|
||||
![
|
||||
'applyBlur',
|
||||
'applyShadow',
|
||||
'isActive',
|
||||
'focus',
|
||||
'position',
|
||||
'size',
|
||||
].includes(prop);
|
||||
|
||||
const StyledButton = styled('button', { shouldForwardProp })<
|
||||
Pick<
|
||||
FloatingIconButtonProps,
|
||||
'size' | 'position' | 'applyShadow' | 'applyBlur' | 'focus' | 'isActive'
|
||||
>
|
||||
>`
|
||||
align-items: center;
|
||||
backdrop-filter: ${({ theme, applyBlur }) =>
|
||||
applyBlur ? theme.blur.medium : 'none'};
|
||||
background: ${({ theme, isActive }) =>
|
||||
isActive ? theme.background.transparent.medium : theme.background.primary};
|
||||
border: ${({ focus, theme }) =>
|
||||
focus
|
||||
? `1px solid ${theme.color.blue}`
|
||||
: `1px solid ${theme.border.color.strong}`};
|
||||
border-radius: ${({ position, theme }) => {
|
||||
switch (position) {
|
||||
case 'left':
|
||||
return `${theme.border.radius.sm} 0px 0px ${theme.border.radius.sm}`;
|
||||
case 'right':
|
||||
return `0px ${theme.border.radius.sm} ${theme.border.radius.sm} 0px`;
|
||||
case 'middle':
|
||||
return '0px';
|
||||
case 'standalone':
|
||||
return theme.border.radius.sm;
|
||||
}
|
||||
}};
|
||||
box-shadow: ${({ theme, applyShadow, focus }) =>
|
||||
applyShadow
|
||||
? theme.boxShadow.light
|
||||
: focus
|
||||
? `0 0 0 3px ${theme.color.blue10}`
|
||||
: 'none'};
|
||||
box-sizing: border-box;
|
||||
color: ${({ theme, disabled, focus }) => {
|
||||
return !disabled
|
||||
? focus
|
||||
? theme.color.blue
|
||||
: theme.font.color.tertiary
|
||||
: theme.font.color.extraLight;
|
||||
}};
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
transition: background ${({ theme }) => theme.animation.duration.instant}s
|
||||
ease;
|
||||
white-space: nowrap;
|
||||
|
||||
${({ position, size }) => {
|
||||
const sizeInPx =
|
||||
(size === 'small' ? 24 : 32) - (position === 'standalone' ? 0 : 4);
|
||||
|
||||
return `
|
||||
height: ${sizeInPx}px;
|
||||
width: ${sizeInPx}px;
|
||||
`;
|
||||
}}
|
||||
|
||||
${({ theme, isActive }) =>
|
||||
isActive &&
|
||||
css`
|
||||
&:hover {
|
||||
background: ${theme.background.transparent.lighter};
|
||||
}
|
||||
`}
|
||||
|
||||
&:active {
|
||||
background: ${({ theme, disabled }) =>
|
||||
!disabled ? theme.background.transparent.medium : 'transparent'};
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FloatingIconButton = ({
|
||||
className,
|
||||
Icon,
|
||||
size = 'small',
|
||||
position = 'standalone',
|
||||
applyShadow = true,
|
||||
applyBlur = true,
|
||||
disabled = false,
|
||||
focus = false,
|
||||
onClick,
|
||||
isActive,
|
||||
}: FloatingIconButtonProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledButton
|
||||
disabled={disabled}
|
||||
focus={focus && !disabled}
|
||||
size={size}
|
||||
applyShadow={applyShadow}
|
||||
applyBlur={applyBlur}
|
||||
className={className}
|
||||
position={position}
|
||||
onClick={onClick}
|
||||
isActive={isActive}
|
||||
>
|
||||
{Icon && <Icon size={theme.icon.size.md} />}
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
||||
@ -1,63 +0,0 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
import {
|
||||
FloatingIconButton,
|
||||
FloatingIconButtonPosition,
|
||||
FloatingIconButtonProps,
|
||||
} from './FloatingIconButton';
|
||||
|
||||
const StyledFloatingIconButtonGroupContainer = styled.div`
|
||||
backdrop-filter: blur(20px);
|
||||
background-color: ${({ theme }) => theme.background.primary};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
box-shadow: ${({ theme }) =>
|
||||
`0px 2px 4px 0px ${theme.background.transparent.light}, 0px 0px 4px 0px ${theme.background.transparent.medium}`};
|
||||
display: inline-flex;
|
||||
gap: 2px;
|
||||
padding: 2px;
|
||||
`;
|
||||
|
||||
export type FloatingIconButtonGroupProps = Pick<
|
||||
FloatingIconButtonProps,
|
||||
'className' | 'size'
|
||||
> & {
|
||||
iconButtons: {
|
||||
Icon: IconComponent;
|
||||
onClick?: (event: MouseEvent<any>) => void;
|
||||
isActive?: boolean;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const FloatingIconButtonGroup = ({
|
||||
iconButtons,
|
||||
size,
|
||||
className,
|
||||
}: FloatingIconButtonGroupProps) => (
|
||||
<StyledFloatingIconButtonGroupContainer className={className}>
|
||||
{iconButtons.map(({ Icon, onClick, isActive }, index) => {
|
||||
const position: FloatingIconButtonPosition =
|
||||
iconButtons.length === 1
|
||||
? 'standalone'
|
||||
: index === 0
|
||||
? 'left'
|
||||
: index === iconButtons.length - 1
|
||||
? 'right'
|
||||
: 'middle';
|
||||
|
||||
return (
|
||||
<FloatingIconButton
|
||||
key={`floating-icon-button-${index}`}
|
||||
applyBlur={false}
|
||||
applyShadow={false}
|
||||
Icon={Icon}
|
||||
onClick={onClick}
|
||||
position={position}
|
||||
size={size}
|
||||
isActive={isActive}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</StyledFloatingIconButtonGroupContainer>
|
||||
);
|
||||
@ -1,271 +0,0 @@
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import React from 'react';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
export type IconButtonSize = 'medium' | 'small';
|
||||
export type IconButtonPosition = 'standalone' | 'left' | 'middle' | 'right';
|
||||
export type IconButtonVariant = 'primary' | 'secondary' | 'tertiary';
|
||||
export type IconButtonAccent = 'default' | 'blue' | 'danger';
|
||||
|
||||
export type IconButtonProps = {
|
||||
className?: string;
|
||||
Icon?: IconComponent;
|
||||
variant?: IconButtonVariant;
|
||||
size?: IconButtonSize;
|
||||
position?: IconButtonPosition;
|
||||
accent?: IconButtonAccent;
|
||||
disabled?: boolean;
|
||||
focus?: boolean;
|
||||
dataTestId?: string;
|
||||
ariaLabel?: string;
|
||||
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
};
|
||||
|
||||
const StyledButton = styled.button<
|
||||
Pick<IconButtonProps, 'variant' | 'size' | 'position' | 'accent' | 'focus'>
|
||||
>`
|
||||
align-items: center;
|
||||
${({ theme, variant, accent, disabled, focus }) => {
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
switch (accent) {
|
||||
case 'default':
|
||||
return css`
|
||||
background: ${theme.background.secondary};
|
||||
border-color: ${focus
|
||||
? theme.color.blue
|
||||
: theme.background.transparent.light};
|
||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${theme.accent.tertiary}`
|
||||
: 'none'};
|
||||
color: ${!disabled
|
||||
? theme.font.color.secondary
|
||||
: theme.font.color.extraLight};
|
||||
&:hover {
|
||||
background: ${!disabled
|
||||
? theme.background.tertiary
|
||||
: theme.background.secondary};
|
||||
}
|
||||
&:active {
|
||||
background: ${!disabled
|
||||
? theme.background.quaternary
|
||||
: theme.background.secondary};
|
||||
}
|
||||
`;
|
||||
case 'blue':
|
||||
return css`
|
||||
background: ${theme.color.blue};
|
||||
border-color: ${!disabled
|
||||
? focus
|
||||
? theme.color.blue
|
||||
: theme.background.transparent.light
|
||||
: 'transparent'};
|
||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${theme.accent.tertiary}`
|
||||
: 'none'};
|
||||
color: ${theme.grayScale.gray0};
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
|
||||
${disabled
|
||||
? ''
|
||||
: css`
|
||||
&:hover {
|
||||
background: ${theme.color.blue50};
|
||||
}
|
||||
&:active {
|
||||
background: ${theme.color.blue60};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
case 'danger':
|
||||
return css`
|
||||
background: ${theme.color.red};
|
||||
border-color: ${!disabled
|
||||
? focus
|
||||
? theme.color.red
|
||||
: theme.background.transparent.light
|
||||
: 'transparent'};
|
||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${theme.color.red10}`
|
||||
: 'none'};
|
||||
color: ${theme.grayScale.gray0};
|
||||
opacity: ${disabled ? 0.24 : 1};
|
||||
|
||||
${disabled
|
||||
? ''
|
||||
: css`
|
||||
&:hover,
|
||||
&:active {
|
||||
background: ${theme.color.red50};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
}
|
||||
break;
|
||||
case 'secondary':
|
||||
case 'tertiary':
|
||||
switch (accent) {
|
||||
case 'default':
|
||||
return css`
|
||||
background: ${focus
|
||||
? theme.background.transparent.primary
|
||||
: 'transparent'};
|
||||
border-color: ${variant === 'secondary'
|
||||
? !disabled && focus
|
||||
? theme.color.blue
|
||||
: theme.background.transparent.light
|
||||
: focus
|
||||
? theme.color.blue
|
||||
: 'transparent'};
|
||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${theme.accent.tertiary}`
|
||||
: 'none'};
|
||||
color: ${!disabled
|
||||
? theme.font.color.tertiary
|
||||
: theme.font.color.extraLight};
|
||||
&:hover {
|
||||
background: ${!disabled
|
||||
? theme.background.transparent.light
|
||||
: 'transparent'};
|
||||
}
|
||||
&:active {
|
||||
background: ${!disabled
|
||||
? theme.background.transparent.light
|
||||
: 'transparent'};
|
||||
}
|
||||
`;
|
||||
case 'blue':
|
||||
return css`
|
||||
background: ${focus
|
||||
? theme.background.transparent.primary
|
||||
: 'transparent'};
|
||||
border-color: ${variant === 'secondary'
|
||||
? !disabled
|
||||
? theme.color.blue
|
||||
: theme.color.blue20
|
||||
: focus
|
||||
? theme.color.blue
|
||||
: 'transparent'};
|
||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${theme.accent.tertiary}`
|
||||
: 'none'};
|
||||
color: ${!disabled ? theme.color.blue : theme.accent.accent4060};
|
||||
&:hover {
|
||||
background: ${!disabled
|
||||
? theme.accent.tertiary
|
||||
: 'transparent'};
|
||||
}
|
||||
&:active {
|
||||
background: ${!disabled
|
||||
? theme.accent.secondary
|
||||
: 'transparent'};
|
||||
}
|
||||
`;
|
||||
case 'danger':
|
||||
return css`
|
||||
background: transparent;
|
||||
border-color: ${variant === 'secondary'
|
||||
? theme.border.color.danger
|
||||
: focus
|
||||
? theme.color.red
|
||||
: 'transparent'};
|
||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||
box-shadow: ${!disabled && focus
|
||||
? `0 0 0 3px ${theme.color.red10}`
|
||||
: 'none'};
|
||||
color: ${!disabled ? theme.font.color.danger : theme.color.red20};
|
||||
&:hover {
|
||||
background: ${!disabled
|
||||
? theme.background.danger
|
||||
: 'transparent'};
|
||||
}
|
||||
&:active {
|
||||
background: ${!disabled
|
||||
? theme.background.danger
|
||||
: 'transparent'};
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
border-radius: ${({ position, theme }) => {
|
||||
switch (position) {
|
||||
case 'left':
|
||||
return `${theme.border.radius.sm} 0px 0px ${theme.border.radius.sm}`;
|
||||
case 'right':
|
||||
return `0px ${theme.border.radius.sm} ${theme.border.radius.sm} 0px`;
|
||||
case 'middle':
|
||||
return '0px';
|
||||
case 'standalone':
|
||||
return theme.border.radius.sm;
|
||||
}
|
||||
}};
|
||||
border-style: solid;
|
||||
border-width: ${({ variant, position }) => {
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
case 'secondary':
|
||||
return position === 'middle' ? '1px 0px' : '1px';
|
||||
case 'tertiary':
|
||||
return '0';
|
||||
}
|
||||
}};
|
||||
box-sizing: content-box;
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
font-weight: 500;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
height: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
transition: background 0.1s ease;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
min-width: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export const IconButton = ({
|
||||
className,
|
||||
Icon,
|
||||
variant = 'primary',
|
||||
size = 'medium',
|
||||
accent = 'default',
|
||||
position = 'standalone',
|
||||
disabled = false,
|
||||
focus = false,
|
||||
dataTestId,
|
||||
ariaLabel,
|
||||
onClick,
|
||||
}: IconButtonProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledButton
|
||||
data-testid={dataTestId}
|
||||
variant={variant}
|
||||
size={size}
|
||||
position={position}
|
||||
disabled={disabled}
|
||||
focus={focus}
|
||||
accent={accent}
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
aria-label={ariaLabel}
|
||||
>
|
||||
{Icon && <Icon size={theme.icon.size.md} />}
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
||||
@ -1,51 +0,0 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
import { IconButton, IconButtonPosition, IconButtonProps } from './IconButton';
|
||||
|
||||
const StyledIconButtonGroupContainer = styled.div`
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export type IconButtonGroupProps = Pick<
|
||||
IconButtonProps,
|
||||
'accent' | 'size' | 'variant'
|
||||
> & {
|
||||
iconButtons: {
|
||||
Icon: IconComponent;
|
||||
onClick?: (event: MouseEvent<any>) => void;
|
||||
}[];
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const IconButtonGroup = ({
|
||||
accent,
|
||||
iconButtons,
|
||||
size,
|
||||
variant,
|
||||
className,
|
||||
}: IconButtonGroupProps) => (
|
||||
<StyledIconButtonGroupContainer className={className}>
|
||||
{iconButtons.map(({ Icon, onClick }, index) => {
|
||||
const position: IconButtonPosition =
|
||||
index === 0
|
||||
? 'left'
|
||||
: index === iconButtons.length - 1
|
||||
? 'right'
|
||||
: 'middle';
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
accent={accent}
|
||||
Icon={Icon}
|
||||
onClick={onClick}
|
||||
position={position}
|
||||
size={size}
|
||||
variant={variant}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</StyledIconButtonGroupContainer>
|
||||
);
|
||||
@ -1,102 +0,0 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
export type LightButtonAccent = 'secondary' | 'tertiary';
|
||||
|
||||
export type LightButtonProps = {
|
||||
className?: string;
|
||||
Icon?: IconComponent;
|
||||
title?: string;
|
||||
accent?: LightButtonAccent;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
focus?: boolean;
|
||||
onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
|
||||
};
|
||||
|
||||
const StyledButton = styled.button<
|
||||
Pick<LightButtonProps, 'accent' | 'active' | 'focus'>
|
||||
>`
|
||||
align-items: center;
|
||||
background: transparent;
|
||||
border: ${({ theme, focus }) =>
|
||||
focus ? `1px solid ${theme.color.blue}` : 'none'};
|
||||
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
box-shadow: ${({ theme, focus }) =>
|
||||
focus ? `0 0 0 3px ${theme.color.blue10}` : 'none'};
|
||||
color: ${({ theme, accent, active, disabled, focus }) => {
|
||||
switch (accent) {
|
||||
case 'secondary':
|
||||
return active || focus
|
||||
? theme.color.blue
|
||||
: !disabled
|
||||
? theme.font.color.secondary
|
||||
: theme.font.color.extraLight;
|
||||
case 'tertiary':
|
||||
return active || focus
|
||||
? theme.color.blue
|
||||
: !disabled
|
||||
? theme.font.color.tertiary
|
||||
: theme.font.color.extraLight;
|
||||
}
|
||||
}};
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
height: 24px;
|
||||
padding: ${({ theme }) => {
|
||||
return `0 ${theme.spacing(2)}`;
|
||||
}};
|
||||
|
||||
transition: background 0.1s ease;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme, disabled }) =>
|
||||
!disabled ? theme.background.transparent.light : 'transparent'};
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: ${({ theme, disabled }) =>
|
||||
!disabled ? theme.background.transparent.medium : 'transparent'};
|
||||
}
|
||||
`;
|
||||
|
||||
export const LightButton = ({
|
||||
className,
|
||||
Icon,
|
||||
title,
|
||||
active = false,
|
||||
accent = 'secondary',
|
||||
disabled = false,
|
||||
focus = false,
|
||||
onClick,
|
||||
}: LightButtonProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<StyledButton
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
focus={focus && !disabled}
|
||||
accent={accent}
|
||||
className={className}
|
||||
active={active}
|
||||
>
|
||||
{!!Icon && <Icon size={theme.icon.size.md} />}
|
||||
{title}
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
||||
@ -1,111 +0,0 @@
|
||||
import { ComponentProps, MouseEvent } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
export type LightIconButtonAccent = 'secondary' | 'tertiary';
|
||||
export type LightIconButtonSize = 'small' | 'medium';
|
||||
|
||||
export type LightIconButtonProps = {
|
||||
className?: string;
|
||||
testId?: string;
|
||||
Icon?: IconComponent;
|
||||
title?: string;
|
||||
size?: LightIconButtonSize;
|
||||
accent?: LightIconButtonAccent;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
focus?: boolean;
|
||||
onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
|
||||
} & Pick<ComponentProps<'button'>, 'aria-label' | 'title'>;
|
||||
|
||||
const StyledButton = styled.button<
|
||||
Pick<LightIconButtonProps, 'accent' | 'active' | 'size' | 'focus'>
|
||||
>`
|
||||
align-items: center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
|
||||
border: ${({ disabled, theme, focus }) =>
|
||||
!disabled && focus ? `1px solid ${theme.color.blue}` : 'none'};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
box-shadow: ${({ disabled, theme, focus }) =>
|
||||
!disabled && focus ? `0 0 0 3px ${theme.color.blue10}` : 'none'};
|
||||
color: ${({ theme, accent, active, disabled, focus }) => {
|
||||
switch (accent) {
|
||||
case 'secondary':
|
||||
return active || focus
|
||||
? theme.color.blue
|
||||
: !disabled
|
||||
? theme.font.color.secondary
|
||||
: theme.font.color.extraLight;
|
||||
case 'tertiary':
|
||||
return active || focus
|
||||
? theme.color.blue
|
||||
: !disabled
|
||||
? theme.font.color.tertiary
|
||||
: theme.font.color.extraLight;
|
||||
}
|
||||
}};
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
height: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
transition: background 0.1s ease;
|
||||
|
||||
white-space: nowrap;
|
||||
width: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
min-width: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme, disabled }) =>
|
||||
!disabled ? theme.background.transparent.light : 'transparent'};
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: ${({ theme, disabled }) =>
|
||||
!disabled ? theme.background.transparent.medium : 'transparent'};
|
||||
}
|
||||
`;
|
||||
|
||||
export const LightIconButton = ({
|
||||
'aria-label': ariaLabel,
|
||||
className,
|
||||
testId,
|
||||
Icon,
|
||||
active = false,
|
||||
size = 'small',
|
||||
accent = 'secondary',
|
||||
disabled = false,
|
||||
focus = false,
|
||||
onClick,
|
||||
title,
|
||||
}: LightIconButtonProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledButton
|
||||
data-testid={testId}
|
||||
aria-label={ariaLabel}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
focus={focus && !disabled}
|
||||
accent={accent}
|
||||
className={className}
|
||||
size={size}
|
||||
active={active}
|
||||
title={title}
|
||||
>
|
||||
{Icon && <Icon size={theme.icon.size.sm} />}
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
||||
@ -1,53 +0,0 @@
|
||||
import { FunctionComponent, MouseEvent, ReactElement } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
import { LightIconButton, LightIconButtonProps } from './LightIconButton';
|
||||
|
||||
const StyledLightIconButtonGroupContainer = styled.div`
|
||||
display: inline-flex;
|
||||
gap: 2px;
|
||||
`;
|
||||
|
||||
export type LightIconButtonGroupProps = Pick<
|
||||
LightIconButtonProps,
|
||||
'className' | 'size'
|
||||
> & {
|
||||
iconButtons: {
|
||||
Wrapper?: FunctionComponent<{ iconButton: ReactElement }>;
|
||||
Icon: IconComponent;
|
||||
accent?: LightIconButtonProps['accent'];
|
||||
onClick?: (event: MouseEvent<any>) => void;
|
||||
disabled?: boolean;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const LightIconButtonGroup = ({
|
||||
iconButtons,
|
||||
size,
|
||||
className,
|
||||
}: LightIconButtonGroupProps) => (
|
||||
<StyledLightIconButtonGroupContainer className={className}>
|
||||
{iconButtons.map(({ Wrapper, Icon, accent, onClick }, index) => {
|
||||
const iconButton = (
|
||||
<LightIconButton
|
||||
key={`light-icon-button-${index}`}
|
||||
Icon={Icon}
|
||||
accent={accent}
|
||||
disabled={!onClick}
|
||||
onClick={onClick}
|
||||
size={size}
|
||||
/>
|
||||
);
|
||||
|
||||
return Wrapper ? (
|
||||
<Wrapper
|
||||
key={`light-icon-button-wrapper-${index}`}
|
||||
iconButton={iconButton}
|
||||
/>
|
||||
) : (
|
||||
iconButton
|
||||
);
|
||||
})}
|
||||
</StyledLightIconButtonGroupContainer>
|
||||
);
|
||||
@ -1,130 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import React from 'react';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
export type MainButtonVariant = 'primary' | 'secondary';
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
fullWidth?: boolean;
|
||||
width?: number;
|
||||
variant?: MainButtonVariant;
|
||||
soon?: boolean;
|
||||
} & React.ComponentProps<'button'>;
|
||||
|
||||
const StyledButton = styled.button<
|
||||
Pick<Props, 'fullWidth' | 'width' | 'variant'>
|
||||
>`
|
||||
align-items: center;
|
||||
background: ${({ theme, variant, disabled }) => {
|
||||
if (disabled === true) {
|
||||
return theme.background.secondary;
|
||||
}
|
||||
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
return theme.background.primaryInverted;
|
||||
case 'secondary':
|
||||
return theme.background.primary;
|
||||
default:
|
||||
return theme.background.primary;
|
||||
}
|
||||
}};
|
||||
border: 1px solid;
|
||||
border-color: ${({ theme, disabled, variant }) => {
|
||||
if (disabled === true) {
|
||||
return theme.background.transparent.lighter;
|
||||
}
|
||||
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
return theme.background.transparent.strong;
|
||||
case 'secondary':
|
||||
return theme.border.color.medium;
|
||||
default:
|
||||
return theme.background.primary;
|
||||
}
|
||||
}};
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
${({ theme, disabled }) => {
|
||||
if (disabled === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return `box-shadow: ${theme.boxShadow.light};`;
|
||||
}}
|
||||
color: ${({ theme, variant, disabled }) => {
|
||||
if (disabled === true) {
|
||||
return theme.font.color.light;
|
||||
}
|
||||
|
||||
switch (variant) {
|
||||
case 'primary':
|
||||
return theme.font.color.inverted;
|
||||
case 'secondary':
|
||||
return theme.font.color.primary;
|
||||
default:
|
||||
return theme.font.color.primary;
|
||||
}
|
||||
}};
|
||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
justify-content: center;
|
||||
outline: none;
|
||||
padding: ${({ theme }) => theme.spacing(2)} ${({ theme }) => theme.spacing(3)};
|
||||
max-height: ${({ theme }) => theme.spacing(8)};
|
||||
width: ${({ fullWidth, width }) =>
|
||||
fullWidth ? '100%' : width ? `${width}px` : 'auto'};
|
||||
${({ theme, variant, disabled }) => {
|
||||
switch (variant) {
|
||||
case 'secondary':
|
||||
return `
|
||||
&:hover {
|
||||
background: ${theme.background.tertiary};
|
||||
}
|
||||
`;
|
||||
default:
|
||||
return `
|
||||
&:hover {
|
||||
background: ${
|
||||
!disabled
|
||||
? theme.background.primaryInvertedHover
|
||||
: theme.background.secondary
|
||||
};};
|
||||
}
|
||||
`;
|
||||
}
|
||||
}};
|
||||
`;
|
||||
|
||||
type MainButtonProps = Props & {
|
||||
Icon?: IconComponent;
|
||||
};
|
||||
|
||||
export const MainButton = ({
|
||||
Icon,
|
||||
title,
|
||||
width,
|
||||
fullWidth = false,
|
||||
variant = 'primary',
|
||||
type,
|
||||
onClick,
|
||||
disabled,
|
||||
className,
|
||||
}: MainButtonProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledButton
|
||||
className={className}
|
||||
{...{ disabled, fullWidth, width, onClick, type, variant }}
|
||||
>
|
||||
{Icon && <Icon size={theme.icon.size.sm} />}
|
||||
{title}
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
||||
@ -1,50 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
const StyledIconButton = styled.button`
|
||||
align-items: center;
|
||||
background: ${({ theme }) => theme.color.blue};
|
||||
border: none;
|
||||
|
||||
border-radius: 50%;
|
||||
color: ${({ theme }) => theme.font.color.inverted};
|
||||
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
height: 20px;
|
||||
|
||||
justify-content: center;
|
||||
|
||||
outline: none;
|
||||
padding: 0;
|
||||
transition:
|
||||
color 0.1s ease-in-out,
|
||||
background 0.1s ease-in-out;
|
||||
|
||||
&:disabled {
|
||||
background: ${({ theme }) => theme.background.quaternary};
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
cursor: default;
|
||||
}
|
||||
width: 20px;
|
||||
`;
|
||||
|
||||
type RoundedIconButtonProps = {
|
||||
Icon: IconComponent;
|
||||
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
|
||||
export const RoundedIconButton = ({
|
||||
Icon,
|
||||
onClick,
|
||||
disabled,
|
||||
className,
|
||||
}: RoundedIconButtonProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<StyledIconButton className={className} {...{ disabled, onClick }}>
|
||||
{<Icon size={theme.icon.size.md} />}
|
||||
</StyledIconButton>
|
||||
);
|
||||
};
|
||||
@ -1,27 +0,0 @@
|
||||
{/* Button.mdx */}
|
||||
|
||||
import { Meta, Controls, Story } from '@storybook/blocks';
|
||||
import * as ButtonStories from './Button.stories';
|
||||
|
||||
<Meta of={ButtonStories} />
|
||||
|
||||
Button is a clickable interactive element that triggers a response.
|
||||
|
||||
You can place text and icons inside of a button.
|
||||
|
||||
Buttons are often used for form submissions and to toggle elements into view.
|
||||
|
||||
<Story of={ButtonStories.Default} />
|
||||
<br />
|
||||
|
||||
## Properties
|
||||
|
||||
<Controls />
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { Button } from '@/ui/button/components/Button';
|
||||
|
||||
<Button title="Click me" />;
|
||||
```
|
||||
@ -1,281 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconSearch,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import {
|
||||
Button,
|
||||
ButtonAccent,
|
||||
ButtonPosition,
|
||||
ButtonSize,
|
||||
ButtonVariant,
|
||||
} from '../Button';
|
||||
|
||||
const meta: Meta<typeof Button> = {
|
||||
title: 'UI/Input/Button/Button',
|
||||
component: Button,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Button>;
|
||||
|
||||
export const Default: Story = {
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
},
|
||||
args: {
|
||||
title: 'Button',
|
||||
size: 'small',
|
||||
variant: 'primary',
|
||||
inverted: false,
|
||||
accent: 'danger',
|
||||
disabled: false,
|
||||
focus: false,
|
||||
fullWidth: false,
|
||||
soon: false,
|
||||
position: 'standalone',
|
||||
Icon: IconSearch,
|
||||
className: '',
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof Button> = {
|
||||
args: { title: 'Filter', Icon: IconSearch },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
focus: { control: false },
|
||||
fullWidth: { control: false },
|
||||
soon: { control: false },
|
||||
position: { control: false },
|
||||
className: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'], focus: ['.focus'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies ButtonSize[],
|
||||
props: (size: ButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'active':
|
||||
return { active: true };
|
||||
case 'disabled+focus':
|
||||
return { focus: true, disabled: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: ['default', 'blue', 'danger'] satisfies ButtonAccent[],
|
||||
props: (accent: ButtonAccent) => ({ accent }),
|
||||
},
|
||||
{
|
||||
name: 'variants',
|
||||
values: [
|
||||
'primary',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
] satisfies ButtonVariant[],
|
||||
props: (variant: ButtonVariant) => ({ variant }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const SoonCatalog: CatalogStory<Story, typeof Button> = {
|
||||
args: { title: 'Filter', Icon: IconSearch, soon: true },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
focus: { control: false },
|
||||
fullWidth: { control: false },
|
||||
soon: { control: false },
|
||||
position: { control: false },
|
||||
className: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'], focus: ['.focus'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies ButtonSize[],
|
||||
props: (size: ButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'active':
|
||||
return { active: true };
|
||||
case 'disabled+focus':
|
||||
return { focus: true, disabled: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: ['default', 'blue', 'danger'] satisfies ButtonAccent[],
|
||||
props: (accent: ButtonAccent) => ({ accent }),
|
||||
},
|
||||
{
|
||||
name: 'variants',
|
||||
values: [
|
||||
'primary',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
] satisfies ButtonVariant[],
|
||||
props: (variant: ButtonVariant) => ({ variant }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const PositionCatalog: CatalogStory<Story, typeof Button> = {
|
||||
args: { title: 'Filter', Icon: IconSearch },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
focus: { control: false },
|
||||
fullWidth: { control: false },
|
||||
soon: { control: false },
|
||||
position: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'], focus: ['.focus'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'positions',
|
||||
values: [
|
||||
'standalone',
|
||||
'left',
|
||||
'middle',
|
||||
'right',
|
||||
] satisfies ButtonPosition[],
|
||||
props: (position: ButtonPosition) => ({ position }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'active':
|
||||
return { active: true };
|
||||
case 'disabled+focus':
|
||||
return { focus: true, disabled: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies ButtonSize[],
|
||||
props: (size: ButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'variants',
|
||||
values: [
|
||||
'primary',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
] satisfies ButtonVariant[],
|
||||
props: (variant: ButtonVariant) => ({ variant }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const FullWidth: Story = {
|
||||
args: { title: 'Filter', Icon: IconSearch, fullWidth: true },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
focus: { control: false },
|
||||
disabled: { control: false },
|
||||
fullWidth: { control: false },
|
||||
soon: { control: false },
|
||||
position: { control: false },
|
||||
className: { control: false },
|
||||
Icon: { control: false },
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
@ -1,80 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconCheckbox,
|
||||
IconNotes,
|
||||
IconTimelineEvent,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { Button, ButtonAccent, ButtonSize, ButtonVariant } from '../Button';
|
||||
import { ButtonGroup } from '../ButtonGroup';
|
||||
|
||||
const meta: Meta<typeof ButtonGroup> = {
|
||||
title: 'UI/Input/Button/ButtonGroup',
|
||||
component: ButtonGroup,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ButtonGroup>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
size: 'small',
|
||||
variant: 'primary',
|
||||
accent: 'danger',
|
||||
children: [
|
||||
<Button Icon={IconNotes} title="Note" />,
|
||||
<Button Icon={IconCheckbox} title="Task" />,
|
||||
<Button Icon={IconTimelineEvent} title="Activity" />,
|
||||
],
|
||||
},
|
||||
argTypes: {
|
||||
children: { control: false },
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof ButtonGroup> = {
|
||||
args: {
|
||||
children: [
|
||||
<Button Icon={IconNotes} title="Note" />,
|
||||
<Button Icon={IconCheckbox} title="Task" />,
|
||||
<Button Icon={IconTimelineEvent} title="Activity" />,
|
||||
],
|
||||
},
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
children: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'], focus: ['.focus'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies ButtonSize[],
|
||||
props: (size: ButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: ['default', 'blue', 'danger'] satisfies ButtonAccent[],
|
||||
props: (accent: ButtonAccent) => ({ accent }),
|
||||
},
|
||||
{
|
||||
name: 'variants',
|
||||
values: [
|
||||
'primary',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
] satisfies ButtonVariant[],
|
||||
props: (variant: ButtonVariant) => ({ variant }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,18 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { ComponentDecorator } from 'twenty-ui';
|
||||
|
||||
import { ColorPickerButton } from '../ColorPickerButton';
|
||||
|
||||
const meta: Meta<typeof ColorPickerButton> = {
|
||||
title: 'UI/Input/Button/ColorPickerButton',
|
||||
component: ColorPickerButton,
|
||||
decorators: [ComponentDecorator],
|
||||
args: { colorName: 'green' },
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ColorPickerButton>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Selected: Story = { args: { isSelected: true } };
|
||||
@ -1,85 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconSearch,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { FloatingButton, FloatingButtonSize } from '../FloatingButton';
|
||||
|
||||
const meta: Meta<typeof FloatingButton> = {
|
||||
title: 'UI/Input/Button/FloatingButton',
|
||||
component: FloatingButton,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof FloatingButton>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
title: 'Filter',
|
||||
size: 'small',
|
||||
disabled: false,
|
||||
focus: false,
|
||||
applyBlur: true,
|
||||
applyShadow: true,
|
||||
position: 'standalone',
|
||||
Icon: IconSearch,
|
||||
},
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof FloatingButton> = {
|
||||
args: { title: 'Filter', Icon: IconSearch },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
disabled: { control: false },
|
||||
position: { control: false },
|
||||
focus: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies FloatingButtonSize[],
|
||||
props: (size: FloatingButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'disabled+focus':
|
||||
return { disabled: true, focus: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,62 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconCheckbox,
|
||||
IconNotes,
|
||||
IconTimelineEvent,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { FloatingButton, FloatingButtonSize } from '../FloatingButton';
|
||||
import { FloatingButtonGroup } from '../FloatingButtonGroup';
|
||||
|
||||
const meta: Meta<typeof FloatingButtonGroup> = {
|
||||
title: 'UI/Input/Button/FloatingButtonGroup',
|
||||
component: FloatingButtonGroup,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof FloatingButtonGroup>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
size: 'small',
|
||||
children: [
|
||||
<FloatingButton Icon={IconNotes} />,
|
||||
<FloatingButton Icon={IconCheckbox} />,
|
||||
<FloatingButton Icon={IconTimelineEvent} />,
|
||||
],
|
||||
},
|
||||
argTypes: {
|
||||
children: { control: false },
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof FloatingButtonGroup> = {
|
||||
args: {
|
||||
children: [
|
||||
<FloatingButton Icon={IconNotes} />,
|
||||
<FloatingButton Icon={IconCheckbox} />,
|
||||
<FloatingButton Icon={IconTimelineEvent} />,
|
||||
],
|
||||
},
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
children: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'], focus: ['.focus'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies FloatingButtonSize[],
|
||||
props: (size: FloatingButtonSize) => ({ size }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,86 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconSearch,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import {
|
||||
FloatingIconButton,
|
||||
FloatingIconButtonSize,
|
||||
} from '../FloatingIconButton';
|
||||
|
||||
const meta: Meta<typeof FloatingIconButton> = {
|
||||
title: 'UI/Input/Button/FloatingIconButton',
|
||||
component: FloatingIconButton,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof FloatingIconButton>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
size: 'small',
|
||||
disabled: false,
|
||||
focus: false,
|
||||
applyBlur: true,
|
||||
applyShadow: true,
|
||||
position: 'standalone',
|
||||
Icon: IconSearch,
|
||||
},
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof FloatingIconButton> = {
|
||||
args: { Icon: IconSearch },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
disabled: { control: false },
|
||||
focus: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies FloatingIconButtonSize[],
|
||||
props: (size: FloatingIconButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'disabled+focus':
|
||||
return { disabled: true, focus: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,56 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconCheckbox,
|
||||
IconNotes,
|
||||
IconTimelineEvent,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { FloatingIconButtonSize } from '../FloatingIconButton';
|
||||
import { FloatingIconButtonGroup } from '../FloatingIconButtonGroup';
|
||||
|
||||
const meta: Meta<typeof FloatingIconButtonGroup> = {
|
||||
title: 'UI/Input/Button/FloatingIconButtonGroup',
|
||||
component: FloatingIconButtonGroup,
|
||||
args: {
|
||||
iconButtons: [
|
||||
{ Icon: IconNotes },
|
||||
{ Icon: IconCheckbox },
|
||||
{ Icon: IconTimelineEvent },
|
||||
],
|
||||
},
|
||||
argTypes: {
|
||||
iconButtons: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof FloatingIconButtonGroup>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
size: 'small',
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof FloatingIconButtonGroup> = {
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'], focus: ['.focus'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies FloatingIconButtonSize[],
|
||||
props: (size: FloatingIconButtonSize) => ({ size }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,181 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconSearch,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import {
|
||||
IconButton,
|
||||
IconButtonAccent,
|
||||
IconButtonPosition,
|
||||
IconButtonSize,
|
||||
IconButtonVariant,
|
||||
} from '../IconButton';
|
||||
|
||||
const meta: Meta<typeof IconButton> = {
|
||||
title: 'UI/Input/Button/IconButton',
|
||||
component: IconButton,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof IconButton>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
size: 'small',
|
||||
variant: 'primary',
|
||||
accent: 'danger',
|
||||
disabled: false,
|
||||
focus: false,
|
||||
position: 'standalone',
|
||||
Icon: IconSearch,
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof IconButton> = {
|
||||
args: { Icon: IconSearch },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
focus: { control: false },
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
Icon: { control: false },
|
||||
position: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies IconButtonSize[],
|
||||
props: (size: IconButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'active':
|
||||
return { active: true };
|
||||
case 'disabled+focus':
|
||||
return { focus: true, disabled: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: ['default', 'blue', 'danger'] satisfies IconButtonAccent[],
|
||||
props: (accent: IconButtonAccent) => ({ accent }),
|
||||
},
|
||||
{
|
||||
name: 'variants',
|
||||
values: [
|
||||
'primary',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
] satisfies IconButtonVariant[],
|
||||
props: (variant: IconButtonVariant) => ({ variant }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const PositionCatalog: CatalogStory<Story, typeof IconButton> = {
|
||||
args: { Icon: IconSearch },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
focus: { control: false },
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
position: { control: false },
|
||||
Icon: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'positions',
|
||||
values: [
|
||||
'standalone',
|
||||
'left',
|
||||
'middle',
|
||||
'right',
|
||||
] satisfies IconButtonPosition[],
|
||||
props: (position: IconButtonPosition) => ({ position }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'active':
|
||||
return { active: true };
|
||||
case 'disabled+focus':
|
||||
return { focus: true, disabled: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies IconButtonSize[],
|
||||
props: (size: IconButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'variants',
|
||||
values: [
|
||||
'primary',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
] satisfies IconButtonVariant[],
|
||||
props: (variant: IconButtonVariant) => ({ variant }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,77 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconCheckbox,
|
||||
IconNotes,
|
||||
IconTimelineEvent,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import {
|
||||
IconButtonAccent,
|
||||
IconButtonSize,
|
||||
IconButtonVariant,
|
||||
} from '../IconButton';
|
||||
import { IconButtonGroup } from '../IconButtonGroup';
|
||||
|
||||
const meta: Meta<typeof IconButtonGroup> = {
|
||||
title: 'UI/Input/Button/IconButtonGroup',
|
||||
component: IconButtonGroup,
|
||||
args: {
|
||||
iconButtons: [
|
||||
{ Icon: IconNotes },
|
||||
{ Icon: IconCheckbox },
|
||||
{ Icon: IconTimelineEvent },
|
||||
],
|
||||
},
|
||||
argTypes: {
|
||||
iconButtons: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof IconButtonGroup>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
size: 'small',
|
||||
variant: 'primary',
|
||||
accent: 'danger',
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof IconButtonGroup> = {
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies IconButtonSize[],
|
||||
props: (size: IconButtonSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: ['default', 'blue', 'danger'] satisfies IconButtonAccent[],
|
||||
props: (accent: IconButtonAccent) => ({ accent }),
|
||||
},
|
||||
{
|
||||
name: 'variants',
|
||||
values: [
|
||||
'primary',
|
||||
'secondary',
|
||||
'tertiary',
|
||||
] satisfies IconButtonVariant[],
|
||||
props: (variant: IconButtonVariant) => ({ variant }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,89 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconSearch,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { LightButton, LightButtonAccent } from '../LightButton';
|
||||
|
||||
const meta: Meta<typeof LightButton> = {
|
||||
title: 'UI/Input/Button/LightButton',
|
||||
component: LightButton,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof LightButton>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
title: 'Filter',
|
||||
accent: 'secondary',
|
||||
disabled: false,
|
||||
active: false,
|
||||
focus: false,
|
||||
Icon: IconSearch,
|
||||
},
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof LightButton> = {
|
||||
args: { title: 'Filter', Icon: IconSearch },
|
||||
argTypes: {
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
active: { control: false },
|
||||
focus: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'accents',
|
||||
values: ['secondary', 'tertiary'] satisfies LightButtonAccent[],
|
||||
props: (accent: LightButtonAccent) => ({ accent }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'active',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
'disabled+active',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'active':
|
||||
return { active: true };
|
||||
case 'disabled+focus':
|
||||
return { disabled: true, focus: true };
|
||||
case 'disabled+active':
|
||||
return { disabled: true, active: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,98 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
CatalogStory,
|
||||
ComponentDecorator,
|
||||
IconSearch,
|
||||
} from 'twenty-ui';
|
||||
|
||||
import {
|
||||
LightIconButton,
|
||||
LightIconButtonAccent,
|
||||
LightIconButtonSize,
|
||||
} from '../LightIconButton';
|
||||
|
||||
const meta: Meta<typeof LightIconButton> = {
|
||||
title: 'UI/Input/Button/LightIconButton',
|
||||
component: LightIconButton,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof LightIconButton>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
title: 'Filter',
|
||||
accent: 'secondary',
|
||||
disabled: false,
|
||||
active: false,
|
||||
focus: false,
|
||||
Icon: IconSearch,
|
||||
},
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof LightIconButton> = {
|
||||
args: { title: 'Filter', Icon: IconSearch },
|
||||
argTypes: {
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
active: { control: false },
|
||||
focus: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
pseudo: { hover: ['.hover'], active: ['.pressed'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'states',
|
||||
values: [
|
||||
'default',
|
||||
'hover',
|
||||
'pressed',
|
||||
'disabled',
|
||||
'active',
|
||||
'focus',
|
||||
'disabled+focus',
|
||||
'disabled+active',
|
||||
],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'default':
|
||||
return {};
|
||||
case 'hover':
|
||||
case 'pressed':
|
||||
return { className: state };
|
||||
case 'focus':
|
||||
return { focus: true };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
case 'active':
|
||||
return { active: true };
|
||||
case 'disabled+focus':
|
||||
return { disabled: true, focus: true };
|
||||
case 'disabled+active':
|
||||
return { disabled: true, active: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: ['secondary', 'tertiary'] satisfies LightIconButtonAccent[],
|
||||
props: (accent: LightIconButtonAccent) => ({ accent }),
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['small', 'medium'] satisfies LightIconButtonSize[],
|
||||
props: (size: LightIconButtonSize) => ({ size }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
@ -1,61 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||
import { ComponentDecorator, IconBrandGoogle } from 'twenty-ui';
|
||||
|
||||
import { MainButton } from '../MainButton';
|
||||
|
||||
const clickJestFn = fn();
|
||||
|
||||
const meta: Meta<typeof MainButton> = {
|
||||
title: 'UI/Input/Button/MainButton',
|
||||
component: MainButton,
|
||||
decorators: [ComponentDecorator],
|
||||
args: { title: 'A primary Button', onClick: clickJestFn },
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof MainButton>;
|
||||
|
||||
export const Default: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(clickJestFn).toHaveBeenCalledTimes(0);
|
||||
const button = canvas.getByRole('button');
|
||||
await userEvent.click(button);
|
||||
|
||||
expect(clickJestFn).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
};
|
||||
|
||||
export const WithIcon: Story = {
|
||||
args: { Icon: IconBrandGoogle },
|
||||
};
|
||||
|
||||
export const DisabledWithIcon: Story = {
|
||||
args: { ...WithIcon.args, disabled: true },
|
||||
};
|
||||
|
||||
export const FullWidth: Story = {
|
||||
args: { fullWidth: true },
|
||||
};
|
||||
|
||||
export const Width: Story = {
|
||||
args: { width: 200 },
|
||||
};
|
||||
|
||||
export const Secondary: Story = {
|
||||
args: { title: 'A secondary Button', variant: 'secondary' },
|
||||
};
|
||||
|
||||
export const SecondaryWithIcon: Story = {
|
||||
args: { ...Secondary.args, ...WithIcon.args },
|
||||
};
|
||||
|
||||
export const SecondaryDisabledWithIcon: Story = {
|
||||
args: { ...SecondaryWithIcon.args, disabled: true },
|
||||
};
|
||||
|
||||
export const SecondaryFullWidth: Story = {
|
||||
args: { ...Secondary.args, ...FullWidth.args },
|
||||
};
|
||||
@ -1,30 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||
import { ComponentDecorator, IconArrowRight } from 'twenty-ui';
|
||||
|
||||
import { RoundedIconButton } from '../RoundedIconButton';
|
||||
|
||||
const clickJestFn = fn();
|
||||
|
||||
const meta: Meta<typeof RoundedIconButton> = {
|
||||
title: 'UI/Input/Button/RoundedIconButton',
|
||||
component: RoundedIconButton,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof RoundedIconButton>;
|
||||
|
||||
export const Default: Story = {
|
||||
decorators: [ComponentDecorator],
|
||||
argTypes: { Icon: { control: false } },
|
||||
args: { onClick: clickJestFn, Icon: IconArrowRight },
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(clickJestFn).toHaveBeenCalledTimes(0);
|
||||
const button = canvas.getByRole('button');
|
||||
await userEvent.click(button);
|
||||
|
||||
expect(clickJestFn).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user