Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shared button component #10347

Merged
merged 3 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions packages/replay-next/components/Button.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.Button {
font-family: var(--font-family-default);
font-size: 0.875rem;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like using non-standard font sizes and pixel sizes here, but I matched the old styles exactly so this switch would be less controversial.

line-height: 1rem;
font-weight: 500;
padding: 0.5rem 0.75rem;
border: 1px solid transparent;
border-radius: 0.375rem;
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 1ch;
}
.Button:disabled {
--accent-color: var(--background-color-disabled-button);
--accent-color-hover: var(--background-color-disabled-button);
--contrast-color: var(--color-disabled-button);

color: var(--color-dimmer);
}

.Button[data-color="primary"]:not(:disabled) {
--accent-color: var(--primary-accent);
--accent-color-hover: var(--primary-accent-hover);
--contrast-color: var(--color-primary-button);
}
.Button[data-color="secondary"]:not(:disabled) {
--accent-color: var(--secondary-accent);
--accent-color-hover: var(--secondary-accent-hover);
--contrast-color: var(--color-secondary-button);
}

.Button[data-variant="outline"] {
border-color: var(--accent-color);
}
.Button[data-variant="outline"]:hover {
border-color: var(--accent-color-hover);
}
.Button[data-variant="solid"] {
background-color: var(--accent-color);
color: var(--contrast-color);
}
.Button[data-variant="solid"]:hover {
background-color: var(--accent-color-hover);
}

.Button[data-size="large"] {
font-size: 1rem;
line-height: 1.5rem;
padding: 0.75rem 1.5rem;
border-radius: 0.375rem;
}
.Button[data-size="small"] {
font-size: 0.75rem;
line-height: 1rem;
padding: 0.375rem 0.625rem;
border-radius: 0.25rem;
}
25 changes: 25 additions & 0 deletions packages/replay-next/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ButtonHTMLAttributes } from "react";

import styles from "./Button.module.css";

export function Button({
className = "",
color = "primary",
size = "normal",
variant = "solid",
...rest
}: ButtonHTMLAttributes<HTMLButtonElement> & {
color?: "primary" | "secondary";
size?: "normal" | "large" | "small";
variant?: "outline" | "solid";
}) {
return (
<button
className={`${className} ${styles.Button}`}
data-color={color}
data-size={size}
data-variant={variant}
{...rest}
/>
);
}
6 changes: 3 additions & 3 deletions packages/replay-next/pages/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@
--color-link: var(--primary-accent);
--color-primary-button: #ffffff;
--color-secondary-button: #ffffff;
--color-disabled-button: #ffffff;
--color-disabled-button: var(--color-default);
--color-high-contrast-button: #ffffff;
--color-warning: #fce2a1;
--color-search-results: #d7d7db;
Expand Down Expand Up @@ -745,7 +745,7 @@
--background-color-contrast-5: #e1e6ed;

--background-color-default: #e9e9e9;
--background-color-disabled-button: #666666;
--background-color-disabled-button: #e6e7eb;
--background-color-error: #fcefee;
--background-color-highlight-change: mark;
--background-color-high-contrast-button: #f2f2f2;
Expand Down Expand Up @@ -777,7 +777,7 @@
--color-default: #223344;
--color-dim: rgba(135, 135, 137, 0.9);
--color-dimmer: #aaaaaa;
--color-disabled-button: var(--theme-base-100);
--color-disabled-button: var(--color-default);
--color-error: #ff0000;
--color-highlight-change: marktext;
--color-high-contrast-button: #000000;
Expand Down
21 changes: 0 additions & 21 deletions src/ui/components/Library/Library.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,6 @@
border-bottom: 1px solid var(--chrome);
}

:root:global(.theme-dark) .editButton {
background-color: var(--theme-base-80);
color: #fff;
border: none;
}

:root:global(.theme-dark) .editButton:hover {
background-color: var(--primary-accent-hover);
color: #fff;
border: none;
}

:root:global(.theme-dark) .recordingsBackground {
background-color: transparent;
color: var(--body-color);
Expand Down Expand Up @@ -102,15 +90,6 @@
border-bottom: 1px solid var(--theme-base-90);
}

:root:global(.theme-light) .editButton {
background-color: #fff;
}

:root:global(.theme-light) .editButton:hover {
background-color: var(--primary-accent-hover);
color: #fff;
}

:root:global(.theme-light) .recordingsBackground {
background-color: transparent;
color: var(--body-color);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { RecordingId } from "@replayio/protocol";
import classNames from "classnames";
import React, { useState } from "react";
import { useState } from "react";

import { assert } from "protocol/utils";
import { Button } from "replay-next/components/Button";
import { Recording } from "shared/graphql/types";
import { useGetTeamIdFromRoute } from "ui/components/Library/Team/utils";
import { isTestSuiteReplay } from "ui/components/TestSuite/utils/isTestSuiteReplay";
import hooks from "ui/hooks";
import { WorkspaceId } from "ui/state/app";
import { useIsPublicEnabled } from "ui/utils/org";

import { DisabledButton, getButtonClasses } from "../../../../../shared/Button";
import { useConfirm } from "../../../../../shared/Confirm";
import MaterialIcon from "../../../../../shared/MaterialIcon";
import PortalDropdown from "../../../../../shared/PortalDropdown";
Expand Down Expand Up @@ -98,23 +97,22 @@ export default function BatchActionDropdown({

if (!selectedIds.length) {
return (
<DisabledButton className="space-x-1 leading-4">
<Button disabled>
<MaterialIcon outlined className="font-bold" iconSize="sm">
expand_more
</MaterialIcon>
<span>{`${selectedIds.length} item${selectedIds.length > 1 ? "s" : ""} selected`}</span>
</DisabledButton>
</Button>
);
}

const buttonClasses = classNames("bg-white", getButtonClasses("blue", "secondary", "md"));
const button = (
<span className={"flex flex-row items-center space-x-1 leading-4 text-primaryAccent"}>
<Button variant="outline">
<MaterialIcon outlined className="font-bold" iconSize="sm">
expand_more
</MaterialIcon>
<span>{`${selectedIds.length} item${selectedIds.length > 1 ? "s" : ""} selected`}</span>
</span>
</Button>
);

let allRecordingsOwnedByCurrentUser = true;
Expand Down Expand Up @@ -147,7 +145,6 @@ export default function BatchActionDropdown({
return (
<PortalDropdown
buttonContent={button}
buttonStyle={buttonClasses}
setExpanded={setExpanded}
expanded={expanded}
distance={0}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { useRouter } from "next/router";
import React from "react";

import { Button } from "replay-next/components/Button";
import { Recording } from "shared/graphql/types";
import { Workspace } from "shared/graphql/types";
import { setModal } from "ui/actions/app";
import { MY_LIBRARY_TEAM } from "ui/components/Library/Team/TeamContextRoot";
import { useGetTeamIdFromRoute } from "ui/components/Library/Team/utils";
import hooks from "ui/hooks";
import { useAppDispatch } from "ui/setup/hooks";

import { PrimaryButton, SecondaryButton } from "../../../../../shared/Button";
import BatchActionDropdown from "./BatchActionDropdown";
import TeamTrialEnd from "./TeamTrialEnd";
import styles from "../../../../Library.module.css";
Expand Down Expand Up @@ -40,9 +38,7 @@ function ViewerHeaderActions({
selectedIds={selectedIds}
recordings={recordings}
/>
<PrimaryButton color="blue" onClick={handleDoneEditing}>
Done
</PrimaryButton>
<Button onClick={handleDoneEditing}>Done</Button>
</>
);
}
Expand All @@ -56,26 +52,14 @@ function ViewerHeaderActions({
return (
<>
{!isLibrary ? (
<SecondaryButton
className={styles.editButton}
color="blue"
onClick={() => launchWorkspaceSettings()}
>
Add team member
</SecondaryButton>
<Button onClick={() => launchWorkspaceSettings()}>Add team member</Button>
) : (
<></>
)}

{recordings.length != 0 ? (
<>
<SecondaryButton
className={styles.editButton}
color="blue"
onClick={() => setIsEditing(true)}
>
Edit
</SecondaryButton>
<Button onClick={() => setIsEditing(true)}>Edit</Button>
</>
) : (
<></>
Expand Down Expand Up @@ -113,7 +97,7 @@ export default function ViewerHeader({
);

return (
<div className={`m-2 flex flex-row items-center justify-between ${styles.libraryHeaderButton}`}>
<div className={`m-2 flex flex-row items-center justify-between`}>
{HeaderLeft}
<div className="flex flex-row items-center space-x-3">
{currentWorkspaceId ? <TeamTrialEnd currentWorkspaceId={currentWorkspaceId} /> : null}
Expand Down
8 changes: 2 additions & 6 deletions src/ui/components/shared/APIKeys.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useEffect, useMemo, useRef, useState } from "react";

import { Button } from "replay-next/components/Button";
import { ApiKey, ApiKeyResponse, ApiKeyScope } from "shared/graphql/types";

import { Button, DisabledButton, PrimaryButton } from "./Button";
import { useConfirm } from "./Confirm";
import TextInput from "./Forms/TextInput";
import MaterialIcon from "./MaterialIcon";
Expand Down Expand Up @@ -176,11 +176,7 @@ export default function APIKeys({
value={label}
/>

{canSubmit ? (
<PrimaryButton color="blue">Add</PrimaryButton>
) : (
<DisabledButton>Add</DisabledButton>
)}
<Button disabled={!canSubmit}>Add</Button>
</fieldset>
{scopes && scopes.length > 1 ? (
<fieldset className="w-full">
Expand Down
9 changes: 0 additions & 9 deletions src/ui/components/shared/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,3 @@ export const PrimaryButton = (props: ButtonProps & { color: Colors }) => (
export const SecondaryButton = (props: ButtonProps & { color: Colors }) => (
<Button {...props} size="md" style="secondary" />
);
export const DisabledButton = ({ className, ...rest }: ButtonProps) => (
<Button
{...rest}
size="md"
style="disabled"
className={classNames(className, "cursor-default")}
color="gray"
/>
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { ChangeEvent, useMemo, useState } from "react";

import { Button } from "replay-next/components/Button";
import { WorkspaceUser } from "shared/graphql/types";
import * as actions from "ui/actions/app";
import { useRedirectToTeam } from "ui/components/Library/Team/utils";
Expand All @@ -12,7 +13,6 @@ import { validateEmail } from "ui/utils/helpers";
import { trackEvent } from "ui/utils/telemetry";

import Base64Image from "../Base64Image";
import { Button, DisabledButton, PrimaryButton } from "../Button";
import { useConfirm } from "../Confirm";
import { TextInput } from "../Forms";
import InvitationLink from "../NewWorkspaceModal/InvitationLink";
Expand Down Expand Up @@ -117,13 +117,7 @@ function WorkspaceForm() {
onChange={onChange}
className="border-inputBorder"
/>
{isLoading ? (
<DisabledButton>Loading...</DisabledButton>
) : canSubmit ? (
<PrimaryButton color="blue">Invite</PrimaryButton>
) : (
<DisabledButton>Invite</DisabledButton>
)}
<Button disabled={isLoading || !canSubmit}>{isLoading ? "Loading..." : "Invite"}</Button>
</div>
{errorMessage ? <div className="py-3 text-xs text-red-500">{errorMessage}</div> : null}
</form>
Expand Down Expand Up @@ -225,7 +219,7 @@ const settings: Settings<
<div className="font-semibold">Delete this team</div>
<div className="">{`This cannot be reversed.`}</div>
</div>
<Button color="red" onClick={handleDeleteTeam} size="md" style="primary">
<Button color="secondary" onClick={handleDeleteTeam}>
Delete this team
</Button>
</div>
Expand Down
Loading