-
Notifications
You must be signed in to change notification settings - Fork 202
feat(downstate): docs + implementation for example components #2520
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
Changes from all commits
99554f9
7c7a321
aa9ecc0
30eebf3
993a550
9db3bf5
54d5c7e
68c3002
a4490cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
export const withDownStateDimensionCapture = (selector) => (Story, context) => { | ||
const captureDownStateDimensions = () => { | ||
const components = document.querySelectorAll(selector); | ||
components.forEach((component) => { | ||
const { width, height } = component.getBoundingClientRect(); | ||
component.style.setProperty('--spectrum-downstate-width', `${width}px`); | ||
component.style.setProperty('--spectrum-downstate-height', `${height}px`); | ||
}); | ||
}; | ||
|
||
document.addEventListener("DOMContentLoaded", () => { | ||
// Wait to make sure the story is fully rendered (otherwise width/height can be wrong) | ||
setTimeout(() => { | ||
captureDownStateDimensions(); | ||
}, 100); | ||
}); | ||
|
||
return Story(context); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { Template } from "../../../components/button/stories/template"; | ||
|
||
export default { | ||
title: "Foundations/Down state", | ||
description: | ||
"Buttons allow users to perform an action or to navigate to another page. They have multiple styles for various needs, and are ideal for calling attention to where a user needs to do something in order to move forward in a flow.", | ||
component: "Button", | ||
args: { | ||
rootClass: "spectrum-Button", | ||
}, | ||
parameters: { | ||
actions: { | ||
handles: ['click .spectrum-Button'], | ||
}, | ||
status: { | ||
type: process.env.MIGRATED_PACKAGES.includes("button") | ||
? "migrated" | ||
: undefined, | ||
}, | ||
}, | ||
tags: ['foundation'], | ||
}; | ||
|
||
export const ButtonDownState = Template.bind({}); | ||
ButtonDownState.args = { | ||
label: "Edit", | ||
variant: "accent", | ||
customStyles: { | ||
"--spectrum-downstate-width": "72px", | ||
"--spectrum-downstate-height": "32px" | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { Template } from "../../../components/checkbox/stories/template"; | ||
|
||
export default { | ||
title: "Foundations/Down state", | ||
description: | ||
"Checkboxes allow users to select multiple items from a list of individual items, or mark one individual item as selected.", | ||
component: "Checkbox", | ||
args: { | ||
rootClass: "spectrum-Checkbox", | ||
}, | ||
parameters: { | ||
actions: { | ||
handles: ['click input[type="checkbox"]'], | ||
}, | ||
status: { | ||
type: process.env.MIGRATED_PACKAGES.includes("checkbox") | ||
? "migrated" | ||
: undefined, | ||
}, | ||
}, | ||
tags: ['foundation'], | ||
}; | ||
|
||
export const CheckboxDownState = Template.bind({}); | ||
CheckboxDownState.args = { | ||
label: "Checkbox", | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Meta, Story } from '@storybook/blocks'; | ||
import * as Checkbox from './checkbox-down-state.stories.js'; | ||
import * as Button from './button-down-state.stories.js'; | ||
|
||
<Meta title="Foundations/Down state" /> | ||
|
||
# Down state | ||
|
||
Down state is a Spectrum 2 feature that creates the illusion of components being pressed-in when active. This functionality is already included in Spectrum 2 components that require down state in this project. It is implemented with a CSS transform. The implementation depends on the size of the interactable element, as shown in the examples below. | ||
|
||
## Examples | ||
|
||
### Minimum perspective | ||
|
||
For elements that have a width of 24px or less, the minimum perspective token is used to apply the down state. One example of a component that uses this token is the checkbox: | ||
|
||
<Story of={Checkbox.CheckboxDownState} /> | ||
|
||
In this case, we use the minimum perspective token: | ||
|
||
``` | ||
transform: | ||
perspective(var(--spectrum-component-size-minimum-perspective-down)) | ||
translateZ(var(--spectrum-component-size-difference-down)); | ||
``` | ||
|
||
### Calculated perspective | ||
|
||
For elements that have a width of greater than 24px, we need to use the component's width and height to apply the down state. One example of a component that uses this logic is the button: | ||
|
||
<Story of={Button.ButtonDownState} /> | ||
|
||
In this case, we use a max formula to calculate the perspective based on component width and height (this helps us account for components that may be very wide): | ||
|
||
``` | ||
transform: | ||
perspective(max( | ||
var(--spectrum-downstate-height), | ||
var(--spectrum-downstate-width) * var(--spectrum-component-size-width-ratio-down) | ||
)) | ||
translateZ(var(--spectrum-component-size-difference-down)); | ||
``` | ||
|
||
*Note that in this case, users are required to develop an implementation to determine the width and height of the component. Assign these values to the `--spectrum-downstate-width` and `--spectrum-downstate-height` custom properties in a `style` attribute on the HTML element to expose them for use in the CSS.* |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ import { html } from "lit"; | |
import { ifDefined } from "lit/directives/if-defined.js"; | ||
import { styleMap } from "lit/directives/style-map.js"; | ||
import { when } from "lit/directives/when.js"; | ||
import { withDownStateDimensionCapture } from "../../../.storybook/decorators"; | ||
|
||
import { default as IconStories } from "@spectrum-css/icon/stories/icon.stories.js"; | ||
import { Template as Typography } from "@spectrum-css/typography/stories/template.js"; | ||
|
@@ -12,6 +13,7 @@ export default { | |
description: | ||
"Buttons allow users to perform an action or to navigate to another page. They have multiple styles for various needs, and are ideal for calling attention to where a user needs to do something in order to move forward in a flow.", | ||
component: "Button", | ||
decorators: [withDownStateDimensionCapture('.spectrum-Button:not(:disabled)')], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will need to be added to all stories of components that require the capture of width/height as they migrate to S2. I'll try to note that in the appropriate Jira tickets. |
||
argTypes: { | ||
size: { | ||
name: "Size", | ||
|
@@ -100,7 +102,7 @@ export default { | |
name: "Layout", | ||
description: "How the buttons align in the preview (Storybook only).", | ||
type: { name: "string" }, | ||
table: { | ||
table: { | ||
type: { summary: "string" }, | ||
category: "Advanced" | ||
}, | ||
|
@@ -349,4 +351,4 @@ Wrapping.args = { | |
showIconOnlyButton: false, | ||
variant: "accent", | ||
label: "An example of text overflow behavior within the button component. When the button text is too long for the horizontal space available, it wraps to form another line.", | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -150,6 +150,12 @@ governing permissions and limitations under the License. | |
} | ||
} | ||
|
||
&:not(.is-readOnly):active { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This approach will not work in case the SWC wants to disable downstate for checkbox. This is tightly coupled with the css transform. We need to cascade the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey Rajdeep! Can you help me understand what needs to change? One piece of context that might be helpful is for components like Checkbox which are smaller than 24px, the transform perspective is not based on the width and height of the component, it is based on a set value per the design spec. |
||
.spectrum-Checkbox-input:not(:disabled) + .spectrum-Checkbox-box { | ||
transform: perspective(var(--spectrum-component-size-minimum-perspective-down)) translateZ(var(--spectrum-component-size-difference-down)); | ||
} | ||
} | ||
|
||
/* Selected Invalid */ | ||
&.is-invalid { | ||
.spectrum-Checkbox-input:checked + .spectrum-Checkbox-box, | ||
|
@@ -372,6 +378,7 @@ governing permissions and limitations under the License. | |
} | ||
} | ||
} | ||
|
||
/* stylelint-enable max-nesting-depth */ | ||
|
||
.spectrum-Checkbox-label { | ||
|
@@ -571,7 +578,7 @@ governing permissions and limitations under the License. | |
outline-style: auto; | ||
outline-offset: var(--highcontrast-checkbox-focus-indicator-gap, var(--mod-checkbox-focus-indicator-gap, var(--spectrum-checkbox-focus-indicator-gap))); | ||
/* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties */ | ||
outline-width: var(--mod-focus-indicator-thickness, var(--spectrum-focus-indicator-thickness)); | ||
outline-width: var(--mod-focus-indicator-thickness, var(--spectrum-focus-indicator-thickness)); | ||
|
||
&::after { | ||
box-shadow: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! Looks like these dimensions are being captured well in the Storybook buttons!