-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: editable dismissible tab component (#38788)
## Description Addition of a template component that combines editable entity name and dismissible tab. Fixes #37649 ## Automation /ok-to-test tags="@tag.Sanity" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!CAUTION] > 🔴 🔴 🔴 Some tests have failed. > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/12925482595> > Commit: 23c8fbe > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12925482595&attempt=2&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank">Cypress dashboard</a>. > Tags: @tag.Sanity > Spec: > The following are new failures, please fix them before merging the PR: <ol> > <li>cypress/e2e/Regression/ClientSide/OtherUIFeatures/GlobalSearch_spec.js</ol> > <a href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master" target="_blank">List of identified flaky tests</a>. > <hr>Thu, 23 Jan 2025 11:42:24 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced `DismissibleTab` component with interactive close and click functionality. - Added `EditableEntityName` component for editing entity names with validation. - Created `EditableDismissibleTab` component combining dismissible and editable behaviors. - Added new Storybook stories for `DismissibleTab`, `EditableDismissibleTab`, and `EditableEntityName` components. - **Improvements** - Enhanced design system with new styled components for better interactivity and appearance. - **Refactoring** - Reorganized hook and component imports. - Updated export statements in various files to improve module accessibility. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
1 parent
72251cb
commit efceb1e
Showing
24 changed files
with
429 additions
and
9 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
app/client/packages/design-system/ads/src/DismissibleTab/DismissibleTab.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* eslint-disable no-console */ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
import { DismissibleTab } from "."; | ||
|
||
const meta: Meta<typeof DismissibleTab> = { | ||
title: "ADS/Components/Dismissible Tab", | ||
component: DismissibleTab, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof DismissibleTab>; | ||
|
||
export const Basic: Story = { | ||
args: { | ||
isActive: true, | ||
dataTestId: "t--dismissible-tab", | ||
children: "Dismissible tab", | ||
}, | ||
}; |
55 changes: 55 additions & 0 deletions
55
app/client/packages/design-system/ads/src/DismissibleTab/DismissibleTab.styles.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import styled from "styled-components"; | ||
|
||
import { Button as ADSButton } from ".."; | ||
|
||
export const Tab = styled.div` | ||
position: relative; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
flex-shrink: 0; | ||
gap: var(--ads-v2-spaces-2); | ||
height: 100%; | ||
font-size: 12px; | ||
color: var(--ads-v2-color-fg); | ||
cursor: pointer; | ||
border-top-left-radius: var(--ads-v2-border-radius); | ||
border-top-right-radius: var(--ads-v2-border-radius); | ||
border-left: 1px solid transparent; | ||
border-right: 1px solid transparent; | ||
border-top: 3px solid transparent; | ||
padding: var(--ads-v2-spaces-3); | ||
padding-top: 6px; | ||
&.active { | ||
background: var(--ads-v2-colors-control-field-default-bg); | ||
border-top-color: var(--ads-v2-color-bg-brand); | ||
border-left-color: var(--ads-v2-color-border-muted); | ||
border-right-color: var(--ads-v2-color-border-muted); | ||
span { | ||
font-weight: var(--ads-v2-font-weight-bold); | ||
} | ||
} | ||
& > .tab-close { | ||
opacity: 0; | ||
transition: opacity 0.2s ease; | ||
} | ||
&:hover > .tab-close, | ||
&:focus-within > .tab-close, | ||
&.active > .tab-close { | ||
opacity: 1; | ||
} | ||
`; | ||
|
||
export const CloseButton = styled(ADSButton)` | ||
border-radius: 2px; | ||
cursor: pointer; | ||
padding: var(--ads-v2-spaces-1); | ||
max-width: 16px; | ||
max-height: 16px; | ||
`; |
43 changes: 43 additions & 0 deletions
43
app/client/packages/design-system/ads/src/DismissibleTab/DismissibleTab.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React from "react"; | ||
|
||
import clsx from "classnames"; | ||
|
||
import { Icon } from ".."; | ||
|
||
import * as Styled from "./DismissibleTab.styles"; | ||
import { DATA_TEST_ID } from "./constants"; | ||
|
||
import type { DismissibleTabProps } from "./DismissibleTab.types"; | ||
|
||
export const DismissibleTab = ({ | ||
children, | ||
dataTestId, | ||
isActive, | ||
onClick, | ||
onClose, | ||
onDoubleClick, | ||
}: DismissibleTabProps) => { | ||
return ( | ||
<Styled.Tab | ||
className={clsx("editor-tab", isActive && "active")} | ||
data-testid={dataTestId} | ||
onClick={onClick} | ||
onDoubleClick={onDoubleClick} | ||
> | ||
{children} | ||
<Styled.CloseButton | ||
aria-label="Close tab" | ||
className="tab-close" | ||
data-testid={DATA_TEST_ID.CLOSE_BUTTON} | ||
isIconButton | ||
kind="tertiary" | ||
onClick={onClose} | ||
role="tab" | ||
size="sm" | ||
tabIndex={0} | ||
> | ||
<Icon name="close-line" /> | ||
</Styled.CloseButton> | ||
</Styled.Tab> | ||
); | ||
}; |
10 changes: 10 additions & 0 deletions
10
app/client/packages/design-system/ads/src/DismissibleTab/DismissibleTab.types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import type React from "react"; | ||
|
||
export interface DismissibleTabProps { | ||
children: React.ReactNode; | ||
dataTestId?: string; | ||
isActive: boolean; | ||
onClick: () => void; | ||
onClose: (e: React.MouseEvent) => void; | ||
onDoubleClick?: () => void; | ||
} |
3 changes: 3 additions & 0 deletions
3
app/client/packages/design-system/ads/src/DismissibleTab/constants.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const DATA_TEST_ID = { | ||
CLOSE_BUTTON: "t--tab-close-btn", | ||
}; |
2 changes: 2 additions & 0 deletions
2
app/client/packages/design-system/ads/src/DismissibleTab/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { DismissibleTab } from "./DismissibleTab"; | ||
export type { DismissibleTabProps } from "./DismissibleTab.types"; |
53 changes: 53 additions & 0 deletions
53
...design-system/ads/src/Templates/EditableDismissibleTab/EditableDismissibleTab.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* eslint-disable no-console */ | ||
import React from "react"; | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
import { EditableDismissibleTab } from "."; | ||
import styled from "styled-components"; | ||
|
||
import { Icon } from "../.."; | ||
|
||
const meta: Meta<typeof EditableDismissibleTab> = { | ||
title: "ADS/Templates/Editable Dismissible Tab", | ||
component: EditableDismissibleTab, | ||
}; | ||
|
||
const EntityIcon = styled.div` | ||
height: 18px; | ||
width: 18px; | ||
box-sizing: border-box; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
svg, | ||
img { | ||
height: 100%; | ||
width: 100%; | ||
} | ||
`; | ||
|
||
const JSIcon = () => { | ||
return ( | ||
<EntityIcon> | ||
<Icon name="js-yellow" size="md" /> | ||
</EntityIcon> | ||
); | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof EditableDismissibleTab>; | ||
|
||
export const Basic: Story = { | ||
args: { | ||
isActive: true, | ||
dataTestId: "t--dismissible-tab", | ||
icon: JSIcon(), | ||
name: "Hello", | ||
|
||
onNameSave: console.log, | ||
validateName: (name: string) => | ||
name.length < 3 ? "Name must be at least 3 characters" : null, | ||
}, | ||
}; |
51 changes: 51 additions & 0 deletions
51
...ackages/design-system/ads/src/Templates/EditableDismissibleTab/EditableDismissibleTab.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import React from "react"; | ||
import { noop } from "lodash"; | ||
import { useBoolean } from "usehooks-ts"; | ||
|
||
import { DismissibleTab } from "../.."; | ||
import { EditableEntityName } from ".."; | ||
|
||
import type { EditableDismissibleTabProps } from "./EditableDismissibleTab.types"; | ||
|
||
export const EditableDismissibleTab = (props: EditableDismissibleTabProps) => { | ||
const { | ||
dataTestId, | ||
icon, | ||
isActive, | ||
isEditable = true, | ||
isLoading, | ||
name, | ||
onClick, | ||
onClose, | ||
onNameSave, | ||
validateName, | ||
} = props; | ||
|
||
const { | ||
setFalse: exitEditMode, | ||
setTrue: enterEditMode, | ||
value: isEditing, | ||
} = useBoolean(false); | ||
|
||
const handleDoubleClick = isEditable ? enterEditMode : noop; | ||
|
||
return ( | ||
<DismissibleTab | ||
dataTestId={dataTestId} | ||
isActive={isActive} | ||
onClick={onClick} | ||
onClose={onClose} | ||
onDoubleClick={handleDoubleClick} | ||
> | ||
<EditableEntityName | ||
icon={icon} | ||
isEditing={isEditing} | ||
isLoading={isLoading} | ||
name={name} | ||
onExitEditing={exitEditMode} | ||
onNameSave={onNameSave} | ||
validateName={validateName} | ||
/> | ||
</DismissibleTab> | ||
); | ||
}; |
14 changes: 14 additions & 0 deletions
14
...es/design-system/ads/src/Templates/EditableDismissibleTab/EditableDismissibleTab.types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import type React from "react"; | ||
|
||
export interface EditableDismissibleTabProps { | ||
dataTestId?: string; | ||
icon: React.ReactNode; | ||
isActive: boolean; | ||
isEditable?: boolean; | ||
isLoading: boolean; | ||
name: string; | ||
onClick: () => void; | ||
onClose: () => void; | ||
onNameSave: (name: string) => void; | ||
validateName: (name: string) => string | null; | ||
} |
1 change: 1 addition & 0 deletions
1
app/client/packages/design-system/ads/src/Templates/EditableDismissibleTab/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { EditableDismissibleTab } from "./EditableDismissibleTab"; |
53 changes: 53 additions & 0 deletions
53
...ackages/design-system/ads/src/Templates/EditableEntityName/EditableEntityName.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* eslint-disable no-console */ | ||
import React from "react"; | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import styled from "styled-components"; | ||
|
||
import { Icon } from "../.."; | ||
import { EditableEntityName } from "."; | ||
|
||
const EntityIcon = styled.div` | ||
height: 18px; | ||
width: 18px; | ||
box-sizing: border-box; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
svg, | ||
img { | ||
height: 100%; | ||
width: 100%; | ||
} | ||
`; | ||
|
||
const JSIcon = () => { | ||
return ( | ||
<EntityIcon> | ||
<Icon name="js-yellow" size="md" /> | ||
</EntityIcon> | ||
); | ||
}; | ||
|
||
const meta: Meta<typeof EditableEntityName> = { | ||
title: "ADS/Templates/Editable Entity Name", | ||
component: EditableEntityName, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof EditableEntityName>; | ||
|
||
export const Basic: Story = { | ||
args: { | ||
name: "Hello", | ||
onNameSave: console.log, | ||
onExitEditing: console.log, | ||
icon: JSIcon(), | ||
inputTestId: "t--editable-name", | ||
isEditing: true, | ||
isLoading: false, | ||
validateName: (name: string) => | ||
name.length < 3 ? "Name must be at least 3 characters" : null, | ||
}, | ||
}; |
29 changes: 29 additions & 0 deletions
29
.../packages/design-system/ads/src/Templates/EditableEntityName/EditableEntityName.styles.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import styled from "styled-components"; | ||
import { Text as ADSText } from "../../Text"; | ||
|
||
export const Root = styled.div` | ||
display: flex; | ||
flex-direction: row; | ||
flex-wrap: nowrap; | ||
justify-content: start; | ||
align-items: center; | ||
gap: var(--ads-v2-spaces-2); | ||
`; | ||
|
||
export const Text = styled(ADSText)` | ||
min-width: 3ch; | ||
bottom: -0.5px; | ||
`; | ||
|
||
export const IconContainer = styled.div` | ||
height: 12px; | ||
width: 12px; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
flex-shrink: 0; | ||
img { | ||
width: 12px; | ||
} | ||
`; |
Oops, something went wrong.