1
1
mirror of https://github.com/primer/css.git synced 2024-11-09 12:22:47 +03:00

ActionList followup (#1780)

* collapse state updates

* inset variant

* pseudo, you fine as you are

* tree view pattern draft

* tree view structure

* move treeview to new pr

* Stylelint auto-fixes

* Create fresh-schools-pull.md

Co-authored-by: Actions Auto Build <actions@github.com>
This commit is contained in:
Katie Langerman 2021-12-03 08:50:31 -08:00 committed by GitHub
parent ee27583f59
commit 8e9ba62d30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 233 additions and 26 deletions

View File

@ -0,0 +1,5 @@
---
"@primer/css": patch
---
ActionList followup

View File

@ -72,6 +72,18 @@ export default {
table: { table: {
category: 'HTML' category: 'HTML'
} }
},
listPadding: {
options: [0, 1], // iterator
mapping: ['', 'ActionList--full'], // values
control: {
type: 'inline-radio',
labels: ['inset', 'full-bleed']
},
description: 'ActionList includes 8px padding by default, full-bleed removes all padding',
table: {
category: 'CSS'
}
} }
} }
} }
@ -83,10 +95,16 @@ export const ListTemplate = ({
ariaLabel, ariaLabel,
ariaLabelledBy, ariaLabelledBy,
subGroup, subGroup,
listboxMultiSelect listboxMultiSelect,
listPadding
}) => ( }) => (
<ul <ul
className={clsx('ActionList', showDividers && 'ActionList--divided', subGroup && 'ActionList--subGroup')} className={clsx(
'ActionList',
showDividers && 'ActionList--divided',
subGroup && 'ActionList--subGroup',
listPadding && `${listPadding}`
)}
role={role} role={role}
aria-label={ariaLabel && ariaLabel} aria-label={ariaLabel && ariaLabel}
aria-labelledby={ariaLabelledBy && ariaLabelledBy} aria-labelledby={ariaLabelledBy && ariaLabelledBy}
@ -102,6 +120,7 @@ Playground.args = {
subGroup: false, subGroup: false,
showDividers: false, showDividers: false,
listboxMultiSelect: false, listboxMultiSelect: false,
listPadding: '',
ariaLabelledBy: '', ariaLabelledBy: '',
groupId: '', groupId: '',
children: ( children: (

View File

@ -51,6 +51,13 @@ export default {
category: 'CSS' category: 'CSS'
} }
}, },
containsActiveSubItem: {
defaultValue: false,
control: {type: 'boolean'},
table: {
category: 'CSS'
}
},
leadingVisual: { leadingVisual: {
defaultValue: '', defaultValue: '',
name: 'leadingVisual', name: 'leadingVisual',
@ -146,6 +153,13 @@ export default {
category: 'Interactive' category: 'Interactive'
} }
}, },
collapsibleLeading: {
defaultValue: false,
control: {type: 'boolean'},
table: {
category: 'Interactive'
}
},
singleSelect: { singleSelect: {
defaultValue: false, defaultValue: false,
control: {type: 'boolean'}, control: {type: 'boolean'},
@ -207,7 +221,9 @@ export const ListItemTemplate = ({
listSingleSelect, listSingleSelect,
listMultiSelect, listMultiSelect,
listSemantic, listSemantic,
ariaDisabled ariaDisabled,
containsActiveSubItem,
collapsibleLeading
}) => { }) => {
const [isCollapsed, itemIsCollapsed] = useToggle() const [isCollapsed, itemIsCollapsed] = useToggle()
const [isChecked, itemIsChecked] = useToggle() const [isChecked, itemIsChecked] = useToggle()
@ -218,9 +234,10 @@ export const ListItemTemplate = ({
ariaCurrent && 'ActionList-item--navActive', ariaCurrent && 'ActionList-item--navActive',
subItem && `ActionList-item--subItem`, subItem && `ActionList-item--subItem`,
containsSubItem && `ActionList-item--hasSubItem`, containsSubItem && `ActionList-item--hasSubItem`,
containsActiveSubItem && `ActionList-item--hasActiveSubItem`,
variant && `${variant}` variant && `${variant}`
)} )}
onClick={collapsible ? itemIsCollapsed : itemIsChecked} onClick={collapsible || collapsibleLeading ? itemIsCollapsed : itemIsChecked}
role={ role={
singleSelect singleSelect
? 'menuitemradio' ? 'menuitemradio'
@ -235,8 +252,8 @@ export const ListItemTemplate = ({
: undefined : undefined
} }
id={id} id={id}
aria-haspopup={collapsible ? 'true' : undefined} aria-haspopup={collapsible || collapsibleLeading ? 'true' : undefined}
aria-expanded={collapsible ? (isCollapsed ? 'false' : 'true') : undefined} aria-expanded={collapsible || collapsibleLeading ? (isCollapsed ? 'false' : 'true') : undefined}
aria-checked={singleSelect || multiSelect ? (isChecked ? 'true' : 'false') : undefined} aria-checked={singleSelect || multiSelect ? (isChecked ? 'true' : 'false') : undefined}
aria-selected={listSingleSelect || listMultiSelect ? (isChecked ? 'true' : 'false') : undefined} aria-selected={listSingleSelect || listMultiSelect ? (isChecked ? 'true' : 'false') : undefined}
aria-disabled={ariaDisabled ? 'true' : undefined} aria-disabled={ariaDisabled ? 'true' : undefined}
@ -254,7 +271,12 @@ export const ListItemTemplate = ({
leadingVisual && leadingVisualSize && `${leadingVisualSize}` leadingVisual && leadingVisualSize && `${leadingVisualSize}`
)} )}
> >
{(leadingAction || singleSelect || multiSelect || listSingleSelect || listMultiSelect) && ( {(leadingAction ||
singleSelect ||
multiSelect ||
listSingleSelect ||
listMultiSelect ||
collapsibleLeading) && (
<span className="ActionList-item-action ActionList-item-action--leading"> <span className="ActionList-item-action ActionList-item-action--leading">
{singleSelect || {singleSelect ||
(listSingleSelect && ( (listSingleSelect && (
@ -290,6 +312,20 @@ export const ListItemTemplate = ({
/> />
</svg> </svg>
))} ))}
{collapsibleLeading && (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="16"
height="16"
className="ActionList-item-collapseIcon"
>
<path
fill-rule="evenodd"
d="M12.78 6.22a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06 0L3.22 7.28a.75.75 0 011.06-1.06L8 9.94l3.72-3.72a.75.75 0 011.06 0z"
></path>
</svg>
)}
{leadingAction} {leadingAction}
</span> </span>
)} )}
@ -346,7 +382,12 @@ export const ListItemTemplate = ({
leadingVisual && leadingVisualSize && `${leadingVisualSize}` leadingVisual && leadingVisualSize && `${leadingVisualSize}`
)} )}
> >
{(leadingAction || singleSelect || multiSelect || listSingleSelect || listMultiSelect) && ( {(leadingAction ||
singleSelect ||
multiSelect ||
listSingleSelect ||
listMultiSelect ||
collapsibleLeading) && (
<span className="ActionList-item-action ActionList-item-action--leading"> <span className="ActionList-item-action ActionList-item-action--leading">
{(singleSelect || listSingleSelect) && ( {(singleSelect || listSingleSelect) && (
<svg <svg
@ -380,6 +421,20 @@ export const ListItemTemplate = ({
/> />
</svg> </svg>
)} )}
{collapsibleLeading && (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="16"
height="16"
className="ActionList-item-collapseIcon"
>
<path
fill-rule="evenodd"
d="M12.78 6.22a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06 0L3.22 7.28a.75.75 0 011.06-1.06L8 9.94l3.72-3.72a.75.75 0 011.06 0z"
></path>
</svg>
)}
{leadingAction} {leadingAction}
</span> </span>
)} )}

View File

@ -32,6 +32,7 @@ NavWithSubItems.args = {
listSemantic listSemantic
collapsible collapsible
containsSubItem containsSubItem
containsActiveSubItem
text="Nav Item" text="Nav Item"
children={ children={
<ListTemplate <ListTemplate
@ -58,6 +59,51 @@ NavWithSubItems.decorators = [
) )
] ]
export const NavWithNoActiveSubItems = ListTemplate.bind({})
NavWithNoActiveSubItems.storyName = '[Nav] Links + nested collapsible group w/ no active children'
NavWithNoActiveSubItems.args = {
...ListTemplate.args,
...ListItemTemplate.args,
role: undefined,
ariaLabel: 'Main menu description',
showDividers: false,
children: (
<>
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate
listSemantic
collapsible
containsSubItem
text="Nav Item"
children={
<ListTemplate
subGroup
ariaLabel="Sub nav description"
children={
<>
<ListItemTemplate subItem text="Sub Nav Item" href="/" listSemantic />
<ListItemTemplate subItem text="Sub Nav Item" href="/" listSemantic />
<ListItemTemplate subItem text="Sub Nav Item" href="/" listSemantic />
</>
}
/>
}
/>
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate text="Nav Item" href="/" listSemantic />
</>
)
}
NavWithNoActiveSubItems.decorators = [
Story => (
<nav>
<Story />
</nav>
)
]
export const NavWithSubItemsLeadingVisual16px = ListTemplate.bind({}) export const NavWithSubItemsLeadingVisual16px = ListTemplate.bind({})
NavWithSubItemsLeadingVisual16px.storyName = '[Nav] Links + nested collapsible group leadingVisual 16px' NavWithSubItemsLeadingVisual16px.storyName = '[Nav] Links + nested collapsible group leadingVisual 16px'
NavWithSubItemsLeadingVisual16px.args = { NavWithSubItemsLeadingVisual16px.args = {
@ -92,6 +138,7 @@ NavWithSubItemsLeadingVisual16px.args = {
<ListItemTemplate <ListItemTemplate
listSemantic listSemantic
containsSubItem containsSubItem
containsActiveSubItem
collapsible collapsible
text="Nav Item" text="Nav Item"
href="/" href="/"
@ -177,6 +224,7 @@ NavWithSubItemsLeadingVisual20px.args = {
<ListItemTemplate <ListItemTemplate
listSemantic listSemantic
containsSubItem containsSubItem
containsActiveSubItem
text="Nav Item" text="Nav Item"
href="/" href="/"
leadingVisualSize="ActionList-content--visual20" leadingVisualSize="ActionList-content--visual20"
@ -261,6 +309,7 @@ NavWithSubItemsLeadingVisual24px.args = {
<ListItemTemplate <ListItemTemplate
listSemantic listSemantic
containsSubItem containsSubItem
containsActiveSubItem
text="Nav Item" text="Nav Item"
href="/" href="/"
leadingVisualSize="ActionList-content--visual24" leadingVisualSize="ActionList-content--visual24"
@ -389,6 +438,7 @@ MenuWithSectionDivider.args = {
<DividerTemplate title="Section DividerTemplate (subtle)" id="some-unique-id" /> <DividerTemplate title="Section DividerTemplate (subtle)" id="some-unique-id" />
<ListItemTemplate <ListItemTemplate
containsSubItem containsSubItem
containsActiveSubItem
children={ children={
<ListTemplate <ListTemplate
ariaLabelledBy="some-unique-id" ariaLabelledBy="some-unique-id"
@ -616,6 +666,7 @@ NavWithSubItemsLeadingVisual16pxSubSections.args = {
<ListItemTemplate <ListItemTemplate
listSemantic listSemantic
containsSubItem containsSubItem
containsActiveSubItem
text="Moderation options" text="Moderation options"
// href="/" // href="/"
collapsible collapsible
@ -626,6 +677,7 @@ NavWithSubItemsLeadingVisual16pxSubSections.args = {
children={ children={
<ListTemplate <ListTemplate
containsSubItem containsSubItem
containsActiveSubItem
subGroup subGroup
ariaLabel="Sub nav descrioption" ariaLabel="Sub nav descrioption"
children={ children={
@ -725,3 +777,42 @@ NavWithSubItemsLeadingVisual16pxSubSections.decorators = [
</nav> </nav>
) )
] ]
export const ActionListFullBleed = ListTemplate.bind({})
ActionListFullBleed.storyName = '[List] Full bleed Action List inside box'
ActionListFullBleed.args = {
...ListTemplate.args,
...ListItemTemplate.args,
role: undefined,
ariaLabel: 'Main menu description',
showDividers: false,
listPadding: 'ActionList--full',
children: (
<>
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate
listSemantic
collapsible
containsSubItem
text="Nav Item"
children={
<ListTemplate
subGroup
ariaLabel="Sub nav description"
children={
<>
<ListItemTemplate subItem text="Sub Nav Item" href="/" listSemantic ariaCurrent="page" />
<ListItemTemplate subItem text="Sub Nav Item" href="/" listSemantic />
<ListItemTemplate subItem text="Sub Nav Item" href="/" listSemantic />
</>
}
/>
}
/>
<ListItemTemplate text="Nav Item" href="/" listSemantic />
<ListItemTemplate text="Nav Item" href="/" listSemantic />
</>
)
}

View File

@ -5,6 +5,17 @@
box-shadow: 0 0 0 2px var(--color-accent-fg); // this color breaks convention box-shadow: 0 0 0 2px var(--color-accent-fg); // this color breaks convention
} }
@mixin activeIndicatorLine {
position: absolute;
top: calc(50% - 12px);
left: -$actionList-item-padding-horizontal;
width: $spacer-1;
height: $spacer-4;
content: '';
background: var(--color-accent-fg);
border-radius: $border-radius;
}
// <li> // <li>
.ActionList-item { .ActionList-item {
position: relative; position: relative;
@ -77,25 +88,26 @@
// active state [aria-current] // active state [aria-current]
&.ActionList-item--navActive:not(.ActionList-item--danger) { &.ActionList-item--navActive {
background: var(--color-action-list-item-default-selected-bg); &:not(.ActionList-item--subItem) {
.ActionList-item-label {
// stylelint-disable-next-line selector-max-specificity font-weight: $font-weight-bold;
&::before, }
+ .ActionList-item::before {
visibility: hidden;
} }
// blue accent line &:not(.ActionList-item--danger) {
&::after { background: var(--color-action-list-item-default-selected-bg);
position: absolute;
top: calc(50% - 12px); // stylelint-disable-next-line selector-max-specificity
left: -$actionList-item-padding-horizontal; &::before,
width: $spacer-1; + .ActionList-item::before {
height: $spacer-4; visibility: hidden;
content: ''; }
background: var(--color-accent-fg);
border-radius: $border-radius; // blue accent line
&::after {
@include activeIndicatorLine;
}
} }
} }
@ -111,7 +123,7 @@
display: block; display: block;
} }
&.ActionList-item--hasSubItem { &.ActionList-item--hasActiveSubItem {
// stylelint-disable-next-line selector-max-specificity // stylelint-disable-next-line selector-max-specificity
> .ActionList-content > .ActionList-item-label { > .ActionList-content > .ActionList-item-label {
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
@ -128,6 +140,26 @@
.ActionList--subGroup { .ActionList--subGroup {
display: none; display: none;
} }
// show active indicator on parent collapse if child is active
&.ActionList-item--hasActiveSubItem {
background: var(--color-action-list-item-default-selected-bg);
.ActionList-item-label {
font-weight: $font-weight-bold;
}
// stylelint-disable-next-line selector-max-specificity
&::before,
+ .ActionList-item::before {
visibility: hidden;
}
// blue accent line
&::after {
@include activeIndicatorLine;
}
}
} }
// checkbox item [aria-checked] // checkbox item [aria-checked]

View File

@ -3,6 +3,11 @@
padding: $spacer-2; padding: $spacer-2;
} }
// full bleed
.ActionList--full {
padding: 0;
}
// dividers // dividers
.ActionList--divided { .ActionList--divided {