aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-06-24 11:42:21 -0300
committerSebastian <sebasjm@gmail.com>2022-06-24 11:42:21 -0300
commit50379a1d5b89822dd32618c32433cf12d1a1779e (patch)
treef6851306ed7bb39429f5336ece0151fee128631f
parentb06ae62de00a536525eac342c3dcb99d45c9eb86 (diff)
mui menu, select input inprogress
-rw-r--r--packages/taler-wallet-webextension/src/mui/Button.tsx15
-rw-r--r--packages/taler-wallet-webextension/src/mui/Menu.stories.tsx172
-rw-r--r--packages/taler-wallet-webextension/src/mui/Menu.tsx135
-rw-r--r--packages/taler-wallet-webextension/src/mui/index.stories.tsx3
-rw-r--r--packages/taler-wallet-webextension/src/mui/input/SelectStandard.tsx44
-rw-r--r--packages/taler-wallet-webextension/src/mui/style.tsx19
6 files changed, 376 insertions, 12 deletions
diff --git a/packages/taler-wallet-webextension/src/mui/Button.tsx b/packages/taler-wallet-webextension/src/mui/Button.tsx
index 7afa3643c..a7657ae29 100644
--- a/packages/taler-wallet-webextension/src/mui/Button.tsx
+++ b/packages/taler-wallet-webextension/src/mui/Button.tsx
@@ -16,11 +16,11 @@
import { ComponentChildren, h, VNode, JSX } from "preact";
import { css } from "@linaria/core";
// eslint-disable-next-line import/extensions
-import { theme, ripple, Colors, rippleOutlined } from "./style";
+import { theme, Colors, rippleEnabled, rippleEnabledOutlined } from "./style";
// eslint-disable-next-line import/extensions
import { alpha } from "./colors/manipulation";
-const buttonBaseStyle = css`
+export const buttonBaseStyle = css`
display: inline-flex;
align-items: center;
justify-content: center;
@@ -318,6 +318,7 @@ interface BaseProps extends JSX.HTMLAttributes<HTMLButtonElement> {
onClick?: () => Promise<void>;
containedRipple?: boolean;
children?: ComponentChildren;
+ svg?: any;
}
function ButtonBase({
@@ -325,7 +326,7 @@ function ButtonBase({
children,
containedRipple,
onClick,
- dangerouslySetInnerHTML,
+ svg,
...rest
}: BaseProps): VNode {
function doClick(): void {
@@ -334,14 +335,14 @@ function ButtonBase({
const classNames = [
buttonBaseStyle,
_class,
- containedRipple ? ripple : rippleOutlined,
+ containedRipple ? rippleEnabled : rippleEnabledOutlined,
].join(" ");
- if (dangerouslySetInnerHTML) {
+ if (svg) {
return (
<button
onClick={doClick}
class={classNames}
- dangerouslySetInnerHTML={dangerouslySetInnerHTML}
+ dangerouslySetInnerHTML={{ __html: svg }}
{...rest}
/>
);
@@ -375,7 +376,7 @@ export function IconButton({
fill: currentColor;
`,
].join(" ")}
- dangerouslySetInnerHTML={{ __html: svg }}
+ svg={svg}
/>
);
}
diff --git a/packages/taler-wallet-webextension/src/mui/Menu.stories.tsx b/packages/taler-wallet-webextension/src/mui/Menu.stories.tsx
new file mode 100644
index 000000000..60e373be4
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/mui/Menu.stories.tsx
@@ -0,0 +1,172 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Menu, MenuItem } from "./Menu.jsx";
+import { Paper } from "./Paper.js";
+
+export default {
+ title: "mui/menu",
+ component: Menu,
+};
+
+export const BasicExample = (): VNode => {
+ const [open, setOpen] = useState(false);
+ async function handleClose(): Promise<void> {
+ setOpen(false);
+ }
+ async function handleClick(): Promise<void> {
+ setOpen(true);
+ }
+ return (
+ <Menu open={open} onClose={handleClose} onClick={handleClick}>
+ <MenuItem onClick={handleClose}>Profile</MenuItem>
+ <MenuItem onClick={handleClose}>My account</MenuItem>
+ <MenuItem onClick={handleClose}>Logout</MenuItem>
+ </Menu>
+ );
+};
+
+import { styled } from "@linaria/react";
+// eslint-disable-next-line import/extensions
+import { theme } from "./style";
+import { Typography } from "./Typography.js";
+import { Divider } from "./Divider.js";
+
+const ListItemIcon = styled.div`
+ min-width: 36px;
+ color: ${theme.palette.action.active};
+ flex-shrink: 0;
+ display: inline-flex;
+`;
+
+const IconCut = (): VNode => (
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ aria-hidden="true"
+ focusable="false"
+ style={{
+ width: "1em",
+ height: "1em",
+ }}
+ >
+ <path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z" />
+ </svg>
+);
+
+const IconCopy = (): VNode => (
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ aria-hidden="true"
+ focusable="false"
+ style={{
+ width: "1em",
+ height: "1em",
+ }}
+ >
+ <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
+ </svg>
+);
+
+const IconPaste = (): VNode => (
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ aria-hidden="true"
+ focusable="false"
+ style={{
+ width: "1em",
+ height: "1em",
+ }}
+ >
+ <path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z" />
+ </svg>
+);
+
+const IconCloud = (): VNode => (
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ aria-hidden="true"
+ focusable="false"
+ style={{
+ width: "1em",
+ height: "1em",
+ }}
+ >
+ <path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z" />
+ </svg>
+);
+
+const ListItemText = styled.div`
+ flex: 1 1 auto;
+ min-width: 0px;
+ margin-top: 4px;
+ margin-bottom: 4px;
+`;
+
+export function IconMenu(): VNode {
+ return (
+ <div style={{ width: 320 }}>
+ <Paper>
+ <ul>
+ <MenuItem>
+ <ListItemIcon>
+ <IconCut />
+ </ListItemIcon>
+ <ListItemText>Cut</ListItemText>
+ <Typography variant="body2" /* color="text.secondary" */>
+ ⌘X
+ </Typography>
+ </MenuItem>
+ <MenuItem>
+ <ListItemIcon>
+ <IconCopy />
+ </ListItemIcon>
+ <ListItemText>Copy</ListItemText>
+ <Typography variant="body2" /* color="text.secondary" */>
+ ⌘C
+ </Typography>
+ </MenuItem>
+ <MenuItem>
+ <ListItemIcon>
+ <IconPaste />
+ </ListItemIcon>
+ <ListItemText>Paste</ListItemText>
+ <Typography variant="body2" /* color="text.secondary" */>
+ ⌘V
+ </Typography>
+ </MenuItem>
+ <Divider />
+ <MenuItem>
+ <ListItemIcon>
+ <IconCloud />
+ </ListItemIcon>
+ <ListItemText>Web Clipboard</ListItemText>
+ </MenuItem>
+ </ul>
+ </Paper>
+ </div>
+ );
+}
diff --git a/packages/taler-wallet-webextension/src/mui/Menu.tsx b/packages/taler-wallet-webextension/src/mui/Menu.tsx
new file mode 100644
index 000000000..941abfee4
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/mui/Menu.tsx
@@ -0,0 +1,135 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+import { css } from "@linaria/core";
+import { h, VNode, Fragment, ComponentChildren } from "preact";
+import { buttonBaseStyle } from "./Button.js";
+import { alpha } from "./colors/manipulation.js";
+import { Paper } from "./Paper.js";
+// eslint-disable-next-line import/extensions
+import { Colors, ripple, theme } from "./style";
+
+interface Props {
+ children: ComponentChildren;
+ onClose: () => Promise<void>;
+ onClick: () => Promise<void>;
+ open?: boolean;
+}
+
+const menuPaper = css`
+ max-height: calc(100% - 96px);
+ -webkit-overflow-scrolling: touch;
+`;
+
+const menuList = css`
+ outline: 0px;
+`;
+
+export function Menu({ children, onClose, onClick, open }: Props): VNode {
+ return (
+ <Popover class={menuPaper}>
+ <ul class={menuList}>{children}</ul>
+ </Popover>
+ );
+}
+
+const popoverRoot = css``;
+
+const popoverPaper = css`
+ position: absolute;
+ overflow-y: auto;
+ overflow-x: hidden;
+ min-width: 16px;
+ min-height: 16px;
+ max-width: calc(100% - 32px);
+ max-height: calc(100% - 32px);
+ outline: 0;
+`;
+
+function Popover({ children }: any): VNode {
+ return (
+ <div class={popoverRoot}>
+ <Paper class={popoverPaper}>{children}</Paper>
+ </div>
+ );
+}
+
+const root = css`
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ position: relative;
+ text-decoration: none;
+ min-height: 48px;
+ padding-top: 6px;
+ padding-bottom: 6px;
+ box-sizing: border-box;
+ white-space: nowrap;
+ appearance: none;
+
+ &:not([data-disableGutters]) {
+ padding-left: 16px;
+ padding-right: 16px;
+ }
+
+ [data-dividers] {
+ border-bottom: 1px solid ${theme.palette.divider};
+ background-clip: padding-box;
+ }
+ &:hover {
+ text-decoration: none;
+ background-color: var(--color-main-alpha-half);
+ @media (hover: none) {
+ background-color: transparent;
+ }
+ }
+`;
+
+export function MenuItem({
+ children,
+ onClick,
+ color = "primary",
+}: {
+ children: ComponentChildren;
+ onClick?: () => Promise<void>;
+ color?: Colors;
+}): VNode {
+ function doClick(): void {
+ // if (onClick) onClick();
+ return;
+ }
+ return (
+ <li
+ onClick={doClick}
+ disabled={false}
+ role="menuitem"
+ class={[buttonBaseStyle, root, ripple].join(" ")}
+ style={{
+ "--color-main": theme.palette[color].main,
+ "--color-dark": theme.palette[color].dark,
+ "--color-grey-or-dark": !color
+ ? theme.palette.grey.A100
+ : theme.palette[color].dark,
+ "--color-main-alpha-half": alpha(theme.palette[color].main, 0.7),
+ "--color-main-alpha-opacity": alpha(
+ theme.palette[color].main,
+ theme.palette.action.hoverOpacity,
+ ),
+ }}
+ >
+ {children}
+ </li>
+ );
+}
diff --git a/packages/taler-wallet-webextension/src/mui/index.stories.tsx b/packages/taler-wallet-webextension/src/mui/index.stories.tsx
index ca332f4ea..b70b56698 100644
--- a/packages/taler-wallet-webextension/src/mui/index.stories.tsx
+++ b/packages/taler-wallet-webextension/src/mui/index.stories.tsx
@@ -24,5 +24,6 @@ import * as a3 from "./Grid.stories.js";
import * as a4 from "./Paper.stories.js";
import * as a5 from "./TextField.stories.js";
import * as a6 from "./Alert.stories.js";
+import * as a7 from "./Menu.stories.js";
-export default [a1, a3, a4, a5, a6];
+export default [a1, a3, a4, a5, a6, a7];
diff --git a/packages/taler-wallet-webextension/src/mui/input/SelectStandard.tsx b/packages/taler-wallet-webextension/src/mui/input/SelectStandard.tsx
index d9d9b02ca..6fb2823c7 100644
--- a/packages/taler-wallet-webextension/src/mui/input/SelectStandard.tsx
+++ b/packages/taler-wallet-webextension/src/mui/input/SelectStandard.tsx
@@ -13,8 +13,46 @@
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { h, VNode } from "preact";
+import { css } from "@linaria/core";
+import { h, VNode, Fragment } from "preact";
-export function SelectStandard(): VNode {
- return <div />;
+const SelectSelect = css`
+ height: "auto";
+ min-height: "1.4374em";
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+`;
+
+const SelectIcon = css``;
+
+const SelectNativeInput = css`
+ bottom: 0px;
+ left: 0px;
+ position: "absolute";
+ opacity: 0px;
+ pointer-events: "none";
+ width: 100%;
+ box-sizing: border-box;
+`;
+
+export function SelectStandard({ value }: any): VNode {
+ return (
+ <Fragment>
+ <div class={SelectSelect} role="button">
+ {!value ? (
+ // notranslate needed while Google Translate will not fix zero-width space issue
+ <span className="notranslate">&#8203;</span>
+ ) : (
+ value
+ )}
+ <input
+ class={SelectNativeInput}
+ aria-hidden
+ tabIndex={-1}
+ value={Array.isArray(value) ? value.join(",") : value}
+ />
+ </div>
+ </Fragment>
+ );
}
diff --git a/packages/taler-wallet-webextension/src/mui/style.tsx b/packages/taler-wallet-webextension/src/mui/style.tsx
index 3f0a61c86..32fa412e5 100644
--- a/packages/taler-wallet-webextension/src/mui/style.tsx
+++ b/packages/taler-wallet-webextension/src/mui/style.tsx
@@ -63,6 +63,23 @@ export const ripple = css`
transition: background 0.2s;
+ &:hover {
+ background: var(--color-main)
+ radial-gradient(circle, transparent 1%, var(--color-dark) 1%)
+ center/15000%;
+ }
+ &:active {
+ background-color: var(--color-main);
+ background-size: 100%;
+ transition: background 0s;
+ }
+`;
+
+export const rippleEnabled = css`
+ background-position: center;
+
+ transition: background 0.2s;
+
&:hover:enabled {
background: var(--color-main)
radial-gradient(circle, transparent 1%, var(--color-dark) 1%)
@@ -75,7 +92,7 @@ export const ripple = css`
}
`;
-export const rippleOutlined = css`
+export const rippleEnabledOutlined = css`
background-position: center;
transition: background 0.2s;