Skip to content

Commit 673f292

Browse files
committed
Merge remote-tracking branch 'origin/dev'
2 parents 71ebf5d + d6618bf commit 673f292

24 files changed

Lines changed: 1049 additions & 13 deletions

File tree

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ package.json
1010
README.md
1111
.storybook
1212
yarn.lock
13+
tsconfig.json

src/classes/Tabs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"Tabs":"Polaris-Tabs","Wrapper":"Polaris-Tabs__Wrapper","fitted":"Polaris-Tabs--fitted","TabContainer":"Polaris-Tabs__TabContainer","Title":"Polaris-Tabs__Title","fillSpace":"Polaris-Tabs--fillSpace","Tab":"Polaris-Tabs__Tab","Tab-selected":"Polaris-Tabs__Tab--selected","titleWithIcon":"Polaris-Tabs--titleWithIcon","Panel":"Polaris-Tabs__Panel","Panel-hidden":"Polaris-Tabs__Panel--hidden","List":"Polaris-Tabs__List","Item":"Polaris-Tabs__Item","DisclosureTab":"Polaris-Tabs__DisclosureTab","DisclosureTab-visible":"Polaris-Tabs__DisclosureTab--visible","DisclosureActivator":"Polaris-Tabs__DisclosureActivator","TabMeasurer":"Polaris-Tabs__TabMeasurer"}

