Skip to content

Commit

Permalink
feat: governance components
Browse files Browse the repository at this point in the history
  • Loading branch information
yyyyaaa committed Nov 6, 2023
1 parent 3c1136a commit c95cb61
Show file tree
Hide file tree
Showing 42 changed files with 2,860 additions and 18 deletions.
27 changes: 27 additions & 0 deletions compiler/scaffold.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,31 @@ module.exports = {
path: "../number-field",
},
},
"governance-checkbox": {
jsxMap: {
ScaffoldGovernanceCheckbox: "GovernanceCheckbox",
},
import: {
imports: { GovernanceCheckbox: "default" },
path: "../governance-checkbox",
},
},
"governance-radio": {
jsxMap: {
ScaffoldGovernanceRadio: "GovernanceRadio",
},
import: {
imports: { GovernanceRadio: "default" },
path: "../governance-radio",
},
},
"governance-radio-group": {
jsxMap: {
ScaffoldGovernanceRadioGroup: "GovernanceRadioGroup",
},
import: {
imports: { GovernanceRadioGroup: "default" },
path: "../governance-radio-group",
},
},
};
5 changes: 2 additions & 3 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@
"@floating-ui/dom": "^1.5.2",
"@floating-ui/react": "^0.26.0",
"@formkit/auto-animate": "1.0.0-beta.6",
"@react-aria/i18n": "^3.8.4",
"@react-aria/numberfield": "^3.9.1",
"@react-aria/utils": "^3.21.1",
"@react-stately/numberfield": "^3.6.2",
"@vanilla-extract/css": "^1.12.0",
"@vanilla-extract/css-utils": "^0.1.3",
"@vanilla-extract/dynamic": "^2.0.3",
Expand All @@ -69,6 +66,8 @@
"immer": "^9.0.19",
"lodash": "^4.17.21",
"rainbow-sprinkles": "^0.17.0",
"react-aria": "^3.29.1",
"react-stately": "^3.27.1",
"zustand": "4.4.6"
},
"peerDependencies": {
Expand Down
106 changes: 106 additions & 0 deletions packages/react/scaffolds/governance-checkbox/governance-checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import * as React from "react";
import { useToggleState } from "react-stately";
import { useCheckbox, useFocusRing, VisuallyHidden } from "react-aria";
import Box from "@/ui/box";
import Stack from "@/ui/stack";
import type { GovernanceCheckboxProps } from "./governance-checkbox.types";

export default function GovernanceCheckbox(props: GovernanceCheckboxProps) {
const state = useToggleState(props);
const ref = React.useRef(null);
const { inputProps } = useCheckbox(props, state, ref);
const { isFocusVisible, focusProps } = useFocusRing();
const isSelected =
state.isSelected && !props.isIndeterminate && !props.isRejected;

return (
<Box
as="label"
display="flex"
alignItems="center"
fontFamily="$body"
fontSize="$sm"
fontWeight="$normal"
color="$text"
opacity={props.isDisabled ? 0.4 : 1}
>
<VisuallyHidden>
<input {...inputProps} {...focusProps} ref={ref} />
</VisuallyHidden>

<Stack
direction="horizontal"
space="$4"
attributes={{
alignItems: "center",
}}
>
<svg width={16} height={16} viewBox="0 0 18 18" aria-hidden="true">
{isSelected && (
<>
<path
d="M4 17.0001C2.34315 17.0001 1 15.6569 1 14.0001V4C1 2.34315 2.34315 1 4 1H14C15.6569 1 17 2.34315 17 4L17 14.0001C17 15.6569 15.6569 17.0001 14 17.0001H4Z"
fill="#E5FFE4"
/>
<path
d="M12 7L7.5253 11L6 9.63651M17 4L17 14.0001C17 15.6569 15.6569 17.0001 14 17.0001H4C2.34315 17.0001 1 15.6569 1 14.0001V4C1 2.34315 2.34315 1 4 1H14C15.6569 1 17 2.34315 17 4Z"
fill="#E5FFE4"
stroke="#36BB35"
strokeWidth="1.66667"
strokeLinecap="round"
strokeLinejoin="round"
/>
</>
)}

{props.isIndeterminate && (
<>
<path
d="M4.5 17.0001C2.84315 17.0001 1.5 15.6569 1.5 14.0001V4C1.5 2.34315 2.84315 1 4.5 1H14.5C16.1569 1 17.5 2.34315 17.5 4L17.5 14.0001C17.5 15.6569 16.1569 17.0001 14.5 17.0001H4.5Z"
fill="#E0E5ED"
/>
<path
d="M6.5 9H12.5M17.5 4L17.5 14.0001C17.5 15.6569 16.1569 17.0001 14.5 17.0001H4.5C2.84315 17.0001 1.5 15.6569 1.5 14.0001V4C1.5 2.34315 2.84315 1 4.5 1H14.5C16.1569 1 17.5 2.34315 17.5 4Z"
fill="#E0E5ED"
stroke="#697584"
strokeWidth="1.66667"
strokeLinecap="round"
strokeLinejoin="round"
/>
</>
)}

{props.isRejected && (
<>
<path
d="M4 17.0001C2.34315 17.0001 1 15.6569 1 14.0001V4C1 2.34315 2.34315 1 4 1H14C15.6569 1 17 2.34315 17 4L17 14.0001C17 15.6569 15.6569 17.0001 14 17.0001H4Z"
fill="#FFDBDB"
/>
<path
d="M11.8284 6.17157L9 9M9 9L6.17157 11.8284M9 9L11.8284 11.8284M9 9L6.17157 6.17157M17 4L17 14.0001C17 15.6569 15.6569 17.0001 14 17.0001H4C2.34315 17.0001 1 15.6569 1 14.0001V4C1 2.34315 2.34315 1 4 1H14C15.6569 1 17 2.34315 17 4Z"
fill="#FFDBDB"
stroke="#C73636"
strokeWidth="1.66667"
strokeLinecap="round"
/>
</>
)}

{isFocusVisible && (
<rect
x={1}
y={1}
width={22}
height={22}
fill="none"
stroke="orange"
strokeWidth={2}
/>
)}
</svg>

<Box as="p">{props.children}</Box>
</Stack>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AriaCheckboxProps } from "react-aria";

export interface GovernanceCheckboxProps extends AriaCheckboxProps {
isRejected?: boolean;
children?: React.ReactNode;
}
1 change: 1 addition & 0 deletions packages/react/scaffolds/governance-checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./governance-checkbox";
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as React from "react";
import type { RadioGroupState } from "react-stately";

export const RadioContext = React.createContext<RadioGroupState | null>(null);
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useRadioGroup, VisuallyHidden } from "react-aria";
import { useRadioGroupState } from "react-stately";
import Text from "@/ui/text";
import { RadioContext } from "./governance-radio-group.context";
import type { GovernanceRadioGroupProps } from "./governance-radio-group.types";

export default function GovernanceRadioGroup(props: GovernanceRadioGroupProps) {
const { children, label, description, errorMessage } = props;
const state = useRadioGroupState(props);
const { radioGroupProps, labelProps, descriptionProps, errorMessageProps } =
useRadioGroup(props, state);

return (
<div {...radioGroupProps}>
<VisuallyHidden>
<span {...labelProps}>{label}</span>
</VisuallyHidden>

<RadioContext.Provider value={state}>{children}</RadioContext.Provider>

{description && (
<Text domAttributes={descriptionProps} fontSize="$xs">
{description}
</Text>
)}
{errorMessage && state.isInvalid && (
<Text domAttributes={errorMessageProps} fontSize="$xs" color="$red300">
{errorMessage}
</Text>
)}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AriaRadioGroupProps } from "react-aria";

export interface GovernanceRadioGroupProps extends AriaRadioGroupProps {
children?: React.ReactNode;
}
1 change: 1 addition & 0 deletions packages/react/scaffolds/governance-radio-group/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./governance-radio-group";
14 changes: 14 additions & 0 deletions packages/react/scaffolds/governance-radio/governance-radio.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { style } from "@vanilla-extract/css";
import { themeVars } from "@/styles/themes.css";

export const radioCircleDefault = style({
stroke: themeVars.colors.textSecondary,
});

export const radioCircleSelected = style({
stroke: themeVars.colors.text,
});

export const radioCircleDisabled = style({
stroke: themeVars.colors.inputDisabledText,
});
94 changes: 94 additions & 0 deletions packages/react/scaffolds/governance-radio/governance-radio.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import * as React from "react";
import clx from "clsx";
import Box from "@/ui/box";
import Text from "@/ui/text";
import { useRadio, useFocusRing, VisuallyHidden } from "react-aria";
import { RadioContext } from "../governance-radio-group/governance-radio-group.context";
import * as styles from "./governance-radio.css";
import { standardTransitionProperties } from "@/ui/shared/shared.css";
import type { GovernanceRadioProps } from "./governance-radio.types";

const defaultCircle = {
cx: "8.33301",
cy: "8",
r: "7.33333",
strokeWidth: "1.33333",
};

const selectedCircle = {
cx: "8.66699",
cy: "8",
r: "6",
strokeWidth: "4",
};

export default function GovernanceRadio(props: GovernanceRadioProps) {
const { children } = props;
const state = React.useContext(RadioContext);
const ref = React.useRef(null);
const { inputProps, isSelected, isDisabled } = useRadio(props, state, ref);
const { isFocusVisible, focusProps } = useFocusRing();

return (
<Box
as="label"
display="flex"
alignItems="center"
minWidth="100px"
padding={{
mobile: "$4",
tablet: "$10",
desktop: "$10",
}}
width="auto"
height="48px"
borderRadius="$md"
borderColor={
isFocusVisible
? "$blue400"
: isDisabled
? "transparent"
: "$inputBorder"
}
flex={{
mobile: "1",
tablet: "1",
desktop: "none",
}}
borderWidth="1px"
borderStyle="$solid"
backgroundColor={isSelected && !isDisabled ? "$inputBg" : "$cardBg"}
className={standardTransitionProperties}
>
<VisuallyHidden>
<input {...inputProps} {...focusProps} ref={ref} />
</VisuallyHidden>

<svg width="17" height="16" viewBox="0 0 17 16" aria-hidden="true">
<circle
fill="none"
{...(isSelected ? selectedCircle : defaultCircle)}
className={clx(
isDisabled
? styles.radioCircleDisabled
: isSelected
? styles.radioCircleSelected
: styles.radioCircleDefault
)}
/>
</svg>

<Text
as="div"
fontSize="$sm"
fontWeight="$semibold"
color="$text"
attributes={{
marginLeft: "$6",
}}
>
{children}
</Text>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AriaRadioProps } from "react-aria";

export interface GovernanceRadioProps extends AriaRadioProps {
children?: React.ReactNode;
}
1 change: 1 addition & 0 deletions packages/react/scaffolds/governance-radio/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./governance-radio";
5 changes: 2 additions & 3 deletions packages/react/scaffolds/number-field/number-field.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useState, useId, forwardRef } from "react";
import { useNumberFieldState } from "@react-stately/numberfield";
import { useNumberField } from "@react-aria/numberfield";
import { useLocale } from "@react-aria/i18n";
import { useNumberFieldState } from "react-stately";
import { useNumberField, useLocale } from "react-aria";
import { mergeRefs } from "@react-aria/utils";

import clx from "clsx";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReactNode } from "react";
import type { Sprinkles } from "@/styles/rainbow-sprinkles.css";
import type { AriaNumberFieldProps } from "@react-aria/numberfield";
import type { AriaNumberFieldProps } from "react-aria";

export interface NumberInputProps {
// ==== Core logic props
Expand Down
6 changes: 6 additions & 0 deletions packages/react/stories/Link.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ export const Primary: Story = {
args: {
href: "google.com",
target: "_blank",
background: true,
underline: true,
color: {
base: "$textSecondary",
hover: "$linkHover",
},
children: "Go to google",
},
};
30 changes: 30 additions & 0 deletions packages/react/stories/governance/GovernanceCheckbox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { useState } from "react";
import type { Meta, StoryObj } from "@storybook/react";

import Stack from "../../src/ui/stack";
import GovernanceCheckbox from "../../src/ui/governance-checkbox";

const meta: Meta<typeof GovernanceCheckbox> = {
component: GovernanceCheckbox,
title: "Governance/GovernanceCheckbox",
tags: ["autodocs"],
argTypes: {},
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Primary: Story = {
args: {},
render: (props) => {
const [isOpen, setIsOpen] = useState(false);
return (
<Stack direction="vertical" space="$4">
<GovernanceCheckbox isIndeterminate>Pending</GovernanceCheckbox>
<GovernanceCheckbox isSelected>Passed</GovernanceCheckbox>
<GovernanceCheckbox isRejected>Rejected</GovernanceCheckbox>
</Stack>
);
},
};
Loading

0 comments on commit c95cb61

Please sign in to comment.