Skip to content
Snippets Groups Projects
Unverified Commit 9dd03566 authored by Anton Kulyk's avatar Anton Kulyk Committed by GitHub
Browse files

Extract `DraggableSidebarLink` component (#25457)

* Export `SidebarLinkProps`

* Expose `SidebarLink's` left & right containers

That'd allow styling left and right elements from external components

* Extract `DraggableSidebarLink` component

Based on sortable bookmarks code

* Use `DraggableSidebarLink` in `BookmarkList`

* Fix dragged item styles
parent ffeeb37c
No related branches found
Tags v0.33.1
No related merge requests found
Showing with 90 additions and 50 deletions
import styled from "@emotion/styled";
import { css } from "@emotion/react";
import { color } from "metabase/lib/colors";
import Icon from "metabase/components/Icon";
import { DraggableSidebarLink } from "../../SidebarItems";
import { SidebarLink } from "../../SidebarItems";
type SidebarBookmarkItem = {
isSorting: boolean;
};
export const DragIcon = styled(Icon)`
left: 2px;
opacity: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: grab;
`;
export const SidebarBookmarkItem = styled(SidebarLink)<SidebarBookmarkItem>`
export const SidebarBookmarkItem = styled(DraggableSidebarLink)`
padding-left: 0.75rem;
position: relative;
&:hover {
button {
......@@ -33,10 +16,6 @@ export const SidebarBookmarkItem = styled(SidebarLink)<SidebarBookmarkItem>`
outline: none;
}
}
> svg {
opacity: 0.3;
}
}
button {
......@@ -50,20 +29,4 @@ export const SidebarBookmarkItem = styled(SidebarLink)<SidebarBookmarkItem>`
outline: none;
}
}
${props =>
props.isSorting &&
css`
&:hover {
background: white;
svg {
color: ${color("brand-light")} !important;
}
button {
opacity: 0;
}
}
`}
`;
......@@ -2,8 +2,6 @@ import React, { useCallback, useEffect, useState } from "react";
import { t } from "ttag";
import { connect } from "react-redux";
import "./sortable.css";
import {
SortableContainer,
SortableElement,
......@@ -20,7 +18,7 @@ import * as Urls from "metabase/lib/urls";
import { SelectedItem } from "../../types";
import { SidebarHeading } from "../../MainNavbar.styled";
import { DragIcon, SidebarBookmarkItem } from "./BookmarkList.styled";
import { SidebarBookmarkItem } from "./BookmarkList.styled";
const mapDispatchToProps = {
onDeleteBookmark: ({ item_id, type }: Bookmark) =>
......@@ -91,10 +89,9 @@ const BookmarkItem = ({
url={url}
icon={icon}
isSelected={isSelected}
isSorting={isSorting}
isDragging={isSorting}
hasDefaultIconStyle={!isIrregularCollection}
onClick={onSelect}
left={<DragIcon name="grabber2" size={12} />}
right={
<button onClick={onRemove}>
<Tooltip tooltip={t`Remove bookmark`} placement="bottom">
......
import styled from "@emotion/styled";
import { css } from "@emotion/react";
import Icon from "metabase/components/Icon";
import { color } from "metabase/lib/colors";
import SidebarLink from "./SidebarLink";
export const DragIcon = styled(Icon)`
left: 2px;
opacity: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: grab;
`;
// Notice that dragged item styles are defined in sortable.css file
// This is a limitation of react-sortable-hoc library
export const StyledSidebarLink = styled(SidebarLink)<{ isDragging: boolean }>`
position: relative;
&:hover {
${DragIcon} {
opacity: 0.3;
}
}
${props =>
props.isDragging &&
css`
&:hover {
background: ${color("bg-white")};
${SidebarLink.Icon}, ${DragIcon} {
color: ${color("brand-light")} !important;
}
${SidebarLink.RightElement} {
opacity: 0;
}
}
`}
`;
import React from "react";
import { SidebarLinkProps } from "./SidebarLink";
import { DragIcon, StyledSidebarLink } from "./DraggableSidebarLink.styled";
import "./sortable.css";
interface Props extends Omit<SidebarLinkProps, "left"> {
isDragging: boolean;
}
function DraggableSidebarLink(props: Props) {
return (
<StyledSidebarLink
{...props}
left={<DragIcon name="grabber2" size={12} />}
/>
);
}
export default DraggableSidebarLink;
......@@ -127,3 +127,6 @@ export function NameContainer({ children: itemName }: { children: string }) {
}
return <TreeNode.NameContainer>{itemName}</TreeNode.NameContainer>;
}
export const LeftElementContainer = styled.div``;
export const RightElementContainer = styled.div``;
......@@ -11,9 +11,11 @@ import {
NodeRoot,
SidebarIcon,
FullWidthButton,
LeftElementContainer,
RightElementContainer,
} from "./SidebarItems.styled";
interface Props {
interface SidebarLinkProps {
children: string;
url?: string;
icon?: string | IconProps | React.ReactElement;
......@@ -51,7 +53,7 @@ function SidebarLink({
left = null,
right = null,
...props
}: Props) {
}: SidebarLinkProps) {
const renderIcon = useCallback(() => {
if (!icon) {
return null;
......@@ -83,16 +85,25 @@ function SidebarLink({
onMouseDown={disableImageDragging}
{...props}
>
{React.isValidElement(left) && left}
{React.isValidElement(left) && (
<LeftElementContainer>{left}</LeftElementContainer>
)}
<Content>
{icon && renderIcon()}
<NameContainer>{children}</NameContainer>
</Content>
{React.isValidElement(right) && right}
{React.isValidElement(right) && (
<RightElementContainer>{right}</RightElementContainer>
)}
</NodeRoot>
);
}
export type { SidebarLinkProps };
export default Object.assign(SidebarLink, {
NameContainers: [ItemName, TreeNode.NameContainer],
Icon: SidebarIcon,
LeftElement: LeftElementContainer,
RightElement: RightElementContainer,
});
export { default as DraggableSidebarLink } from "./DraggableSidebarLink";
export { default as SidebarCollectionLink } from "./SidebarCollectionLink";
export { default as SidebarDataAppLink } from "./SidebarDataAppLink";
export { default as SidebarLink } from "./SidebarLink";
.react-sortable-hoc-helper.sorting {
background: white;
border-bottom: 2px solid var(--color-brand);
}
.react-sortable-hoc-helper.sorting > svg {
.react-sortable-hoc-helper.sorting .Icon-grabber2 {
color: var(--color-brand);
opacity: 0.5;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment