Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Add small dropdown button variant (#597)
Browse files Browse the repository at this point in the history
* Add VButtonGroup component

* Add small size for dropdown button

* Use small size button for audio layout and match heights across play/pause and download buttons

* Remove unused VButtonGRoup component
  • Loading branch information
sarayourfriend authored Jan 18, 2022
1 parent f974ac3 commit 3864d34
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 18 deletions.
8 changes: 8 additions & 0 deletions src/components/DownloadButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
v-if="filesizes"
:dropdown-aria-label="$t('download-button.aria.dropdown-label')"
:is-single-item="formats.length === 1"
:size="size"
>
<template #default="{ buttonProps }">
<a
Expand Down Expand Up @@ -77,6 +78,13 @@ export default {
return formats.every((format) => properties.every((p) => p in format))
},
},
size: {
type: /** @type {import('@nuxtjs/composition-api').PropType<'medium' | 'small'>} */ (
String
),
default: 'medium',
validator: (v) => ['medium', 'small'].includes(v),
},
},
data() {
const savedFormatExtension =
Expand Down
55 changes: 50 additions & 5 deletions src/components/DropdownButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="flex">
<slot
:button-props="{
class: 'dropdown-button rounded-s-sm rounded-e-none',
class: `dropdown-button rounded-s-sm rounded-e-none dropdown-button-${size}`,
type: 'button',
}"
/>
Expand All @@ -13,7 +13,10 @@
ref="dropdownButton"
type="button"
class="dropdown-button ms-1 rounded-e-sm rounded-s-none w-14"
:class="{ 'dropdown-button-active': isOpen }"
:class="[
isOpen && 'dropdown-button-active',
`dropdown-icon-button-${size}`,
]"
aria-haspopup="menu"
:aria-label="safeDropdownAriaLabel"
:aria-expanded="isOpen"
Expand Down Expand Up @@ -47,9 +50,10 @@
</template>

<script>
import { defineComponent } from '@nuxtjs/composition-api'
import caretDown from '~/assets/icons/caret-down.svg'
const DropdownButton = {
const DropdownButton = defineComponent({
name: 'DropdownButton',
props: {
dropdownAriaLabel: {
Expand All @@ -60,6 +64,13 @@ const DropdownButton = {
type: Boolean,
required: false,
},
size: {
type: /** @type {import('@nuxtjs/composition-api').PropType<'medium' | 'small'>} */ (
String
),
default: 'medium',
validator: (v) => ['medium', 'small'].includes(v),
},
},
data() {
return {
Expand All @@ -71,6 +82,11 @@ const DropdownButton = {
this.dropdownAriaLabel || this.$t('dropdown-button.aria.arrow-label'),
}
},
computed: {
sizeClass() {
return `dropdown-button-${this.size}`
},
},
mounted() {
document.addEventListener('click', this.onClickout)
},
Expand Down Expand Up @@ -144,14 +160,43 @@ const DropdownButton = {
}
},
},
}
})
export default DropdownButton
</script>

<style lang="css" scoped>
.dropdown-button {
@apply flex items-center justify-center bg-pink text-white font-bold p-4 leading-6 transition-shadow duration-100 ease-linear disabled:opacity-70 focus:outline-none focus-visible:ring focus-visible:ring-offset-2 focus-visible:ring-pink hover:bg-dark-pink no-underline appearance-none;
@apply flex items-center justify-center bg-pink text-white font-bold transition-shadow duration-100 ease-linear disabled:opacity-70 focus:outline-none focus-visible:ring focus-visible:ring-offset-2 focus-visible:ring-pink hover:bg-dark-pink no-underline appearance-none;
}
.dropdown-icon-button-medium,
.dropdown-button-medium {
@apply p-4 leading-6;
}
/*
Note the bespoke `py-[0.86rem]` class used below is necessary
to match the height of the small Audio play/pause button.
This is currently the only application of the DropdownButton
component (via the DownloadButton component) so as a stop-gap
solution to get the redesign out the door in a timely manner it
is necessary.
In the future it would be nice to coordinate these sizes across
all our buttons, regardless of content (icon vs text for example)
so that don't have to worry about things like this. We should feel
free to use sizes like 0.86rem if they're the right size, but it is
good to avoid the long term effects of scattering too many ad-hoc
sizes throughout the codebase.
*/
.dropdown-button-small {
@apply px-4 py-[0.86rem] leading-3;
}
.dropdown-icon-button-small {
@apply px-0 py-[0.86rem] leading-3 w-10;
}
.dropdown-button-active {
Expand Down
1 change: 1 addition & 0 deletions src/components/VAudioTrack/layouts/VFullLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<DownloadButton
class="ms-auto order-1 sm:order-2"
:formats="getFormats(audio)"
:size="isSmall ? 'small' : 'medium'"
/>
</div>
</div>
Expand Down
21 changes: 16 additions & 5 deletions src/components/VButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ const VButton = defineComponent({
* @default 'button'
*/
as: {
type: String,
type: /** @type {import('@nuxtjs/composition-api').PropType<'a' | 'button'>} */ (
String
),
default: 'button',
validate: (v) => ['a', 'button', 'NuxtLink'].includes(v),
},
Expand All @@ -71,7 +73,9 @@ const VButton = defineComponent({
* @default 'primary'
*/
variant: {
type: String,
type: /** @type {import('@nuxtjs/composition-api').PropType<'primary' | 'secondary' | 'tertiary' | 'action-menu' | 'action-menu-muted' | 'grouped'>} */ (
String
),
default: 'primary',
validate: (v) =>
[
Expand Down Expand Up @@ -101,7 +105,9 @@ const VButton = defineComponent({
* @default 'medium'
*/
size: {
type: String,
type: /** @type {import('@nuxtjs/composition-api').PropType<'large' | 'medium' | 'small' | 'disabled'>} */ (
String
),
default: 'medium',
validate: (v) => ['large', 'medium', 'small', 'disabled'].includes(v),
},
Expand Down Expand Up @@ -135,12 +141,17 @@ const VButton = defineComponent({
* @default 'button'
*/
type: {
type: String,
type: /** @type {import('@nuxtjs/composition-api').PropType<'buton' | 'submit' | 'reset'>} */ (
String
),
default: 'button',
validate: (v) => ['button', 'submit', 'reset'].includes(v),
},
},
/* eslint-disable no-unused-vars */
/**
* @param {Props} props
* @param {import('@nuxtjs/composition-api').SetupContext}
*/
setup(props, { attrs }) {
const propsRef = toRefs(props)
const disabledAttributeRef = ref(propsRef.disabled.value)
Expand Down
26 changes: 18 additions & 8 deletions src/components/meta/DropdownButton.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ import DropdownButton from '~/components/DropdownButton'
export default {
title: 'Components/DropdownButton',
component: DropdownButton,
argTypes: {
size: {
type: 'select',
options: ['medium', 'small'],
},
},
}

export const Default = () => ({
export const Default = (args, { argTypes }) => ({
template: `
<div>
<DropdownButton>
<DropdownButton v-bind="$props">
<template #default="{ buttonProps }">
<button v-bind="buttonProps" class="whitespace-nowrap" @click="onClick">Download {{ activeItem?.name ?? '' }}</button>
</template>
Expand All @@ -24,14 +30,18 @@ export const Default = () => ({
Test element below
</div>
`,
data: () => ({
items: [
{ name: 'Item 1', active: false },
{ name: 'Item 2', active: false },
],
}),
props: Object.keys(argTypes).filter((i) => i !== 'items'),
data() {
return {
items: [
{ name: 'Item 1', active: false },
{ name: 'Item 2', active: false },
],
}
},
computed: {
activeItem() {
console.log(this)
return this.items.find((item) => item.active)
},
},
Expand Down

0 comments on commit 3864d34

Please sign in to comment.