Updates all icons to use SVGs

This commit is contained in:
Chris Anderson 2023-03-06 20:41:26 -06:00
parent 2a833e571a
commit cdf5d06224
28 changed files with 200 additions and 77 deletions

6
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,6 @@
{
"eslint.workingDirectories": [
"./apps/ui",
"./apps/platform"
]
}

View file

@ -19,7 +19,6 @@
"@types/uuid": "^9.0.0", "@types/uuid": "^9.0.0",
"autoprefixer": "^10.4.12", "autoprefixer": "^10.4.12",
"axios": "0.27.2", "axios": "0.27.2",
"bootstrap-icons": "1.10.3",
"clsx": "^1.2.1", "clsx": "^1.2.1",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"date-fns-tz": "^1.3.7", "date-fns-tz": "^1.3.7",

View file

@ -1,5 +1,5 @@
.ui-button { .ui-button {
display: inline-block; display: inline-flex;
border: 1px solid transparent; border: 1px solid transparent;
background: transparent; background: transparent;
border-radius: var(--border-radius); border-radius: var(--border-radius);
@ -14,14 +14,21 @@
transition: .2s; transition: .2s;
text-decoration: none; text-decoration: none;
position: relative; position: relative;
align-items: center;
gap: 5px;
} }
.ui-button i { .ui-button .button-icon,
margin-right: 5px; .ui-button .button-icon svg {
margin-left: -1px; width: 16px;
height: 16px;
} }
.ui-button.ui-button-no-children i { .ui-button .button-icon {
margin-left: -2px;
}
.ui-button.ui-button-no-children .button-icon {
margin: 0; margin: 0;
} }

View file

@ -10,7 +10,7 @@ type BaseButtonProps = PropsWithChildren<{
children?: React.ReactNode children?: React.ReactNode
variant?: ButtonVariant variant?: ButtonVariant
size?: ButtonSize size?: ButtonSize
icon?: string icon?: React.ReactNode
isLoading?: boolean isLoading?: boolean
}> & JSX.IntrinsicElements['button'] }> & JSX.IntrinsicElements['button']
@ -28,7 +28,7 @@ const LinkButton = forwardRef(function LinkButton(props: LinkButtonProps, ref: R
<Link to={props.to} className={ <Link to={props.to} className={
`ui-button ${props.variant ?? 'primary'} ${props.size ?? 'regular'}` `ui-button ${props.variant ?? 'primary'} ${props.size ?? 'regular'}`
} ref={ref}> } ref={ref}>
{props.icon != null && <i className={`bi bi-${props.icon}`} /> } {props.icon && (<span className="button-icon">{props.icon}</span>)}
{props.children} {props.children}
</Link> </Link>
) )
@ -61,7 +61,7 @@ const Button = forwardRef(function Button(props: ButtonProps, ref: Ref<HTMLButto
ref={ref} ref={ref}
disabled={disabled ?? isLoading} disabled={disabled ?? isLoading}
> >
{icon != null && <i className={`bi bi-${icon}`} /> } {icon && (<span className="button-icon">{icon}</span>)}
{children} {children}
</button> </button>
) )

View file

@ -5,12 +5,13 @@
box-shadow: rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px; box-shadow: rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
z-index: 999; z-index: 999;
min-width: 150px; min-width: 150px;
padding: 5px 0; padding: 3px 0;
font-size: 13px;
overflow: hidden;
} }
.ui-menu-item { .ui-menu-item {
padding: 10px; padding: 7px 10px;
border-bottom: 1px solid var(--color-grey);
display: flex; display: flex;
gap: 5px; gap: 5px;
align-items: center; align-items: center;
@ -25,7 +26,8 @@
} }
.ui-menu-item svg { .ui-menu-item svg {
width: 16px; width: 14px;
height: 16px; height: 14px;
margin-top: -1px; margin-top: -1px;
margin-right: 5px;
} }

View file

