@nextcloud/vue
Version:
Nextcloud vue components
1 lines • 35 kB
Source Map (JSON)
{"version":3,"file":"NcButton-CWPBzbcC.mjs","sources":["../../src/components/NcButton/NcButton.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<docs>\n\n### General description\nGeneral purpose button component. See props for different options.\n[Use material design icons only for icons](https://www.npmjs.com/package/vue-material-design-icons) and remember to set their size to 20.\n\n### Usage\n### Custom icon slot\nTo be used with `vue-material-design-icons` only. For icon classes use the `default-icon` slot.\nIt can be used with one or multiple actions.\n```\n<template>\n<div class=\"wrapper\">\n\t<!-- Style selector -->\n\t<div class=\"grid\">\n\t\t<NcCheckboxRadioSwitch :checked.sync=\"style\" value=\"text\" name=\"style\" type=\"radio\">Text only</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch :checked.sync=\"style\" value=\"icon\" name=\"style\" type=\"radio\">Icon only</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch :checked.sync=\"style\" value=\"icontext\" name=\"style\" type=\"radio\">Icon and text</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch :checked.sync=\"disabled\" type=\"checkbox\">Disabled</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch :checked.sync=\"size\" value=\"small\" name=\"size\" type=\"radio\">Small</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch :checked.sync=\"size\" value=\"normal\" name=\"size\" type=\"radio\">Normal (default)</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch :checked.sync=\"size\" value=\"large\" name=\"size\" type=\"radio\">Large</NcCheckboxRadioSwitch>\n\t</div>\n\n\t<h5>Standard buttons</h5>\n\t<div class=\"grid\">\n\t\t<p>Tertiary, no background</p>\n\t\t<p>Tertiary</p>\n\t\t<p>Secondary</p>\n\t\t<p>Primary</p>\n\t\t<NcButton\n\t\t\taria-label=\"Example text\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:size=\"size\"\n\t\t\tvariant=\"tertiary-no-background\">\n\t\t\t<template v-if=\"style.indexOf('icon') !== -1\" #icon>\n\t\t\t\t<Video\n\t\t\t\t\t:size=\"20\" />\n\t\t\t</template>\n\t\t\t<template v-if=\"style.indexOf('text') !== -1\">Example text</template>\n\t\t</NcButton>\n\t\t<NcButton\n\t\t\taria-label=\"Example text\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:size=\"size\"\n\t\t\tvariant=\"tertiary\">\n\t\t\t<template v-if=\"style.indexOf('icon') !== -1\" #icon>\n\t\t\t\t<Video\n\t\t\t\t\t:size=\"20\" />\n\t\t\t</template>\n\t\t\t<template v-if=\"style.indexOf('text') !== -1\">Example text</template>\n\t\t</NcButton>\n\t\t<NcButton\n\t\t\taria-label=\"Example text\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:size=\"size\">\n\t\t\t<template v-if=\"style.indexOf('icon') !== -1\" #icon>\n\t\t\t\t<Video\n\t\t\t\t\t:size=\"20\" />\n\t\t\t</template>\n\t\t\t<template v-if=\"style.indexOf('text') !== -1\">Example text</template>\n\t\t</NcButton>\n\t\t<NcButton\n\t\t\taria-label=\"Example text\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:size=\"size\"\n\t\t\tvariant=\"primary\">\n\t\t\t<template v-if=\"style.indexOf('icon') !== -1\" #icon>\n\t\t\t\t<Video\n\t\t\t\t\t:size=\"20\" />\n\t\t\t</template>\n\t\t\t<template v-if=\"style.indexOf('text') !== -1\">Example text</template>\n\t\t</NcButton>\n\t</div>\n\n\t<!-- Wide button -->\n\t<h5>Wide button</h5>\n\t<NcButton\n\t\t:disabled=\"disabled\"\n\t\t:size=\"size\"\n\t\t:wide=\"true\"\n\t\ttext=\"Example text\">\n\t\t<template #icon>\n\t\t\t<Video\n\t\t\t\t:size=\"20\" />\n\t\t</template>\n\t\tExample text\n\t</NcButton>\n\n\t<!-- Special buttons -->\n\t<h5>Special buttons</h5>\n\t<div class=\"grid\">\n\t\t<p>Success</p>\n\t\t<p>Warning</p>\n\t\t<p>Error</p>\n\t\t<p> - </p>\n\t\t<NcButton\n\t\t\t:disabled=\"disabled\"\n\t\t\t:size=\"size\"\n\t\t\tvariant=\"success\">\n\t\t\t<template #icon>\n\t\t\t\t<Video\n\t\t\t\t\t:size=\"20\" />\n\t\t\t</template>\n\t\t\tExample text\n\t\t</NcButton>\n\t\t<NcButton\n\t\t\t:disabled=\"disabled\"\n\t\t\t:size=\"size\"\n\t\t\tvariant=\"warning\">\n\t\t\t<template #icon>\n\t\t\t\t<Video\n\t\t\t\t\t:size=\"20\" />\n\t\t\t</template>\n\t\t\tExample text\n\t\t</NcButton>\n\t\t<NcButton\n\t\t\t:disabled=\"disabled\"\n\t\t\t:size=\"size\"\n\t\t\tvariant=\"error\">\n\t\t\t<template #icon>\n\t\t\t\t<Video\n\t\t\t\t\t:size=\"20\" />\n\t\t\t</template>\n\t\t\tExample text\n\t\t</NcButton>\n\t\t<p> - </p>\n\t</div>\n</div>\n\n</template>\n<script>\nimport Video from 'vue-material-design-icons/Video.vue'\n\nexport default {\n\tcomponents: {\n\t\tVideo,\n\t},\n\tdata() {\n\t\treturn {\n\t\t\ttoggled: false,\n\t\t\tdisabled: false,\n\t\t\tsize: 'normal',\n\t\t\tstyle: 'icontext',\n\t\t}\n\t}\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.wrapper {\n\tpadding: 0 12px;\n}\n\n.grid {\n\tdisplay: grid;\n\tgap: 12px;\n\tgrid-template-columns: 1fr 1fr 1fr 1fr;\n\tgrid-template-rows: repeat(auto-fill, auto);\n\tposition: relative;\n\tmargin: 12px 0;\n}\n\nh5 {\n\tfont-weight: bold;\n\tmargin: 40px 0 20px 0;\n}\n\np {\n\ttext-align: center;\n\tmargin: 4px 0 12px 0;\n\tcolor: var(--color-text-maxcontrast)\n}\n\nbutton {\n\tmargin: auto;\n}\n</style>\n```\n\n### Alignment\nSometimes it is required to change the icon alignment on the button, like for switching between pages as in following example:\n\n```vue\n<template>\n\t<div style=\"display: flex; flex-direction: column; gap: 12px;\">\n\t\t<NcButton aria-label=\"center (default)\" variant=\"secondary\" wide>\n\t\t\t<template #icon>\n\t\t\t\t<IconLeft :size=\"20\" />\n\t\t\t</template>\n\t\t\tcenter (default)\n\t\t</NcButton>\n\t\t<NcButton alignment=\"center-reverse\" aria-label=\"center-reverse\" variant=\"secondary\" wide>\n\t\t\t<template #icon>\n\t\t\t\t<IconRight :size=\"20\" />\n\t\t\t</template>\n\t\t\tcenter-reverse\n\t\t</NcButton>\n\t\t<div style=\"display: flex; gap: 12px;\">\n\t\t\t<div style=\"display: flex; flex-direction: column; gap: 12px; flex: 1\">\n\t\t\t\t<NcButton alignment=\"start\" aria-label=\"start\" variant=\"secondary\" wide>\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<IconLeft :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\tstart\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton alignment=\"start-reverse\" aria-label=\"start-reverse\" variant=\"secondary\" wide>\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<IconRight :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\tstart-reverse\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<div style=\"display: flex; flex-direction: column; gap: 12px; flex: 1\">\n\t\t\t\t<NcButton alignment=\"end\" aria-label=\"end\" variant=\"secondary\" wide>\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<IconLeft :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\tend\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton alignment=\"end-reverse\" aria-label=\"end-reverse\" variant=\"secondary\" wide>\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<IconRight :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\tend-reverse\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</template>\n<script>\nimport IconLeft from 'vue-material-design-icons/ArrowLeft.vue'\nimport IconRight from 'vue-material-design-icons/ArrowRight.vue'\n\nexport default {\n\tcomponents: {\n\t\tIconLeft,\n\t\tIconRight,\n\t},\n}\n</script>\n```\n\n### Pressed state\n\nIt is possible to make the button stateful by adding a pressed state, e.g. if you like to create a favorite button.\nThe button will have the required `aria` attribute for accessibility and visual style (`primary` when pressed, and the configured variant otherwise).\n\nDo not change `text` or `aria-label` of the pressed/unpressed button. See: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-pressed\n\n```vue\n<template>\n\t<div>\n\t\t<div style=\"display: flex; gap: 12px;\">\n\t\t\t<NcButton :pressed.sync=\"isFavorite\" aria-label=\"Favorite\" variant=\"tertiary-no-background\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<IconStar v-if=\"isFavorite\" :size=\"20\" />\n\t\t\t\t\t<IconStarOutline v-else :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t</NcButton>\n\n\t\t\t<NcButton :pressed.sync=\"isFavorite\" variant=\"tertiary\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<IconStar v-if=\"isFavorite\" :size=\"20\" />\n\t\t\t\t\t<IconStarOutline v-else :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\tFavorite\n\t\t\t</NcButton>\n\n\t\t\t<NcButton :pressed.sync=\"isFavorite\" aria-label=\"Favorite\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<IconStar v-if=\"isFavorite\" :size=\"20\" />\n\t\t\t\t\t<IconStarOutline v-else :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t</NcButton>\n\t\t</div>\n\t\t<div>\n\t\t\tIt is {{ isFavorite ? 'a' : 'not a' }} favorite.\n\t\t</div>\n\t</div>\n</template>\n<script>\nimport IconStar from 'vue-material-design-icons/Star.vue'\nimport IconStarOutline from 'vue-material-design-icons/StarOutline.vue'\n\nexport default {\n\tcomponents: {\n\t\tIconStar,\n\t\tIconStarOutline,\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tisFavorite: false,\n\t\t}\n\t},\n\tmethods: {\n\t\ttoggleFavorite() {\n\t\t\tthis.isFavorite = !this.isFavorite\n\t\t},\n\t},\n}\n</script>\n```\n\n### Usage example: Sorting table columns\nThe standard way to implement sortable table column headers should be like this:\n\n```vue\n<template>\n\t<table>\n\t\t<thead>\n\t\t\t<tr>\n\t\t\t\t<th :aria-sorted=\"sortedName\" class=\"row-name\">\n\t\t\t\t\t<NcButton alignment=\"start-reverse\"\n\t\t\t\t\t\t:wide=\"true\"\n\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t@click=\"sortName\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<IconDown v-if=\"sortedName === 'ascending'\" class=\"sort-icon\" :size=\"20\" />\n\t\t\t\t\t\t\t<IconUp v-else-if=\"sortedName === 'descending'\" class=\"sort-icon\" :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<span class=\"table-header\">Name</span>\n\t\t\t\t\t</NcButton>\n\t\t\t\t</th>\n\t\t\t\t<th :aria-sorted=\"sortedSize\" class=\"row-size\">\n\t\t\t\t\t<NcButton alignment=\"end\"\n\t\t\t\t\t\t:wide=\"true\"\n\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t@click=\"sortSize\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<IconDown v-if=\"sortedSize === 'ascending'\" class=\"sort-icon\" :size=\"20\" />\n\t\t\t\t\t\t\t<IconUp v-else-if=\"sortedSize === 'descending'\" class=\"sort-icon\" :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<span class=\"table-header\">Size</span>\n\t\t\t\t\t</NcButton>\n\t\t\t\t</th>\n\t\t\t</tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr>\n\t\t\t\t<td class=\"row-name\">Lorem ipsum</td>\n\t\t\t\t<td class=\"row-size\">8 MiB</td>\n\t\t\t</tr>\n\t\t</tbody>\n\t</table>\n</template>\n<script>\nimport IconUp from 'vue-material-design-icons/MenuUp.vue'\nimport IconDown from 'vue-material-design-icons/MenuDown.vue'\n\nexport default {\n\tcomponents: {\n\t\tIconUp,\n\t\tIconDown,\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tsortedName: null,\n\t\t\tsortedSize: null,\n\t\t}\n\t},\n\tmethods: {\n\t\tsortName() {\n\t\t\tif (this.sortedName === 'ascending') {\n\t\t\t\tthis.sortedName = 'descending'\n\t\t\t} else if (this.sortedName === 'descending') {\n\t\t\t\tthis.sortedName = null\n\t\t\t} else {\n\t\t\t\tthis.sortedName = 'ascending'\n\t\t\t}\n\t\t},\n\t\tsortSize() {\n\t\t\tif (this.sortedSize === 'ascending') {\n\t\t\t\tthis.sortedSize = 'descending'\n\t\t\t} else if (this.sortedSize === 'descending') {\n\t\t\t\tthis.sortedSize = null\n\t\t\t} else {\n\t\t\t\tthis.sortedSize = 'ascending'\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n<style>\ntable {\n\ttable-layout: fixed;\n\twidth: 300px;\n}\n\ntd.row-name {\n\tpadding-inline-start: 16px;\n}\n\ntd.row-size {\n\ttext-align: end;\n\tpadding-inline-end: 16px;\n}\n\n.table-header {\n\tfont-weight: normal;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.sort-icon {\n\tcolor: var(--color-text-maxcontrast);\n\tposition: relative;\n\tinset-inline: -10px;\n}\n\n.row-size .sort-icon {\n\tinset-inline: 10px;\n}\n</style>\n```\n\n</docs>\n\n<script>\nimport { isLegacy32 } from '../../utils/legacy.ts'\nimport { logger } from '../../utils/logger.ts'\n\nexport default {\n\tname: 'NcButton',\n\n\tinject: {\n\t\tgetNcPopoverTriggerAttrs: {\n\t\t\tfrom: 'NcPopover:trigger:attrs',\n\t\t\tdefault: () => () => ({}),\n\t\t},\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Set the text and icon alignment\n\t\t *\n\t\t * @default 'center'\n\t\t */\n\t\talignment: {\n\t\t\ttype: String,\n\t\t\tdefault: 'center',\n\t\t\tvalidator: (alignment) => ['start', 'start-reverse', 'center', 'center-reverse', 'end', 'end-reverse'].includes(alignment),\n\t\t},\n\n\t\t/**\n\t\t * Toggles the disabled state of the button on and off.\n\t\t */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Specify the button size\n\t\t * Accepted values: `'small'`, `'normal'` (default), `'large'`\n\t\t */\n\t\tsize: {\n\t\t\ttype: String,\n\t\t\tdefault: 'normal',\n\t\t\tvalidator(value) {\n\t\t\t\treturn ['small', 'normal', 'large'].includes(value)\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Specifies the HTML button type.\n\t\t * Accepted values: submit, reset, button.\n\t\t *\n\t\t * For legacy reasons this can also be used to set the variant of the button (color schema).\n\t\t * This is discouraged but the accepted values are:\n\t\t * primary, secondary, tertiary, tertiary-no-background, tertiary-on-primary, error, warning, success.\n\t\t *\n\t\t * @default 'secondary' (will change with v9)\n\t\t * @deprecated The behavior will change in v9 to only allow the native HTML button types - use `variant` instead for setting the appearance of the button.\n\t\t */\n\t\ttype: {\n\t\t\ttype: String,\n\t\t\tvalidator(value) {\n\t\t\t\treturn ['primary', 'secondary', 'tertiary', 'tertiary-no-background', 'tertiary-on-primary', 'error', 'warning', 'success'].includes(value)\n\t\t\t\t\t|| ['submit', 'reset', 'button'].includes(value)\n\t\t\t},\n\n\t\t\tdefault: 'secondary',\n\t\t},\n\n\t\t/**\n\t\t * Specifies the button native type\n\t\t * Accepted values: submit, reset, button. If left empty,\n\t\t * the default \"button\" type will be used.\n\t\t *\n\t\t * @deprecated use `type` instead - will be removed with v9\n\t\t */\n\t\tnativeType: {\n\t\t\ttype: String,\n\t\t\tvalidator(value) {\n\t\t\t\treturn ['submit', 'reset', 'button'].indexOf(value) !== -1\n\t\t\t},\n\n\t\t\tdefault: 'button',\n\t\t},\n\n\t\t/**\n\t\t * Specifies whether the button should span all the available width.\n\t\t * By default, buttons span the whole width of the container.\n\t\t */\n\t\twide: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Always try to provide an aria-label to your button. Make it more\n\t\t * specific than the button's name by provide some more context. E.g. if\n\t\t * the name of the button is \"send\" in the Mail app, the aria label could\n\t\t * be \"Send email\".\n\t\t */\n\t\tariaLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Providing the href attribute turns the button component into an `a`\n\t\t * element.\n\t\t */\n\t\thref: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Target for the `a` element if `href` is set.\n\t\t */\n\t\ttarget: {\n\t\t\ttype: String,\n\t\t\tdefault: '_self',\n\t\t},\n\n\t\t/**\n\t\t * Providing the download attribute with href downloads file when clicking.\n\t\t */\n\t\tdownload: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Providing the to attribute turns the button component into a `router-link`\n\t\t * element. Takes precedence over the href attribute.\n\t\t */\n\t\tto: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Pass in `true` if you want the matching behaviour of `router-link` to\n\t\t * be non-inclusive: https://router.vuejs.org/api/#exact\n\t\t */\n\t\texact: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * @deprecated To be removed in @nextcloud/vue 9. Migration guide: remove ariaHidden prop from NcAction* components.\n\t\t * @todo Add a check in @nextcloud/vue 9 that this prop is not provided,\n\t\t * otherwise root element will inherit incorrect aria-hidden.\n\t\t */\n\t\tariaHidden: {\n\t\t\ttype: Boolean,\n\t\t\t// eslint-disable-next-line vue/no-boolean-default\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The pressed state of the button if it has a checked state\n\t\t * This will add the `aria-pressed` attribute and for the button to have the primary style in checked state.\n\t\t *\n\t\t * Pressed state is not supported for links\n\t\t */\n\t\tpressed: {\n\t\t\ttype: Boolean,\n\t\t\t// eslint-disable-next-line vue/no-boolean-default\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Specifies the button variant.\n\t\t *\n\t\t * Accepted values: primary, secondary, tertiary, tertiary-no-background, tertiary-on-primary, error, warning, success.\n\t\t *\n\t\t * @default 'secondary'\n\t\t * @since 8.24.0\n\t\t */\n\t\tvariant: {\n\t\t\ttype: String,\n\t\t\tvalidator(value) {\n\t\t\t\treturn ['primary', 'secondary', 'tertiary', 'tertiary-no-background', 'tertiary-on-primary', 'error', 'warning', 'success'].includes(value)\n\t\t\t},\n\n\t\t\tdefault: 'secondary',\n\t\t},\n\t},\n\n\temits: ['update:pressed', 'click'],\n\n\tcomputed: {\n\t\t/**\n\t\t * The real type to be used for the button, enforces `primary` for pressed state and, if stateful button, any other type for not pressed state\n\t\t * Otherwise the type property is used.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trealVariant() {\n\t\t\t// Force *primary* when pressed\n\t\t\tif (this.pressed) {\n\t\t\t\treturn 'primary'\n\t\t\t}\n\t\t\t// If not pressed but button is configured as stateful button then the type must not be primary\n\t\t\tif (this.pressed === false && (this.type === 'primary' || this.variant === 'primary')) {\n\t\t\t\treturn 'secondary'\n\t\t\t}\n\t\t\t// handle legacy behavior\n\t\t\tif (this.type !== 'secondary' && ['primary', 'tertiary', 'tertiary-no-background', 'tertiary-on-primary', 'error', 'warning', 'success'].includes(this.type)) {\n\t\t\t\treturn this.type\n\t\t\t}\n\t\t\t// otherwise use the configured variant\n\t\t\treturn this.variant\n\t\t},\n\n\t\t/**\n\t\t * The HTML button type\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trealType() {\n\t\t\tif (typeof this.pressed === 'boolean') {\n\t\t\t\treturn 'button'\n\t\t\t}\n\t\t\t// Handle legacy behavior\n\t\t\tif (this.nativeType !== 'button') {\n\t\t\t\treturn this.nativeType\n\t\t\t}\n\t\t\t// Also handling legacy behavior: Ensure we do not conflict here\n\t\t\tif (['primary', 'secondary', 'tertiary', 'tertiary-no-background', 'tertiary-on-primary', 'error', 'warning', 'success'].includes(this.type)) {\n\t\t\t\treturn this.nativeType\n\t\t\t}\n\t\t\t// otherwise use the type\n\t\t\treturn this.type\n\t\t},\n\n\t\t/**\n\t\t * The variant is one of the tertiary- ones\n\t\t */\n\t\tisTertiary() {\n\t\t\treturn this.realVariant.startsWith('tertiary')\n\t\t},\n\n\t\t/**\n\t\t * The flexbox alignment of the button content\n\t\t */\n\t\tflexAlignment() {\n\t\t\treturn this.alignment.split('-')[0]\n\t\t},\n\n\t\t/**\n\t\t * If the button content should be reversed (icon on the end)\n\t\t */\n\t\tisReverseAligned() {\n\t\t\treturn this.alignment.includes('-')\n\t\t},\n\n\t\tncPopoverTriggerAttrs() {\n\t\t\treturn this.getNcPopoverTriggerAttrs()\n\t\t},\n\t},\n\n\t/**\n\t * The render function to display the component\n\t *\n\t * @param {Function} h The function to create VNodes\n\t * @return {object|undefined} The created VNode\n\t */\n\trender(h) {\n\t\tconst hasText = !!this.$slots.default\n\t\tconst hasIcon = this.$slots?.icon\n\n\t\t/**\n\t\t * Always fill either the text prop or the ariaLabel one.\n\t\t */\n\t\tif (!hasText && !this.ariaLabel) {\n\t\t\tlogger.warn('You need to fill either the text or the ariaLabel props in the button component.', {\n\t\t\t\ttext: this.$slots.default?.[0]?.text,\n\t\t\t\tariaLabel: this.ariaLabel,\n\t\t\t}, this)\n\t\t}\n\n\t\tconst isLink = (this.to || this.href)\n\n\t\tconst hasPressed = !isLink && typeof this.pressed === 'boolean'\n\n\t\tconst renderButton = ({ href, navigate, isActive, isExactActive } = {}) => h(\n\t\t\tisLink ? 'a' : 'button',\n\t\t\t{\n\t\t\t\tclass: [\n\t\t\t\t\t'button-vue',\n\t\t\t\t\t`button-vue--size-${this.size}`,\n\t\t\t\t\t{\n\t\t\t\t\t\t'button-vue--icon-only': hasIcon && !hasText,\n\t\t\t\t\t\t'button-vue--text-only': hasText && !hasIcon,\n\t\t\t\t\t\t'button-vue--icon-and-text': hasIcon && hasText,\n\t\t\t\t\t\t[`button-vue--vue-${this.realVariant}`]: this.realVariant,\n\t\t\t\t\t\t'button-vue--legacy': isLegacy32,\n\t\t\t\t\t\t'button-vue--tertiary': this.isTertiary,\n\t\t\t\t\t\t'button-vue--wide': this.wide,\n\t\t\t\t\t\t[`button-vue--${this.flexAlignment}`]: this.flexAlignment !== 'center',\n\t\t\t\t\t\t'button-vue--reverse': this.isReverseAligned,\n\t\t\t\t\t\tactive: isActive,\n\t\t\t\t\t\t'router-link-exact-active': isExactActive,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tattrs: {\n\t\t\t\t\t'aria-label': this.ariaLabel,\n\t\t\t\t\t'aria-pressed': hasPressed ? this.pressed.toString() : undefined,\n\t\t\t\t\tdisabled: this.disabled,\n\t\t\t\t\ttype: isLink ? null : this.realType,\n\t\t\t\t\trole: isLink ? 'button' : null,\n\t\t\t\t\thref: this.to ? href : (this.href || null),\n\t\t\t\t\ttarget: isLink ? (this.target || '_self') : null,\n\t\t\t\t\trel: isLink ? 'nofollow noreferrer noopener' : null,\n\t\t\t\t\tdownload: (!this.to && this.href && this.download) ? this.download : null,\n\t\t\t\t\t// If this button is used as a popover trigger, we need to apply trigger attrs, e.g. aria attributes\n\t\t\t\t\t...this.ncPopoverTriggerAttrs,\n\t\t\t\t\t// Inherit all the component attrs\n\t\t\t\t\t...this.$attrs,\n\t\t\t\t},\n\t\t\t\ton: {\n\t\t\t\t\t...this.$listeners,\n\t\t\t\t\tclick: ($event) => {\n\t\t\t\t\t\tif (hasPressed) {\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Update the current pressed state of the button (if the `pressed` property was configured)\n\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t * @property {boolean} newValue The new `pressed`-state\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.$emit('update:pressed', !this.pressed)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// We have to both navigate and emit the click event\n\t\t\t\t\t\tthis.$emit('click', $event)\n\t\t\t\t\t\tnavigate?.($event)\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t[\n\t\t\t\th('span', { class: 'button-vue__wrapper' }, [\n\t\t\t\t\thasIcon\n\t\t\t\t\t\t? h('span', {\n\t\t\t\t\t\t\t\tclass: 'button-vue__icon',\n\t\t\t\t\t\t\t\tattrs: {\n\t\t\t\t\t\t\t\t\t'aria-hidden': 'true',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}, [this.$slots.icon])\n\t\t\t\t\t\t: null,\n\t\t\t\t\thasText ? h('span', { class: 'button-vue__text' }, [this.$slots.default]) : null,\n\t\t\t\t]),\n\t\t\t],\n\t\t)\n\n\t\t// If we have a router-link, we wrap the button in it\n\t\tif (this.to) {\n\t\t\treturn h('router-link', {\n\t\t\t\tprops: {\n\t\t\t\t\tcustom: true,\n\t\t\t\t\tto: this.to,\n\t\t\t\t\texact: this.exact,\n\t\t\t\t},\n\t\t\t\tscopedSlots: {\n\t\t\t\t\tdefault: renderButton,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\t// Otherwise we simply return the button\n\t\treturn renderButton()\n\t},\n}\n\n</script>\n\n<style lang=\"scss\" scoped>\n.button-vue {\n\t--button-size: var(--default-clickable-area);\n\t--button-inner-size: calc(var(--button-size) - 4px); // without the outer border\n\t--button-radius: var(--border-radius-element, calc(var(--button-size) / 2));\n\t--button-padding-default: clamp(var(--default-grid-baseline), var(--button-radius), calc(var(--default-grid-baseline) * 4));\n\t--button-padding: var(--default-grid-baseline) var(--button-padding-default);\n\n\t// General styles\n\t// by default use secondary styling\n\tcolor: var(--color-primary-element-light-text);\n\tbackground-color: var(--color-primary-element-light);\n\tborder: 1px solid var(--color-primary-element-light-hover);\n\tborder-bottom-width: 2px;\n\tborder-radius: var(--button-radius);\n\tbox-sizing: border-box;\n\t// adjust position and size\n\tposition: relative;\n\twidth: fit-content;\n\toverflow: hidden;\n\tpadding-block: 1px 0; // center the content as border is 1px top and 2px bottom\n\tpadding-inline: var(--button-padding);\n\tmin-height: var(--button-size);\n\tmin-width: var(--button-size);\n\t// display setup\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\ttransition-property: color, border-color, background-color;\n\ttransition-duration: 0.1s;\n\ttransition-timing-function: linear;\n\tcursor: pointer;\n\tfont-size: var(--default-font-size);\n\tfont-weight: bold;\n\n\t&--size-small {\n\t\t--button-size: var(--clickable-area-small, 24px);\n\t\t--button-radius: var(--border-radius); // make the border radius even smaller for small buttons\n\t}\n\n\t&--size-large {\n\t\t--button-size: var(--clickable-area-large, 48px);\n\t}\n\n\t// Cursor pointer on element and all children\n\t&,\n\t& :deep(*) {\n\t\tcursor: pointer;\n\t}\n\n\t// No outline feedback for focus. Handled with a toggled class in js (see data)\n\t&:focus {\n\t\toutline: none;\n\t}\n\n\t&:disabled {\n\t\tcursor: default;\n\t\topacity: $opacity_disabled;\n\t\t// Gives a wash out effect\n\t\tfilter: saturate($opacity_normal);\n\n\t\t& :deep(*) {\n\t\t\tcursor: default;\n\t\t}\n\t}\n\n\t// Default button type\n\t&:hover:not(:disabled) {\n\t\tbackground-color: var(--color-primary-element-light-hover);\n\t}\n\n\t// Back to the default color for this button when active\n\t// TODO: add ripple effect\n\t&:active {\n\t\tbackground-color: var(--color-primary-element-light);\n\t}\n\n\t&__wrapper {\n\t\tdisplay: inline-flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\twidth: 100%;\n\t}\n\n\t&--end &__wrapper {\n\t\tjustify-content: end;\n\t}\n\t&--start &__wrapper {\n\t\tjustify-content: start;\n\t}\n\t&--reverse &__wrapper {\n\t\tflex-direction: row-reverse;\n\t}\n\n\t&--reverse#{&}--icon-and-text {\n\t\t--button-padding: var(--button-padding-default) var(--default-grid-baseline);\n\t}\n\n\t&__icon {\n\t\t--default-clickable-area: var(--button-inner-size); // ensure icons align with current button size\n\t\theight: var(--button-inner-size);\n\t\twidth: var(--button-inner-size);\n\t\tmin-height: var(--button-inner-size);\n\t\tmin-width: var(--button-inner-size);\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\talign-items: center;\n\t}\n\n\t// For small buttons we need to adjust the icon size\n\t&--size-small &__icon {\n\t\t:deep(> *) {\n\t\t\tmax-height: 16px;\n\t\t\tmax-width: 16px;\n\t\t}\n\t\t:deep(svg) {\n\t\t\theight: 16px;\n\t\t\twidth: 16px;\n\t\t}\n\t}\n\n\t&__text {\n\t\tfont-weight: bold;\n\t\tmargin-bottom: 1px;\n\t\tpadding: 2px 0;\n\t\twhite-space: nowrap;\n\t\ttext-overflow: ellipsis;\n\t\toverflow: hidden;\n\t}\n\n\t// Icon-only button\n\t&--icon-only {\n\t\t--button-padding: clamp(var(--default-grid-baseline), var(--button-radius), calc(var(--default-grid-baseline) * 4));\n\t\tline-height: 1;\n\t\twidth: var(--button-size) !important;\n\t}\n\n\t// Text-only button\n\t&--text-only {\n\t\t--button-padding: var(--button-padding-default);\n\n\t\t& .button-vue__text {\n\t\t\tmargin-inline: 4px;\n\t\t}\n\t}\n\n\t// Wide button spans the whole width of the container\n\t&--wide {\n\t\twidth: 100%;\n\t}\n\n\t&:focus-visible {\n\t\toutline: 2px solid var(--color-main-text) !important;\n\t\tbox-shadow: 0 0 0 4px var(--color-main-background) !important;\n\t\t&.button-vue--vue-tertiary-on-primary {\n\t\t\toutline: 2px solid var(--color-primary-element-text);\n\t\t\tborder-radius: var(--border-radius-element, var(--border-radius));\n\t\t\tbackground-color: transparent;\n\t\t}\n\t}\n\n\t// Button types\n\n\t// Primary\n\t&--vue-primary {\n\t\tbackground-color: var(--color-primary-element);\n\t\tborder-color: var(--color-primary-element-hover);\n\t\tcolor: var(--color-primary-element-text);\n\n\t\t&:hover:not(:disabled) {\n\t\t\tbackground-color: var(--color-primary-element-hover);\n\t\t}\n\t\t// Back to the default color for this button when active\n\t\t// TODO: add ripple effect\n\t\t&:active {\n\t\t\tbackground-color: var(--color-primary-element);\n\t\t}\n\t}\n\n\t// Secondary\n\t&--vue-secondary {\n\t\tbackground-color: var(--color-primary-element-light);\n\t\tborder-color: var(--color-primary-element-light-hover);\n\t\tcolor: var(--color-primary-element-light-text);\n\n\t\t&:hover:not(:disabled) {\n\t\t\tcolor: var(--color-primary-element-light-text);\n\t\t\tbackground-color: var(--color-primary-element-light-hover);\n\t\t}\n\t}\n\n\t// Tertiary\n\t&--tertiary,\n\t&--vue-tertiary {\n\t\tbackground-color: transparent;\n\t\tborder-color: transparent;\n\t\tcolor: var(--color-main-text);\n\n\t\t&:hover:not(:disabled) {\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t}\n\t}\n\n\t// Tertiary, no background\n\t&--vue-tertiary-no-background {\n\t\t&:hover:not(:disabled) {\n\t\t\tbackground-color: transparent;\n\t\t}\n\t}\n\n\t// Tertiary on primary color (like the header)\n\t&--vue-tertiary-on-primary {\n\t\tcolor: var(--color-primary-element-text);\n\n\t\t&:hover:not(:disabled) {\n\t\t\tbackground-color: transparent;\n\t\t}\n\t}\n\n\t// Success\n\t&--vue-success {\n\t\tbackground-color: var(--color-success);\n\t\tborder-color: var(--color-success-hover);\n\t\tcolor: var(--color-success-text);\n\n\t\t&:hover:not(:disabled) {\n\t\t\tbackground-color: var(--color-success-hover);\n\t\t}\n\t\t// Back to the default color for this button when active\n\t\t// : add ripple effect\n\t\t&:active {\n\t\t\tbackground-color: var(--color-success);\n\t\t}\n\t}\n\n\t// Warning\n\t&--vue-warning {\n\t\tbackground-color: var(--color-warning);\n\t\tborder-color: var(--color-warning-hover);\n\t\tcolor: var(--color-warning-text);\n\n\t\t&:hover:not(:disabled) {\n\t\t\tbackground-color: var(--color-warning-hover);\n\t\t}\n\t\t// Back to the default color for this button when active\n\t\t// TODO: add ripple effect\n\t\t&:active {\n\t\t\tbackground-color: var(--color-warning);\n\t\t}\n\t}\n\n\t// Error\n\t&--vue-error {\n\t\tbackground-color: var(--color-error);\n\t\tborder-color: var(--color-error-hover);\n\t\tcolor: var(--color-error-text);\n\n\t\t&:hover:not(:disabled) {\n\t\t\tbackground-color: var(--color-error-hover);\n\t\t}\n\t\t// Back to the default color for this button when active\n\t\t// TODO: add ripple effect\n\t\t&:active {\n\t\t\tbackground-color: var(--color-error);\n\t\t}\n\t}\n\n\t// before Nextcloud 32\n\t&--legacy {\n\t\t--button-inner-size: var(--button-size);\n\t\tborder: none;\n\t\tpadding-block: 0;\n\n\t\t&.button-vue--vue-error,\n\t\t&.button-vue--vue-success,\n\t\t&.button-vue--vue-warning {\n\t\t\tcolor: white;\n\t\t}\n\t}\n}\n\n</style>\n"],"names":[],"mappings":"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"}