feat: update UI styles and enhance status indicator components

This commit is contained in:
twwu 2024-11-21 15:13:16 +08:00
parent 13bb4aa721
commit c5b9a829c0
7 changed files with 233 additions and 156 deletions

View File

@ -2,11 +2,11 @@
import type { FC } from 'react'
import React, { useState } from 'react'
import useSWR from 'swr'
import { ArrowLeftIcon } from '@heroicons/react/24/solid'
import { createContext, useContext } from 'use-context-selector'
import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation'
import { omit } from 'lodash-es'
import { RiArrowDownSLine, RiArrowLeftLine, RiLayoutRight2Line } from '@remixicon/react'
import { OperationAction, StatusItem } from '../list'
import s from '../style.module.css'
import Completed from './completed'
@ -21,7 +21,7 @@ import Loading from '@/app/components/base/loading'
import type { MetadataType } from '@/service/datasets'
import { checkSegmentBatchImportProgress, fetchDocumentDetail, segmentBatchImport } from '@/service/datasets'
import { ToastContext } from '@/app/components/base/toast'
import type { DocForm } from '@/models/datasets'
import type { DocForm, ParentMode, ProcessMode } from '@/models/datasets'
import { useDatasetDetailContext } from '@/context/dataset-detail'
import FloatRightContainer from '@/app/components/base/float-right-container'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
@ -31,17 +31,36 @@ export const DocumentContext = createContext<{ datasetId?: string; documentId?:
type DocumentTitleProps = {
extension?: string
name?: string
processMode?: ProcessMode
parent_mode?: ParentMode
iconCls?: string
textCls?: string
wrapperCls?: string
}
export const DocumentTitle: FC<DocumentTitleProps> = ({ extension, name, iconCls, textCls, wrapperCls }) => {
export const DocumentTitle: FC<DocumentTitleProps> = ({ extension, name, processMode, parent_mode, iconCls, textCls, wrapperCls }) => {
const localExtension = extension?.toLowerCase() || name?.split('.')?.pop()?.toLowerCase()
return <div className={cn('flex items-center justify-start flex-1', wrapperCls)}>
<div className={cn(s[`${localExtension || 'txt'}Icon`], style.titleIcon, iconCls)}></div>
<span className={cn('font-semibold text-lg text-gray-900 ml-1', textCls)}> {name || '--'}</span>
</div>
return (
<div className={cn('flex items-center justify-start flex-1 cursor-pointer', wrapperCls)}>
{/* // todo: add file switcher */}
<div className='flex items-center ml-1 px-2 py-0.5 rounded-lg hover:bg-state-base-hover'>
{/* // todo: add icons map */}
<div className={cn(s[`${localExtension || 'txt'}Icon`], style.titleIcon, iconCls)}></div>
<div className='flex flex-col items-start ml-1 mr-0.5'>
<div className='flex items-center'>
<span className={cn('system-md-semibold', textCls)}> {name || '--'}</span>
<RiArrowDownSLine className='h-4 w-4 text-text-primary'/>
</div>
<div className='flex items-center gap-x-0.5'>
<div className='w-3 h-3 bg-text-tertiary'/>
<span className={'system-2xs-medium-uppercase'}>
{`${processMode || '--'}${processMode === 'hierarchical' ? `·${parent_mode || '--'}` : ''}`}
</span>
</div>
</div>
</div>
</div>
)
}
type Props = {
@ -130,14 +149,17 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
return (
<DocumentContext.Provider value={{ datasetId, documentId, docForm: documentDetail?.doc_form || '' }}>
<div className='flex flex-col h-full'>
<div className='flex min-h-16 border-b-gray-100 border-b items-center p-4 justify-between flex-wrap gap-y-2'>
<div onClick={backToPrev} className={'shrink-0 rounded-full w-8 h-8 flex justify-center items-center border-gray-100 cursor-pointer border hover:border-gray-300 shadow-[0px_12px_16px_-4px_rgba(16,24,40,0.08),0px_4px_6px_-2px_rgba(16,24,40,0.03)]'}>
<ArrowLeftIcon className='text-primary-600 fill-current stroke-current h-4 w-4' />
<div className='flex items-center justify-between flex-wrap min-h-16 pl-3 pr-4 py-2.5 border-b border-b-divider-subtle'>
<div onClick={backToPrev} className={'shrink-0 rounded-full w-8 h-8 flex justify-center items-center cursor-pointer hover:bg-components-button-tertiary-bg'}>
<RiArrowLeftLine className='text-components-button-ghost-text hover:text-text-tertiary w-4 h-4' />
</div>
<Divider className='!h-4' type='vertical' />
<DocumentTitle extension={documentDetail?.data_source_info?.upload_file?.extension} name={documentDetail?.name} />
<div className='flex items-center flex-wrap gap-y-2'>
<StatusItem status={documentDetail?.display_status || 'available'} scene='detail' errorMessage={documentDetail?.error || ''} />
<DocumentTitle
extension={documentDetail?.data_source_info?.upload_file?.extension}
name={documentDetail?.name}
wrapperCls='mr-2'
processMode={documentDetail?.dataset_process_rule?.mode}
/>
<div className='flex items-center flex-wrap'>
{embeddingAvailable && documentDetail && !documentDetail.archived && (
<SegmentAdd
importStatus={importStatus}
@ -146,6 +168,20 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
showBatchModal={showBatchModal}
/>
)}
<Divider type='vertical' className='!bg-divider-regular !h-[14px] !mx-3'/>
<StatusItem
status={documentDetail?.display_status || 'available'}
scene='detail'
errorMessage={documentDetail?.error || ''}
textCls='font-semibold text-xs uppercase'
detail={{
enabled: documentDetail?.enabled || false,
archived: documentDetail?.archived || false,
id: documentId,
}}
datasetId={datasetId}
onUpdate={handleOperate}
/>
<OperationAction
scene='detail'
embeddingAvailable={embeddingAvailable}
@ -159,12 +195,14 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
}}
datasetId={datasetId}
onUpdate={handleOperate}
className='!w-[216px]'
className='!w-[200px]'
/>
<button
className={cn(style.layoutRightIcon, showMetadata ? style.iconShow : style.iconClose)}
className={style.layoutRightIcon}
onClick={() => setShowMetadata(!showMetadata)}
/>
>
<RiLayoutRight2Line className={cn('w-4 h-4', showMetadata ? 'text-components-button-secondary-accent-text' : 'text-components-button-secondary-text')} />
</button>
</div>
</div>
<div className='flex flex-row flex-1' style={{ height: 'calc(100% - 4rem)' }}>

View File

@ -66,13 +66,13 @@ const SegmentAdd: FC<ISegmentAddProps> = ({
return (
<div className='flex items-center rounded-lg border-[0.5px] border-components-button-secondary-border
bg-components-button-secondary-bg shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px] mr-2'>
bg-components-button-secondary-bg shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px] relative z-20'>
<div
className='inline-flex items-center px-2.5 py-2 border-r-[1px] border-r-divider-subtle cursor-pointer'
onClick={showNewSegmentModal}
>
<RiAddLine className='w-4 h-4 text-components-button-secondary-accent-text' />
<span className='text-components-button-secondary-accent-text text-[13px] leading-[16px] font-medium px-0.5 ml-0.5'>
<span className='text-components-button-secondary-accent-text text-[13px] leading-[16px] font-medium capitalize px-0.5 ml-0.5'>
{t('datasetDocuments.list.action.addButton')}
</span>
</div>
@ -83,7 +83,7 @@ const SegmentAdd: FC<ISegmentAddProps> = ({
htmlContent={
<div className='w-full p-1'>
<div
className='py-1.5 px-2 flex items-center hover:bg-state-base-hover rounded-lg cursor-pointer text-text-tertiary system-md-regular'
className='py-1.5 px-2 flex items-center hover:bg-state-base-hover rounded-lg cursor-pointer text-text-secondary system-md-regular'
onClick={showBatchModal}
>
{t('datasetDocuments.list.action.batchAdd')}
@ -99,7 +99,7 @@ const SegmentAdd: FC<ISegmentAddProps> = ({
open ? '!bg-state-base-hover' : '')}
popupClassName='!min-w-[128px] !bg-components-panel-bg-blur !rounded-xl border-[0.5px] !ring-0
border-components-panel-border !shadow-xl !shadow-shadow-shadow-5 backdrop-blur-[5px]'
className='min-w-[128px] h-fit !z-20'
className='min-w-[128px] h-fit'
/>
</div>
)

View File

@ -5,11 +5,7 @@
@apply h-6 w-6 !important;
}
.layoutRightIcon {
@apply w-8 h-8 ml-2 box-border border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer hover:shadow-[0_1px_2px_rgba(16,24,40,0.05)];
}
.iconShow {
background: center center url(../assets/layoutRightShow.svg) no-repeat;
}
.iconClose {
background: center center url(../assets/layoutRightClose.svg) no-repeat;
@apply p-2 ml-2 border-[0.5px] border-components-button-secondary-border hover:border-components-button-secondary-border-hover
rounded-lg bg-components-button-secondary-bg hover:bg-components-button-secondary-bg-hover cursor-pointer
shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px];
}

View File

@ -1,11 +1,15 @@
/* eslint-disable no-mixed-operators */
'use client'
import type { FC, SVGProps } from 'react'
import type { FC } from 'react'
import React, { useCallback, useEffect, useState } from 'react'
import { useBoolean, useDebounceFn } from 'ahooks'
import { ArrowDownIcon, TrashIcon } from '@heroicons/react/24/outline'
import { ArrowDownIcon } from '@heroicons/react/24/outline'
import { pick } from 'lodash-es'
import {
RiArchive2Line,
RiDeleteBinLine,
RiEditLine,
RiEqualizer2Line,
RiLoopLeftLine,
RiMoreFill,
} from '@remixicon/react'
import { useContext } from 'use-context-selector'
@ -23,7 +27,7 @@ import Popover from '@/app/components/base/popover'
import Confirm from '@/app/components/base/confirm'
import Tooltip from '@/app/components/base/tooltip'
import { ToastContext } from '@/app/components/base/toast'
import type { IndicatorProps } from '@/app/components/header/indicator'
import type { ColorMap, IndicatorProps } from '@/app/components/header/indicator'
import Indicator from '@/app/components/header/indicator'
import { asyncRunSafe } from '@/utils'
import { formatNumber } from '@/utils/format'
@ -34,30 +38,6 @@ import { DataSourceType, type DocumentDisplayStatus, type SimpleDocumentDetail }
import type { CommonResponse } from '@/models/common'
import useTimestamp from '@/hooks/use-timestamp'
export const SettingsIcon = ({ className }: SVGProps<SVGElement>) => {
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
<path d="M2 5.33325L10 5.33325M10 5.33325C10 6.43782 10.8954 7.33325 12 7.33325C13.1046 7.33325 14 6.43782 14 5.33325C14 4.22868 13.1046 3.33325 12 3.33325C10.8954 3.33325 10 4.22868 10 5.33325ZM6 10.6666L14 10.6666M6 10.6666C6 11.7712 5.10457 12.6666 4 12.6666C2.89543 12.6666 2 11.7712 2 10.6666C2 9.56202 2.89543 8.66659 4 8.66659C5.10457 8.66659 6 9.56202 6 10.6666Z" stroke="#667085" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
}
export const SyncIcon = () => {
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.69773 13.1783C7.29715 13.8879 9.20212 13.8494 10.8334 12.9075C13.5438 11.3427 14.4724 7.87704 12.9076 5.16672L12.7409 4.87804M3.09233 10.8335C1.52752 8.12314 2.45615 4.65746 5.16647 3.09265C6.7978 2.15081 8.70277 2.11227 10.3022 2.82185M1.66226 10.8892L3.48363 11.3773L3.97166 9.5559M12.0284 6.44393L12.5164 4.62256L14.3378 5.1106" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
}
export const FilePlusIcon = ({ className }: SVGProps<SVGElement>) => {
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
<path d="M13.3332 6.99992V4.53325C13.3332 3.41315 13.3332 2.85309 13.1152 2.42527C12.9234 2.04895 12.6175 1.74299 12.2412 1.55124C11.8133 1.33325 11.2533 1.33325 10.1332 1.33325H5.8665C4.7464 1.33325 4.18635 1.33325 3.75852 1.55124C3.3822 1.74299 3.07624 2.04895 2.88449 2.42527C2.6665 2.85309 2.6665 3.41315 2.6665 4.53325V11.4666C2.6665 12.5867 2.6665 13.1467 2.88449 13.5746C3.07624 13.9509 3.3822 14.2569 3.75852 14.4486C4.18635 14.6666 4.7464 14.6666 5.8665 14.6666H7.99984M9.33317 7.33325H5.33317M6.6665 9.99992H5.33317M10.6665 4.66659H5.33317M11.9998 13.9999V9.99992M9.99984 11.9999H13.9998" stroke="#667085" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
}
export const ArchiveIcon = ({ className }: SVGProps<SVGElement>) => {
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
<path d="M2.66683 5.33106C2.55749 5.32824 2.47809 5.32191 2.40671 5.30771C1.87779 5.2025 1.46432 4.78904 1.35912 4.26012C1.3335 4.13132 1.3335 3.97644 1.3335 3.66667C1.3335 3.3569 1.3335 3.20201 1.35912 3.07321C1.46432 2.54429 1.87779 2.13083 2.40671 2.02562C2.53551 2 2.69039 2 3.00016 2H13.0002C13.3099 2 13.4648 2 13.5936 2.02562C14.1225 2.13083 14.536 2.54429 14.6412 3.07321C14.6668 3.20201 14.6668 3.3569 14.6668 3.66667C14.6668 3.97644 14.6668 4.13132 14.6412 4.26012C14.536 4.78904 14.1225 5.2025 13.5936 5.30771C13.5222 5.32191 13.4428 5.32824 13.3335 5.33106M6.66683 8.66667H9.3335M2.66683 5.33333H13.3335V10.8C13.3335 11.9201 13.3335 12.4802 13.1155 12.908C12.9238 13.2843 12.6178 13.5903 12.2415 13.782C11.8137 14 11.2536 14 10.1335 14H5.86683C4.74672 14 4.18667 14 3.75885 13.782C3.38252 13.5903 3.07656 13.2843 2.88482 12.908C2.66683 12.4802 2.66683 11.9201 2.66683 10.8V5.33333Z" stroke="#667085" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
}
export const useIndexStatus = () => {
const { t } = useTranslation()
return {
@ -72,6 +52,15 @@ export const useIndexStatus = () => {
}
}
const STATUS_TEXT_COLOR_MAP: ColorMap = {
green: 'text-util-colors-green-green-600',
orange: 'text-util-colors-warning-warning-600',
red: 'text-util-colors-red-red-600',
blue: 'text-util-colors-blue-light-blue-light-600',
yellow: 'text-util-colors-warning-warning-600',
gray: 'text-text-tertiary',
}
// status item for list
export const StatusItem: FC<{
status: DocumentDisplayStatus
@ -79,16 +68,75 @@ export const StatusItem: FC<{
scene?: 'list' | 'detail'
textCls?: string
errorMessage?: string
}> = ({ status, reverse = false, scene = 'list', textCls = '', errorMessage }) => {
detail?: {
enabled: boolean
archived: boolean
id: string
}
datasetId?: string
onUpdate?: (operationName?: string) => void
}> = ({ status, reverse = false, scene = 'list', textCls = '', errorMessage, datasetId = '', detail, onUpdate }) => {
const DOC_INDEX_STATUS_MAP = useIndexStatus()
const localStatus = status.toLowerCase() as keyof typeof DOC_INDEX_STATUS_MAP
const { enabled = false, archived = false, id = '' } = detail || {}
const { notify } = useContext(ToastContext)
const { t } = useTranslation()
const onOperate = async (operationName: OperationName) => {
let opApi = deleteDocument
switch (operationName) {
case 'enable':
opApi = enableDocument
break
case 'disable':
opApi = disableDocument
break
}
const [e] = await asyncRunSafe<CommonResponse>(opApi({ datasetId, documentId: id }) as Promise<CommonResponse>)
if (!e)
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
else
notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') })
onUpdate?.(operationName)
}
const { run: handleSwitch } = useDebounceFn((operationName: OperationName) => {
if (operationName === 'enable' && enabled)
return
if (operationName === 'disable' && !enabled)
return
onOperate(operationName)
}, { wait: 500 })
return <div className={
cn('flex items-center',
reverse ? 'flex-row-reverse' : '',
scene === 'detail' ? s.statusItemDetail : '')
}>
<Indicator color={DOC_INDEX_STATUS_MAP[localStatus]?.color as IndicatorProps['color']} className={reverse ? 'ml-2' : 'mr-2'} />
<span className={cn('text-gray-700 text-sm', textCls)}>{DOC_INDEX_STATUS_MAP[localStatus]?.text}</span>
<span className={cn(`${STATUS_TEXT_COLOR_MAP[DOC_INDEX_STATUS_MAP[localStatus].color as keyof typeof STATUS_TEXT_COLOR_MAP]} text-sm`, textCls)}>
{DOC_INDEX_STATUS_MAP[localStatus]?.text}
</span>
{
scene === 'detail' && (
<div className='flex justify-between items-center ml-1.5'>
<Tooltip
popupContent={t('datasetDocuments.list.action.enableWarning')}
popupClassName='text-text-secondary system-xs-medium'
needsDelay
disabled={!archived}
>
<Switch
defaultValue={archived ? false : enabled}
onChange={v => !archived && handleSwitch(v ? 'enable' : 'disable')}
disabled={archived}
size='md'
/>
</Tooltip>
</div>
)
}
{
errorMessage && (
<Tooltip
@ -216,85 +264,72 @@ export const OperationAction: FC<{
</>
)}
{embeddingAvailable && (
<Popover
htmlContent={
<div className='w-full py-1'>
{!isListScene && <>
<div className='flex justify-between items-center mx-4 pt-2'>
<span className={cn(s.actionName, 'font-medium')}>
{!archived && enabled ? t('datasetDocuments.list.index.enable') : t('datasetDocuments.list.index.disable')}
</span>
<Tooltip
popupContent={t('datasetDocuments.list.action.enableWarning')}
popupClassName='!font-semibold'
needsDelay
disabled={!archived}
>
<div>
<Switch
defaultValue={archived ? false : enabled}
onChange={v => !archived && handleSwitch(v ? 'enable' : 'disable')}
disabled={archived}
size='md'
/>
<>
<Tooltip
popupContent={t('datasetDocuments.list.action.settings')}
popupClassName='text-text-secondary system-xs-medium'
needsDelay
>
<div
className={cn('rounded-lg mr-2 cursor-pointer',
!isListScene
? 'p-2 bg-components-button-secondary-bg hover:bg-components-button-secondary-bg-hover border-[0.5px] border-components-button-secondary-border hover:border-components-button-secondary-border-hover shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px]'
: 'p-0.5 hover:bg-state-base-hover')}
onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}>
<RiEqualizer2Line className='w-4 h-4 text-components-button-secondary-text' />
</div>
</Tooltip>
<Popover
htmlContent={
<div className='w-full py-1'>
{!archived && (
<>
<div className={s.actionItem} onClick={() => {
handleShowRenameModal({
id: detail.id,
name: detail.name,
})
}}>
<RiEditLine className='w-4 h-4 text-text-tertiary' />
<span className={s.actionName}>{t('datasetDocuments.list.table.rename')}</span>
</div>
</Tooltip>
</div>
<div className='mx-4 pb-1 pt-0.5 text-xs text-gray-500'>
{!archived && enabled ? t('datasetDocuments.list.index.enableTip') : t('datasetDocuments.list.index.disableTip')}
</div>
<Divider />
</>}
{!archived && (
<>
<div className={s.actionItem} onClick={() => {
handleShowRenameModal({
id: detail.id,
name: detail.name,
})
}}>
<Edit03 className='w-4 h-4 text-gray-500' />
<span className={s.actionName}>{t('datasetDocuments.list.table.rename')}</span>
{['notion_import', DataSourceType.WEB].includes(data_source_type) && (
<div className={s.actionItem} onClick={() => onOperate('sync')}>
<RiLoopLeftLine className='w-4 h-4 text-text-tertiary' />
<span className={s.actionName}>{t('datasetDocuments.list.action.sync')}</span>
</div>
)}
<Divider className='my-1' />
</>
)}
{!archived && <div className={s.actionItem} onClick={() => onOperate('archive')}>
<RiArchive2Line className='w-4 h-4 text-text-tertiary' />
<span className={s.actionName}>{t('datasetDocuments.list.action.archive')}</span>
</div>}
{archived && (
<div className={s.actionItem} onClick={() => onOperate('un_archive')}>
<RiArchive2Line className='w-4 h-4 text-text-tertiary' />
<span className={s.actionName}>{t('datasetDocuments.list.action.unarchive')}</span>
</div>
<div className={s.actionItem} onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}>
<SettingsIcon />
<span className={s.actionName}>{t('datasetDocuments.list.action.settings')}</span>
</div>
{['notion_import', DataSourceType.WEB].includes(data_source_type) && (
<div className={s.actionItem} onClick={() => onOperate('sync')}>
<SyncIcon />
<span className={s.actionName}>{t('datasetDocuments.list.action.sync')}</span>
</div>
)}
<Divider className='my-1' />
</>
)}
{!archived && <div className={s.actionItem} onClick={() => onOperate('archive')}>
<ArchiveIcon />
<span className={s.actionName}>{t('datasetDocuments.list.action.archive')}</span>
</div>}
{archived && (
<div className={s.actionItem} onClick={() => onOperate('un_archive')}>
<ArchiveIcon />
<span className={s.actionName}>{t('datasetDocuments.list.action.unarchive')}</span>
)}
<div className={cn(s.actionItem, s.deleteActionItem, 'group')} onClick={() => setShowModal(true)}>
<RiDeleteBinLine className={'w-4 h-4 text-text-tertiary group-hover:text-text-destructive'} />
<span className={cn(s.actionName, 'group-hover:text-text-destructive')}>{t('datasetDocuments.list.action.delete')}</span>
</div>
)}
<div className={cn(s.actionItem, s.deleteActionItem, 'group')} onClick={() => setShowModal(true)}>
<TrashIcon className={'w-4 h-4 stroke-current text-gray-500 stroke-2 group-hover:text-red-500'} />
<span className={cn(s.actionName, 'group-hover:text-red-500')}>{t('datasetDocuments.list.action.delete')}</span>
</div>
</div>
}
trigger='click'
position='br'
btnElement={
<div className={cn(s.commonIcon)}>
<RiMoreFill className='w-4 h-4 text-gray-700' />
</div>
}
btnClassName={open => cn(isListScene ? s.actionIconWrapperList : s.actionIconWrapperDetail, open ? '!bg-gray-100 !shadow-none' : '!bg-transparent')}
className={`flex justify-end !w-[200px] h-fit !z-20 ${className}`}
/>
}
trigger='click'
position='br'
btnElement={
<div className={cn(s.commonIcon)}>
<RiMoreFill className='w-4 h-4 text-text-components-button-secondary-text' />
</div>
}
btnClassName={open => cn(isListScene ? s.actionIconWrapperList : s.actionIconWrapperDetail, open ? '!bg-gray-100 !shadow-none' : '!bg-transparent')}
popupClassName='!w-full'
className={`flex justify-end !w-[200px] h-fit !z-20 ${className}`}
/>
</>
)}
{showModal
&& <Confirm

View File

@ -18,16 +18,18 @@
@apply h-6 w-6 rounded-md border-none p-1 hover:bg-gray-100 !important;
}
.actionIconWrapperDetail {
@apply h-8 w-8 p-2 hover:bg-gray-50 border border-gray-200 hover:border-gray-300 hover:shadow-[0_1px_2px_rgba(16,24,40,0.05)] !important;
@apply p-2 bg-components-button-secondary-bg hover:bg-components-button-secondary-bg-hover
border-[0.5px] border-components-button-secondary-border hover:border-components-button-secondary-border-hover
shadow-xs shadow-shadow-shadow-3 !important;
}
.actionItem {
@apply h-9 py-2 px-3 mx-1 flex items-center gap-2 hover:bg-gray-100 rounded-lg cursor-pointer;
}
.deleteActionItem {
@apply hover:bg-red-50 !important;
@apply hover:bg-state-destructive-hover !important;
}
.actionName {
@apply text-gray-700 text-sm;
@apply text-text-secondary text-sm;
}
.addFileBtn {
@apply mt-4 w-fit !text-[13px] text-primary-600 font-medium bg-white border-[0.5px];
@ -94,7 +96,8 @@
background-image: url(~@/assets/docx.svg);
}
.statusItemDetail {
@apply h-8 font-medium border border-gray-200 inline-flex items-center rounded-lg pl-3 pr-4 mr-2;
@apply border-[0.5px] border-components-button-secondary-border inline-flex items-center
rounded-lg pl-2.5 pr-2 py-2 mr-2 shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px];
}
.tdValue {
@apply text-sm overflow-hidden text-ellipsis whitespace-nowrap;

View File

@ -7,7 +7,7 @@ export type IndicatorProps = {
className?: string
}
type ColorMap = {
export type ColorMap = {
green: string
orange: string
red: string
@ -17,28 +17,28 @@ type ColorMap = {
}
const BACKGROUND_MAP: ColorMap = {
green: 'bg-[#31C48D]',
orange: 'bg-[#FF5A1F]',
red: 'bg-[#F04438]',
blue: 'bg-[#36BFFA]',
yellow: 'bg-[#FDB022]',
gray: 'bg-[#D0D5DD]',
green: 'bg-components-badge-status-light-success-bg',
orange: 'bg-components-badge-status-light-warning-bg',
red: 'bg-components-badge-status-light-error-bg',
blue: 'bg-components-badge-status-light-normal-bg',
yellow: 'bg-components-badge-status-light-warning-bg',
gray: 'bg-components-badge-status-light-disabled-bg',
}
const BORDER_MAP: ColorMap = {
green: 'border-[#0E9F6E]',
orange: 'border-[#D03801]',
red: 'border-[#D92D20]',
blue: 'border-[#0BA5EC]',
yellow: 'border-[#F79009]',
gray: 'border-[#98A2B3]',
green: 'border-components-badge-status-light-success-border-inner',
orange: 'border-components-badge-status-light-warning-border-inner',
red: 'border-components-badge-status-light-error-border-inner',
blue: 'border-components-badge-status-light-normal-border-inner',
yellow: 'border-components-badge-status-light-warning-border-inner',
gray: 'border-components-badge-status-light-disabled-border-inner',
}
const SHADOW_MAP: ColorMap = {
green: 'shadow-[0_0_5px_-3px_rgba(14,159,110,0.1),0.5px_0.5px_3px_rgba(14,159,110,0.3),inset_1.5px_1.5px_0px_rgba(255,255,255,0.2)]',
orange: 'shadow-[0_0_5px_-3px_rgba(255,90,31,0.2),0.5px_0.5px_3px_rgba(255, 90, 31, 0.3), inset_1.5px_1.5px_0_rgba(255, 255, 255, 0.2)]',
red: 'shadow-[0_0_5px_-3px_rgba(249,112,102,0.1),0.5px_0.5px_3px_rgba(249, 112, 102, 0.2), inset_1.5px_1.5px_0_rgba(255, 255, 255, 0.4)]',
blue: 'shadow-[0_0_5px_-3px_rgba(208, 213, 221, 0.1),0.5px_0.5px_3px_rgba(208, 213, 221, 0.3), inset_1.5px_1.5px_0_rgba(255, 255, 255, 0.2)]',
yellow: 'shadow-[0_0_5px_-3px_rgba(253, 176, 34, 0.1),0.5px_0.5px_3px_rgba(253, 176, 34, 0.3), inset_1.5px_1.5px_0_rgba(255, 255, 255, 0.2)]',
gray: 'shadow-[0_0_5px_-3px_rgba(208, 213, 221, 0.1),0.5px_0.5px_3px_rgba(208, 213, 221, 0.3), inset_1.5px_1.5px_0_rgba(255, 255, 255, 0.2)]',
green: 'shadow-status-indicator-green-shadow',
orange: 'shadow-status-indicator-warning-shadow',
red: 'shadow-status-indicator-red-shadow',
blue: 'shadow-status-indicator-blue-shadow',
yellow: 'shadow-status-indicator-warning-shadow',
gray: 'shadow-status-indicator-gray-shadow',
}
export default function Indicator({

View File

@ -80,6 +80,11 @@ module.exports = {
'xl': '0px 8px 8px -4px rgba(16, 24, 40, 0.03), 0px 20px 24px -4px rgba(16, 24, 40, 0.08)',
'2xl': '0px 24px 48px -12px rgba(16, 24, 40, 0.18)',
'3xl': '0px 32px 64px -12px rgba(16, 24, 40, 0.14)',
'status-indicator-green-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-success-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-warning-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-warning-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-red-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-error-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-blue-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-normal-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
'status-indicator-gray-shadow': '0px 1px 2px 0px var(--color-components-badge-status-light-disabled-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)',
},
opacity: {
2: '0.02',