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

feat(Range): new component #290

Merged
merged 22 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module.exports = {
root: true,
extends: ['@nuxt/eslint-config'],
rules: {
'comma-dangle': ['error', 'never'],
'space-before-function-paren': ['error', 'always'],
'vue/multi-word-component-names': 0,
'vue/max-attributes-per-line': ['error', {
singleline: {
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ dist
.DS_Store
.history
.vercel
.idea
6 changes: 6 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"trailingComma": "none",
"tabWidth": 2,
"semi": false,
"singleQuote": true
}
7 changes: 7 additions & 0 deletions docs/components/content/examples/RangeExample.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script setup>
const value = ref(50)
</script>

<template>
<URange v-model="value" />
</template>
2 changes: 1 addition & 1 deletion docs/content/1.getting-started/3.theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Likewise, you can't define a `primary` color in your `tailwind.config.ts` as it
We'd advise you to use those colors in your components and pages, e.g. `text-primary-500 dark:text-primary-400`, `bg-gray-100 dark:bg-gray-900`, etc. so your app automatically adapts when changing your `app.config.ts`.
::

Components having a `color` prop like [Avatar](/elements/avatar#chip), [Badge](/elements/badge#style), [Button](/elements/button#style), [Input](/elements/input#style) (inherited in [Select](/forms/select) and [SelectMenu](/forms/select-menu)) and [Notification](/overlays/notification#timeout) will use the `primary` color by default but will handle all the colors defined in your `tailwind.config.ts` or the default Tailwind CSS colors.
Components having a `color` prop like [Avatar](/elements/avatar#chip), [Badge](/elements/badge#style), [Button](/elements/button#style), [Input](/elements/input#style) (inherited in [Select](/forms/select) and [SelectMenu](/forms/select-menu)), [Range](/forms/range) and [Notification](/overlays/notification#timeout) will use the `primary` color by default but will handle all the colors defined in your `tailwind.config.ts` or the default Tailwind CSS colors.

Variant classes of those components are defined with a syntax like `bg-{color}-500 dark:bg-{color}-400` so they can be used with any color. However, this means that Tailwind will not find those classes and therefore will not generate the corresponding CSS.

Expand Down
101 changes: 101 additions & 0 deletions docs/content/3.forms/8.range.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
github: true
description: Display a range field
navigation:
badge: "Edge"
---

## Usage

Use a `v-model` to make the Range reactive.

::component-example
#default
:range-example

#code
```vue
<script setup>
const value = ref(50)
</script>

<template>
<URange v-model="value" />
</template>
```
::

### Style

Use the `color` prop to change the visual style of the Range.

::component-card
---
baseProps:
name: range'
placeholder: 'Search...'
props:
color: 'primary'
---
::

### Size

Use the `size` prop to change the size of the Range.

::component-card
---
baseProps:
name: 'range'
props:
size: 'md'
---
::

### Disabled

Use the `disabled` prop to disable the Range.

::component-card
---
baseProps:
name: 'range'
props:
disabled: true
---
::

### Min and Max

Use the `min` and `max` prop to configure the Range.

::component-card
---
baseProps:
name: 'range'
props:
min: 0
max: 100
---
::

### Step

Use the `step` prop to change the step increment.

::component-card
---
baseProps:
name: 'range'
props:
step: 20
---
::

## Props

:component-props

## Preset

:component-preset
33 changes: 25 additions & 8 deletions src/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,26 @@ const kebabCase = (str: string) => {

const safelistByComponent = {
avatar: (colorsAsRegex) => [{
pattern: new RegExp(`bg-(${colorsAsRegex})-500`)
}, {
pattern: new RegExp(`bg-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`bg-(${colorsAsRegex})-500`)
}],
badge: (colorsAsRegex) => [{
pattern: new RegExp(`bg-(${colorsAsRegex})-50`)
}, {
pattern: new RegExp(`bg-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`text-(${colorsAsRegex})-500`)
}, {
pattern: new RegExp(`text-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`ring-(${colorsAsRegex})-500`)
pattern: new RegExp(`text-(${colorsAsRegex})-500`)
}, {
pattern: new RegExp(`ring-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`ring-(${colorsAsRegex})-500`)
}],
button: (colorsAsRegex) => [{
pattern: new RegExp(`bg-(${colorsAsRegex})-50`),
Expand Down Expand Up @@ -98,16 +98,33 @@ const safelistByComponent = {
pattern: new RegExp(`ring-(${colorsAsRegex})-500`),
variants: ['focus']
}],
notification: (colorsAsRegex) => [{
range: (colorsAsRegex) => [{
pattern: new RegExp(`bg-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`bg-(${colorsAsRegex})-500`)
}, {
pattern: new RegExp(`bg-(${colorsAsRegex})-400`),
pattern: new RegExp(`text-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`text-(${colorsAsRegex})-500`)
}, {
pattern: new RegExp(`ring-(${colorsAsRegex})-400`),
variants: ['dark:focus-visible']
}, {
pattern: new RegExp(`ring-(${colorsAsRegex})-500`),
variants: ['focus-visible']
}],
notification: (colorsAsRegex) => [{
pattern: new RegExp(`bg-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`bg-(${colorsAsRegex})-500`)
}, {
pattern: new RegExp(`text-(${colorsAsRegex})-400`),
variants: ['dark']
}, {
pattern: new RegExp(`text-(${colorsAsRegex})-500`)
}]
}

Expand All @@ -116,7 +133,7 @@ const colorsAsRegex = (colors: string[]): string => colors.join('|')
export const excludeColors = (colors: object) => Object.keys(omit(colors, colorsToExclude)).map(color => kebabCase(color)) as string[]

export const generateSafelist = (colors: string[]) => {
const safelist = ['avatar', 'badge', 'button', 'input', 'notification'].flatMap(component => safelistByComponent[component](colorsAsRegex(colors)))
const safelist = ['avatar', 'badge', 'button', 'input', 'range', 'notification'].flatMap(component => safelistByComponent[component](colorsAsRegex(colors)))

return [
...safelist,
Expand Down
40 changes: 37 additions & 3 deletions src/runtime/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,10 @@ const input = {
},
color: {
white: {
outline: 'shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400',
outline: 'shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
},
gray: {
outline: 'shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400',
outline: 'shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
}
},
variant: {
Expand Down Expand Up @@ -400,7 +400,7 @@ const textarea = {
default: {
size: 'sm',
color: 'white',
variant: 'outline',
variant: 'outline'
}
}

Expand Down Expand Up @@ -510,6 +510,39 @@ const toggle = {
}
}

const range = {
wrapper: 'relative w-full',
base: 'w-full absolute appearance-none cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 focus:outline-none [&::-webkit-slider-runnable-track]:h-full [&::-moz-slider-runnable-track]:h-full',
background: 'bg-gray-200 dark:bg-gray-700',
rounded: 'rounded-lg',
ring: 'focus-visible:ring-2 focus-visible:ring-{color}-500 dark:focus-visible:ring-{color}-400 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-gray-900',
progress: {
base: 'absolute inset-0 h-full pointer-events-none',
rounded: 'rounded-l-lg',
background: 'bg-{color}-500 dark:bg-{color}-400'
},
thumb: {
base: `[&::-webkit-slider-thumb]:relative [&::-moz-range-thumb]:relative [&::-webkit-slider-thumb]:z-[1] [&::-moz-range-thumb]:z-[1] [&::-webkit-slider-thumb]:appearance-none [&::-moz-range-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0`,
color: 'text-{color}-500 dark:text-{color}-400',
background: '[&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:dark:bg-gray-900 [&::-moz-range-thumb]:bg-current',
ring: '[&::-webkit-slider-thumb]:ring-2 [&::-webkit-slider-thumb]:ring-current',
size: {
sm: '[&::-webkit-slider-thumb]:h-3 [&::-moz-range-thumb]:h-3 [&::-webkit-slider-thumb]:w-3 [&::-moz-range-thumb]:w-3 [&::-webkit-slider-thumb]:-mt-1 [&::-moz-range-thumb]:-mt-1',
md: '[&::-webkit-slider-thumb]:h-4 [&::-moz-range-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-moz-range-thumb]:w-4 [&::-webkit-slider-thumb]:-mt-1 [&::-moz-range-thumb]:-mt-1',
lg: '[&::-webkit-slider-thumb]:h-5 [&::-moz-range-thumb]:h-5 [&::-webkit-slider-thumb]:w-5 [&::-moz-range-thumb]:w-5 [&::-webkit-slider-thumb]:-mt-1 [&::-moz-range-thumb]:-mt-1'
}
},
size: {
sm: 'h-1',
md: 'h-2',
lg: 'h-3'
},
default: {
size: 'md',
color: 'primary'
}
}

// Layout

const card = {
Expand Down Expand Up @@ -872,6 +905,7 @@ export default {
checkbox,
radio,
toggle,
range,
card,
container,
skeleton,
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/components/data/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import appConfig from '#build/app.config'

// const appConfig = useAppConfig()

function defaultComparator<T>(a: T, z: T): boolean {
function defaultComparator<T> (a: T, z: T): boolean {
return a === z
}

Expand Down
Loading