@ -4,6 +4,7 @@ import { usePopper } from 'react-popper'
import Button, { ButtonSize, ButtonVariant } from './Button' import Button, { ButtonSize, ButtonVariant } from './Button'
import './Menu.css' import './Menu.css'
import { Placement } from '@popperjs/core' import { Placement } from '@popperjs/core'
import { ThreeDotsIcon } from './icons'
interface MenuProps { interface MenuProps {
thing?: string thing?: string
@ -40,7 +41,7 @@ export default function Menu({ children, variant, size, placement }: PropsWithCh
ref={setReferenceElement} ref={setReferenceElement}
variant={variant ?? 'plain'} variant={variant ?? 'plain'}
size={size} size={size}
icon="three-dots"></Popover.Button> icon={<ThreeDotsIcon />}></Popover.Button>
<Popover.Panel <Popover.Panel
ref={setPopperElement} ref={setPopperElement}

View file

@ -1,6 +1,7 @@
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from '@headlessui/react'
import { Fragment, PropsWithChildren, ReactNode } from 'react' import { Fragment, PropsWithChildren, ReactNode } from 'react'
import Button from './Button' import Button from './Button'
import { CloseIcon } from './icons'
import './Modal.css' import './Modal.css'
export interface ModalStateProps { export interface ModalStateProps {
@ -55,7 +56,7 @@ export default function Modal({
<Button <Button
variant="secondary" variant="secondary"
onClick={() => onClose(false)} onClick={() => onClose(false)}
icon="x-lg" icon={<CloseIcon />}
> >
{'Exit'} {'Exit'}
</Button> </Button>

View file

@ -1,10 +1,10 @@
import * as React from 'react' import * as React from 'react'
import { NavLink as BaseNavLink, NavLinkProps as BaseNavLinkProps } from 'react-router-dom' import { NavLink as BaseNavLink, NavLinkProps as BaseNavLinkProps } from 'react-router-dom'
export type NavLinkProps = BaseNavLinkProps & { key: string, icon?: string } export type NavLinkProps = BaseNavLinkProps & { key: string, icon?: React.ReactNode }
const NavLink = React.forwardRef( const NavLink = React.forwardRef(
function NavLink({ ...props }: NavLinkProps, ref: React.Ref<HTMLAnchorElement> | undefined) { function NavLink({ icon, ...props }: NavLinkProps, ref: React.Ref<HTMLAnchorElement> | undefined) {
return ( return (
<BaseNavLink <BaseNavLink
ref={ref} ref={ref}
@ -19,7 +19,7 @@ const NavLink = React.forwardRef(
} }
> >
<> <>
{props.icon && <i className={`bi ${props.icon}`} />} {icon && (<div className="nav-icon">{icon}</div>)}
&nbsp; &nbsp;
{props.children} {props.children}
</> </>

View file

@ -17,6 +17,7 @@
.ui-pagination .pagination-button { .ui-pagination .pagination-button {
background: var(--color-background); background: var(--color-background);
font-size: 16px; font-size: 16px;
line-height: 15px;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
color: var(--color-primary); color: var(--color-primary);
@ -29,7 +30,7 @@
.ui-pagination .pagination-button:disabled { .ui-pagination .pagination-button:disabled {
color: var(--color-primary-soft); color: var(--color-primary-soft);
cursor: auto; cursor: not-allowed;
} }
.ui-pagination .pagination-button:disabled:hover { .ui-pagination .pagination-button:disabled:hover {
@ -41,13 +42,22 @@
font-weight: 500; font-weight: 500;
} }
.ui-pagination .prev i { .ui-pagination .prev,
margin-right: 5px; .ui-pagination .next {
display: flex;
align-items: center;
gap: 5px;
}
.ui-pagination .prev svg,
.ui-pagination .next svg {
width: 16px;
} }
.ui-pagination .next { .ui-pagination .next {
border-right-width: 0px; border-right-width: 0px;
} }
.ui-pagination .next i {
margin-left: 5px; .ui-pagination .next svg {
width: 16px;
} }

View file

@ -1,3 +1,4 @@
import { ChevronLeftIcon, ChevronRightIcon } from './icons'
import './Pagination.css' import './Pagination.css'
interface PaginationProps { interface PaginationProps {
@ -81,7 +82,7 @@ export default function Pagination({
<button className="pagination-button prev" <button className="pagination-button prev"
disabled={page <= 0} disabled={page <= 0}
onClick={() => onChangePage(page - 1)}> onClick={() => onChangePage(page - 1)}>
<i className="bi bi-arrow-left"></i> <ChevronLeftIcon />
Previous Previous
</button> </button>
{ {
@ -95,7 +96,7 @@ export default function Pagination({
disabled={(page + 1) >= total} disabled={(page + 1) >= total}
onClick={() => onChangePage(page + 1)}> onClick={() => onChangePage(page + 1)}>
Next Next
<i className="bi bi-arrow-right"></i> <ChevronRightIcon />
</button> </button>
</div> </div>
) )

View file

@ -59,7 +59,7 @@ nav {
} }
nav a { nav a {
display: block; display: flex;
padding: 15px; padding: 15px;
text-decoration: none; text-decoration: none;
color: var(--color-primary); color: var(--color-primary);
@ -67,6 +67,8 @@ nav a {
font-size: 15px; font-size: 15px;
font-weight: 500; font-weight: 500;
margin-bottom: 5px; margin-bottom: 5px;
align-items: center;
gap: 5px;
} }
nav a:hover { nav a:hover {
@ -79,8 +81,10 @@ nav a.selected {
background: var(--color-primary); background: var(--color-primary);
} }
nav a i { nav a .nav-icon {
margin-right: 5px; width: 16px;
height: 16px;
display: flex;
} }
.sidebar-profile { .sidebar-profile {

View file

@ -2,7 +2,7 @@ import './Sidebar.css'
import NavLink from './NavLink' import NavLink from './NavLink'
import { ReactComponent as Logo } from '../assets/logo.svg' import { ReactComponent as Logo } from '../assets/logo.svg'
import { Link, NavLinkProps, useNavigate } from 'react-router-dom' import { Link, NavLinkProps, useNavigate } from 'react-router-dom'
import { PropsWithChildren, useContext } from 'react' import { PropsWithChildren, ReactNode, useContext } from 'react'
import { AdminContext, ProjectContext } from '../contexts' import { AdminContext, ProjectContext } from '../contexts'
import api from '../api' import api from '../api'
import { PreferencesContext } from './PreferencesContext' import { PreferencesContext } from './PreferencesContext'
@ -10,9 +10,10 @@ import { useResolver } from '../hooks'
import { SingleSelect } from './form/SingleSelect' import { SingleSelect } from './form/SingleSelect'
import Button, { LinkButton } from './Button' import Button, { LinkButton } from './Button'
import ButtonGroup from './ButtonGroup' import ButtonGroup from './ButtonGroup'
import { MoonIcon, PlusIcon, SunIcon } from './icons'
interface SidebarProps { interface SidebarProps {
links?: Array<NavLinkProps & { key: string, icon: string }> links?: Array<NavLinkProps & { key: string, icon: ReactNode }>
} }
export default function Sidebar({ children, links }: PropsWithChildren<SidebarProps>) { export default function Sidebar({ children, links }: PropsWithChildren<SidebarProps>) {
@ -51,7 +52,7 @@ export default function Sidebar({ children, links }: PropsWithChildren<SidebarPr
textAlign: 'center', textAlign: 'center',
}} }}
> >
<LinkButton size="small" variant="primary" to="/projects/new" icon="plus"> <LinkButton size="small" variant="primary" to="/projects/new" icon={<PlusIcon />}>
{'Create Project'} {'Create Project'}
</LinkButton> </LinkButton>
</div> </div>
@ -74,7 +75,7 @@ export default function Sidebar({ children, links }: PropsWithChildren<SidebarPr
<Button <Button
variant="plain" variant="plain"
size="small" size="small"
icon={preferences.mode === 'dark' ? 'moon' : 'sun'} icon={preferences.mode === 'dark' ? <MoonIcon /> : <SunIcon />}
onClick={() => setPreferences({ ...preferences, mode: preferences.mode === 'dark' ? 'light' : 'dark' })} onClick={() => setPreferences({ ...preferences, mode: preferences.mode === 'dark' ? 'light' : 'dark' })}
/> />
<Button <Button

View file

@ -1,31 +1,110 @@
export { default as ChevronLeftIcon } from '@heroicons/react/24/solid/ChevronLeftIcon' export const ChevronLeftIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
export { default as ChevronRightIcon } from '@heroicons/react/24/solid/ChevronRightIcon' <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
export { default as ChevronUpDownIcon } from '@heroicons/react/24/outline/ChevronUpDownIcon' </svg>
export { default as CheckIcon } from '@heroicons/react/24/outline/CheckIcon'
export { default as UserCircle } from '@heroicons/react/24/outline/UserCircleIcon'
export const DuplicateIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> export const ChevronRightIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
export const ChevronUpDownIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" />
</svg>
export const CheckIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
</svg>
export const UserCircle = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
export const PlusIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
export const ThreeDotsIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM12.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM18.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0z" />
</svg>
export const DuplicateIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" /> <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" />
</svg> </svg>
export const EditIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> export const EditIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" /> <path strokeLinecap="round" strokeLinejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
</svg> </svg>
export const ArchiveIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> export const ArchiveIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5m6 4.125l2.25 2.25m0 0l2.25 2.25M12 13.875l2.25-2.25M12 13.875l-2.25 2.25M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" /> <path strokeLinecap="round" strokeLinejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5m6 4.125l2.25 2.25m0 0l2.25 2.25M12 13.875l2.25-2.25M12 13.875l-2.25 2.25M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" />
</svg> </svg>
export const EmailIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> export const TrashIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
</svg>
export const EmailIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" /> <path strokeLinecap="round" strokeLinejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" />
</svg> </svg>
export const TextIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> export const TextIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 01.865-.501 48.172 48.172 0 003.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z" /> <path strokeLinecap="round" strokeLinejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 01.865-.501 48.172 48.172 0 003.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z" />
</svg> </svg>
export const PushIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> export const PushIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" /> <path strokeLinecap="round" strokeLinejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" />
</svg> </svg>
export const WebhookIcon = () => <svg height="24" viewBox="0 0 32 32" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m16 3c-3.855469 0-7 3.144531-7 7 0 2.09375 1.035156 3.871094 2.5 5.15625l-2.09375 3.875c-.136719-.019531-.265625-.03125-.40625-.03125-1.644531 0-3 1.355469-3 3s1.355469 3 3 3 3-1.355469 3-3c0-.796875-.328125-1.523437-.84375-2.0625l2.84375-5.28125-.75-.5c-1.347656-.894531-2.25-2.410156-2.25-4.15625 0-2.773437 2.226563-5 5-5 2.773438 0 5 2.226563 5 5 0 .585938-.097656 1.136719-.28125 1.65625l1.875.6875c.261719-.730469.40625-1.527344.40625-2.34375 0-3.855469-3.144531-7-7-7zm0 4c-1.644531 0-3 1.355469-3 3s1.355469 3 3 3c.140625 0 .269531-.011719.40625-.03125l2.75 4.375.5.8125.84375-.5c.734375-.425781 1.585938-.65625 2.5-.65625 2.773438 0 5 2.226563 5 5 0 2.773438-2.226562 5-5 5-1.488281 0-2.804687-.632812-3.71875-1.65625l-1.5 1.3125c1.28125 1.429688 3.152344 2.34375 5.21875 2.34375 3.855469 0 7-3.144531 7-7s-3.144531-7-7-7c-.921875 0-1.722656.363281-2.53125.6875l-2.28125-3.65625c.5-.535156.8125-1.25.8125-2.03125 0-1.644531-1.355469-3-3-3zm0 2c.5625 0 1 .4375 1 1s-.4375 1-1 1-1-.4375-1-1 .4375-1 1-1zm-8.15625 6.09375c-.800781.136719-1.601562.414063-2.34375.84375-3.335937 1.925781-4.488281 6.226563-2.5625 9.5625 1.925781 3.335938 6.222656 4.488281 9.5625 2.5625 1.910156-1.105469 2.941406-3.03125 3.25-5.0625h4.4375c.417969 1.15625 1.519531 2 2.8125 2 1.644531 0 3-1.355469 3-3s-1.355469-3-3-3c-1.292969 0-2.394531.84375-2.8125 2h-6.1875v1c0 1.726563-.890625 3.414063-2.5 4.34375-2.402344 1.386719-5.457031.558594-6.84375-1.84375s-.558594-5.457031 1.84375-6.84375c.53125-.308594 1.085938-.496094 1.65625-.59375zm1.15625 5.90625c.5625 0 1 .4375 1 1s-.4375 1-1 1-1-.4375-1-1 .4375-1 1-1zm14 0c.5625 0 1 .4375 1 1s-.4375 1-1 1-1-.4375-1-1 .4375-1 1-1z"/></svg> export const WebhookIcon = () => <svg height="24" viewBox="0 0 32 32" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m16 3c-3.855469 0-7 3.144531-7 7 0 2.09375 1.035156 3.871094 2.5 5.15625l-2.09375 3.875c-.136719-.019531-.265625-.03125-.40625-.03125-1.644531 0-3 1.355469-3 3s1.355469 3 3 3 3-1.355469 3-3c0-.796875-.328125-1.523437-.84375-2.0625l2.84375-5.28125-.75-.5c-1.347656-.894531-2.25-2.410156-2.25-4.15625 0-2.773437 2.226563-5 5-5 2.773438 0 5 2.226563 5 5 0 .585938-.097656 1.136719-.28125 1.65625l1.875.6875c.261719-.730469.40625-1.527344.40625-2.34375 0-3.855469-3.144531-7-7-7zm0 4c-1.644531 0-3 1.355469-3 3s1.355469 3 3 3c.140625 0 .269531-.011719.40625-.03125l2.75 4.375.5.8125.84375-.5c.734375-.425781 1.585938-.65625 2.5-.65625 2.773438 0 5 2.226563 5 5 0 2.773438-2.226562 5-5 5-1.488281 0-2.804687-.632812-3.71875-1.65625l-1.5 1.3125c1.28125 1.429688 3.152344 2.34375 5.21875 2.34375 3.855469 0 7-3.144531 7-7s-3.144531-7-7-7c-.921875 0-1.722656.363281-2.53125.6875l-2.28125-3.65625c.5-.535156.8125-1.25.8125-2.03125 0-1.644531-1.355469-3-3-3zm0 2c.5625 0 1 .4375 1 1s-.4375 1-1 1-1-.4375-1-1 .4375-1 1-1zm-8.15625 6.09375c-.800781.136719-1.601562.414063-2.34375.84375-3.335937 1.925781-4.488281 6.226563-2.5625 9.5625 1.925781 3.335938 6.222656 4.488281 9.5625 2.5625 1.910156-1.105469 2.941406-3.03125 3.25-5.0625h4.4375c.417969 1.15625 1.519531 2 2.8125 2 1.644531 0 3-1.355469 3-3s-1.355469-3-3-3c-1.292969 0-2.394531.84375-2.8125 2h-6.1875v1c0 1.726563-.890625 3.414063-2.5 4.34375-2.402344 1.386719-5.457031.558594-6.84375-1.84375s-.558594-5.457031 1.84375-6.84375c.53125-.308594 1.085938-.496094 1.65625-.59375zm1.15625 5.90625c.5625 0 1 .4375 1 1s-.4375 1-1 1-1-.4375-1-1 .4375-1 1-1zm14 0c.5625 0 1 .4375 1 1s-.4375 1-1 1-1-.4375-1-1 .4375-1 1-1z"/></svg>
export const UsersIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
</svg>
export const CampaignsIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M10.34 15.84c-.688-.06-1.386-.09-2.09-.09H7.5a4.5 4.5 0 110-9h.75c.704 0 1.402-.03 2.09-.09m0 9.18c.253.962.584 1.892.985 2.783.247.55.06 1.21-.463 1.511l-.657.38c-.551.318-1.26.117-1.527-.461a20.845 20.845 0 01-1.44-4.282m3.102.069a18.03 18.03 0 01-.59-4.59c0-1.586.205-3.124.59-4.59m0 9.18a23.848 23.848 0 018.835 2.535M10.34 6.66a23.847 23.847 0 008.835-2.535m0 0A23.74 23.74 0 0018.795 3m.38 1.125a23.91 23.91 0 011.014 5.395m-1.014 8.855c-.118.38-.245.754-.38 1.125m.38-1.125a23.91 23.91 0 001.014-5.395m0-3.46c.495.413.811 1.035.811 1.73 0 .695-.316 1.317-.811 1.73m0-3.46a24.347 24.347 0 010 3.46" />
</svg>
export const JourneysIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16">
<path fillRule="evenodd" d="M6 3.5A1.5 1.5 0 0 1 7.5 2h1A1.5 1.5 0 0 1 10 3.5v1A1.5 1.5 0 0 1 8.5 6v1H11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 5 7h2.5V6A1.5 1.5 0 0 1 6 4.5v-1zM8.5 5a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1zM3 11.5A1.5 1.5 0 0 1 4.5 10h1A1.5 1.5 0 0 1 7 11.5v1A1.5 1.5 0 0 1 5.5 14h-1A1.5 1.5 0 0 1 3 12.5v-1zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1zm4.5.5a1.5 1.5 0 0 1 1.5-1.5h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1A1.5 1.5 0 0 1 9 12.5v-1zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1z"/>
</svg>
export const ListsIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm-.375 5.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" />
</svg>
export const SettingsIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z" />
<path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
export const MoonIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" />
</svg>
export const SunIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
</svg>
export const SendIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5" />
</svg>
export const RestartIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
export const ForbiddenIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
export const CloseIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
export const UploadIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" />
</svg>
export const ImageIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" />
</svg>

View file

@ -44,7 +44,7 @@
--color-grey-soft: #252b3a; --color-grey-soft: #252b3a;
--color-primary: var(--color-white); --color-primary: var(--color-white);
--color-primary-soft: #e8ebed; --color-primary-soft: #919496;
--color-background: var(--color-black); --color-background: var(--color-black);
--color-background-soft: #1a1f2b; --color-background-soft: #1a1f2b;

View file

@ -10,6 +10,7 @@ import { Campaign, Template } from '../../types'
import api from '../../api' import api from '../../api'
import { CampaignTag } from './Campaigns' import { CampaignTag } from './Campaigns'
import LaunchCampaign from './LaunchCampaign' import LaunchCampaign from './LaunchCampaign'
import { ForbiddenIcon, RestartIcon, SendIcon } from '../../ui/icons'
export const locales = (templates: Template[]) => templates?.map(item => { export const locales = (templates: Template[]) => templates?.map(item => {
const language = languageName(item.locale) const language = languageName(item.locale)
@ -74,10 +75,10 @@ export default function CampaignDetail() {
] ]
const action = { const action = {
draft: <Button icon="send" onClick={() => setIsLaunchOpen(true)}>Launch Campaign</Button>, draft: <Button icon={<SendIcon />} onClick={() => setIsLaunchOpen(true)}>Launch Campaign</Button>,
aborted: <Button icon="send" onClick={() => setIsLaunchOpen(true)}>Restart Campaign</Button>, aborted: <Button icon={<RestartIcon />} onClick={() => setIsLaunchOpen(true)}>Restart Campaign</Button>,
scheduled: <Button icon="send" onClick={() => setIsLaunchOpen(true)}>Change Schedule</Button>, scheduled: <Button icon={<SendIcon />} onClick={() => setIsLaunchOpen(true)}>Change Schedule</Button>,
running: <Button icon="send" onClick={() => setIsLaunchOpen(true)}>Abort Campaign</Button>, running: <Button icon={<ForbiddenIcon />} onClick={() => setIsLaunchOpen(true)}>Abort Campaign</Button>,
finished: <></>, finished: <></>,
} }

View file

@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router'
import api from '../../api' import api from '../../api'
import { CampaignState } from '../../types' import { CampaignState } from '../../types'
import Button from '../../ui/Button' import Button from '../../ui/Button'
import { ArchiveIcon, DuplicateIcon, EditIcon } from '../../ui/icons' import { ArchiveIcon, DuplicateIcon, EditIcon, PlusIcon } from '../../ui/icons'
import Menu, { MenuItem } from '../../ui/Menu' import Menu, { MenuItem } from '../../ui/Menu'
import PageContent from '../../ui/PageContent' import PageContent from '../../ui/PageContent'
import { SearchTable, useSearchTableQueryState } from '../../ui/SearchTable' import { SearchTable, useSearchTableQueryState } from '../../ui/SearchTable'
@ -49,7 +49,7 @@ export default function Campaigns() {
return ( return (
<> <>
<PageContent title="Campaigns" actions={ <PageContent title="Campaigns" actions={
<Button icon="plus-lg" onClick={() => setIsCreateOpen(true)}>Create Campaign</Button> <Button icon={<PlusIcon />} onClick={() => setIsCreateOpen(true)}>Create Campaign</Button>
}> }>
<SearchTable <SearchTable
{...state} {...state}
@ -79,13 +79,13 @@ export default function Campaigns() {
cell: ({ item: { id } }) => ( cell: ({ item: { id } }) => (
<Menu size="small"> <Menu size="small">
<MenuItem onClick={() => handleEditCampaign(id)}> <MenuItem onClick={() => handleEditCampaign(id)}>
<EditIcon /> Edit <EditIcon />Edit
</MenuItem> </MenuItem>
<MenuItem onClick={async () => await handleDuplicateCampaign(id)}> <MenuItem onClick={async () => await handleDuplicateCampaign(id)}>
<DuplicateIcon /> Duplicate <DuplicateIcon />Duplicate
</MenuItem> </MenuItem>
<MenuItem onClick={async () => await handleArchiveCampaign(id)}> <MenuItem onClick={async () => await handleArchiveCampaign(id)}>
<ArchiveIcon /> Archive <ArchiveIcon />Archive
</MenuItem> </MenuItem>
</Menu> </Menu>
), ),

View file

@ -15,6 +15,7 @@ import { PreferencesContext } from '../../ui/PreferencesContext'
import CreateLocaleModal from './CreateLocaleModal' import CreateLocaleModal from './CreateLocaleModal'
import ImageGalleryModal from './ImageGalleryModal' import ImageGalleryModal from './ImageGalleryModal'
import Modal from '../../ui/Modal' import Modal from '../../ui/Modal'
import { ImageIcon } from '../../ui/icons'
const HtmlEditor = ({ template, setTemplate }: { template: Template, setTemplate: (template: Template) => void }) => { const HtmlEditor = ({ template, setTemplate }: { template: Template, setTemplate: (template: Template) => void }) => {
@ -89,7 +90,7 @@ const HtmlEditor = ({ template, setTemplate }: { template: Template, setTemplate
<div className="editor-toolbar"> <div className="editor-toolbar">
<Button <Button
variant="secondary" variant="secondary"
icon="image" icon={<ImageIcon />}
onClick={() => setShowImages(true)} onClick={() => setShowImages(true)}
>Images</Button> >Images</Button>
</div> </div>

View file

@ -8,6 +8,7 @@ import FormWrapper from '../../ui/form/FormWrapper'
import Modal from '../../ui/Modal' import Modal from '../../ui/Modal'
import PageContent from '../../ui/PageContent' import PageContent from '../../ui/PageContent'
import { SearchTable, useSearchTableQueryState } from '../../ui/SearchTable' import { SearchTable, useSearchTableQueryState } from '../../ui/SearchTable'
import { PlusIcon } from '../../ui/icons'
import { TagPicker } from '../settings/TagPicker' import { TagPicker } from '../settings/TagPicker'
export default function Journeys() { export default function Journeys() {
@ -20,7 +21,7 @@ export default function Journeys() {
<PageContent <PageContent
title="Journeys" title="Journeys"
actions={ actions={
<Button icon="plus-lg" onClick={() => setOpen('create')}> <Button icon={<PlusIcon />} onClick={() => setOpen('create')}>
Create Journey Create Journey
</Button> </Button>
} }

View file

@ -36,6 +36,7 @@ import Login from './auth/Login'
import OnboardingStart from './auth/OnboardingStart' import OnboardingStart from './auth/OnboardingStart'
import Onboarding from './auth/Onboarding' import Onboarding from './auth/Onboarding'
import OnboardingProject from './auth/OnboardingProject' import OnboardingProject from './auth/OnboardingProject'
import { CampaignsIcon, JourneysIcon, ListsIcon, SettingsIcon, UsersIcon } from '../ui/icons'
export const useRoute = (includeProject = true) => { export const useRoute = (includeProject = true) => {
const { projectId = '' } = useParams() const { projectId = '' } = useParams()
@ -116,31 +117,31 @@ export const router = createBrowserRouter([
key: 'campaigns', key: 'campaigns',
to: 'campaigns', to: 'campaigns',
children: 'Campaigns', children: 'Campaigns',
icon: 'bi-megaphone', icon: <CampaignsIcon />,
}, },
{ {
key: 'journeys', key: 'journeys',
to: 'journeys', to: 'journeys',
children: 'Journeys', children: 'Journeys',
icon: 'bi-diagram-2', icon: <JourneysIcon />,
}, },
{ {
key: 'users', key: 'users',
to: 'users', to: 'users',
children: 'Users', children: 'Users',
icon: 'bi-people', icon: <UsersIcon />,
}, },
{ {
key: 'lists', key: 'lists',
to: 'lists', to: 'lists',
children: 'Lists', children: 'Lists',
icon: 'bi-list-ol', icon: <ListsIcon />,
}, },
{ {
key: 'settings', key: 'settings',
to: 'settings', to: 'settings',
children: 'Settings', children: 'Settings',
icon: 'bi-gear', icon: <SettingsIcon />,
}, },
]} ]}
> >

View file

@ -9,6 +9,7 @@ import TextField from '../../ui/form/TextField'
import FormWrapper from '../../ui/form/FormWrapper' import FormWrapper from '../../ui/form/FormWrapper'
import Modal from '../../ui/Modal' import Modal from '../../ui/Modal'
import { SearchTable, useSearchTableState } from '../../ui/SearchTable' import { SearchTable, useSearchTableState } from '../../ui/SearchTable'
import { PlusIcon } from '../../ui/icons'
export default function ProjectApiKeys() { export default function ProjectApiKeys() {
@ -32,7 +33,7 @@ export default function ProjectApiKeys() {
onSelectRow={(row: ProjectApiKey) => navigate(`${row.id}`)} onSelectRow={(row: ProjectApiKey) => navigate(`${row.id}`)}
title="API Keys" title="API Keys"
actions={ actions={
<Button icon="plus-lg" size="small" onClick={() => setIsModalOpen(true)}> <Button icon={<PlusIcon />} size="small" onClick={() => setIsModalOpen(true)}>
Create Key Create Key
</Button> </Button>
} }

View file

@ -12,6 +12,7 @@ import Modal, { ModalProps } from '../../ui/Modal'
import Tile, { TileGrid } from '../../ui/Tile' import Tile, { TileGrid } from '../../ui/Tile'
import { snakeToTitle } from '../../utils' import { snakeToTitle } from '../../utils'
import './IntegrationModal.css' import './IntegrationModal.css'
import { ChevronLeftIcon } from '../../ui/icons'
interface IntegrationModalProps extends Omit<ModalProps, 'title'> { interface IntegrationModalProps extends Omit<ModalProps, 'title'> {
provider: Provider | undefined provider: Provider | undefined
@ -61,7 +62,7 @@ export default function IntegrationModal({ onChange, provider, ...props }: Integ
{meta && <> {meta && <>
{!provider?.id && <div style={{ marginBottom: '10px' }}> {!provider?.id && <div style={{ marginBottom: '10px' }}>
<Button <Button
icon="chevron-left" icon={<ChevronLeftIcon />}
variant="secondary" variant="secondary"
size="small" size="small"
onClick={() => setMeta(undefined)}>Integrations</Button> onClick={() => setMeta(undefined)}>Integrations</Button>

View file

@ -4,6 +4,7 @@ import { ProjectContext } from '../../contexts'
import { Provider } from '../../types' import { Provider } from '../../types'
import Button from '../../ui/Button' import Button from '../../ui/Button'
import Heading from '../../ui/Heading' import Heading from '../../ui/Heading'
import { PlusIcon } from '../../ui/icons'
import { SearchTable, useSearchTableState } from '../../ui/SearchTable' import { SearchTable, useSearchTableState } from '../../ui/SearchTable'
import IntegrationModal from './IntegrationModal' import IntegrationModal from './IntegrationModal'
@ -16,7 +17,7 @@ export default function Integrations() {
return ( return (
<> <>
<Heading size="h3" title="Integrations" actions={ <Heading size="h3" title="Integrations" actions={
<Button icon="plus-lg" size="small" onClick={() => { <Button icon={<PlusIcon />} size="small" onClick={() => {
setProvider(undefined) setProvider(undefined)
setIsModalOpen(true) setIsModalOpen(true)
}}>Add Integration</Button> }}>Add Integration</Button>

View file

@ -9,6 +9,7 @@ import { Subscription } from '../../types'
import TextField from '../../ui/form/TextField' import TextField from '../../ui/form/TextField'
import { SingleSelect } from '../../ui/form/SingleSelect' import { SingleSelect } from '../../ui/form/SingleSelect'
import Button from '../../ui/Button' import Button from '../../ui/Button'
import { PlusIcon } from '../../ui/icons'
export default function Subscriptions() { export default function Subscriptions() {
const navigate = useNavigate() const navigate = useNavigate()
@ -31,11 +32,11 @@ export default function Subscriptions() {
<> <>
<Button <Button
variant="primary" variant="primary"
icon="plus" icon={<PlusIcon />}
size="small" size="small"
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
> >
{'Create Subscription'} Create Subscription
</Button> </Button>
</> </>
} }

View file

@ -5,6 +5,7 @@ import { Tag } from '../../types'
import Button from '../../ui/Button' import Button from '../../ui/Button'
import FormWrapper from '../../ui/form/FormWrapper' import FormWrapper from '../../ui/form/FormWrapper'
import TextField from '../../ui/form/TextField' import TextField from '../../ui/form/TextField'
import { PlusIcon } from '../../ui/icons'
import Modal from '../../ui/Modal' import Modal from '../../ui/Modal'
import { SearchTable, useSearchTableState } from '../../ui/SearchTable' import { SearchTable, useSearchTableState } from '../../ui/SearchTable'
@ -36,7 +37,7 @@ export default function Tags() {
size="small" size="small"
variant="primary" variant="primary"
onClick={() => setEditing({ id: 0, name: 'New Tag' })} onClick={() => setEditing({ id: 0, name: 'New Tag' })}
icon="plus" icon={<PlusIcon />}
> >
{'Create Tag'} {'Create Tag'}
</Button> </Button>

View file

@ -7,7 +7,7 @@ import Button from '../../ui/Button'
import { DataTableCol } from '../../ui/DataTable' import { DataTableCol } from '../../ui/DataTable'
import { SelectionProps } from '../../ui/form/Field' import { SelectionProps } from '../../ui/form/Field'
import FormWrapper from '../../ui/form/FormWrapper' import FormWrapper from '../../ui/form/FormWrapper'
import { ArchiveIcon } from '../../ui/icons' import { ArchiveIcon, PlusIcon } from '../../ui/icons'
import Menu, { MenuItem } from '../../ui/Menu' import Menu, { MenuItem } from '../../ui/Menu'
import Modal from '../../ui/Modal' import Modal from '../../ui/Modal'
import { SearchTable, SearchTableQueryState, useSearchTableState } from '../../ui/SearchTable' import { SearchTable, SearchTableQueryState, useSearchTableState } from '../../ui/SearchTable'
@ -92,7 +92,7 @@ export default function Teams() {
title="Team" title="Team"
onDeleteRow={handleDeleteProjectAdmin} onDeleteRow={handleDeleteProjectAdmin}
actions={ actions={
<Button icon="plus-lg" size="small" onClick={() => setIsModalOpen(true)}> <Button icon={<PlusIcon />} size="small" onClick={() => setIsModalOpen(true)}>
Add Team Member Add Team Member
</Button> </Button>
} }

View file

@ -16,6 +16,7 @@ import { snakeToTitle } from '../../utils'
import UploadField from '../../ui/form/UploadField' import UploadField from '../../ui/form/UploadField'
import { SearchTable, useSearchTableState } from '../../ui/SearchTable' import { SearchTable, useSearchTableState } from '../../ui/SearchTable'
import { useRoute } from '../router' import { useRoute } from '../router'
import { EditIcon, UploadIcon } from '../../ui/icons'
import { TagPicker } from '../settings/TagPicker' import { TagPicker } from '../settings/TagPicker'
const RuleSection = ({ list, onRuleSave }: { list: DynamicList, onRuleSave: (rule: WrapperRule) => void }) => { const RuleSection = ({ list, onRuleSave }: { list: DynamicList, onRuleSave: (rule: WrapperRule) => void }) => {
@ -64,10 +65,10 @@ export default function ListDetail() {
<> <>
{list.type === 'static' && <Button {list.type === 'static' && <Button
variant="secondary" variant="secondary"
icon="upload" icon={<UploadIcon />}
onClick={() => setIsUploadOpen(true)} onClick={() => setIsUploadOpen(true)}
>Upload List</Button>} >Upload List</Button>}
<Button icon="pencil" onClick={() => setIsEditListOpen(true)}>Edit List</Button> <Button icon={<EditIcon />} onClick={() => setIsEditListOpen(true)}>Edit List</Button>
</> </>
}> }>

View file

@ -10,6 +10,7 @@ import Modal from '../../ui/Modal'
import PageContent from '../../ui/PageContent' import PageContent from '../../ui/PageContent'
import ListTable from './ListTable' import ListTable from './ListTable'
import { createWrapperRule } from './RuleBuilder' import { createWrapperRule } from './RuleBuilder'
import { PlusIcon } from '../../ui/icons'
import { TagPicker } from '../settings/TagPicker' import { TagPicker } from '../settings/TagPicker'
export default function Lists() { export default function Lists() {
@ -24,7 +25,7 @@ export default function Lists() {
title="Lists" title="Lists"
actions={ actions={
<Button <Button
icon="plus-lg" icon={<PlusIcon />}
onClick={() => setIsModalOpen(true) } onClick={() => setIsModalOpen(true) }
> >
Create List Create List

View file

@ -3,6 +3,7 @@ import Button from '../../ui/Button'
import ButtonGroup from '../../ui/ButtonGroup' import ButtonGroup from '../../ui/ButtonGroup'
import { SingleSelect } from '../../ui/form/SingleSelect' import { SingleSelect } from '../../ui/form/SingleSelect'
import TextField from '../../ui/form/TextField' import TextField from '../../ui/form/TextField'
import { PlusIcon, TrashIcon } from '../../ui/icons'
import './RuleBuilder.css' import './RuleBuilder.css'
interface RuleSetParams { interface RuleSetParams {
@ -110,7 +111,7 @@ const RuleSet = ({ group, onChange, onDelete }: RuleSetParams) => {
{onDelete && <Button {onDelete && <Button
size="small" size="small"
variant="plain" variant="plain"
icon="trash" icon={<TrashIcon />}
onClick={onDelete} onClick={onDelete}
/>} />}
</div>} </div>}
@ -130,20 +131,20 @@ const RuleSet = ({ group, onChange, onDelete }: RuleSetParams) => {
? <Button ? <Button
size="small" size="small"
variant="secondary" variant="secondary"
icon="plus" icon={<PlusIcon />}
onClick={() => handleAddUserRule()} onClick={() => handleAddUserRule()}
>Add Condition</Button> >Add Condition</Button>
: <> : <>
<Button <Button
size="small" size="small"
variant="secondary" variant="secondary"
icon="plus" icon={<PlusIcon />}
onClick={() => handleAddUserRule()} onClick={() => handleAddUserRule()}
>Add User Condition</Button> >Add User Condition</Button>
<Button <Button
size="small" size="small"
variant="secondary" variant="secondary"
icon="plus" icon={<PlusIcon />}
onClick={() => handleAddEventRule()} onClick={() => handleAddEventRule()}
>Add Event Condition</Button> >Add Event Condition</Button>
</> </>
@ -209,7 +210,7 @@ const RuleView = ({ rule, onChange, onDelete }: RuleParams) => {
/> />
<Button <Button
size="small" size="small"
icon="trash" icon={<TrashIcon />}
variant="secondary" variant="secondary"
onClick={onDelete} /> onClick={onDelete} />
</ButtonGroup> </ButtonGroup>