Skip to content

Commit 61cf086

Browse files
[polaris.shopify.com] Add ability to collapse types in props table. (#7254)
### WHY are these changes introduced? Hot on the heels of #6757 being merged, this change introduces the ability to collapse props after being expanded. This allows users to expand ("explore") and then collapse ("focus") props as needed depending on the types they want to see. **Before** https://user-images.githubusercontent.com/49090/191797340-233d321e-121e-4029-8ae2-7b4ddcb21f93.mp4 **After** https://user-images.githubusercontent.com/49090/191797509-5674e76a-caf4-4615-97ef-4f483325a7c2.mp4 ### WHAT is this pull request doing? - Adds an additional function to collapse props within the props table. - Wraps the `TypeTable` in `<AnimatePresence>` per [Framer's instruction](https://www.framer.com/docs/animate-presence/##exit-animations) when using exit animations on `div.motion` as well as a `key`. - Updated `hasBenExpanded` to `hasBeenExpanded` -- think this was a typo. - I also introduced a subtle hover state on the clickable types, since it wasn't immediately obvious to me that they were interactable. ### How to 🎩 🖥 [Local development instructions](https://github.com/Shopify/polaris/blob/main/README.md#local-development) 🗒 [General tophatting guidelines](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md) 📄 [Changelog guidelines](https://github.com/Shopify/polaris/blob/main/.github/CONTRIBUTING.md#changelog) Run the Polaris docs: 1. `dev up` 2. `cd polaris.shopify.com && yarn run dev` 3. Open up a component page - e.g. http://localhost:3000/components/option-list ### 🎩 checklist - 🚫 Tested on [mobile](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing) - [x] Tested on [multiple browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers) - [x] Tested for [accessibility](https://github.com/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md) - 🚫 Updated the component's `README.md` with documentation changes - [x] [Tophatted documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide Co-authored-by: Marten Bjork <marten.bjork@shopify.com>
1 parent f714012 commit 61cf086

File tree

3 files changed

+85
-26
lines changed

3 files changed

+85
-26
lines changed

.changeset/forty-cobras-lay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'polaris.shopify.com': minor
3+
---
4+
5+
Added ability to collapse props that have been expanded.

polaris.shopify.com/src/components/PropsTable/PropsTable.module.scss

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,25 @@
3434
}
3535

3636
.TypeTableHeader {
37+
display: flex;
38+
align-items: center;
3739
width: 100%;
3840
text-align: left;
3941
color: var(--code-keyword);
4042
font-family: var(--font-family-mono);
4143
padding: 0.66em 1em;
4244
background: rgba(0, 0, 0, 0.02);
45+
46+
button {
47+
margin-left: auto;
48+
background: transparent;
49+
color: var(--text-subdued);
50+
51+
&:hover {
52+
color: var(--text-strong);
53+
}
54+
}
55+
4356
@include dark-mode {
4457
background: rgba(255, 255, 255, 0.05);
4558
}
@@ -66,7 +79,6 @@
6679

6780
.Key {
6881
display: flex;
69-
flex-direction: column;
7082
gap: 0.6rem;
7183

7284
@media screen and (max-width: $breakpointMobile) {

polaris.shopify.com/src/components/PropsTable/PropsTable.tsx

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ function PropsTable({types, componentName}: Props) {
5959
</div>
6060
)}
6161

62-
<TypeTable types={types} type={propsForComponent} />
62+
<AnimatePresence initial={false}>
63+
<TypeTable types={types} type={propsForComponent} />
64+
</AnimatePresence>
6365
</div>
6466
</TypeContext.Provider>
6567
);
@@ -70,58 +72,80 @@ type ExpandedTypeInfo = {memberName: string | null; typeName: string};
7072
const ExpandedTypesContext = createContext<{
7173
expandedTypes: ExpandedTypeInfo[];
7274
expandType: (typeName: string) => void;
75+
collapseType: (typeName: string) => void;
7376
currentMember: string | null;
74-
}>({expandType: () => undefined, expandedTypes: [], currentMember: null});
77+
}>({
78+
expandType: () => undefined,
79+
collapseType: () => undefined,
80+
expandedTypes: [],
81+
currentMember: null,
82+
});
7583

