mirror of
https://github.com/primer/css.git
synced 2024-11-26 02:38:32 +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:
parent
ee27583f59
commit
8e9ba62d30
5
.changeset/fresh-schools-pull.md
Normal file
5
.changeset/fresh-schools-pull.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@primer/css": patch
|
||||
---
|
||||
|
||||
ActionList followup
|
@ -72,6 +72,18 @@ export default {
|
||||
table: {
|
||||
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,
|
||||
ariaLabelledBy,
|
||||
subGroup,
|
||||
listboxMultiSelect
|
||||
listboxMultiSelect,
|
||||
listPadding
|
||||
}) => (
|
||||
<ul
|
||||
className={clsx('ActionList', showDividers && 'ActionList--divided', subGroup && 'ActionList--subGroup')}
|
||||
className={clsx(
|
||||
'ActionList',
|
||||
showDividers && 'ActionList--divided',
|
||||
subGroup && 'ActionList--subGroup',
|
||||
listPadding && `${listPadding}`
|
||||
)}
|
||||
role={role}
|
||||
aria-label={ariaLabel && ariaLabel}
|
||||
aria-labelledby={ariaLabelledBy && ariaLabelledBy}
|
||||
@ -102,6 +120,7 @@ Playground.args = {
|
||||
subGroup: false,
|
||||
showDividers: false,
|
||||
listboxMultiSelect: false,
|
||||
listPadding: '',
|
||||
ariaLabelledBy: '',
|
||||
groupId: '',
|
||||
children: (
|
||||
|
@ -51,6 +51,13 @@ export default {
|
||||
category: 'CSS'
|
||||
}
|
||||
},
|
||||
containsActiveSubItem: {
|
||||
defaultValue: false,
|
||||
control: {type: 'boolean'},
|
||||
table: {
|
||||
category: 'CSS'
|
||||
}
|
||||
},
|
||||
leadingVisual: {
|
||||
defaultValue: '',
|
||||
name: 'leadingVisual',
|
||||
@ -146,6 +153,13 @@ export default {
|
||||
category: 'Interactive'
|
||||
}
|
||||
},
|
||||
collapsibleLeading: {
|
||||
defaultValue: false,
|
||||
control: {type: 'boolean'},
|
||||
table: {
|
||||
category: 'Interactive'
|
||||
}
|
||||
},
|
||||
singleSelect: {
|
||||
defaultValue: false,
|
||||
control: {type: 'boolean'},
|
||||
@ -207,7 +221,9 @@ export const ListItemTemplate = ({
|
||||
listSingleSelect,
|
||||
listMultiSelect,
|
||||
listSemantic,
|
||||
ariaDisabled
|
||||
ariaDisabled,
|
||||
containsActiveSubItem,
|
||||
collapsibleLeading
|
||||
}) => {
|
||||
const [isCollapsed, itemIsCollapsed] = useToggle()
|
||||
const [isChecked, itemIsChecked] = useToggle()
|
||||
@ -218,9 +234,10 @@ export const ListItemTemplate = ({
|
||||
ariaCurrent && 'ActionList-item--navActive',
|
||||
subItem && `ActionList-item--subItem`,
|
||||
containsSubItem && `ActionList-item--hasSubItem`,
|
||||
containsActiveSubItem && `ActionList-item--hasActiveSubItem`,
|
||||
variant && `${variant}`
|
||||
)}
|
||||
onClick={collapsible ? itemIsCollapsed : itemIsChecked}
|
||||
onClick={collapsible || collapsibleLeading ? itemIsCollapsed : itemIsChecked}
|
||||
role={
|
||||
singleSelect
|
||||
? 'menuitemradio'
|
||||
@ -235,8 +252,8 @@ export const ListItemTemplate = ({
|
||||
: undefined
|
||||
}
|
||||
id={id}
|
||||
aria-haspopup={collapsible ? 'true' : undefined}
|
||||
aria-expanded={collapsible ? (isCollapsed ? 'false' : 'true') : undefined}
|
||||
aria-haspopup={collapsible || collapsibleLeading ? 'true' : undefined}
|
||||
aria-expanded={collapsible || collapsibleLeading ? (isCollapsed ? 'false' : 'true') : undefined}
|
||||
aria-checked={singleSelect || multiSelect ? (isChecked ? 'true' : 'false') : undefined}
|
||||
aria-selected={listSingleSelect || listMultiSelect ? (isChecked ? 'true' : 'false') : undefined}
|
||||
aria-disabled={ariaDisabled ? 'true' : undefined}
|
||||
@ -254,7 +271,12 @@ export const ListItemTemplate = ({
|
||||
leadingVisual && leadingVisualSize && `${leadingVisualSize}`
|
||||
)}
|
||||
>
|
||||
{(leadingAction || singleSelect || multiSelect || listSingleSelect || listMultiSelect) && (
|
||||
{(leadingAction ||
|
||||
singleSelect ||
|
||||
multiSelect ||
|
||||
listSingleSelect ||
|
||||
listMultiSelect ||
|
||||
collapsibleLeading) && (
|
||||
<span className="ActionList-item-action ActionList-item-action--leading">
|
||||
{singleSelect ||
|
||||
(listSingleSelect && (
|
||||
@ -290,6 +312,20 @@ export const ListItemTemplate = ({
|
||||
/>
|
||||
</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}
|
||||
</span>
|
||||
)}
|
||||
@ -346,7 +382,12 @@ export const ListItemTemplate = ({
|
||||
leadingVisual && leadingVisualSize && `${leadingVisualSize}`
|
||||
)}
|
||||
>
|
||||
{(leadingAction || singleSelect || multiSelect || listSingleSelect || listMultiSelect) && (
|
||||
{(leadingAction ||
|
||||
singleSelect ||
|
||||
multiSelect ||
|
||||
listSingleSelect ||
|
||||
listMultiSelect ||
|
||||
collapsibleLeading) && (
|
||||
<span className="ActionList-item-action ActionList-item-action--leading">
|
||||
{(singleSelect || listSingleSelect) && (
|
||||
<svg
|
||||
@ -380,6 +421,20 @@ export const ListItemTemplate = ({
|
||||
/>
|
||||
</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}
|
||||
</span>
|
||||
)}
|
||||
|
@ -32,6 +32,7 @@ NavWithSubItems.args = {
|
||||
listSemantic
|
||||
collapsible
|
||||
containsSubItem
|
||||
containsActiveSubItem
|
||||
text="Nav Item"
|
||||
children={
|
||||
<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({})
|
||||
NavWithSubItemsLeadingVisual16px.storyName = '[Nav] Links + nested collapsible group leadingVisual 16px'
|
||||
NavWithSubItemsLeadingVisual16px.args = {
|
||||
@ -92,6 +138,7 @@ NavWithSubItemsLeadingVisual16px.args = {
|
||||
<ListItemTemplate
|
||||
listSemantic
|
||||
containsSubItem
|
||||
containsActiveSubItem
|
||||
collapsible
|
||||
text="Nav Item"
|
||||
href="/"
|
||||
@ -177,6 +224,7 @@ NavWithSubItemsLeadingVisual20px.args = {
|
||||
<ListItemTemplate
|
||||
listSemantic
|
||||
containsSubItem
|
||||
containsActiveSubItem
|
||||
text="Nav Item"
|
||||
href="/"
|
||||
leadingVisualSize="ActionList-content--visual20"
|
||||
@ -261,6 +309,7 @@ NavWithSubItemsLeadingVisual24px.args = {
|
||||
<ListItemTemplate
|
||||
listSemantic
|
||||
containsSubItem
|
||||
containsActiveSubItem
|
||||
text="Nav Item"
|
||||
href="/"
|
||||
leadingVisualSize="ActionList-content--visual24"
|
||||
@ -389,6 +438,7 @@ MenuWithSectionDivider.args = {
|
||||
<DividerTemplate title="Section DividerTemplate (subtle)" id="some-unique-id" />
|
||||
<ListItemTemplate
|
||||
containsSubItem
|
||||
containsActiveSubItem
|
||||
children={
|
||||
<ListTemplate
|
||||
ariaLabelledBy="some-unique-id"
|
||||
@ -616,6 +666,7 @@ NavWithSubItemsLeadingVisual16pxSubSections.args = {
|
||||
<ListItemTemplate
|
||||
listSemantic
|
||||
containsSubItem
|
||||
containsActiveSubItem
|
||||
text="Moderation options"
|
||||
// href="/"
|
||||
collapsible
|
||||
@ -626,6 +677,7 @@ NavWithSubItemsLeadingVisual16pxSubSections.args = {
|
||||
children={
|
||||
<ListTemplate
|
||||
containsSubItem
|
||||
containsActiveSubItem
|
||||
subGroup
|
||||
ariaLabel="Sub nav descrioption"
|
||||
children={
|
||||
@ -725,3 +777,42 @@ NavWithSubItemsLeadingVisual16pxSubSections.decorators = [
|
||||
</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 />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -5,6 +5,17 @@
|
||||
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>
|
||||
.ActionList-item {
|
||||
position: relative;
|
||||
@ -77,25 +88,26 @@
|
||||
|
||||
// active state [aria-current]
|
||||
|
||||
&.ActionList-item--navActive:not(.ActionList-item--danger) {
|
||||
background: var(--color-action-list-item-default-selected-bg);
|
||||
|
||||
// stylelint-disable-next-line selector-max-specificity
|
||||
&::before,
|
||||
+ .ActionList-item::before {
|
||||
visibility: hidden;
|
||||
&.ActionList-item--navActive {
|
||||
&:not(.ActionList-item--subItem) {
|
||||
.ActionList-item-label {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
|
||||
// blue accent line
|
||||
&::after {
|
||||
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;
|
||||
&:not(.ActionList-item--danger) {
|
||||
background: var(--color-action-list-item-default-selected-bg);
|
||||
|
||||
// stylelint-disable-next-line selector-max-specificity
|
||||
&::before,
|
||||
+ .ActionList-item::before {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
// blue accent line
|
||||
&::after {
|
||||
@include activeIndicatorLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +123,7 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.ActionList-item--hasSubItem {
|
||||
&.ActionList-item--hasActiveSubItem {
|
||||
// stylelint-disable-next-line selector-max-specificity
|
||||
> .ActionList-content > .ActionList-item-label {
|
||||
font-weight: $font-weight-bold;
|
||||
@ -128,6 +140,26 @@
|
||||
.ActionList--subGroup {
|
||||
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]
|
||||
|
@ -3,6 +3,11 @@
|
||||
padding: $spacer-2;
|
||||
}
|
||||
|
||||
// full bleed
|
||||
.ActionList--full {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
// dividers
|
||||
|
||||
.ActionList--divided {
|
||||
|
Loading…
Reference in New Issue
Block a user