Skip to content

Commit

Permalink
Create Switch component
Browse files Browse the repository at this point in the history
  • Loading branch information
psirenny authored Apr 22, 2024
1 parent eb1c568 commit 73c46ec
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 22 deletions.
43 changes: 21 additions & 22 deletions packages/ui/src/components/switch/switch.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Form, Switch } from "react-aria-components";
import { Form } from "react-aria-components";
import { useIntl } from "react-intl";
import { Switch, SwitchButton, SwitchLabel, SwitchThumb } from "./switch";

const PreviewSwitch = (properties: {
hasLabel: boolean;
Expand All @@ -15,28 +16,26 @@ const PreviewSwitch = (properties: {
return (
<div className={`w-full ${isSquished ? "max-w-36" : "max-w-sm"}`}>
<Form className="relative w-full">
<div className="mt-3">
<Switch
className="group flex"
isDisabled={isDisabled}
isReadOnly={isReadonly}
value="isLimitedToFriends"
<Switch
className="group inline-flex"
isDisabled={isDisabled}
isReadOnly={isReadonly}
value="isLimitedToFriends"
>
<SwitchButton
className={`group relative isolate inline-flex h-6 w-11 rounded-full border-2 border-transparent bg-neutral-a-3 transition duration-200 ease-in-out group-focus-visible:outline group-focus-visible:outline-2 group-focus-visible:outline-primary-7 group-disabled:bg-neutral-a-3 ${isPrimary ? "group-selected:bg-primary-9" : "group-selected:bg-neutral-9"}`}
>
<span
className={`group relative isolate inline-flex h-6 w-11 rounded-full border-2 border-transparent bg-neutral-a-3 transition duration-200 ease-in-out group-focus-visible:outline group-focus-visible:outline-2 group-focus-visible:outline-primary-7 group-disabled:bg-neutral-a-3 ${isPrimary ? "group-selected:bg-primary-9" : "group-selected:bg-neutral-9"}`}
>
<span className="pointer-events-none relative inline-block size-5 rounded-full bg-white shadow transition-all duration-200 ease-in-out will-change-transform translate-x-0 group-selected:translate-x-5 group-disabled:bg-neutral-2 group-disabled:shadow-none" />
</span>
{hasLabel ? (
<span className="ms-3 flex-1 text-sm font-medium leading-6 text-neutral-12 group-disabled:text-neutral-11">
{intl.formatMessage({
defaultMessage: "Receive notifications",
id: "D6jkwD",
})}
</span>
) : null}
</Switch>
</div>
<SwitchThumb />
</SwitchButton>
{hasLabel ? (
<SwitchLabel>
{intl.formatMessage({
defaultMessage: "Receive notifications",
id: "D6jkwD",
})}
</SwitchLabel>
) : null}
</Switch>
</Form>
</div>
);
Expand Down
63 changes: 63 additions & 0 deletions packages/ui/src/components/switch/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* eslint-disable react/jsx-props-no-spreading */
import React, { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes } from "react";
import { Switch as SwitchPrimitive } from "react-aria-components";
import { cx } from "@/helpers/cx";

export const Switch = forwardRef<
ElementRef<typeof SwitchPrimitive>,
ComponentPropsWithoutRef<typeof SwitchPrimitive> & {
className?: string | undefined;
isPrimary?: boolean | undefined;
}
>(({ className, isPrimary = false, ...properties }, reference) => {
const mergedClassName = cx("group inline-flex", className);
return (
<SwitchPrimitive
className={mergedClassName}
data-is-primary={isPrimary}
{...properties}
ref={reference}
/>
);
});

Switch.displayName = "Switch";

export const SwitchLabel = forwardRef<
HTMLSpanElement,
HTMLAttributes<HTMLSpanElement> & { className?: string | undefined }
>(({ className, ...properties }, reference) => {
const mergedClassName = cx(
"ms-3 flex-1 text-sm font-medium leading-6 text-neutral-12 group-disabled:text-neutral-11",
className,
);
return <span className={mergedClassName} {...properties} ref={reference} />;
});

SwitchLabel.displayName = "SwitchLabel";

export const SwitchButton = forwardRef<
HTMLSpanElement,
HTMLAttributes<HTMLSpanElement> & { className?: string | undefined }
>(({ className, ...properties }, reference) => {
const mergedClassName = cx(
"group relative isolate inline-flex h-6 w-11 rounded-full border-2 border-transparent bg-neutral-a-3 transition duration-200 ease-in-out group-data-[is-primary=true]:bg-primary-9 group-focus-visible:outline group-focus-visible:outline-2 group-focus-visible:outline-primary-7 group-selected:bg-neutral-9 group-disabled:bg-neutral-a-3",
className,
);
return <span className={mergedClassName} {...properties} ref={reference} />;
});

SwitchButton.displayName = "SwitchButton";

export const SwitchThumb = forwardRef<
HTMLSpanElement,
HTMLAttributes<HTMLSpanElement> & { className?: string | undefined }
>(({ className, ...properties }, reference) => {
const mergedClassName = cx(
"pointer-events-none relative inline-block size-5 rounded-full bg-white shadow transition-all duration-200 ease-in-out will-change-transform translate-x-0 group-selected:translate-x-5 group-disabled:bg-neutral-2 group-disabled:shadow-none",
className,
);
return <span className={mergedClassName} {...properties} ref={reference} />;
});

SwitchThumb.displayName = "SwitchThumb";

0 comments on commit 73c46ec

Please sign in to comment.