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

Feature/custom button #625

Open
wants to merge 26 commits into
base: feature/ant5
Choose a base branch
from
Open

Feature/custom button #625

wants to merge 26 commits into from

Conversation

interim17
Copy link
Contributor

@interim17 interim17 commented Jan 15, 2025

Time estimate or Size

small/medium
the final PR into the feature branch for this migration??

Problem

Button styling got messed up during ant migration

Also our approach to styling buttons is a bit all over the place.

Solution

Replace NavButton with more general CustomButton, a styled-component.

Delete: NavButton et. al, and light-theme.css and its directory.

The light-theme file was a bit of an anachronism from auto-conversion work.

ButtonClass

Is expanded to cover all five of our basic button styled from the figma master guide (light and dark primary, light and dark secondary, and action buttons). Using the enum instead of raw strings is more type-safe and developer friendly.
Native antd variant prop is omitted and replaced with our own custom variants.

CustomButton

As in the case of DropdownMenuItems, antd can be a bit heavy handed with class names, and also swaps out underlying html in certain cases.
Using a styled-component helps address specificity and consolidate the styling of buttons in one place.

Other buttons in the app (ViewportButton and DropdownMenuItems) are functionally and stylistically distinct, and either weren't much affected in migration or have already been addressed.

Comment on lines 12 to 27
interface CustomButtonProps extends Omit<AntButtonProps, "type" | "variant"> {
variant?: ButtonClass;
titleText?: string;
icon?: ReactNode;
onClick?: () => void;
}

interface TooltipText {
defaultText: string;
disabledText?: string;
}

interface TooltilButtonProps extends CustomButtonProps {
tooltipText: TooltipText;
tooltipPlacement?: TooltipPlacement;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently the style rules, basic button, and button with tooltip are all here in the same file. I'm open to the argument that they be split up! But at this stage I like having it all in one place.

@interim17 interim17 marked this pull request as ready for review January 15, 2025 21:08
@interim17 interim17 requested a review from a team as a code owner January 15, 2025 21:08
@interim17 interim17 requested review from ShrimpCryptid and removed request for a team January 15, 2025 21:08
Copy link
Contributor

@ShrimpCryptid ShrimpCryptid left a comment

Choose a reason for hiding this comment

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

Some minor comments but this approach is really elegant! LGTM!

Comment on lines 1 to +9
import React from "react";
import { Link } from "react-router-dom";
import { Button, message, Upload, UploadProps } from "antd";
import { message, Upload, UploadProps } from "antd";
import { CloseOutlined } from "@ant-design/icons";
import { RcFile } from "antd/lib/upload";

import { ButtonClass } from "../../constants/interfaces";
import { VIEWER_PATHNAME } from "../../routes";
import { CustomButton } from "../CustomButton";
Copy link
Contributor

Choose a reason for hiding this comment

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

This is making me think it might be nice to add an import sorting plugin to the repo...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, I want that

Comment on lines 87 to +109
button: {
hoverBg: baseColors.transparent,
activeBg: baseColors.transparent,
primary: {
light: {
background: baseColors.dark.five,
text: baseColors.gray.six,
hover: {
background: baseColors.dark.one,
text: semanticColors.primaryPurple,
},
active: {
background: baseColors.dark.one,
text: semanticColors.primaryPurple,
},
focus: {
outline: semanticColors.primaryPurple,
},
disabled: {
background: baseColors.purple.three,
text: baseColors.gray.six,
},
},
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a big fan of this nested structure! I should clean up TFE's theme type at some point.

disabledText?: string;
}

interface TooltilButtonProps extends CustomButtonProps {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
interface TooltilButtonProps extends CustomButtonProps {
interface TooltipButtonProps extends CustomButtonProps {

}

&:active:not(:disabled) {
background-color: ${hover.background};
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I feel like I'd expect this to be active.background, though I can see why it would be redundant if none of the buttons change background between active and hover states.

Comment on lines 169 to 171
const [tooltipRenderText, setTooltipRenderText] = useState(
disabled ? tooltipText.disabledText : tooltipText.defaultText
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need to be stateful? Is this to prevent the rendered text from changing while the tooltip is open?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey good catch, no it doesn't. Also the tooltip behavior wasn't actually working with the new disabled prop so this comment helped me catch that!

Adding a wrapper div to handle the mouse events so disabled buttons still show tooltips, and making tooltipRenderText a plain const since the button always re renders!

Copy link

@tyler-foster tyler-foster left a comment

Choose a reason for hiding this comment

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

Smells reasonable to me!

Left some minor comments. Not sure I'm up to speed with the latest CSS technology.

--dark-theme-secondary-button-disabled-bg: transparent;
--dark-theme-secondary-button-disabled-border: var(--dark-theme-header-bg);
--dark-theme-secondary-button-disabled-color: var(--dim-gray-two);
/* --dark-theme-primary-button-bg: var(--baby-purple);

Choose a reason for hiding this comment

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

Are lines 60 and 61 here still necessary?

@@ -42,8 +42,10 @@ export type TooltipPlacement =
| "rightBottom";

export enum ButtonClass {

Choose a reason for hiding this comment

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

Too lazy to check this myself - is this enum used anywhere beyond the CustomButton component props? If not, would it be the right idea to just export it from CustomButton? That's what I would do, but I don't typically make big constant files like these.

border: 1px solid ${variant === "primary" ? background : border};
color: ${text};

&&& {

Choose a reason for hiding this comment

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

Yeesh. Which brand of CSS magic does this triple ampersand belong to? Does this mean "parent-parent-parent"..?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No! It's both better and worse than that.

In styled-components this just directly raises the specificity of the current selector. Yes, this is arbitrary and smells a bit like using !important but for me its a needed workaround for quality of life when styling antd.

Because some antd components apply many different class names, change element nesting, and even changes which base html element is rendered for different components, it can be tricky to ensure that our styles will be consistently applied. This solves that in a brute force kind of way, but is better than using !important because these triple applied class hashes CAN be overridden by something of greater selector specificity, whereas !important ignores the specificity hierarchy entirely.

When our styles don't really map onto ant's opinions very well, I prefer to just sort of veto all their styling by using this triple ampersand.

Choose a reason for hiding this comment

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

Thanks, I sort of it get it now.

Does there come a point where we eschew the ant buttons altogether and just roll our own from scratch 🤔 ? I'd be curious as to when the team would consider that to be worth it.
This isn't a request for changes though! Feel free to resolve.

Base automatically changed from feature/ant5-styling to feature/ant5 January 30, 2025 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants