Skip to content

Commit

Permalink
feat(VList): revamp VList component (#57)
Browse files Browse the repository at this point in the history
* feat(VList): add CSS Properties support

* feat(VList): add new `dense` style

* feat(VList): add new `small` style

* feat(VList): add custom style example

* feat(VList): add divider inset style

* fix(VList): set default color to inherit

* fix(VList): fix extra span on appended text

* chore: improve bundle size
  • Loading branch information
gravitano authored Dec 6, 2022
1 parent 35aa4c4 commit fe50100
Show file tree
Hide file tree
Showing 8 changed files with 378 additions and 39 deletions.
1 change: 1 addition & 0 deletions packages/list/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ This package provides 5 components: `List`, `ListItem`, `ListItemDivider`, `List
```vue
<script setup lang="ts">
import {List, ListItem, ListItemDivider} from '@gits-id/list';
import '@gits-id/list/dist/style.css';
</script>
<template>
Expand Down
172 changes: 172 additions & 0 deletions packages/list/src/List.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
:root {
--v-list-padding-y: theme('padding.1');
--v-list-padding-x: theme('padding.1');
--v-list-gap: theme('gap.0');
--v-list-bg-color: theme('colors.transparent');

/* item */
--v-list-item-bg-color: theme('colors.transparent');
--v-list-item-color: inherit;
--v-list-item-padding-y: theme('padding.2');
--v-list-item-padding-x: theme('padding.3');
--v-list-item-border-radius: theme('borderRadius.DEFAULT');
--v-list-item-border-width: theme('borderWidth.DEFAULT');
--v-list-item-border-color: theme('colors.transparent');
--v-list-item-border-style: solid;
--v-list-item-gap: theme('gap.4');
--v-list-item-font-size: theme('fontSize.base');
--v-list-item-font-weight: theme('fontWeight.normal');
--v-list-item-line-height: theme('lineHeight.normal');
--v-list-item-text-align: left;

/* item hover */
--v-list-item-hover-bg-color: theme('colors.gray.100');
--v-list-item-hover-color: theme('colors.gray.700');

/* append & prepend */
--v-list-item-append-prepend-min-width: theme('width.5');

/* item header */
--v-list-item-header-bg-color: var(--v-list-item-bg-color);
--v-list-item-header-color: theme('colors.gray.500');
--v-list-item-header-padding-y: theme('padding.1');
--v-list-item-header-padding-x: var(--v-list-item-padding-x);
--v-list-item-header-border-radius: var(--v-list-item-border-radius);
--v-list-item-header-border-width: var(--v-list-item-border-width);
--v-list-item-header-border-color: var(--v-list-item-border-color);
--v-list-item-header-border-style: var(--v-list-item-border-style);
--v-list-item-header-gap: var(--v-list-item-gap);
--v-list-item-header-font-size: theme('fontSize.sm');
--v-list-item-header-font-weight: var(--v-list-item-font-weight);
--v-list-item-header-line-height: var(--v-list-item-line-height);
--v-list-item-header-text-transform: uppercase;
--v-list-item-header-text-align: var(--v-list-item-text-align);

/* divider */
--v-list-item-divider-width: theme('borderWidth.DEFAULT');
--v-list-item-divider-color: theme('colors.gray.200');
--v-list-item-divider-style: solid;
}

.v-list {
padding: var(--v-list-padding-y) var(--v-list-padding-x);
gap: var(--v-list-gap);
background-color: var(--v-list-bg-color);

@apply flex flex-col overflow-hidden;
}

.v-list-item {
padding: var(--v-list-item-padding-y) var(--v-list-item-padding-x);
gap: var(--v-list-item-gap);
background-color: var(--v-list-item-bg-color);
color: var(--v-list-item-color);
font-size: var(--v-list-item-font-size);
font-weight: var(--v-list-item-font-weight);
line-height: var(--v-list-item-line-height);
text-align: var(--v-list-item-text-align);
border-radius: var(--v-list-item-border-radius);

@apply flex items-center transition duration-300;
}

.v-list:not(.divide-y) .v-list-item {
border-width: var(--v-list-item-border-width);
border-style: var(--v-list-item-border-style);
border-color: var(--v-list-item-border-color);
}

.v-list-item--hover:hover,
.v-list--hover .v-list-item:hover:not(.v-list-item--hoverable) {
background-color: var(--v-list-item-hover-bg-color);
color: var(--v-list-item-hover-color);
}

.v-list-item-content {
@apply flex-1 select-none truncate whitespace-nowrap;
}

.v-list-item-prepend,
.v-list-item-append {
min-width: var(--v-list-item-append-prepend-min-width);

@apply flex gap-1 justify-center items-center;
}

.v-list-item-icon {
@apply transition duration-300 transform w-5 h-5;
}

/* flush */
.v-list--flush {
padding: 0;
}

/* shaped */
.v-list--shaped .v-list-item:not(.v-list-item--shaped) {
border-radius: 0px;
border-top-right-radius: theme('borderRadius.full');
border-bottom-right-radius: theme('borderRadius.full');
}

/* tile */
.v-list--tile .v-list-item,
.v-list-item--tile {
--v-list-item-border-radius: theme('borderRadius.none');
}

/* rounded */
.v-list--rounded .v-list-item,
.v-list-item--rounded {
--v-list-item-border-radius: theme('borderRadius.full');
}

/* item header */
.v-list-item-header {
padding: var(--v-list-item-header-padding-y) var(--v-list-item-header-padding-x);
gap: var(--v-list-item-header-gap);
background-color: var(--v-list-item-header-bg-color);
color: var(--v-list-item-header-color);
font-size: var(--v-list-item-header-font-size);
font-weight: var(--v-list-item-header-font-weight);
line-height: var(--v-list-item-header-line-height);
border-width: var(--v-list-item-header-border-width);
border-style: var(--v-list-item-header-border-style);
border-color: var(--v-list-item-header-border-color);
text-transform: var(--v-list-item-header-text-transform);
text-align: var(--v-list-item-header-text-align);
}

/* item divider */
.v-list-item-divider {
border-bottom-width: var(--v-list-item-divider-width);
border-bottom-style: var(--v-list-item-divider-style);
border-bottom-color: var(--v-list-item-divider-color);

@apply my-1;
}

.v-list-item-divider--inset {
--margin: calc(var(--v-list-item-append-prepend-min-width) + var(--v-list-item-padding-x) + var(--v-list-item-gap));

width: calc(100% - var(--margin));
margin-left: var(--margin);
}

/* dense */
.v-list--dense .v-list-item,
.v-list-item--dense {
--v-list-item-padding-y: theme('padding.1');
--v-list-item-padding-x: theme('padding.1');
--v-list-item-gap: theme('padding.1');
}

/* small */
.v-list--small .v-list-item,
.v-list-item--small {
--v-list-item-padding-y: theme('padding.1');
--v-list-item-padding-x: theme('padding.2');
--v-list-item-gap: theme('padding.2');
--v-list-item-font-size: theme('fontSize.sm');
--v-list-item-line-height: theme('lineHeight.normal');
}
136 changes: 127 additions & 9 deletions packages/list/src/List.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export const Hover: Story = (args) => ({
return {args};
},
template: `
<List v-bind="args">
<ListItem hover>Default</ListItem>
<List v-bind="args" hover>
<ListItem>Default</ListItem>
<ListItem hover hover-class="hover:bg-primary-200 hover:text-primary-700">
Custom Class
</ListItem>
Expand All @@ -63,6 +63,61 @@ export const Hover: Story = (args) => ({
`,
});

