Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit c2d1e3e

Browse files
Merge pull request #44 from chakra-ui/feat/modal
feat: modal component
2 parents f8688e9 + 718bc68 commit c2d1e3e

File tree

124 files changed

+4463
-523
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+4463
-523
lines changed

.DS_Store

0 Bytes
Binary file not shown.

.changeset/rare-ads-impress.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
'@chakra-ui/c-accordion': minor
3+
'@chakra-ui/c-alert': minor
4+
'@chakra-ui/c-button': minor
5+
'@chakra-ui/c-code': minor
6+
'@chakra-ui/c-flex': minor
7+
'@chakra-ui/c-focus-lock': minor
8+
'@chakra-ui/c-icon': minor
9+
'@chakra-ui/c-modal': minor
10+
'@chakra-ui/c-motion': minor
11+
'@chakra-ui/c-popper': minor
12+
'@chakra-ui/c-portal': minor
13+
'@chakra-ui/c-reset': minor
14+
'@chakra-ui/c-scroll-lock': minor
15+
'@chakra-ui/c-spinner': minor
16+
'@chakra-ui/c-visually-hidden': minor
17+
'@chakra-ui/vue-next': minor
18+
'@chakra-ui/vue-layout': minor
19+
'@chakra-ui/vue-theme': minor
20+
'@chakra-ui/vue-theme-tools': minor
21+
'@chakra-ui/vue-utils': minor
22+
'@chakra-ui/vue-a11y': minor
23+
'@chakra-ui/vue-composables': minor
24+
'@chakra-ui/vue-auto-import': minor
25+
'@chakra-ui/vue-docs': minor
26+
---
27+
28+
- Adds Modal component
29+
- Adds FocusLock composable, directive and component
30+
- Adds ScrollLock composable, directive and component
31+
- Improves TSX support

.eslintignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ dist
44
# At the time of writing this, I could not find any helpful
55
# documentation for adding ESLint for Vue 3 projects running on Vite.
66
# For this reason, we ignore the playground directory.
7-
playground
7+
playground
8+
snapshots.js

_templates/generator/component/component.ts.ejs.t

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
---
22
to: packages/<%=h.changeCase.paramCase(name)%>/src/<%=h.changeCase.paramCase(name)%>.ts
33
---
4+
/**
5+
* Hey! Welcome to @chakra-ui/vue-next <%= h.changeCase.pascalCase(name) %>
6+
*
7+
* <%=h.changeCase.sentence(description)%>
8+
*
9+
* @see Docs https://next.vue.chakra-ui.com/<%=h.changeCase.paramCase(name)%>
10+
* @see Source https://github.com/chakra-ui/chakra-ui-vue-next/blob/master/packages/<%=h.changeCase.paramCase(name)%>/src/<%=h.changeCase.paramCase(name)%>/<%=h.changeCase.paramCase(name)%>.ts
11+
* @see WAI-ARIA https://www.w3.org/TR/wai-aria-practices-1.2
12+
*/
413

514
import { h, defineComponent, PropType } from 'vue'
615
import { chakra, DOMElements } from '@chakra-ui/vue-system'

babel.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ const testConfig = {
3535
[
3636
'@babel/preset-env',
3737
{
38-
targets: { node: true },
38+
targets: { node: 'current' },
3939
},
4040
],
4141
],
42-
plugins: ['@vue/babel-plugin-jsx'],
42+
plugins: ['@vue/babel-plugin-jsx', '@babel/plugin-transform-runtime'],
4343
},
4444
},
4545
}

docs/.vitepress/config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ function getSetupSidebar() {
6565
{
6666
text: 'Composables',
6767
children: [
68-
{ text: 'usePopper', link: '/composables/use-popper' }
68+
{ text: 'usePopper', link: '/composables/use-popper' },
69+
{ text: 'useFocusLock', link: '/composables/use-focus-lock' }
6970
]
7071
}
7172
]

docs/composables/use-focus-lock.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# useFocusLock
2+
3+
The **`useFocusLock`** hook is an internal hook for Chakra UI Vue used to encapsulate `focus-trap` into an extendable composable hook.
4+
5+
This allows us to compose the behaviour required for focus trapping accessible dialogs and modals into a single hook and can be extended as a component
6+
7+
## Import
8+
9+
```bash
10+
import { useFocusLock } from "@chakra-ui/c-focus-lock"
11+
```
12+
13+
This composable accepts options to modify the positioning fo the popover as well as the modifiers of the popper. It returns an object of properties that can be used to bind the template refs to the popper instance
14+
15+
## Usage
16+
17+
```vue
18+
<template>
19+
<chakra.div
20+
:ref="lock"
21+
p="4"
22+
border="4px dashed"
23+
rounded="lg"
24+
border-color="gray.400"
25+
d="inline-block"
26+
>
27+
<chakra.p mb="2">Inside focus trap</chakra.p>
28+
<c-button @click="options.enabled = true" color-scheme="teal">
29+
Enable focus lock
30+
</c-button>
31+
<c-button :ref="initialFocus" color-scheme="yellow" mx="2"
32+
>Button 2</c-button
33+
>
34+
<c-button color-scheme="blue">Button 3</c-button>
35+
</chakra.div>
36+
</template>
37+
38+
<script lang="ts">
39+
import { useFocusLock, FocusLockOptions } from '@chakra-ui/c-focus-lock'
40+
import { defineComponent, reactive } from 'vue'
41+
42+
export default defineComponent({
43+
setup() {
44+
const options: FocusLockOptions = reactive({
45+
enabled: true,
46+
onActivate: () => {
47+
console.log('focus lock ENABLED')
48+
},
49+
onDeactivate: () => {
50+
console.log('focus lock DEACTIVATED')
51+
},
52+
})
53+
54+
const { lock, initialFocus } = useFocusLock(options)
55+
56+
return {
57+
lock,
58+
options,
59+
initialFocus,
60+
}
61+
},
62+
})
63+
</script>
64+
65+
66+
```
67+
68+
## Props
69+
These are the options for the `usePopper` composable. These properties are similar to the options listed in the [@popperjs/core](https://popper.js.org/docs/v2/) documentation.
70+
```ts
71+
export interface FocusLockOptions {
72+
/**
73+
* Determines whether the focus lock is active or inactive
74+
* @default true
75+
*/
76+
enabled: boolean
77+
/**
78+
* Invoked handler when focus-lock is activated
79+
*/
80+
onActivate?: () => void
81+
/**
82+
* Invoked handler when focus-lock is deactivated
83+
*/
84+
onDeactivate?: () => void
85+
/**
86+
* Invoked handler when focus-lock is activated.
87+
*
88+
* By default, an error will be thrown if the focus lock
89+
* contains no elements in its tab order. With this
90+
* option you can specify a fallback element to
91+
* programmatically receive focus if no other
92+
* tabbable elements are found.
93+
*/
94+
fallbackFocus?: FocusTarget
95+
/**
96+
* Determines whether focus lock is activated when user clicks outside.
97+
* @default true
98+
*/
99+
clickOutsideDeactivates?: boolean | ((e: MouseEvent) => boolean)
100+
persistentFocus?: boolean | ((e: MouseEvent) => boolean)
101+
/**
102+
* Determines whether to return focus to the previously focused element
103+
* before the focus-trap was activated, after the focus trap has been deactivated.
104+
*/
105+
returnFocus?: boolean
106+
preventScroll?: boolean
107+
escapeDeactivates?: boolean
108+
delayInitialFocus?: boolean
109+
}
110+
```

docs/guides/component-guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ we advice to follow to deliver on the quality expectations.
9494

9595
### General
9696

97-
- Ensure you check the `@chakra-ui/vue-hooks`, and `@chakra-ui/vue-utils` package to be
97+
- Ensure you check the `@chakra-ui/vue-composables`, and `@chakra-ui/vue-utils` package to be
9898
sure we don't already have the hook you're looking to create.
9999
- Leverage existing code, hook, or utils as much as possible.
100100
- Separate component logic from UI by writing hooks, and then writing the

package.json

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
"workspaces": [
99
"packages/*",
1010
"tooling/*",
11-
"website",
12-
"tests"
11+
"website"
1312
],
1413
"scripts": {
1514
"pkg": "manypkg run",
@@ -20,7 +19,7 @@
2019
"scaffold": "hygen generator",
2120
"release": "yarn changeset publish",
2221
"build": "lerna run build --no-private --stream",
23-
"dev": "NODE_ENV=development vite serve playground --config ./vite.config.ts",
22+
"dev": "NODE_ENV=development vite serve playground --config ./vite.config.ts --open",
2423
"playground:build": "yarn install && yarn build && yarn bootstrap && NODE_ENV=production vite build playground --config ./vite.config.ts",
2524
"cy:open": "cypress open-ct",
2625
"cy:run": "cypress run-ct --quiet",
@@ -55,6 +54,7 @@
5554
"@testing-library/jest-dom": "^5.11.9",
5655
"@testing-library/user-event": "^12.6.2",
5756
"@testing-library/vue": "^6.3.4",
57+
"@types/body-scroll-lock": "^2.6.1",
5858
"@types/jest": "^26.0.20",
5959
"@types/jest-axe": "^3.5.1",
6060
"@types/lodash.camelcase": "^4.3.6",
@@ -70,10 +70,13 @@
7070
"@vue/eslint-config-typescript": "^5.1.0",
7171
"@vuedx/typecheck": "^0.4.1",
7272
"@vuedx/typescript-plugin-vue": "^0.4.1",
73-
"@vueuse/motion": "1.5.4",
7473
"@vueuse/core": "4.9.1",
74+
"@vueuse/integrations": "^4.8.1",
75+
"@vueuse/motion": "^1.5.4",
76+
"aria-hidden": "^1.1.2",
7577
"axe-core": "^4.1.2",
7678
"babel-jest": "^26.6.3",
79+
"body-scroll-lock": "^3.1.5",
7780
"change-case": "^4.1.1",
7881
"chokidar": "^3.5.1",
7982
"concurrently": "^5.3.0",
@@ -82,6 +85,7 @@
8285
"css-get-unit": "^1.0.1",
8386
"csstype": "^3.0.5",
8487
"dequal": "^2.0.2",
88+
"dom-focus-lock": "^1.0.4",
8589
"esbuild-jest": "^0.4.0",
8690
"eslint": "^7.0.0",
8791
"eslint-config-prettier": "^6.12.0",
@@ -93,6 +97,7 @@
9397
"eslint-plugin-standard": "^4.0.1",
9498
"eslint-plugin-vue": "^7.0.0",
9599
"feather-icons-paths": "^1.0.8",
100+
"focus-trap": "^6.3.0",
96101
"fs-extra": "^9.0.1",
97102
"husky": "^4.3.8",
98103
"hygen": "^6.0.4",
@@ -124,10 +129,14 @@
124129
"vue3-perfect-scrollbar": "^1.5.5"
125130
},
126131
"devDependencies": {
132+
"@babel/plugin-transform-runtime": "^7.13.15",
127133
"@cypress/snapshot": "^2.1.7",
128134
"@cypress/vite-dev-server": "^1.2.6",
129-
"@cypress/vue": "^3.0.1",
135+
"@cypress/vue": "^3",
130136
"@vue/test-utils": "^2.0.0-rc.6",
131-
"cypress": "^7.2.0"
137+
"cypress": "^7.2.0",
138+
"cypress-commands": "^1.1.0",
139+
"cypress-plugin-tab": "^1.0.5",
140+
"local-cypress": "^1.2.1"
132141
}
133142
}

