-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
33ea39c
commit cdadedd
Showing
5 changed files
with
345 additions
and
1 deletion.
There are no files selected for viewing
54 changes: 54 additions & 0 deletions
54
packages/tooltip/src/components/popover/Popover2.module.css
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,54 @@ | ||
.floating { | ||
display: flex; | ||
flex-direction: row; | ||
align-items: center; | ||
background: white; | ||
color: white; | ||
border-radius: var(--swui-border-radius); | ||
padding: var(--swui-metrics-spacing) calc(var(--swui-metrics-indent) * 2); | ||
box-shadow: var(--swui-shadow-popover); | ||
|
||
&.withIcon { | ||
padding: calc(var(--swui-metrics-spacing) * 0.5); | ||
padding-right: calc(var(--swui-metrics-indent) * 2); | ||
} | ||
} | ||
|
||
.iconWrapper { | ||
/* State vars */ | ||
--current-bg-color: transparent; | ||
--current-border-color: var(--lhds-color-ui-50); | ||
--current-icon-color: var(--lhds-color-ui-50); | ||
|
||
/* Styling */ | ||
display: inline-flex; | ||
flex-direction: row; | ||
white-space: nowrap; | ||
background-color: var(--current-bg-color); | ||
border: 1px solid var(--current-border-color); | ||
border-radius: var(--swui-border-radius); | ||
padding: calc(var(--swui-metrics-spacing) * 0.5); | ||
align-items: flex-start; | ||
|
||
svg { | ||
color: var(--current-icon-color); | ||
} | ||
|
||
&.info { | ||
--current-border-color: var(--lhds-color-blue-300); | ||
--current-bg-color: var(--lhds-color-blue-100); | ||
--current-icon-color: var(--lhds-color-blue-700); | ||
} | ||
|
||
&.warning { | ||
--current-border-color: var(--lhds-color-orange-300); | ||
--current-bg-color: var(--lhds-color-orange-100); | ||
--current-icon-color: var(--lhds-color-orange-700); | ||
} | ||
|
||
&.error { | ||
--current-border-color: var(--lhds-color-red-300); | ||
--current-bg-color: var(--lhds-color-red-100); | ||
--current-icon-color: var(--lhds-color-red-700); | ||
} | ||
} |
147 changes: 147 additions & 0 deletions
147
packages/tooltip/src/components/popover/Popover2.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,147 @@ | ||
import { | ||
Box, | ||
Column, | ||
Indent, | ||
Row, | ||
SeparatorLine, | ||
Spacing, | ||
Text, | ||
} from "@stenajs-webui/core"; | ||
import { FlatButton, Icon, stenaTrash } from "@stenajs-webui/elements"; | ||
import * as React from "react"; | ||
import { ActionPrompt } from "./ActionPrompt"; | ||
import { Popover2 } from "./Popover2"; | ||
import { PopoverButton } from "./PopoverButton"; | ||
|
||
export default { | ||
title: "tooltip/Popover2", | ||
component: Popover2, | ||
subcomponents: { PopoverButton, ActionPrompt }, | ||
}; | ||
|
||
export const Standard = () => ( | ||
<Box indent={10} spacing={10} display={"inline-block"}> | ||
<PopoverButton | ||
content={<ActionPrompt />} | ||
renderButton={() => <FlatButton leftIcon={stenaTrash} />} | ||
/> | ||
</Box> | ||
); | ||
|
||
export const OnClick = () => ( | ||
<Box indent={10} spacing={10} display={"inline-block"}> | ||
<PopoverButton | ||
content={<ActionPrompt />} | ||
renderButton={({ onClick }) => ( | ||
<FlatButton leftIcon={stenaTrash} onClick={onClick} /> | ||
)} | ||
/> | ||
</Box> | ||
); | ||
|
||
export const NoArrow = () => ( | ||
<Box indent={10} spacing={10} display={"inline-block"}> | ||
<PopoverButton | ||
content={<ActionPrompt />} | ||
renderButton={({ onClick }) => ( | ||
<FlatButton leftIcon={stenaTrash} onClick={onClick} /> | ||
)} | ||
arrow={false} | ||
/> | ||
</Box> | ||
); | ||
|
||
export const NoPadding = () => ( | ||
<Box indent={10} spacing={10} display={"inline-block"}> | ||
<PopoverButton | ||
disablePadding | ||
content={ | ||
<Column> | ||
<Indent spacing> | ||
<Text>The line has</Text> | ||
</Indent> | ||
<SeparatorLine /> | ||
<Indent spacing> | ||
<Text>no padding</Text> | ||
</Indent> | ||
</Column> | ||
} | ||
renderButton={({ onClick }) => ( | ||
<FlatButton leftIcon={stenaTrash} onClick={onClick} /> | ||
)} | ||
/> | ||
</Box> | ||
); | ||
|
||
export const Variants = () => ( | ||
<Box indent={10} spacing={10} display={"inline-block"}> | ||
<PopoverButton | ||
content={<ActionPrompt />} | ||
renderButton={({ onClick }) => ( | ||
<FlatButton label={"standard"} onClick={onClick} /> | ||
)} | ||
/> | ||
|
||
<Spacing /> | ||
|
||
<PopoverButton | ||
content={<ActionPrompt />} | ||
renderButton={({ onClick }) => ( | ||
<FlatButton label={"info"} onClick={onClick} /> | ||
)} | ||
variant={"info"} | ||
/> | ||
|
||
<Spacing /> | ||
|
||
<PopoverButton | ||
content={<Text>Some warning.</Text>} | ||
variant={"warning"} | ||
renderButton={({ onClick }) => ( | ||
<FlatButton label={"warning"} onClick={onClick} /> | ||
)} | ||
/> | ||
|
||
<Spacing /> | ||
|
||
<PopoverButton | ||
content={ | ||
<Row> | ||
<Icon icon={stenaTrash} /> | ||
<Indent /> | ||
<Text>Something went wrong.</Text> | ||
</Row> | ||
} | ||
variant={"error"} | ||
renderButton={({ onClick }) => ( | ||
<FlatButton label={"error"} onClick={onClick} /> | ||
)} | ||
/> | ||
</Box> | ||
); | ||
|
||
export const ControlOpen = () => ( | ||
<Box indent={10} spacing={10} display={"inline-block"}> | ||
<Popover2 content={<ActionPrompt />} visible> | ||
<FlatButton leftIcon={stenaTrash} /> | ||
</Popover2> | ||
</Box> | ||
); | ||
|
||
const Alerter = () => { | ||
alert("I was rendered."); | ||
|
||
return <Text>I alert when I am rendered.</Text>; | ||
}; | ||
|
||
export const Lazy = () => ( | ||
<Box indent={10} spacing={10} display={"inline-block"}> | ||
<PopoverButton | ||
content={<Alerter />} | ||
lazy | ||
renderButton={({ onClick }) => ( | ||
<FlatButton leftIcon={stenaTrash} onClick={onClick} /> | ||
)} | ||
/> | ||
</Box> | ||
); |
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,109 @@ | ||
import * as React from "react"; | ||
import { PropsWithChildren, ReactNode, useRef } from "react"; | ||
import { Placement } from "../tooltip/Tooltip"; | ||
import { | ||
arrow, | ||
autoUpdate, | ||
flip, | ||
FloatingArrow, | ||
FloatingFocusManager, | ||
offset, | ||
shift, | ||
useDismiss, | ||
useFloating, | ||
useInteractions, | ||
useRole, | ||
useTransitionStyles, | ||
} from "@floating-ui/react"; | ||
import cx from "classnames"; | ||
import moduleStyles from "./Popover2.module.css"; | ||
|
||
export type PopoverVariant = | ||
| "standard" | ||
| "info" | ||
| "warning" | ||
| "error" | ||
| "outlined"; | ||
|
||
export type PopoverTheme = "light" | "dark"; | ||
|
||
export interface Popover2Props extends PropsWithChildren { | ||
visible?: boolean; | ||
onRequestClose?: () => void; | ||
placement?: Placement; | ||
arrow?: boolean; | ||
disablePadding?: boolean; | ||
lazy?: boolean; | ||
variant?: PopoverVariant; | ||
theme?: PopoverTheme; | ||
content: ReactNode; | ||
} | ||
|
||
const ARROW_WIDTH = 12; | ||
const ARROW_HEIGHT = 8; | ||
const GAP = 2; | ||
|
||
export const Popover2: React.FC<Popover2Props> = ({ | ||
children, | ||
variant, | ||
content, | ||
visible, | ||
arrow: arrowVisible = true, | ||
}) => { | ||
const arrowRef = useRef(null); | ||
|
||
const { refs, floatingStyles, context } = useFloating({ | ||
open: visible, | ||
middleware: [ | ||
offset(ARROW_HEIGHT + GAP), | ||
flip({ padding: 5 }), | ||
shift({ padding: 5 }), | ||
arrow({ element: arrowRef }), | ||
], | ||
whileElementsMounted: autoUpdate, | ||
}); | ||
|
||
const { isMounted, styles } = useTransitionStyles(context, { | ||
initial: { | ||
opacity: 0, | ||
}, | ||
}); | ||
|
||
const dismiss = useDismiss(context); | ||
const role = useRole(context); | ||
|
||
const { getReferenceProps } = useInteractions([dismiss, role]); | ||
|
||
return ( | ||
<> | ||
<div ref={refs.setReference} {...getReferenceProps()}> | ||
{children} | ||
</div> | ||
|
||
{isMounted && ( | ||
<FloatingFocusManager context={context} modal={false}> | ||
<div ref={refs.setFloating} style={floatingStyles}> | ||
<div | ||
style={styles} | ||
className={cx( | ||
moduleStyles.floating, | ||
variant && moduleStyles.withIcon | ||
)} | ||
> | ||
{content} | ||
{arrowVisible && ( | ||
<FloatingArrow | ||
ref={arrowRef} | ||
context={context} | ||
width={ARROW_WIDTH} | ||
height={ARROW_HEIGHT} | ||
fill={"white"} | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
</FloatingFocusManager> | ||
)} | ||
</> | ||
); | ||
}; |
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,28 @@ | ||
import * as React from "react"; | ||
import { ReactNode } from "react"; | ||
import { Popover2, Popover2Props } from "./Popover2"; | ||
import { useBoolean } from "@stenajs-webui/core"; | ||
|
||
export type PopoverButtonRenderer = ( | ||
args: PopoverButtonRendererArgs | ||
) => ReactNode; | ||
|
||
export interface PopoverButtonRendererArgs { | ||
onClick: () => void; | ||
} | ||
|
||
export interface PopoverButtonProps extends Omit<Popover2Props, "children"> { | ||
renderButton: PopoverButtonRenderer; | ||
} | ||
|
||
export const PopoverButton: React.FC<PopoverButtonProps> = ({ | ||
renderButton, | ||
...popoverProps | ||
}) => { | ||
const [isOpen, open, close] = useBoolean(false); | ||
return ( | ||
<Popover2 {...popoverProps} visible={isOpen} onRequestClose={close}> | ||
{renderButton({ onClick: open })} | ||
</Popover2> | ||
); | ||
}; |
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