Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NcButton: Allow to format text of button #4367

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
122 changes: 116 additions & 6 deletions src/components/NcButton/NcButton.vue
Expand Up @@ -319,6 +319,118 @@ export default {
}
</script>
```

### Usage example: Sorting table columns
The standard way to implement sortable table column headers should be like this:

```vue
<template>
<table>
<thead>
<tr>
<th :aria-sorted="sortedName" class="row-name">
<NcButton alignment="start-reverse"
:wide="true"
type="tertiary"
@click="sortName">
<template #icon>
<IconDown v-if="sortedName === 'ascending'" class="sort-icon" :size="20" />
<IconUp v-else-if="sortedName === 'descending'" class="sort-icon" :size="20" />
</template>
<span class="table-header">Name</span>
</NcButton>
</th>
<th :aria-sorted="sortedSize" class="row-size">
<NcButton alignment="end"
:wide="true"
type="tertiary"
@click="sortSize">
<template #icon>
<IconDown v-if="sortedSize === 'ascending'" class="sort-icon" :size="20" />
<IconUp v-else-if="sortedSize === 'descending'" class="sort-icon" :size="20" />
</template>
<span class="table-header">Size</span>
</NcButton>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="row-name">Lorem ipsum</td>
<td class="row-size">8 MiB</td>
</tr>
</tbody>
</table>
</template>
<script>
import IconUp from 'vue-material-design-icons/MenuUp.vue'
import IconDown from 'vue-material-design-icons/MenuDown.vue'

export default {
components: {
IconUp,
IconDown,
},
data() {
return {
sortedName: null,
sortedSize: null,
}
},
methods: {
sortName() {
if (this.sortedName === 'ascending') {
this.sortedName = 'descending'
} else if (this.sortedName === 'descending') {
this.sortedName = null
} else {
this.sortedName = 'ascending'
}
},
sortSize() {
if (this.sortedSize === 'ascending') {
this.sortedSize = 'descending'
} else if (this.sortedSize === 'descending') {
this.sortedSize = null
} else {
this.sortedSize = 'ascending'
}
},
},
}
</script>
<style>
table {
table-layout: fixed;
width: 300px;
}

td.row-name {
padding-inline-start: 16px;
}

td.row-size {
text-align: right;
padding-inline-end: 16px;
}

.table-header {
font-weight: normal;
color: var(--color-text-maxcontrast);
}

.sort-icon {
color: var(--color-text-maxcontrast);
position: relative;
inset-inline: -10px;
}

.row-size .sort-icon {
inset-inline: 10px;
}
</style>
```

</docs>

<script>
Expand Down Expand Up @@ -485,17 +597,15 @@ export default {
* @return {object|undefined} The created VNode
*/
render(h) {
const text = this.$slots.default?.[0]?.text?.trim?.()

const hasText = !!text
const hasText = !!this.$slots.default
const hasIcon = this.$slots?.icon

/**
* Always fill either the text prop or the ariaLabel one.
*/
if (!text && !this.ariaLabel) {
if (!hasText && !this.ariaLabel) {
console.warn('You need to fill either the text or the ariaLabel props in the button component.', {
text,
text: this.$slots.default?.[0]?.text,
ariaLabel: this.ariaLabel,
},
this)
Expand Down Expand Up @@ -559,7 +669,7 @@ export default {
[this.$slots.icon],
)
: null,
hasText ? h('span', { class: 'button-vue__text' }, [text]) : null,
hasText ? h('span', { class: 'button-vue__text' }, [this.$slots.default]) : null,
]),
],
)
Expand Down