packages/c-alert/examples/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export * as BaseAlert from './base-alert.vue'
22
export * as WithAccent from './with-accent.vue'
33
export * as WithIcon from './with-icon.vue'
44
export * as WithStatus from './with-status.vue'
5-
export * as WithTitle from './with-title.vue'
5+
export * as WithTitle from './with-title.vue'

packages/c-alert/tests/c-alert.cy.tsx

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,24 @@ import { CAlert, CAlertDescription, CAlertIcon, CAlertTitle } from '../src'
55
describe('Alert Examples', () => {
66
Object.entries(Examples).map(([name, example]) => {
77
it(`renders ${name} successfully`, () => {
8-
cy.mount(example.default)
9-
.then(() => {})
10-
.checkA11y()
8+
cy.mount(h(() => <example.default></example.default>)).checkA11y()
119
})
1210
})
1311
})
1412

1513
it('contains the correct role', () => {
16-
cy.mount(Examples.BaseAlert.default)
17-
.then(() => {})
18-
.get('[role=alert]')
19-
.should('exist')
14+
cy.mount(Examples.BaseAlert.default).get('[role=alert]').should('exist')
2015
})
2116

2217
it('renders its children', () => {
2318
cy.mount(
24-
<CAlert data-testid="alert" variant="left-accent" status="info" mb="3">
25-
<CAlertIcon mr="2" />
26-
<CAlertTitle> Info alert </CAlertTitle>
27-
<CAlertDescription> Something just happened </CAlertDescription>
28-
</CAlert>
19+
h(() => (
20+
<CAlert data-testid="alert" variant="left-accent" status="info" mb="3">
21+
<CAlertIcon mr="2" />
22+
<CAlertTitle> Info alert </CAlertTitle>
23+
<CAlertDescription> Something just happened </CAlertDescription>
24+
</CAlert>
25+
))
2926
)
3027
.get('[data-testid=alert]')
3128
.should('contain', 'Info alert')
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * as WithButtonGroup from './with-button-group.vue'
1+
export * as WithButtonGroup from './with-button-group.vue'

packages/c-button/examples/button.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ export * as WithAttachedButtons from './with-attached-buttons.vue'
44
export * as WithButtonSize from '../examples/with-button-size.vue'
55
export * as WithButtonIcon from '../examples/with-button-icon.vue'
66
export * as WithButtonVariants from '../examples/with-button-variants.vue'
7-
export * as WithLoadingStatus from '../examples/with-loading-status.vue'
7+
export * as WithLoadingStatus from '../examples/with-loading-status.vue'

packages/c-button/examples/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export * as Button from './button'
2-
export * as ButtonGroup from './button-group'
2+
export * as ButtonGroup from './button-group'

packages/c-button/examples/with-button-variants.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<template>
22
<div>
3+
<c-button mr="3" variant="luxury"> Solid </c-button>
34
<c-button mr="3" variant="solid" color-scheme="teal"> Solid </c-button>
45
<c-button mr="3" variant="outline" color-scheme="teal"> Outline </c-button>
56
<c-button mr="3" variant="ghost" color-scheme="teal"> Ghost </c-button>

packages/c-button/src/button-group.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ const props = {
3434
...vueThemingProps,
3535
}
3636

37-
type ButtonGroupContext = ComputedRef<ThemingProps & {
38-
isDisabled?: boolean
39-
}>
37+
type ButtonGroupContext = ComputedRef<
38+
ThemingProps & {
39+
isDisabled?: boolean
40+
}
41+
>
4042

4143
const [ButtonGroupProvider, useButtonGroup] = createContext<ButtonGroupContext>(
4244
{
@@ -49,12 +51,14 @@ const CButtonGroup = defineComponent({
4951
name: 'CButtonGroup',
5052
props,
5153
setup(props, { attrs, slots }) {
52-
ButtonGroupProvider(computed(() => ({
53-
size: props.size,
54-
colorScheme: props.colorScheme,
55-
variant: props.variant,
56-
isDisabled: props.isDisabled,
57-
})))
54+
ButtonGroupProvider(
55+
computed(() => ({
56+
size: props.size,
57+
colorScheme: props.colorScheme,
58+
variant: props.variant,
59+
isDisabled: props.isDisabled,
60+
}))
61+
)
5862

5963
const styles = computed(() => {
6064
let groupStyles: SystemStyleObject = {
@@ -77,9 +81,8 @@ const CButtonGroup = defineComponent({
7781

7882
return groupStyles
7983
})
80-
81-
return () => {
8284

85+
return () => {
8386
return h(
8487
chakra('div', { label: 'button__group' }),
8588
{

0 commit comments

Comments
 (0)