Skip to content
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

fix: adding max height and full height to picker menu component #3051

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions .changeset/unlucky-wasps-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@spectrum-css/picker": major

Choose a reason for hiding this comment

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

Should this be a major bump? Seems like this feature is non-breaking.

---

Removing full height mod and keeping max block size for fixed menu height
5 changes: 5 additions & 0 deletions .changeset/yellow-bags-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@spectrum-css/picker": major
---

Adding max height to picker menu
7 changes: 7 additions & 0 deletions components/picker/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,10 @@
color: var(--highcontrast-picker-content-color-disabled, var(--mod-picker-font-color-disabled, var(--spectrum-picker-font-color-disabled)));
}
}

/* Fixed menu height */
.spectrum-Picker--menu-height-fixed {
& + .spectrum-Popover.is-open {

Choose a reason for hiding this comment

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

Do we need the .is-open here? Can't the popover max-block-size be defined independently of being open?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For specificity, I think it's necessary. It also gives other devs more context.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Looking at the render function in the packages/picker/src/Picker.ts, I don't think this is a "Picker" feature so much as it's a "Menu" feature. If we add a block-size property to the root Menu class:

.spectrum-Menu {
	display: inline-block;
	inline-size: var(--mod-menu-inline-size, auto);
	block-size: var(--mod-menu-block-size, auto);
}

Users now have a hook to set a 200px fixed height if they so wish. If the design guidance is to default to 200px, that's a breaking change so maybe we can make note of it to add in the future and deprecate a block-size of auto?

max-block-size: var(--mod-picker-menu-height-fixed, 200px);

Choose a reason for hiding this comment

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

Just for context, did we confirm this default value with design?

}
}
2 changes: 2 additions & 0 deletions components/picker/metadata/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
".spectrum-Picker .spectrum-Picker-icon",
".spectrum-Picker .spectrum-Picker-label",
".spectrum-Picker .spectrum-ProgressCircle",
".spectrum-Picker--menu-height-fixed + .spectrum-Popover.is-open",
".spectrum-Picker--quiet",
".spectrum-Picker--quiet .spectrum-Picker-menuIcon",
".spectrum-Picker--quiet.is-keyboardFocused",
Expand Down Expand Up @@ -124,6 +125,7 @@
"--mod-picker-icon-color-key-focus",
"--mod-picker-inline-size",
"--mod-picker-line-height",
"--mod-picker-menu-height-fixed",

Choose a reason for hiding this comment

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

Same comment as the other one, around the naming 😛

Choose a reason for hiding this comment

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

For the sake of making our discussion public for other folks to be able to follow along, I suggest we consider adding a CSS property to the popover component that allows it to be styled externally. This approach would simplify our implementation on the web components side.

Here's a rough example of how this could look like:

/* In the popover component */
.spectrum-Popover {
    max-block-size: var(--spectrum-popover-max-block-size);
}

/* In the picker component */
.spectrum-Picker--menu-height-fixed {
    & + .spectrum-Popover.is-open {
        --spectrum-popover-max-block-size: var(--mod-picker-menu-height-fixed, 200px);
    }
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

max-block-size: var(--spectrum-popover-max-block-size);

This would require us defining a global variable that can be shared.

Choose a reason for hiding this comment

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

@castastrophe @pfulton
Just to confirm, should we continue leaning more into using the mod properties for features, or is there an alternative approach that would be preferred?

Copy link
Collaborator

Choose a reason for hiding this comment

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

For now, this is our approach. We may revisit it in the near future, but currently we will move forward with this approach (so it's valid here).

"--mod-picker-placeholder-font-style",
"--mod-picker-placeholder-font-weight",
"--mod-picker-spacing-bottom-to-text",
Expand Down
1 change: 1 addition & 0 deletions components/picker/metadata/mods.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
| `--mod-picker-icon-color-key-focus` |
| `--mod-picker-inline-size` |
| `--mod-picker-line-height` |
| `--mod-picker-menu-height-fixed` |
| `--mod-picker-placeholder-font-style` |
| `--mod-picker-placeholder-font-weight` |
| `--mod-picker-spacing-bottom-to-text` |
Expand Down
10 changes: 10 additions & 0 deletions components/picker/stories/picker.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ export default {
},
isQuiet,
isOpen,
menuHeight: {
name: "Max Menu Height",

Choose a reason for hiding this comment

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

I would recommend renaming it to "Menu max block size" (doesn't sound as nice, but I would be for accuracy) - what do you think?

type: {name: "boolean"},
table: {
type: { name: "boolean" },
category: "State",
},
if: { arg: "isOpen", eq: true },
control: "boolean",
},
isKeyboardFocused,
isDisabled,
isLoading,
Expand Down
9 changes: 4 additions & 5 deletions components/picker/stories/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const Picker = ({
customClasses = [],
customStyles = {},
onclick,
menuHeight = false,
} = {}, context = {}) => {
return html`
<button
Expand All @@ -39,6 +40,7 @@ export const Picker = ({
["is-open"]: isOpen,
["is-loading"]: isLoading,
["is-keyboardFocused"]: isKeyboardFocused,
[`${rootClass}--menu-height-fixed`]: menuHeight,

Choose a reason for hiding this comment

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

Have we considered the pros and cons of not having a dedicated API for this feature? For instance, instead of having a specific menu-height class, we could use a generic mod variable applied to the base class. This mod variable would function as a feature toggle, although customers would need to define its value themselves (because we would not have a default fallback).

Choose a reason for hiding this comment

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

But I guess this is a more holistic API design question, maybe the CSS team can help understand when a mod is enough vs a dedicated toggleable class feature.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree, this feels like a good use-case to add a mod rather than new API.

...customClasses.reduce((a, c) => ({ ...a, [c]: true }), {}),
})}
?disabled=${isDisabled}
Expand Down Expand Up @@ -88,8 +90,8 @@ export const Template = ({
withSwitch = false,
fieldLabelStyle = {},
customClasses = [],
customStyles = {},
content = [],
menuHeight = false,
id = getRandomId("picker"),
} = {}, context = {}) => {
const { updateArgs } = context;
Expand Down Expand Up @@ -136,13 +138,10 @@ export const Template = ({
isDisabled,
isReadOnly,
customClasses,
customStyles: {

Choose a reason for hiding this comment

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

Where did these go? 😛

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@rubencarvalho I removed the inline styling of the Picker because it was displaying the label and button inline and overriding the flex-box styling and disrupting the text wrap especially when the label was displayed left. So I "turned it off" by removing this block. I can bring it back if needed

Choose a reason for hiding this comment

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

Oh, thanks for the context! I thought it was a forgotten edit 😄

"display": labelPosition == "left" ? "inline-block" : undefined,
...customStyles,
},
content,
iconName,
labelPosition,
menuHeight,
id,
onclick: function() {
updateArgs({ isOpen: !isOpen });
Expand Down
Loading