7684
function TypeTable({
7785
types,
7886
type,
87+
level = 0,
7988
}: {
8089
types: FilteredTypes;
8190
type: Type;
8291
level?: number;
8392
}) {
8493
const [expandedTypes, setExpandedTypes] = useState<ExpandedTypeInfo[]>([]);
94+
const {collapseType} = useContext(ExpandedTypesContext);
8595

8696
return (
8797
<motion.div
98+
key={type.name}
8899
className={styles.TypeTable}
89100
initial={{opacity: 0, scale: 0.7, height: 0}}
90-
animate={{opacity: 1, scale: 1, height: 'auto'}}
101+
animate={{
102+
opacity: 1,
103+
scale: 1,
104+
height: 'auto',
105+
transition: {ease: 'backOut'},
106+
}}
107+
exit={{opacity: 0, scale: 0, height: 0, transition: {ease: 'backIn'}}}
91108
>
92109
<div className={styles.TypeTableHeader}>
93-
{syntaxKindToDeveloperFriendlyString(type.syntaxKind)} {type.name}
110+
{syntaxKindToDeveloperFriendlyString(type.syntaxKind)} {type.name}{' '}
111+
{typeof level === 'number' && level > 0 && (
112+
<button onClick={() => collapseType(type.name)} aria-label="Collapse">
113+
&times;
114+
</button>
115+
)}
94116
</div>
95117

96118
{!type.members && (
97119
<ExpandedTypesContext.Provider
98120
value={{
99121
expandedTypes,
100-
expandType: (typeName: string) => {
122+
expandType: (typeName: string) =>
101123
setExpandedTypes([
102124
{typeName, memberName: null},
103125
...expandedTypes,
104-
]);
105-
},
126+
]),
127+
collapseType: () => undefined,
106128
currentMember: null,
107129
}}
108130
>
109131
<div className={styles.RawInterfaceValue}>
110132
<Highlighter type={type.value.toString()} />
111133

112-
{expandedTypes
113-
.filter((expanded) => expanded.memberName === null)
114-
.map((expanded) => {
115-
const typeForExpandedType = types[expanded.typeName];
116-
if (!typeForExpandedType) return null;
117-
return (
118-
<TypeTable
119-
key={expanded.typeName}
120-
types={types}
121-
type={typeForExpandedType}
122-
/>
123-
);
124-
})}
134+
<AnimatePresence initial={false}>
135+
{expandedTypes
136+
.filter((expanded) => expanded.memberName === null)
137+
.map((expanded) => {
138+
const typeForExpandedType = types[expanded.typeName];
139+
if (!typeForExpandedType) return null;
140+
return (
141+
<TypeTable
142+
key={expanded.typeName}
143+
types={types}
144+
type={typeForExpandedType}
145+
/>
146+
);
147+
})}
148+
</AnimatePresence>
125149
</div>
126150
</ExpandedTypesContext.Provider>
127151
)}
@@ -137,16 +161,33 @@ function TypeTable({
137161
value,
138162
deprecationMessage,
139163
}) => {
140-
const expandType = (typeName: string) =>
164+
const expandType = (typeName: string) => {
141165
setExpandedTypes([
142166
{typeName, memberName: name},
143167
...expandedTypes,
144168
]);
169+
};
170+
171+
const collapseType = (typeName: string) =>
172+
setExpandedTypes((types) =>
173+
types.filter(
174+
(typeInfo) =>
175+
!(
176+
typeInfo.typeName === typeName &&
177+
typeInfo.memberName === name
178+
),
179+
),
180+
);
145181

146182
return (
147183
<ExpandedTypesContext.Provider
148184
key={name}
149-
value={{expandedTypes, expandType, currentMember: name}}
185+
value={{
186+
expandedTypes,
187+
expandType,
188+
collapseType,
189+
currentMember: name,
190+
}}
150191
>
151192
<span className={styles.Row}>
152193
<dt className={styles.Key}>
@@ -200,6 +241,7 @@ function TypeTable({
200241
key={expanded.typeName}
201242
types={types}
202243
type={typeForExpandedType}
244+
level={level + 1}
203245
/>
204246
);
205247
})}
@@ -226,7 +268,7 @@ function Highlighter({
226268
const {expandType, expandedTypes, currentMember} =
227269
useContext(ExpandedTypesContext);
228270
const {types} = useContext(TypeContext);
229-
const hasBenExpanded = expandedTypes.some(
271+
const hasBeenExpanded = expandedTypes.some(
230272
(expandedType) =>
231273
expandedType.typeName === type &&
232274
expandedType.memberName === currentMember,
@@ -275,8 +317,8 @@ function Highlighter({
275317
<button
276318
className={styles.ExpandableType}
277319
onClick={() => expandType(type)}
278-
disabled={hasBenExpanded}
279-
aria-expanded={hasBenExpanded}
320+
disabled={hasBeenExpanded}
321+
aria-expanded={hasBeenExpanded}
280322
>
281323
{type}
282324
</button>

0 commit comments

Comments
 (0)