Skip to content

[BOOKINGSG-9121][Nghi] migrate toggle and toggle-icon style to linaria#1104

Open
nghitb wants to merge 14 commits intopre-release/v4from
BOOKINGSG-9121
Open

[BOOKINGSG-9121][Nghi] migrate toggle and toggle-icon style to linaria#1104
nghitb wants to merge 14 commits intopre-release/v4from
BOOKINGSG-9121

Conversation

@nghitb
Copy link
Copy Markdown
Contributor

@nghitb nghitb commented Apr 16, 2026

Checklist

  • Migrated the component styles
    • className is chained correctly with clsx
    • User style prop is set as CSS variable
  • Changes follow the project guidelines in CONVENTIONS_V4.md
  • Updated Storybook documentation
  • Added/updated unit tests
  • Added visual tests
  • Listed breaking changes

Comment thread src/toggle/toggle-icon.tsx
Comment thread src/toggle/toggle.tsx
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Let's add a unit test for the component.

@qroll should we also have a e2e story for this component as well?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yep we should be adding the unit tests too

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will do

Comment thread src/toggle/toggle.styles.ts Outdated
Comment thread src/shared/toggle-icon/toggle-icon.styles.ts Outdated
Comment thread src/shared/toggle-icon/toggle-icon.tsx Outdated
Comment thread src/shared/toggle-icon/toggle-icon.tsx Outdated
Comment thread src/toggle/toggle.tsx
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yep we should be adding the unit tests too

Comment thread src/toggle/toggle-icon.tsx
Comment thread src/toggle/toggle.styles.ts Outdated
Comment thread src/toggle/toggle.styles.ts Outdated
Comment thread src/toggle/toggle.styles.ts Outdated
Comment thread src/toggle/toggle.styles.ts Outdated
Comment thread src/toggle/toggle.tsx Outdated
Comment thread src/toggle/toggle.tsx Outdated
Comment thread src/toggle/toggle.tsx Outdated
Comment thread src/toggle/toggle.tsx Outdated
Comment thread src/toggle/toggle.tsx
Comment thread src/toggle/toggle.tsx Outdated
@qroll qroll added the type: chore For technical improvements or refactoring. label Apr 17, 2026
@qroll qroll added this to the v4.0.0-alpha.2 milestone Apr 17, 2026
Comment thread src/toggle/toggle.styles.ts
Comment thread src/shared/toggle-icon/toggle-icon.tsx Outdated
Comment thread src/toggle/toggle.tsx Outdated
Comment thread src/toggle/toggle.styles.ts Outdated
Comment on lines +263 to +266
export const removeButtonDisabled = css`
color: ${Colour["text-disabled"]};
cursor: not-allowed;
`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This has the same content with expandButtonDisabled & errorContainerDisabled. How about we make this as a general disabled class name?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

agree

Comment thread src/toggle/toggle.styles.ts Outdated
Comment on lines +37 to +39
export const toggleTextContainerDisabled = css`
color: ${Colour["text-disabled"]};
`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is similar with childrenDisabled, errorTextDisabled & errorListDisabled. Lets have a general disabled text class name

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

agree

Comment thread src/toggle/toggle.styles.ts Outdated
Comment on lines +330 to +332
export const errorText = css`
color: ${Colour["text-error"]};
`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is similar with errorList

Comment thread src/toggle/toggle.styles.ts
Comment thread src/toggle/toggle.styles.ts Outdated
Comment on lines +71 to +73
export const toggleContainerNoBorderErrorDisabled = css`
border-color: ${Colour["border-error"]};
`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is similar with toggleContainerDefaultErrorDisabled

Comment on lines +78 to +82
&:has(.${headerContainer}:hover) {
@media (pointer: fine) {
background: ${Colour["bg-hover-subtle"]};
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I see a pattern where we have two type of hover styling, for default and selected. Let's extract those to a class name and reference it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

im confused, can u give an example

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Okay, so we can have something like this

const defaultHoverBlock = `
    &:has(.${headerContainer}:hover) {
        @media (pointer: fine) {
            background: ${Colour["bg-hover-subtle"]};
        }
    }
`;

const selectedHoverBlock = `
    &:has(.${headerContainer}:hover) {
        @media (pointer: fine) {
            background: ${Colour["bg-selected-hover"]};

            & .${textContainer} {
                color: ${Colour["text-selected-hover"]};
            }

            & .${toggleIconStyles.wrapperBase} {
                color: ${Colour["icon-selected-hover"]};
            }
        }
    }
`;

and then reference them like

export const toggleContainerNoBorderError = css`
    border-color: ${Colour["border-error"]};
    ${defaultHoverBlock}
`;

export const toggleContainerDefaultSelected = css`
    border-color: ${Colour["border-selected"]};
    background: ${Colour["bg-selected"]};
    ${selectedHoverBlock}
`;

But this makes them just like a regular string

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Or if we want to avoid having literal string, we can introduce a hover class name

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

if we change to a hover classname, it will make the getContainerStateClass more complicated

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We don't have to touch getContainerStateClass. Can instead introduce a new helper for the hover

    const getContainerHoverClass = (() => {
        if (disabled) {
            return undefined;
        }

        if (!error && selected) {
            return styles.toggleContainerHoverSelected;
        }

        return styles.toggleContainerHoverDefault;
    })();

What do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

sure, will do

Comment thread src/toggle/toggle.tsx Outdated
@nghitb nghitb requested a review from ghazwan-gt April 17, 2026 07:58
Comment on lines +39 to +40
checked
error
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

error and checked are mutually exclusive

Comment on lines +79 to +87
test.describe(() => {
test.beforeEach(async ({ story }) => {
await story.init("with-sublabel", { mode: "dark" });
});

test("With sub label (dark mode)", async ({ story }) => {
await compareScreenshot(story, "mount");
});
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't we need dark mode here, already covered by base variants

Comment on lines +102 to +110
test.describe(() => {
test.beforeEach(async ({ story }) => {
await story.init("with-composite", { mode: "dark" });
});

test("With composite section (dark mode)", async ({ story }) => {
await compareScreenshot(story, "mount");
});
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't we need dark mode here, already covered by base variants

@@ -0,0 +1,134 @@
import { test as base, Page } from "@playwright/test";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Add a case for keyboard navigation and also check for focusableWhenDisabled

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: chore For technical improvements or refactoring.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants