diff --git a/_src /atoms/table-cell/TableCell.js b/_src /atoms/table-cell/TableCell.js
deleted file mode 100644
index cff9de648..000000000
--- a/_src /atoms/table-cell/TableCell.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// @vue/component
-export default {
- props: {
- /**
- * Tag for cell
- */
- tag: {
- type: String,
- default: 'td'
- }
- }
-}
diff --git a/_src /atoms/table-cell/TableCell.scss b/_src /atoms/table-cell/TableCell.scss
deleted file mode 100644
index fab60c456..000000000
--- a/_src /atoms/table-cell/TableCell.scss
+++ /dev/null
@@ -1,109 +0,0 @@
-@import '../../../assets/styles/globals';
-
-$table__padding : $spacer--medium !default;
-$table__cell__padding: $spacer $table__padding !default;
-$table__background : $white !default;
-$table__th-background: $gray-lightest !default;
-$table__border : 1px solid $gray-light !default;
-$table__border-bottom: none !default;
-$table__border-radius: $border-radius !default;
-
-.table {
- th {
- display: none;
-
- &:last-child {
- @include mq($screen-m) {
- border-right: 0;
- }
- }
-
- @include mq($screen-m) {
- display: table-cell;
- padding: $table__padding;
- background: $table__th-background;
- border-right: $table__border;
- border-bottom: $table__border;
- }
- }
-
- tr {
- &:last-child {
- border-bottom: $table__border-bottom;
-
- td {
- @include mq($screen-m) {
- border-bottom: $table__border-bottom;
- }
-
- &:first-child {
- @include mq($screen-m) {
- border-bottom-left-radius: $table__border-radius;
- }
- }
-
- &:last-child {
- @include mq($screen-m) {
- border-bottom-right-radius: $table__border-radius;
- }
- }
- }
- }
- }
-
- td {
- display: flex;
- padding: $table__cell__padding;
- background: $table__background;
-
- &::before {
- display: block;
- width: 25%;
- max-width: 25%;
- margin-right: 10px;
- font-weight: bold;
- content: attr(data-th);
-
- @include mq($screen-m) {
- display: none;
- }
- }
-
- &:last-child {
- @include mq($screen-m) {
- border-right: 0;
- }
- }
-
- @include mq($screen-m) {
- display: table-cell;
- padding: $table__padding;
- background: $table__background;
- border-right: $table__border;
- border-bottom: $table__border;
- }
- }
-
- tfoot {
- tr {
- td {
- display: block;
- padding: $table__cell__padding;
- background: $table__background;
- border-bottom: $table__border-bottom;
-
- @include mq($screen-m) {
- display: table-cell;
- padding: $table__padding;
- background: $table__th-background;
- border-top: $table__border;
- border-right: $table__border;
- }
- }
-
- &:first-child {
- border-top: $table__border;
- }
- }
- }
-}
diff --git a/_src /atoms/table-row/TableRow.scss b/_src /atoms/table-row/TableRow.scss
deleted file mode 100644
index 381981d58..000000000
--- a/_src /atoms/table-row/TableRow.scss
+++ /dev/null
@@ -1,75 +0,0 @@
-@import '../../../assets/styles/globals';
-
-$table__row__padding : $spacer--medium 0 !default;
-$table__background--odd : $white !default;
-$table__background--even: $gray-lightest !default;
-$table__border : 1px solid $gray-light !default;
-$table__border-radius : $border-radius !default;
-
-.table {
- &--odd-even {
- tbody {
- tr {
- &:nth-child(odd) {
- background: $table__background--odd;
- }
-
- &:nth-child(even) {
- background: $table__background--even;
- }
-
- &:first-child {
- border-top-left-radius: $table__border-radius;
- border-top-right-radius: $table__border-radius;
-
- @include mq($screen-m) {
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- }
- }
- }
-
- td {
- background-color: transparent;
- }
- }
- }
-
- tr {
- display: block;
- padding: $table__row__padding;
- border-bottom: $table__border;
-
- @include mq($screen-m) {
- display: table-row;
- padding: 0;
- border-bottom: 0;
- }
- }
-
- thead {
- tr {
- padding: 0;
- border-bottom: 0;
-
- @include mq($screen-m) {
- border-top-left-radius: $table__border-radius;
- border-top-right-radius: $table__border-radius;
- }
- }
-
- th {
- &:first-child {
- @include mq($screen-m) {
- border-top-left-radius: $table__border-radius;
- }
- }
-
- &:last-child {
- @include mq($screen-m) {
- border-top-right-radius: $table__border-radius;
- }
- }
- }
- }
-}
diff --git a/_src /atoms/table/Table.scss b/_src /atoms/table/Table.scss
deleted file mode 100644
index 864423127..000000000
--- a/_src /atoms/table/Table.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-@import '../../../assets/styles/globals';
-
-$table__color : $black !default;
-$table__background : $white !default;
-$table__font-size : $font-size-small !default;
-$table__border-radius: $border-radius !default;
-$table__border : 1px solid $gray-light !default;
-
-.table {
- width: 100%;
- color: $table__color;
- font-size: $table__font-size;
- background: $table__background;
- border: $table__border;
- border-radius: $table__border-radius;
- border-collapse: separate;
- border-spacing: 0;
-
- &__caption {
- @include visually-hidden();
- }
-}
diff --git a/_src /atoms/table/Table.stories.js b/_src /atoms/table/Table.stories.js
deleted file mode 100644
index b40d14130..000000000
--- a/_src /atoms/table/Table.stories.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import { storiesOf } from '@storybook/vue'
-import { select } from '@storybook/addon-knobs'
-
-import bodyRows from './mocks/bodyRows.json'
-import headCells from './mocks/headCells.json'
-import footCells from './mocks/footCells.json'
-
-import generateVueInfoTable from '@utils/helpers/generate-vue-info-table.js'
-import getClassKnobsConfig from '@utils/helpers/get-class-knobs-config.js'
-import selectorsConfig from './Table.selectors.json'
-
-import ATable from './Table.vue'
-import ATableRow from '../table-row/TableRow.vue'
-import ATableCell from '../table-cell/TableCell.vue'
-
-const info = `
-
Check Knobs tab to edit component properties dynamically.
- ${generateVueInfoTable(selectorsConfig, 'BEM modifiers')}
-`
-
-const classKnobsConfig = getClassKnobsConfig(selectorsConfig)
-
-storiesOf('Atoms/Table', module)
- .addParameters({ info })
- .add('Default', () => ({
- components: { ATable, ATableRow, ATableCell },
- props: {
- classKnobs: {
- default: select('BEM Modifier', classKnobsConfig)
- }
- },
- data: () => ({
- bodyRows,
- headCells,
- footCells
- }),
- template: `
-
-
-
-
- {{ headCell.text }}
-
-
-
-
-
-
- {{ bodyCell.text }}
-
-
-
-
-
-
- {{ footCell.text }}
-
-
-
-
- `
- }))
diff --git a/src/atoms/table-cell/TableCell.css b/src/atoms/table-cell/TableCell.css
new file mode 100644
index 000000000..8216efec9
--- /dev/null
+++ b/src/atoms/table-cell/TableCell.css
@@ -0,0 +1,112 @@
+.table th {
+ @apply hidden;
+}
+
+@screen md {
+ .table th {
+ @apply table-cell;
+ @apply p-4;
+ @apply bg-gray-200;
+ @apply border-r border-b border-solid border-light;
+ @apply text-left;
+ }
+
+ .table th:last-child {
+ @apply border-r-0;
+ }
+}
+
+.table td {
+ @apply flex;
+ @apply py-2 px-4;
+ @apply bg-white;
+}
+
+@screen md {
+ .table td {
+ @apply table-cell;
+ @apply p-4;
+ @apply border-r border-b border-solid border-light;
+ }
+
+ .table td:last-child {
+ @apply border-r-0;
+ }
+}
+
+.table td::before {
+ content: attr(data-th);
+
+ @apply block;
+ @apply max-w-1/4 mr-2;
+ @apply w-1/4;
+ @apply font-bold;
+}
+
+@screen md {
+ .table td::before {
+ @apply hidden;
+ }
+}
+
+.table tr:last-child td {
+ @apply border-b-0;
+}
+
+.table tfoot td {
+ @apply block;
+ @apply py-2 px-4;
+ @apply bg-white;
+}
+
+@screen md {
+ .table tfoot td {
+ @apply table-cell;
+ @apply p-4;
+ @apply border-t border-r border-b-0 border-solid border-light;
+ }
+}
+
+.table--odd-even tbody td {
+ @apply bg-transparent;
+}
+
+.table--scope-row th {
+ @apply w-1/2;
+ @apply p-4;
+ @apply border-r-0;
+ @apply bg-white;
+ @apply font-normal;
+}
+
+.table--scope-row tr:nth-child(odd) th,
+.table--scope-row tr:nth-child(odd) td {
+ @apply bg-gray-200;
+}
+
+.table--scope-row th + td {
+ @apply flex-col flex-no-wrap;
+ @apply p-4;
+}
+
+@screen sm {
+ .table--scope-row th + td {
+ @apply flex-row;
+ }
+}
+
+.table--scope-row th + td::before {
+ @apply max-w-full w-full;
+ @apply mb-2;
+}
+
+@screen sm {
+ .table--scope-row th + td::before {
+ @apply max-w-1/2 w-1/2;
+ @apply mb-0;
+ }
+}
+
+.table--scope-row tr:last-child td {
+ @apply border-b;
+}
diff --git a/_src /atoms/table-cell/TableCell.html b/src/atoms/table-cell/TableCell.html
similarity index 71%
rename from _src /atoms/table-cell/TableCell.html
rename to src/atoms/table-cell/TableCell.html
index 47a823c39..be536548e 100644
--- a/_src /atoms/table-cell/TableCell.html
+++ b/src/atoms/table-cell/TableCell.html
@@ -1,6 +1,7 @@
diff --git a/src/atoms/table-cell/TableCell.js b/src/atoms/table-cell/TableCell.js
new file mode 100644
index 000000000..8aa6d05f4
--- /dev/null
+++ b/src/atoms/table-cell/TableCell.js
@@ -0,0 +1,26 @@
+// @vue/component
+export default {
+ props: {
+ /**
+ * Tag for cell
+ */
+ tag: {
+ type: String,
+ default: 'td'
+ },
+ /**
+ * Cell role
+ */
+ role: {
+ type: String,
+ default: 'gridcell'
+ },
+ /**
+ * Cell scope
+ */
+ scope: {
+ type: String,
+ default: null
+ }
+ }
+}
diff --git a/src/atoms/table-cell/TableCell.spec.js b/src/atoms/table-cell/TableCell.spec.js
new file mode 100644
index 000000000..683701249
--- /dev/null
+++ b/src/atoms/table-cell/TableCell.spec.js
@@ -0,0 +1,34 @@
+import { mount } from '@vue/test-utils'
+import TableCell from './TableCell.vue'
+
+describe('atoms/TableCell.vue', () => {
+ it('has default structure', () => {
+ const wrapper = mount(TableCell)
+
+ expect(wrapper.element.tagName).toBe('TD')
+ expect(wrapper.element.tagName).toBe('TD')
+ expect(wrapper.attributes().role).toBeDefined()
+ expect(wrapper.attributes().role).toEqual('gridcell')
+ })
+
+ it('renders scope prop when passed', () => {
+ const wrapper = mount(TableCell, {
+ propsData: {
+ scope: 'row'
+ }
+ })
+
+ expect(wrapper.attributes().scope).toBeDefined()
+ expect(wrapper.attributes().scope).toEqual('row')
+ })
+})
+
+it('renders slot text when passed', () => {
+ const wrapper = mount(TableCell, {
+ slots: {
+ default: 'Test table cell'
+ }
+ })
+
+ expect(wrapper.text()).toEqual('Test table cell')
+})
diff --git a/_src /atoms/table-cell/TableCell.vue b/src/atoms/table-cell/TableCell.vue
similarity index 78%
rename from _src /atoms/table-cell/TableCell.vue
rename to src/atoms/table-cell/TableCell.vue
index f1f8fd4bd..c62912bcd 100644
--- a/_src /atoms/table-cell/TableCell.vue
+++ b/src/atoms/table-cell/TableCell.vue
@@ -5,9 +5,8 @@ import ATableCell from './TableCell.js'
export default {
name: 'AlpacaTableCell',
-
mixins: [ATableCell]
}
-
+
diff --git a/src/atoms/table-row/TableRow.css b/src/atoms/table-row/TableRow.css
new file mode 100644
index 000000000..46d6ac078
--- /dev/null
+++ b/src/atoms/table-row/TableRow.css
@@ -0,0 +1,42 @@
+.table tr {
+ @apply block;
+ @apply py-4;
+ @apply border-b border-solid border-light;
+}
+
+.table tr:last-child {
+ @apply border-b-0;
+}
+
+@screen md {
+ .table tr {
+ @apply table-row;
+ @apply py-0;
+ @apply border-b-0;
+ }
+}
+
+.table thead tr {
+ @apply p-0;
+ @apply border-b-0;
+}
+
+.table tfoot tr:first-child {
+ @apply border-t border-solid border-light;
+}
+
+.table tfoot tr:last-child {
+ @apply border-b-0;
+}
+
+.table--odd-even tbody tr:nth-child(odd) {
+ @apply bg-white;
+}
+
+.table--odd-even tbody tr:nth-child(even) {
+ @apply bg-gray-100;
+}
+
+.table--scope-row tbody tr {
+ @apply p-0;
+}
diff --git a/_src /atoms/table-row/TableRow.html b/src/atoms/table-row/TableRow.html
similarity index 100%
rename from _src /atoms/table-row/TableRow.html
rename to src/atoms/table-row/TableRow.html
diff --git a/_src /atoms/table-row/TableRow.js b/src/atoms/table-row/TableRow.js
similarity index 100%
rename from _src /atoms/table-row/TableRow.js
rename to src/atoms/table-row/TableRow.js
diff --git a/src/atoms/table-row/TableRow.spec.js b/src/atoms/table-row/TableRow.spec.js
new file mode 100644
index 000000000..591f1b507
--- /dev/null
+++ b/src/atoms/table-row/TableRow.spec.js
@@ -0,0 +1,25 @@
+import { mount } from '@vue/test-utils'
+import TableRow from './TableRow.vue'
+
+describe('atoms/TableRow.vue', () => {
+ it('has default structure', () => {
+ const wrapper = mount(TableRow)
+
+ expect(wrapper.element.tagName).toBe('TR')
+ expect(wrapper.element.tagName).toBe('TR')
+ expect(wrapper.attributes().role).toBeDefined()
+ expect(wrapper.attributes().role).toEqual('row')
+ })
+
+ it('renders slot when passed', () => {
+ const wrapper = mount(TableRow, {
+ slots: {
+ default: 'Test table row | '
+ }
+ })
+
+ const defaultSlot = wrapper.find('td')
+ expect(defaultSlot.exists()).toBe(true)
+ expect(defaultSlot.text()).toEqual('Test table row')
+ })
+})
diff --git a/_src /atoms/table-row/TableRow.vue b/src/atoms/table-row/TableRow.vue
similarity index 78%
rename from _src /atoms/table-row/TableRow.vue
rename to src/atoms/table-row/TableRow.vue
index da0099f1f..ae56e5b71 100644
--- a/_src /atoms/table-row/TableRow.vue
+++ b/src/atoms/table-row/TableRow.vue
@@ -9,4 +9,4 @@ export default {
}
-
+
diff --git a/src/atoms/table/Table.css b/src/atoms/table/Table.css
new file mode 100644
index 000000000..bcd5556da
--- /dev/null
+++ b/src/atoms/table/Table.css
@@ -0,0 +1,24 @@
+.table {
+ @apply w-full;
+ @apply my-2;
+ @apply bg-white;
+ @apply border border-solid border-light;
+ @apply border-separate;
+ @apply text-sm leading-relaxed;
+
+ border-spacing: 0;
+}
+
+@screen md {
+ .table {
+ @apply text-base;
+ }
+}
+
+.table--scope-row {
+ @apply border-t border-r-0 border-b-0 border-l-0;
+}
+
+.table__caption {
+ @apply sr-only;
+}
diff --git a/_src /atoms/table/Table.html b/src/atoms/table/Table.html
similarity index 100%
rename from _src /atoms/table/Table.html
rename to src/atoms/table/Table.html
diff --git a/_src /atoms/table/Table.js b/src/atoms/table/Table.js
similarity index 100%
rename from _src /atoms/table/Table.js
rename to src/atoms/table/Table.js
diff --git a/_src /atoms/table/Table.selectors.json b/src/atoms/table/Table.selectors.json
similarity index 100%
rename from _src /atoms/table/Table.selectors.json
rename to src/atoms/table/Table.selectors.json
diff --git a/src/atoms/table/Table.spec.js b/src/atoms/table/Table.spec.js
new file mode 100644
index 000000000..e5fff4cf6
--- /dev/null
+++ b/src/atoms/table/Table.spec.js
@@ -0,0 +1,42 @@
+import { mount } from '@vue/test-utils'
+import Table from './Table.vue'
+
+describe('atoms/Table.vue', () => {
+ it('has default structure', () => {
+ const wrapper = mount(Table)
+
+ expect(wrapper.element.tagName).toBe('TABLE')
+ expect(wrapper.classes()).toContain('table')
+ expect(wrapper.classes().length).toBe(1)
+ })
+
+ it('renders caption prop when passed', () => {
+ const wrapper = mount(Table, {
+ propsData: {
+ caption: 'This is a table'
+ }
+ })
+
+ const caption = wrapper.find('caption')
+ expect(caption.exists()).toBe(true)
+ expect(caption.text()).toEqual('This is a table')
+ })
+
+ it('renders slots when defined', () => {
+ const wrapper = mount(Table, {
+ slots: {
+ default: 'Test table |
',
+ caption: 'This is caption slot
'
+ }
+ })
+
+ const captionSlotElement = wrapper.find('div.caption')
+ expect(captionSlotElement.exists()).toBe(true)
+ expect(captionSlotElement.classes()).toContain('caption')
+ expect(captionSlotElement.text()).toEqual('This is caption slot')
+
+ const defaultSlot = wrapper.find('tbody tr td')
+ expect(defaultSlot.exists()).toBe(true)
+ expect(defaultSlot.text()).toEqual('Test table')
+ })
+})
diff --git a/src/atoms/table/Table.stories.js b/src/atoms/table/Table.stories.js
new file mode 100644
index 000000000..0d1a8c032
--- /dev/null
+++ b/src/atoms/table/Table.stories.js
@@ -0,0 +1,110 @@
+import { select } from '@storybook/addon-knobs'
+
+import bodyRows from './mocks/bodyRows.json'
+import headCells from './mocks/headCells.json'
+import footCells from './mocks/footCells.json'
+import scopeRow from './mocks/scopeRow.json'
+
+import getClassKnobsConfig from '@utils/helpers/get-class-knobs-config.js'
+import selectorsConfig from './Table.selectors.json'
+
+import ATable from './Table.vue'
+import ATableRow from '../table-row/TableRow.vue'
+import ATableCell from '../table-cell/TableCell.vue'
+
+const classKnobsConfig = getClassKnobsConfig(selectorsConfig)
+
+export default {
+ title: 'Atoms/Table',
+ component: ATable
+}
+
+export const Default = () => ({
+ components: { ATable, ATableRow, ATableCell },
+ props: {
+ classKnobs: {
+ default: select('BEM Modifier', classKnobsConfig)
+ }
+ },
+ data: () => ({
+ bodyRows,
+ headCells,
+ footCells
+ }),
+ template: `
+
+
+
+
+ {{ headCell.text }}
+
+
+
+
+
+
+ {{ bodyCell.text }}
+
+
+
+
+
+
+ {{ footCell.text }}
+
+
+
+
+ `
+})
+
+export const ScopeRow = () => ({
+ components: { ATable, ATableRow, ATableCell },
+ data: () => ({
+ scopeRow
+ }),
+ template: `
+
+
+
+
+ {{ bodyCell.text }}
+
+
+
+
+ `
+})
diff --git a/_src /atoms/table/Table.vue b/src/atoms/table/Table.vue
similarity index 77%
rename from _src /atoms/table/Table.vue
rename to src/atoms/table/Table.vue
index 4b35c0665..a3baf2b59 100644
--- a/_src /atoms/table/Table.vue
+++ b/src/atoms/table/Table.vue
@@ -5,9 +5,8 @@ import ATable from './Table.js'
export default {
name: 'AlpacaTable',
-
mixins: [ATable]
}
-
+
diff --git a/_src /atoms/table/mocks/bodyRows.json b/src/atoms/table/mocks/bodyRows.json
similarity index 100%
rename from _src /atoms/table/mocks/bodyRows.json
rename to src/atoms/table/mocks/bodyRows.json
diff --git a/_src /atoms/table/mocks/footCells.json b/src/atoms/table/mocks/footCells.json
similarity index 100%
rename from _src /atoms/table/mocks/footCells.json
rename to src/atoms/table/mocks/footCells.json
diff --git a/_src /atoms/table/mocks/headCells.json b/src/atoms/table/mocks/headCells.json
similarity index 100%
rename from _src /atoms/table/mocks/headCells.json
rename to src/atoms/table/mocks/headCells.json
diff --git a/src/atoms/table/mocks/scopeRow.json b/src/atoms/table/mocks/scopeRow.json
new file mode 100644
index 000000000..8c680dd2b
--- /dev/null
+++ b/src/atoms/table/mocks/scopeRow.json
@@ -0,0 +1,50 @@
+[
+ [
+ {
+ "tag": "th",
+ "role": "rowheader",
+ "scope": "row",
+ "text": "Example heading 1",
+ "id": "rowId1"
+ },
+ {
+ "tag": "td",
+ "role": "gridcell",
+ "text": "Example content 1",
+ "data-th": "Example heading 1:",
+ "id": "rowId2"
+ }
+ ],
+ [
+ {
+ "tag": "th",
+ "role": "rowheader",
+ "scope": "row",
+ "text": "Example heading 2",
+ "id": "rowId3"
+ },
+ {
+ "tag": "td",
+ "role": "gridcell",
+ "text": "Example content 2",
+ "data-th": "Example heading 2:",
+ "id": "rowId4"
+ }
+ ],
+ [
+ {
+ "tag": "th",
+ "role": "rowheader",
+ "scope": "row",
+ "text": "Example heading 3",
+ "id": "rowId5"
+ },
+ {
+ "tag": "td",
+ "role": "gridcell",
+ "text": "Example content 3",
+ "data-th": "Example heading 3:",
+ "id": "rowId6"
+ }
+ ]
+]
diff --git a/tailwind.config.js b/tailwind.config.js
index 75537d571..30cc4d1fc 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -3,7 +3,13 @@ module.exports = {
'src/**/*.vue'
],
theme: {
- extend: {},
+ extend: {
+ maxWidth: {
+ '1/4': '25%',
+ '1/2': '50%',
+ '3/4': '75%'
+ }
+ },
screens: {
xs: '320px',
sm: '480px',
@@ -29,9 +35,10 @@ module.exports = {
'seafoam-blue': '#77ccb9',
teal: '#0194ab',
pink: '#ff5b77',
+ transparent: 'transparent',
gray: {
- 100: '#f7f7f9',
- 200: '#fbfbfb',
+ 100: '#fbfbfb',
+ 200: '#f7f7f9',
300: '#eaeaea',
400: '#bdbdbd',
500: '#d8d8d8',