Skip to content

Commit

Permalink
Merge pull request #57 from CivicDataLab/dev
Browse files Browse the repository at this point in the history
add dialog components
  • Loading branch information
PixeledCode authored Mar 24, 2023
2 parents cebaaf7 + 2faae5d commit 57c71d2
Show file tree
Hide file tree
Showing 30 changed files with 1,155 additions and 12 deletions.
11 changes: 8 additions & 3 deletions apps/web/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
export function switchTheme() {
const isDark = document.documentElement.getAttribute('data-theme');
if (isDark === 'dark') {
/**
* Toggles the theme of the page between light and dark.
* Dark and light themes are defined by the CSS variables
* `--color-bg-dark` and `--color-bg-light`.
*/
export function switchTheme(): void {
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
if (isDark) {
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem('opub-theme', 'light');
} else {
Expand Down
2 changes: 2 additions & 0 deletions packages/opub-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
},
"dependencies": {
"@hookform/resolvers": "^2.9.11",
"@radix-ui/react-alert-dialog": "^1.0.3",
"@radix-ui/react-checkbox": "^1.0.1",
"@radix-ui/react-dialog": "^1.0.3",
"@radix-ui/react-label": "^2.0.0",
"@radix-ui/react-popover": "^1.0.5",
"@radix-ui/react-progress": "^1.0.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import '../../../styles/common';

.AlertDialog {
border: 1px solid black;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Meta, StoryObj } from '@storybook/react';
import { Button } from '../Button';
import { Dialog, Content, Trigger } from './AlertDialog';

/**
* A modal dialog that interrupts the user with important content and expects a response.
*
* Reference: https://www.radix-ui.com/docs/primitives/components/alert-dialog
*/
const meta = {
component: Content,
} satisfies Meta<typeof Content>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: ({ ...args }) => {
return (
<Dialog>
<Trigger>
<Button>Discard Changes</Button>
</Trigger>
<Content {...args} />
</Dialog>
);
},
args: {
title: 'Dialog Title',
children: 'Are you sure you want to discard all of your notes?',
primaryAction: {
content: 'Yes, discard',
onAction: () => console.log('discard'),
destructive: true,
},
secondaryActions: [
{
content: 'No, keep changes',
onAction: () => console.log('no'),
},
],
},
};
13 changes: 13 additions & 0 deletions packages/opub-ui/src/components/AlertDialog/AlertDialog.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import { AlertDialog } from "./AlertDialog";

describe("AlertDialog Tests", () => {
beforeEach(() => {
render(<AlertDialog>Component</AlertDialog>);
});

test("should show Component text all the time", () => {
expect(screen.getByText(/Component/i)).toBeInTheDocument();
});
});
99 changes: 99 additions & 0 deletions packages/opub-ui/src/components/AlertDialog/AlertDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import * as AlertDialog from '@radix-ui/react-alert-dialog';
import cx from 'classnames';
import React, { forwardRef, Ref } from 'react';
import { Footer, FooterProps } from '../Dialog/components';
import styles from '../Dialog/Dialog.module.scss';
import { Header } from './components';

const Dialog = AlertDialog.Root;

interface TriggerProps extends AlertDialog.DialogTriggerProps {}
const Trigger = forwardRef(
(
{ children, ...props }: TriggerProps,
ref: Ref<HTMLButtonElement> | undefined
) => {
return (
<AlertDialog.Trigger {...props} asChild ref={ref}>
{children}
</AlertDialog.Trigger>
);
}
);

type ContentProps = {
/** The content to display inside modal */
children: React.ReactNode;
/** Inner content of the footer */
footer?: React.ReactNode;
/** The content for the title of the modal */
title: string | React.ReactNode;
/**
* Hide the title in the modal
* @default false
*/
titleHidden?: boolean;
/** id for the dialog */
id?: string;
/** Disable animations and open modal instantly */
instant?: boolean;
/** Increases the modal width */
large?: boolean;
/** Decreases the modal width */
small?: boolean;
/** Limits modal height on large sceens with scrolling */
limitHeight?: boolean;
/** Sets modal to the height of the viewport on small screens */
fullScreen?: boolean;
} & AlertDialog.DialogContentProps &
FooterProps;

const Content = forwardRef((props: ContentProps, ref: any) => {
const {
children,
title,
titleHidden = false,
id,
instant,
large,
small,
limitHeight,
fullScreen,
footer,
primaryAction,
secondaryActions,
...others
} = props;
const rId = React.useId();
const finalId = props.id || rId;

const classname = cx(
styles.Dialog,
small && styles.sizeSmall,
large && styles.sizeLarge,
limitHeight && styles.limitHeight,
fullScreen && styles.fullScreen
);

return (
<div className={`opub-Dialog`}>
<AlertDialog.Portal>
<AlertDialog.Overlay className={styles.Overlay} />
<AlertDialog.Content ref={ref} className={classname} {...others}>
<div className="sr-only">
<AlertDialog.Title>{title}</AlertDialog.Title>
</div>
<Header id={finalId} titleHidden={titleHidden} children={title} />
<div className={styles.Content}>{children}</div>
<Footer
children={footer}
primaryAction={primaryAction}
secondaryActions={secondaryActions}
/>
</AlertDialog.Content>
</AlertDialog.Portal>
</div>
);
});

export { Dialog, Trigger, Content };
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { AlertDialogCancel } from '@radix-ui/react-alert-dialog';
import { CloseButton } from '@ui/components/Dialog/components';
import { Flex } from '@ui/components/Flex';
import React from 'react';
import { Box } from '../../../Box';
import { Text } from '../../../Text';

export interface HeaderProps {
id: string;
titleHidden: boolean;
children?: React.ReactNode;
onClose?(): void;
}

export function Header({ id, children, titleHidden, onClose }: HeaderProps) {
const titleHiddenMarkup = (
<Box position="absolute" insetInlineEnd="0" zIndex="1">
<Flex gap="var(--space-4)" justifyContent="end" alignItems="center">
<CloseButton titleHidden={titleHidden} onClick={onClose} />
</Flex>
</Box>
);
if (titleHidden || !children) {
return titleHiddenMarkup;
}

return (
<Box
paddingBlockStart="4"
paddingBlockEnd="4"
paddingInlineStart="5"
paddingInlineEnd="5"
borderBlockEnd="divider"
>
<Flex
gap="var(--space-4)"
alignItems="center"
justifyContent="space-between"
>
<Text id={id} as="h2" variant="headingLg" breakWord>
{children}
</Text>
<AlertDialogCancel asChild>
<CloseButton titleHidden={titleHidden} onClick={onClose} />
</AlertDialogCancel>
</Flex>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Header } from './Header/Header';
1 change: 1 addition & 0 deletions packages/opub-ui/src/components/AlertDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AlertDialog } from "./AlertDialog";
20 changes: 20 additions & 0 deletions packages/opub-ui/src/components/Button/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,23 @@ export function buttonFrom(
</Button>
);
}

export function buttonsFrom(
action: ComplexAction,
overrides?: Partial<ButtonProps>
): React.ReactElement<ButtonProps>;
export function buttonsFrom(
actions: ComplexAction[],
overrides?: Partial<ButtonProps>
): React.ReactElement<ButtonProps>[];
export function buttonsFrom(
actions: ComplexAction[] | ComplexAction,
overrides: Partial<ButtonProps> = {}
) {
if (Array.isArray(actions)) {
return actions.map((action, index) => buttonFrom(action, overrides, index));
} else {
const action = actions;
return buttonFrom(action, overrides);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ export const Combobox = React.forwardRef<HTMLInputElement, ComboboxSingleProps>(
const backdropMarkup = <div className={cx(inputStyles.Backdrop)} />;

const finalContent = verticalContent ? (
<div
className={inputStyles.VerticalContent}
// id={`${final}-VerticalContent`}
ref={verticalContentRef}
// onClick={handleClickChild}
>
<div className={inputStyles.VerticalContent} ref={verticalContentRef}>
{verticalContent}
{element}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const MultiSelect = forwardRef<HTMLInputElement, ComboboxProps>(
// this behavior and put DOM focus on the items.
virtualFocus: false,
sameWidth: true,
gutter: verticalContent ? 18 : 8,
gutter: 8,
defaultValue,
value,
setValue: onChange,
Expand Down
Loading

0 comments on commit 57c71d2

Please # to comment.