-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
KDS-1752 Radio, RadioGroup, RadioField (#4101)
* add Radio * Moved radio * add Label + RadioField * add RadioGroup * add Search Field * remove search field * remove search field * RadioField tests * a working radio example * remove old Label * fix up docs + useId * add changeset * ignore label a11y violation * remove useless tests * fix stickersheet alringment
- Loading branch information
Showing
21 changed files
with
960 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--- | ||
--- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
@import "~@kaizen/design-tokens/sass/border"; | ||
@import "~@kaizen/design-tokens/sass/color"; | ||
@import "../../../styles/forms"; | ||
@import "../../../styles/form-variables"; | ||
|
||
$radio-size: 24px; | ||
$icon-size: 10px; | ||
$icon-offset: 5px; | ||
$focus-ring-offset: 2px; | ||
|
||
$dt-color-radio-background-color-hover: $color-gray-200; | ||
$dt-color-radio-disc-color-base: $color-gray-600; | ||
$dt-color-radio-border-color-focus: $color-blue-500; | ||
$dt-color-radio-border-color-focus-reversed: $color-blue-300; | ||
|
||
.radioInput { | ||
@include form-input-visually-hidden; | ||
} | ||
|
||
.icon { | ||
top: $icon-offset; | ||
left: $icon-offset; | ||
width: $icon-size; | ||
height: $icon-size; | ||
border-radius: 50%; | ||
background: $dt-color-radio-disc-color-base; | ||
position: absolute; | ||
|
||
&.reversed { | ||
background: $color-white; | ||
} | ||
} | ||
|
||
.box { | ||
display: block; | ||
position: relative; | ||
background: $color-white; | ||
height: $radio-size; | ||
width: $radio-size; | ||
top: 0; | ||
border: $border-solid-border-width $border-solid-border-style | ||
$dt-color-form-border-color; | ||
box-sizing: border-box; | ||
border-radius: 50%; | ||
|
||
.radioInput:focus:not([disabled]) + & { | ||
border-color: $dt-color-radio-disc-color-base; | ||
} | ||
|
||
.radioInput:focus:not([disabled]) + &::after { | ||
pointer-events: none; | ||
content: ""; | ||
box-sizing: border-box; | ||
position: absolute; | ||
background: transparent; | ||
border-radius: $radio-size + $focus-ring-offset; | ||
border-width: $border-focus-ring-border-width; | ||
border-style: $border-focus-ring-border-style; | ||
border-color: $dt-color-radio-border-color-focus; | ||
top: -$focus-ring-offset - ($radio-size / 8); | ||
left: -$focus-ring-offset - ($radio-size / 8); | ||
width: calc( | ||
#{$radio-size} + #{$focus-ring-offset} + #{$border-solid-border-width} * 2 | ||
); | ||
height: calc( | ||
#{$radio-size} + #{$focus-ring-offset} + #{$border-solid-border-width} * 2 | ||
); | ||
} | ||
|
||
.radioInput:not([disabled]) + &:hover { | ||
border-color: $dt-color-form-border-color-hover; | ||
background-color: $dt-color-radio-background-color-hover; | ||
} | ||
|
||
&.reversed { | ||
border: $border-solid-border-width $border-solid-border-style | ||
rgba($color-white-rgb, 0.65); | ||
background: transparent; | ||
|
||
.radioInput:focus:not([disabled]) + & { | ||
border-color: $color-white; | ||
} | ||
|
||
.radioInput:focus:not([disabled]) + &::after { | ||
border-color: $dt-color-radio-border-color-focus-reversed; | ||
} | ||
|
||
.radioInput:not([disabled]) + &:hover { | ||
border-color: $color-white; | ||
background-color: transparent; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import React, { InputHTMLAttributes } from "react" | ||
import classnames from "classnames" | ||
import { OverrideClassName } from "~types/OverrideClassName" | ||
import styles from "./Radio.module.scss" | ||
|
||
export type RadioProps = OverrideClassName< | ||
Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "checked"> | ||
> & { | ||
/** | ||
* This needs to be enforced to ensure the Radio always gets an id to match a label when composed. | ||
*/ | ||
id: string | ||
name: string | ||
value: string | ||
selectedStatus?: boolean | ||
reversed?: boolean | ||
} | ||
|
||
const renderSelected = ( | ||
selectedStatus: boolean, | ||
reversed: boolean | ||
): React.ReactNode => { | ||
if (selectedStatus) { | ||
return ( | ||
<div className={classnames(styles.icon, reversed && styles.reversed)} /> | ||
) | ||
} | ||
return | ||
} | ||
|
||
export const Radio = ({ | ||
name, | ||
value, | ||
selectedStatus = false, | ||
reversed = false, | ||
onChange, | ||
classNameOverride, | ||
...restProps | ||
}: RadioProps): JSX.Element => ( | ||
// @todo: Move classNameOverride to span | ||
<span> | ||
<input | ||
type="radio" | ||
name={name} | ||
value={value} | ||
checked={selectedStatus} | ||
className={classnames( | ||
styles.radioInput, | ||
classNameOverride, | ||
reversed && styles.reversed | ||
)} | ||
onChange={onChange} | ||
readOnly={onChange === undefined} | ||
{...restProps} | ||
/> | ||
<span className={classnames(styles.box, reversed && styles.reversed)}> | ||
{renderSelected(selectedStatus, reversed)} | ||
</span> | ||
</span> | ||
) | ||
|
||
Radio.displayName = "Radio" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Canvas, Controls, Meta } from "@storybook/blocks" | ||
import { ResourceLinks, KaioNotification, Installation } from "~storybook/components" | ||
import { LinkTo } from "~storybook/components/LinkTo" | ||
import * as RadioStories from "./Radio.stories" | ||
|
||
<Meta of={RadioStories} /> | ||
|
||
# Radio | ||
|
||
<ResourceLinks | ||
sourceCode="https://github.com/cultureamp/kaizen-design-system/tree/main/packages/components/src/Radio" | ||
className="!mb-8" | ||
/> | ||
|
||
<KaioNotification /> | ||
|
||
<Installation | ||
installCommand="yarn add @kaizen/components" | ||
importStatement='import { Radio } from "@kaizen/components"' | ||
/> | ||
|
||
## Overview | ||
|
||
A primitive, not to be used alone. | ||
|
||
|
||
Commonly used via <LinkTo pageId="components-radio-controls-radiofield">RadioField</LinkTo> or <LinkTo pageId="components-radio-controls-radiogroup">RadioGroup</LinkTo>. | ||
|
||
<Canvas of={RadioStories.Playground} /> | ||
<Controls of={RadioStories.Playground} /> |
107 changes: 107 additions & 0 deletions
107
packages/components/src/Radio/Radio/_docs/Radio.stickersheet.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import React from "react" | ||
import { Meta } from "@storybook/react" | ||
import { | ||
StickerSheet, | ||
StickerSheetStory, | ||
} from "~storybook/components/StickerSheet" | ||
import { Radio } from "../index" | ||
|
||
export default { | ||
title: "KAIO-staging/Radio controls/Radio", | ||
parameters: { | ||
chromatic: { disable: false }, | ||
controls: { disable: true }, | ||
a11y: { | ||
config: { | ||
rules: [ | ||
{ | ||
// Built with no label on purpose, to be used within `RadioField` where label is present | ||
id: "label", | ||
enabled: false, | ||
}, | ||
], | ||
}, | ||
}, | ||
}, | ||
} satisfies Meta | ||
|
||
const StickerSheetTemplate: StickerSheetStory = { | ||
render: ({ isReversed }) => ( | ||
<StickerSheet isReversed={isReversed}> | ||
<StickerSheet.Header | ||
headings={["Default", "Focus", "Hover"]} | ||
hasVerticalHeadings | ||
/> | ||
<StickerSheet.Body> | ||
<StickerSheet.Row rowTitle="Off"> | ||
<Radio | ||
id="radio1" | ||
name="radio1" | ||
value="radio1" | ||
reversed={isReversed} | ||
/> | ||
<Radio | ||
id="radio2" | ||
name="radio2" | ||
value="radio2" | ||
reversed={isReversed} | ||
data-sb-pseudo-styles="focus" | ||
/> | ||
<Radio | ||
id="radio3" | ||
name="radio3" | ||
value="radio3" | ||
reversed={isReversed} | ||
data-sb-pseudo-styles="hover" | ||
/> | ||
</StickerSheet.Row> | ||
<StickerSheet.Row rowTitle="On"> | ||
<Radio | ||
id="radio11" | ||
name="radio11" | ||
value="radio11" | ||
reversed={isReversed} | ||
selectedStatus | ||
/> | ||
<Radio | ||
id="radio22" | ||
name="radio22" | ||
value="radio22" | ||
reversed={isReversed} | ||
selectedStatus | ||
data-sb-pseudo-styles="focus" | ||
/> | ||
<Radio | ||
id="radio33" | ||
name="radio33" | ||
value="radio33" | ||
reversed={isReversed} | ||
selectedStatus | ||
data-sb-pseudo-styles="hover" | ||
/> | ||
</StickerSheet.Row> | ||
</StickerSheet.Body> | ||
</StickerSheet> | ||
), | ||
parameters: { | ||
pseudo: { | ||
focus: '[data-sb-pseudo-styles="focus"]', | ||
hover: '[data-sb-pseudo-styles="hover"] + span', | ||
}, | ||
}, | ||
} | ||
|
||
export const StickerSheetDefault: StickerSheetStory = { | ||
...StickerSheetTemplate, | ||
name: "Sticker Sheet (Default)", | ||
} | ||
|
||
export const StickerSheetReversed: StickerSheetStory = { | ||
...StickerSheetTemplate, | ||
name: "Sticker Sheet (Reversed)", | ||
parameters: { | ||
...StickerSheetTemplate.parameters, | ||
backgrounds: { default: "Purple 700" }, | ||
}, | ||
args: { isReversed: true }, | ||
} |
39 changes: 39 additions & 0 deletions
39
packages/components/src/Radio/Radio/_docs/Radio.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { Meta, StoryObj } from "@storybook/react" | ||
import { Radio } from "../index" | ||
|
||
const meta = { | ||
title: "KAIO-staging/Radio controls/Radio", | ||
component: Radio, | ||
args: { | ||
id: "radio", | ||
name: "Radio", | ||
value: "Radio", | ||
}, | ||
parameters: { | ||
a11y: { | ||
config: { | ||
rules: [ | ||
{ | ||
// Built with no label on purpose, to be used within `RadioField` where label is present | ||
id: "label", | ||
enabled: false, | ||
}, | ||
], | ||
}, | ||
}, | ||
}, | ||
} satisfies Meta<typeof Radio> | ||
|
||
export default meta | ||
|
||
type Story = StoryObj<typeof meta> | ||
|
||
export const Playground: Story = { | ||
parameters: { | ||
docs: { | ||
canvas: { | ||
sourceState: "shown", | ||
}, | ||
}, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./Radio" |
49 changes: 49 additions & 0 deletions
49
packages/components/src/Radio/RadioField/RadioField.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
@import "~@kaizen/design-tokens/sass/color"; | ||
@import "~@kaizen/design-tokens/sass/spacing"; | ||
@import "~@kaizen/design-tokens/sass/typography"; | ||
@import "../../../styles/form-variables"; | ||
|
||
$dt-color-radio-background-color-hover: $color-gray-200; | ||
|
||
.container { | ||
position: relative; | ||
overflow-wrap: break-word; | ||
word-wrap: break-word; | ||
word-break: break-word; | ||
margin-bottom: $spacing-sm; | ||
|
||
label { | ||
-webkit-tap-highlight-color: transparent; | ||
|
||
:global(.ideal-sans) & { | ||
// This is to override bootstrap styles. Remove when appropriate | ||
font-size: $typography-paragraph-body-font-size; | ||
padding-top: 0; | ||
} | ||
} | ||
|
||
&.selected { | ||
label { | ||
font-family: $typography-paragraph-body-font-family; | ||
font-size: $typography-paragraph-body-font-size; | ||
line-height: $typography-paragraph-body-line-height; | ||
letter-spacing: $typography-paragraph-body-letter-spacing; | ||
font-weight: $typography-paragraph-bold-font-weight; | ||
position: static; | ||
} | ||
} | ||
|
||
&:not(.reversed) label:hover { | ||
input:not([disabled]) + span { | ||
border-color: $dt-color-form-border-color-hover; | ||
background-color: $dt-color-radio-background-color-hover; | ||
} | ||
} | ||
|
||
&.reversed label:hover { | ||
input:not([disabled]) + span { | ||
border-color: $color-white; | ||
background-color: transparent; | ||
} | ||
} | ||
} |
Oops, something went wrong.