export const Dense: Story = (args) => ({
components: {
List,
ListItem,
ListItemDivider,
},
setup() {
return {args};
},
template: `
<List v-bind="args" dense hover>
<ListItem>Item 1</ListItem>
<ListItem>Item 2</ListItem>
<ListItemDivider />
<ListItem>Item 3</ListItem>
<ListItemDivider />
<ListItem>Item 4</ListItem>
<ListItem>Item 5</ListItem>
</List>
`,
});

export const Small: Story = (args) => ({
components: {
List,
ListItem,
ListItemDivider,
},
setup() {
return {args};
},
template: `
<p>Default</p>
<List v-bind="args" hover>
<ListItem>Item 1</ListItem>
<ListItem>Item 2</ListItem>
<ListItemDivider />
<ListItem>Item 3</ListItem>
<ListItemDivider />
<ListItem>Item 4</ListItem>
<ListItem>Item 5</ListItem>
</List>
<p>Small</p>
<List v-bind="args" small hover>
<ListItem>Item 1</ListItem>
<ListItem>Item 2</ListItem>
<ListItemDivider />
<ListItem>Item 3</ListItem>
<ListItemDivider />
<ListItem>Item 4</ListItem>
<ListItem>Item 5</ListItem>
</List>
`,
});

export const Shaped: Story = (args) => ({
components: {
List,
Expand All @@ -73,9 +128,9 @@ export const Shaped: Story = (args) => ({
return {args};
},
template: `
<List v-bind="args">
<ListItem hover shaped v-for="i in 5" :key="i">Item</ListItem>
<ListItem hover shaped shaped-class="rounded-l-full">
<List v-bind="args" shaped hover>
<ListItem v-for="i in 5" :key="i">Item</ListItem>
<ListItem shaped shaped-class="rounded-l-full">
Custom Shaped Class
</ListItem>
</List>
Expand All @@ -92,8 +147,11 @@ export const Rounded: Story = (args) => ({
return {args};
},
template: `
<List v-bind="args">
<ListItem hover rounded v-for="i in 5" :key="i">Item</ListItem>
<List v-bind="args" rounded hover>
<ListItem v-for="i in 5" :key="i">Item</ListItem>
</List>
<List v-bind="args" hover>
<ListItem rounded v-for="i in 5" :key="i">Item</ListItem>
</List>
`,
});
Expand All @@ -108,6 +166,9 @@ export const Tile: Story = (args) => ({
return {args};
},
template: `
<List v-bind="args" tile hover>
<ListItem v-for="i in 5" :key="i">Item</ListItem>
</List>
<List v-bind="args">
<ListItem hover tile v-for="i in 5" :key="i">Item</ListItem>
</List>
Expand Down Expand Up @@ -374,6 +435,7 @@ export const Collapse: Story = (args) => ({
<ListCollapse>
<template #activator="{isOpen, toggle}">
<ListItem
as="button"
prepend-icon="ri:book-line"
append-icon="ri:arrow-down-s-line"
:append-icon-class="isOpen ? 'rotate-180' : ''"
Expand All @@ -394,6 +456,7 @@ export const Collapse: Story = (args) => ({
<ListCollapse>
<template #activator="{isOpen, toggle}">
<ListItem
as="button"
prepend-icon="ri:user-line"
append-icon="ri:arrow-down-s-line"
:append-icon-class="isOpen ? 'rotate-180' : ''"
Expand Down Expand Up @@ -606,10 +669,11 @@ export const IosSettings: Story = (args) => ({
},
template: `
<List
hover
flush
class="border rounded-xl"
>
<ListItem
hover
tile
append-icon="ri:arrow-right-s-line"
append-icon-class="text-gray-500"
Expand All @@ -631,6 +695,7 @@ export const IosSettings: Story = (args) => ({
</ListItem>
</List>
<List
flush
class="border rounded-xl mt-6 divide divide-y"
>
<ListItem
Expand Down Expand Up @@ -713,7 +778,7 @@ export const ListInDropdown: Story = (args) => ({
},
template: `
<Dropdown label="Dropdown" panel-class="p-0">
<List>
<List flush>
<ListItem
hover
tile
Expand Down Expand Up @@ -843,3 +908,56 @@ export const Event: Story = (args) => ({
</List>
`,
});

export const CustomStyle: Story = (args) => ({
components: {
List,
ListItem,
ListItemDivider,
},
setup() {
return {args};
},
template: `
<List
v-bind="args"
hover
class="border rounded"
:style="{
'--v-list-item-hover-bg-color': '#4f46e5',
'--v-list-item-hover-color': 'white',
}"
>
<ListItem>Item 1</ListItem>
<ListItem>Item 2</ListItem>
<ListItemDivider />
<ListItem>Item 3</ListItem>
<ListItemDivider />
<ListItem>Item 4</ListItem>
<ListItem>Item 5</ListItem>
</List>
`,
});

export const DividerInset: Story = (args) => ({
components: {
List,
ListItem,
ListItemDivider,
},
setup() {
return {args};
},
template: `
<List
v-bind="args"
hover
>
<ListItem prepend-icon="ri:home-line">Item 1</ListItem>
<ListItemDivider inset />
<ListItem append-icon="ri:add-line">Item 3</ListItem>
<ListItemDivider inset />
<ListItem>Item 5</ListItem>
</List>
`,
});
Loading

0 comments on commit fe50100

Please sign in to comment.