src/components/Badge/Badge.vue

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template lang="pug">
22
span(:class="className")
3-
span(v-if="hasIcon", :class="styles.Icon")
3+
span(v-if="!progress && icon", :class="styles.Icon")
44
Icon(:source="icon")
55
template(v-if="hasAccessibilityLabel")
66
span(
@@ -18,6 +18,7 @@ import { inject, ref, computed, onMounted } from 'vue';
1818
import { classNames, variationName } from 'polaris/polaris-react/src/utilities/css';
1919
import styles from '@/classes/Badge.json';
2020
import type { IconSource } from '@/utilities/type';
21+
import { Icon } from '../Icon';
2122
import { VisuallyHidden } from '../VisuallyHidden';
2223
2324
type Status = 'info' | 'success' | 'attention' | 'warning' | 'critical' | 'new';
@@ -68,10 +69,6 @@ const hasAccessibilityLabel= computed(() => props.statusAndProgressLabelOverride
6869
const accessibilityLabel = computed(() => props.statusAndProgressLabelOverride
6970
|| `${statusLabel.value} ${progressLabel.value}`);
7071
71-
const hasIcon = computed(() => {
72-
return !props.progress && props.icon;
73-
});
74-
7572
onMounted(() => {
7673
switch (props.progress) {
7774
case 'incomplete':

src/components/Card/Card.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<template lang="pug">
22
div(:class="className")
33
Header(
4-
v-if="slots.title || actions",
4+
v-if="title || hasSlot(slots.title) || actions",
55
:actions="actions",
66
)
77
template(#title)
8-
slot(name="title")
8+
slot(v-if="hasSlot(slots.title)", name="title")
9+
template(v-else) {{ title }}
910
Section(v-if="sectioned")
1011
slot
1112
slot(v-else)
@@ -63,9 +64,12 @@ import styles from '@/classes/Card.json';
6364
import { ButtonGroup, ActionList, Button, Popover } from '@/components';
6465
import { ButtonFrom } from '@/components/Button';
6566
import type { DisableableAction, ComplexAction } from '@/utilities/interface';
67+
import { hasSlot } from '@/utilities/has-slot';
6668
import { Header, Section } from './components';
6769
6870
export interface CardProps {
71+
/** Title content for the card **/
72+
title?: string;
6973
/** A less prominent card */
7074
subdued?: boolean;
7175
/** Auto wrap content in section */

src/components/Card/README.stories.mdx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,16 @@ import OrdersMinor from '@icons/OrdersMinor.svg';
88
title="Components / Structure / Card"
99
component={ Card }
1010
argTypes={{
11+
propTitle: {
12+
name: 'title',
13+
description: 'Title content for the card.',
14+
table: {
15+
category: 'props',
16+
type: { summary: 'string' },
17+
},
18+
},
1119
title: {
12-
description: 'Title content for the card',
20+
description: 'Title content for the card. This will overwrite the `title` prop.',
1321
table: { type: { summary: null } },
1422
control: { disable: true },
1523
},
@@ -294,3 +302,57 @@ Cards are used to group similar concepts and tasks together to make Shopify easi
294302
</Canvas>
295303

296304
<ArgsTable story="Card" />
305+
306+
---
307+
308+
<br/>
309+
310+
### **CardSection Props**
311+
312+
| Prop | Type | Description |
313+
| ---------------- | ----------------------------- | ----------- |
314+
| title? | String | The title of the section. |
315+
| subdued? | Boolean | A less prominent card. |
316+
| flush? | Boolean | |
317+
| fullWidth? | Boolean | |
318+
| hideOnPrint? | Boolean | Allow the card to be hidden when printing. |
319+
| actions? | ComplexAction[] |
320+
321+
| Slots | Description |
322+
| ---------------- | ----------- |
323+
| #title | The title of the section. This will overwrite the prop `title` if existed. |
324+
325+
<br/>
326+
327+
### **ComplexAction types**
328+
329+
```js
330+
/** A unique identifier for the action */
331+
id?: string;
332+
/** Content the action displays */
333+
content?: string;
334+
/** Visually hidden text for screen readers */
335+
accessibilityLabel?: string;
336+
/** A destination to link to, rendered in the action */
337+
url?: string;
338+
/** Forces url to open in a new tab */
339+
external?: boolean;
340+
/** Whether or not the action is disabled */
341+
disabled?: boolean;
342+
/** Destructive action */
343+
destructive?: boolean;
344+
/** Source of the icon */
345+
icon?: IconSource;
346+
/** Should action be displayed as an outlined button */
347+
outline?: boolean;
348+
/** Should a spinner be displayed */
349+
loading?: boolean;
350+
/** Should action be displayed as a plain link */
351+
plain?: boolean;
352+
/** Callback when an action takes place */
353+
onAction?(): void;
354+
/** Callback when mouse enter */
355+
onMouseEnter?(): void;
356+
/** Callback when element is touched */
357+
onTouchStart?(): void;
358+
```

src/components/Card/components/Section/Section.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template lang="pug">
22
div(:class="className")
33
div(
4-
v-if="slots.title || actions",
4+
v-if="title || hasSlot(slots.title) || actions",
55
:class="styles.SectionHeader",
66
)
77
Stack(v-if="actions", noItemWrap, alignment="baseline")
@@ -11,7 +11,8 @@ div(:class="className")
1111
name="title",
1212
)
1313
Subheading(v-else)
14-
slot(name="title")
14+
slot(v-if="hasSlot(slots.title)", name="title")
15+
template(v-else) {{ title }}
1516
ButtonGroup
1617
ButtonFrom(
1718
v-for="action, index in actions",
@@ -23,7 +24,8 @@ div(:class="className")
2324
template(v-else)
2425
slot(v-if="!isTextOnlyTitle", name="title")
2526
Subheading(v-else)
26-
slot(name="title")
27+
slot(v-if="hasSlot(slots.title)", name="title")
28+
template(v-else) {{ title }}
2729
slot
2830
</template>
2931
<script setup lang="ts">
@@ -32,9 +34,11 @@ import { classNames } from 'polaris/polaris-react/src/utilities/css';
3234
import type { ComplexAction } from '@/utilities/interface';
3335
import { ButtonGroup, Stack, StackItem, Subheading } from '@/components';
3436
import { ButtonFrom } from '@/components/Button';
37+
import { hasSlot } from '@/utilities/has-slot';
3538
import styles from '@/classes/Card.json';
3639
3740
interface CardSectionProps {
41+
title?: string;
3842
subdued?: boolean;
3943
flush?: boolean;
4044
fullWidth?: boolean;
@@ -69,6 +73,6 @@ const isTextOnlyTitle = computed(() => {
6973
}
7074
}
7175
72-
return false;
76+
return true;
7377
});
7478
</script>

src/components/Frame/Frame.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ const hideToast = ({ id }: ToastID) => {
292292
};
293293
294294
const setContextualSaveBar = (saveBarProps: ContextualSaveBarProps) => {
295-
contextualSaveBar.value = { ...saveBarProps };
295+
const { contextControl, secondaryMenu, ...rest } = saveBarProps;
296+
contextualSaveBar.value = rest;
296297
if (!showContextualSaveBar.value) {
297298
showContextualSaveBar.value = true;
298299
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { Meta, Story, Canvas, ArgsTable } from "@storybook/addon-docs";
2+
import { ref } from 'vue';
3+
import { Card, Tabs, Badge, CardSection } from "@/polaris-vue";
4+
import dedent from "ts-dedent";
5+
6+
<Meta
7+
title="Components / Navigation / Tabs"
8+
component={Tabs}
9+
argTypes={{
10+
default: {
11+
table: {
12+
disable: true,
13+
},
14+
},
15+
selected: {
16+
control: { disable: true },
17+
},
18+
tabs: {
19+
table: {
20+
type: { summary: 'TabDescriptor[]' },
21+
},
22+
control: { disable: true },
23+
},
24+
select: {
25+
table: { type: {
26+
summary: '(selectedTabIndex: number) => void',
27+
}},
28+
},
29+
'#tab-id': {
30+
description: 'Slot to show content of the tab. This slot will override the `content` prop of tab.',
31+
table: {
32+
category: 'slots',
33+
type: { summary: null },
34+
},
35+
}
36+
}}
37+
/>
38+
39+
# Tabs
40+
41+
Use to alternate among related views within the same context.
42+
43+
<br/>
44+
45+
export const Template = (args) => ({
46+
components: { Tabs, CardSection, Badge, Card },
47+
setup() {
48+
const selectedTab = ref(0);
49+
const handleTabChange = (selectedTabIndex) => {
50+
selectedTab.value = selectedTabIndex;
51+
};
52+
const tabs = [
53+
{
54+
id: 'all-customers-1',
55+
content: 'All',
56+
accessibilityLabel: 'All customers',
57+
panelID: 'all-customers-content-1',
58+
},
59+
{
60+
id: 'accepts-marketing-1',
61+
content: 'Accepts marketing',
62+
panelID: 'accepts-marketing-content-1',
63+
},
64+
{
65+
id: 'repeat-customers-1',
66+
content: 'Repeat customers',
67+
panelID: 'repeat-customers-content-1',
68+
},
69+
]
70+
return { args, selectedTab, handleTabChange, tabs };
71+
},
72+
template: `
73+
<Card>
74+
<Tabs :tabs="tabs" :selected="selectedTab" @select="handleTabChange" v-bind="args">
75+
<template #all-customers-1>
76+
<span>All <Badge status="new">10+</Badge></span>
77+
</template>
78+
<CardSection :title="tabs[selectedTab].content">
79+
<p v-if="selectedTab === 1">This is specific content of second tab</p>
80+
<p v-else>Tab {{ selectedTab }} selected</p>
81+
</CardSection>
82+
</Tabs>
83+
</Card>
84+
`,
85+
});
86+
87+
<Canvas>
88+
<Story
89+
name="Tabs"
90+
height="200px"
91+
args={{
92+
fitted: false,
93+
}}
94+
parameters={{
95+
docs: {
96+
source: {
97+
state: 'close',
98+
code: dedent`
99+
<Card>
100+
<Tabs :tabs="tabs" :selected="selectedTab" @select="handleTabChange">
101+
<template #all-customers-1>
102+
<span>All <Badge status="new">10+</Badge></span>
103+
</template>
104+
<CardSection :title="tabs[selectedTab].content">
105+
<p v-if="selectedTab === 1">This is specific content of second tab</p>
106+
<p v-else>Tab {{ selectedTab }} selected</p>
107+
</CardSection>
108+
</Tabs>
109+
</Card>\n
110+
<script setup>
111+
const selectedTab = ref(0);
112+
const handleTabChange = (selectedTabIndex) => {
113+
selectedTab.value = selectedTabIndex;
114+
};
115+
const tabs = [
116+
{
117+
id: 'all-customers-1',
118+
content: 'All',
119+
accessibilityLabel: 'All customers',
120+
panelID: 'all-customers-content-1',
121+
},
122+
{
123+
id: 'accepts-marketing-1',
124+
content: 'Accepts marketing',
125+
panelID: 'accepts-marketing-content-1',
126+
},
127+
{
128+
id: 'repeat-customers-1',
129+
content: 'Repeat customers',
130+
panelID: 'repeat-customers-content-1',
131+
},
132+
];
133+
</script>
134+
`,
135+
},
136+
},
137+
}}
138+
>
139+
{Template.bind({})}
140+
</Story>
141+
</Canvas>
142+
143+
<ArgsTable story="Tabs" />
144+
145+
---
146+
147+
<br/>
148+
149+
### **TabDescriptor Props**
150+
151+
```js
152+
/** A unique identifier for the tab */
153+
id: string;
154+
/** A destination to link to */
155+
url?: string;
156+
/** Content for the tab */
157+
content: string;
158+
/** A unique identifier for the panel */
159+
panelID?: string;
160+
/** Visually hidden text for screen readers */
161+
accessibilityLabel?: string;
162+
```

0 commit comments

Comments
 (0)