Skip to content

Commit 6267445

Browse files
authored
feat(filter-pill): DLT-2704 create component (#473)
1 parent 69bda12 commit 6267445

25 files changed

Lines changed: 2133 additions & 19 deletions
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"classes": [
3+
{
4+
"class": "d-filter-pill",
5+
"applies": "N/A",
6+
"description": "Base filter pill style."
7+
},
8+
{
9+
"class": "d-filter-pill__wrapper",
10+
"applies": "N/A",
11+
"description": "Applies relative positioning."
12+
},
13+
{
14+
"class": "d-filter-pill__icon",
15+
"applies": "N/A",
16+
"description": "Applies the icon color."
17+
}
18+
]
19+
}

apps/dialtone-documentation/docs/_data/site-nav.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,10 @@
625625
"text": "Empty State",
626626
"link": "/components/empty-state.html"
627627
},
628+
{
629+
"text": "Filter Pill",
630+
"link": "/components/filter-pill.html"
631+
},
628632
{
629633
"text": "Hovercard",
630634
"link": "/components/hovercard.html"
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
---
2+
title: Filter Pill
3+
description: A Filter Pill offers a button paired with a popover to show and manage filtering options, the label and
4+
content of the filter can be handled through slots and props.
5+
status: beta
6+
# storybook: https://dialtone.dialpad.com/vue/?path=/story/components-filter-pill--default @TODO: Uncomment once it's RFP
7+
---
8+
9+
<code-well-header>
10+
<dt-filter-pill
11+
v-model="exampleFilters"
12+
label="With header, content and footer"
13+
>
14+
</dt-filter-pill>
15+
</code-well-header>
16+
17+
## Variants
18+
19+
### Base
20+
21+
<code-well-header>
22+
<dt-stack direction="row" gap="400">
23+
<dt-filter-pill
24+
label="Simple example"
25+
v-model="baseFilters"
26+
ref="simpleExample"
27+
>
28+
</dt-filter-pill>
29+
</dt-stack>
30+
</code-well-header>
31+
32+
<code-example-tabs
33+
:htmlCode='() => $refs.simpleExample'
34+
vueCode='<dt-filter-pill v-model="[...]" label="..."/>'
35+
showHtmlWarning />
36+
37+
### Disabled
38+
39+
<code-well-header>
40+
<dt-stack direction="row" gap="400">
41+
<dt-filter-pill label="Disabled filter" disabled ref="disabledFilter"></dt-filter-pill>
42+
</dt-stack>
43+
</code-well-header>
44+
45+
<code-example-tabs
46+
:htmlCode='() => $refs.disabledFilter'
47+
vueCode='<dt-filter-pill v-model="[...]" label="..." disabled/>'
48+
showHtmlWarning />
49+
50+
### Active
51+
52+
<code-well-header>
53+
<dt-stack direction="row" gap="400">
54+
<dt-filter-pill
55+
label="Active example"
56+
v-model="activeFilters"
57+
ref="activeExample"
58+
>
59+
</dt-filter-pill>
60+
</dt-stack>
61+
</code-well-header>
62+
63+
<code-example-tabs
64+
:htmlCode='() => $refs.activeExample'
65+
vueCode='<dt-filter-pill v-model="[...]" label="..."/>'
66+
showHtmlWarning />
67+
68+
### Clearable
69+
70+
You can handle the filter resetting, the button will show whenever an active filter is passed.
71+
It will emit the `reset` event when clicked.
72+
73+
<code-well-header>
74+
<dt-stack direction="row" gap="400">
75+
<dt-filter-pill
76+
label="Clearable example"
77+
ref="clearableExample"
78+
v-model="clearableFilters"
79+
>
80+
</dt-filter-pill>
81+
</dt-stack>
82+
</code-well-header>
83+
84+
<code-example-tabs
85+
:htmlCode='() => $refs.clearableExample'
86+
vueCode='<dt-filter-pill label="..." v-model="[...]" />'
87+
showHtmlWarning />
88+
89+
### Non Clearable
90+
91+
Setting the `hide-clear` prop will hide the reset/clear button in case you don't want your filter be reset.
92+
93+
<code-well-header>
94+
<dt-stack direction="row" gap="400">
95+
<dt-filter-pill
96+
label="Non Clearable example"
97+
ref="clearableExample"
98+
v-model="nonClearableFilters"
99+
hide-clear
100+
>
101+
</dt-filter-pill>
102+
</dt-stack>
103+
</code-well-header>
104+
105+
<code-example-tabs
106+
:htmlCode='() => $refs.clearableExample'
107+
vueCode='<dt-filter-pill label="..." v-model="[...]" hide-clear />'
108+
showHtmlWarning />
109+
110+
### Sizes
111+
112+
<code-well-header>
113+
<dt-stack direction="row" gap="300">
114+
<dt-filter-pill
115+
v-for="size in sizes"
116+
:key="size"
117+
:label="size"
118+
:size="size"
119+
ref="smExample"
120+
></dt-filter-pill>
121+
</dt-stack>
122+
</code-well-header>
123+
124+
<code-example-tabs
125+
:htmlCode='() => $refs.smExample[1]'
126+
vueCode='<dt-filter-pill label="..." size="sm" />'
127+
showHtmlWarning />
128+
129+
### With default slot
130+
131+
Using the "default" slot, you're able to override the `label` prop
132+
133+
<code-well-header>
134+
<dt-stack direction="row" gap="400">
135+
<dt-filter-pill
136+
ref="clearableExample"
137+
v-model="defaultSlotFilters"
138+
>
139+
<template #default>
140+
With Default slot
141+
</template>
142+
</dt-filter-pill>
143+
</dt-stack>
144+
</code-well-header>
145+
146+
<code-example-tabs
147+
:htmlCode='() => $refs.clearableExample'
148+
vueCode='<dt-filter-pill label="..." v-model="[...]">
149+
<template #default>
150+
With Default slot
151+
</template>
152+
</dt-filter-pill>'
153+
showHtmlWarning />
154+
155+
### With content slot
156+
157+
Using the "content" slot, you're able to override the popover content, this enables you
158+
to create custom filter pill.
159+
160+
<code-well-header>
161+
<dt-stack direction="row" gap="400">
162+
<dt-filter-pill
163+
label="With content slot"
164+
ref="clearableExample"
165+
v-model="contentSlotFilters"
166+
>
167+
<template #content>
168+
Content slot example
169+
</template>
170+
</dt-filter-pill>
171+
</dt-stack>
172+
</code-well-header>
173+
174+
<code-example-tabs
175+
:htmlCode='() => $refs.clearableExample'
176+
vueCode='<dt-filter-pill label="..." v-model="[...]">
177+
<template #content>
178+
Content slot example
179+
</template>
180+
</dt-filter-pill>'
181+
showHtmlWarning />
182+
183+
## Vue API
184+
185+
<component-vue-api component-name="filterPill"></component-vue-api>
186+
187+
## Classes
188+
189+
<component-class-table component-name="filter-pill"></component-class-table>
190+
191+
<script setup>
192+
import { ref } from 'vue';
193+
import { DtIconSearch, DtIconClose } from '@dialpad/dialtone-icons/vue3';
194+
195+
const inputValue = ref('');
196+
const exampleFilters = ref([
197+
{name: 'Option 1'},
198+
{name: 'Option 2'},
199+
]);
200+
const baseFilters = ref([
201+
{name: 'Option 1'},
202+
{name: 'Option 2'},
203+
{name: 'Option 3'},
204+
]);
205+
const activeFilters = ref([
206+
{name: 'Option 1'},
207+
{name: 'Option 2'},
208+
{name: 'Option 3', active: true}
209+
]);
210+
const clearableFilters = ref([
211+
{name: 'Option 1'},
212+
{name: 'Option 2', active: true},
213+
{name: 'Option 3'}
214+
]);
215+
const nonClearableFilters = ref([
216+
{name: 'Option 1', active: true},
217+
{name: 'Option 2'},
218+
{name: 'Option 3'}
219+
]);
220+
const defaultSlotFilters = ref([
221+
{name: 'Option 1'},
222+
{name: 'Option 2'},
223+
]);
224+
const contentSlotFilters = ref([
225+
{name: 'Option 1'},
226+
{name: 'Option 2'},
227+
]);
228+
const sizes = Object.keys(window.DIALTONE_CONSTANTS.BUTTON_SIZE_MODIFIERS);
229+
const sizeNames = {
230+
xs: 'Extra small',
231+
sm: 'Small',
232+
md: 'Medium',
233+
lg: 'Large',
234+
xl: 'Extra Large',
235+
};
236+
</script>

common/components_list.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module.exports = [
1919
'emoji_picker.vue',
2020
'emoji_text_wrapper.vue',
2121
'empty_state.vue',
22+
'filter_pill.vue',
2223
'hovercard.vue',
2324
'icon.vue',
2425
'image_viewer.vue',
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//
2+
// DIALTONE
3+
// COMPONENTS: FILTER PILL
4+
//
5+
// These are the styles for filter-pill component.
6+
//
7+
//
8+
// TABLE OF CONTENTS
9+
// • BASE STYLE
10+
11+
// @@ BASE STYLE
12+
// ----------------------------------------------------------------------------
13+
.d-filter-pill {
14+
--filter-pill-color-background-selected-hover: color-mix(in srgb, var(--dt-action-color-background-base-active), var(--dt-action-color-foreground-base-active) 5%);
15+
16+
display: inline-flex;
17+
gap: 0;
18+
19+
&__primary {
20+
&--has-clear {
21+
border-start-end-radius: 0;
22+
border-end-end-radius: 0;
23+
}
24+
25+
&--selected:not(:disabled) {
26+
&:hover {
27+
background-color: var(--filter-pill-color-background-selected-hover);
28+
}
29+
30+
&:active {
31+
background-color: var(--dt-action-color-background-base-active);
32+
}
33+
}
34+
}
35+
36+
&__label {
37+
display: flex;
38+
gap: var(--dt-space-300);
39+
max-width: var(--dt-size-875);
40+
font-weight: var(--dt-font-weight-normal);
41+
}
42+
43+
&__label-alpha {
44+
flex: 1;
45+
overflow: hidden;
46+
white-space: nowrap;
47+
text-overflow: ellipsis;
48+
}
49+
50+
&__label-omega {
51+
display: flex;
52+
gap: var(--dt-space-300);
53+
align-items: center;
54+
font-weight: var(--dt-font-weight-bold);
55+
letter-spacing: var(--dt-size-50-negative);
56+
font-variant-numeric: tabular-nums;
57+
58+
&::before {
59+
content: "=";
60+
}
61+
}
62+
63+
&__clear {
64+
--button-padding-x: var(--dt-space-350) !important;
65+
66+
border-inline-start-width: 0;
67+
border-start-start-radius: 0;
68+
border-end-start-radius: 0;
69+
70+
&--selected:not(:disabled) {
71+
&:hover {
72+
background-color: var(--filter-pill-color-background-selected-hover);
73+
}
74+
75+
&:active {
76+
background-color: var(--dt-action-color-background-base-active);
77+
}
78+
}
79+
}
80+
}

packages/dialtone-css/lib/build/less/dialtone.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
@import 'components/emoji';
5959
@import 'components/emoji-text-wrapper';
6060
@import 'components/emoji-picker';
61+
@import 'components/filter-pill';
6162

6263
// -- UTILITIES
6364
@import 'utilities/backgrounds';
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Meta } from '@storybook/blocks';
2+
import * as DtFilterPillStories from './filter_pill.stories.js';
3+
import RedirectToDocs from "@/common/snippets/redirect-to-docs.mdx"
4+
5+
<Meta of={DtFilterPillStories} />
6+
7+
# Filter Pill
8+
9+
<RedirectToDocs name="filter-pill" />

0 commit comments

Comments
 (0)